diff --git a/src/AIAssistant/.aiassistignore b/src/AIAssistant/.aiassistignore
index 6fa6d9f..2e59dd4 100644
--- a/src/AIAssistant/.aiassistignore
+++ b/src/AIAssistant/.aiassistignore
@@ -393,3 +393,45 @@ temp/
aiassist-config.json
.aiassistignore
.gitignore
+
+# Ignore common image file types
+*.jpg
+*.jpeg
+*.png
+*.gif
+*.bmp
+*.tiff
+*.tif
+*.webp
+*.ico
+*.svg
+
+# Ignore common video file types
+*.mp4
+*.mov
+*.avi
+*.mkv
+*.flv
+*.wmv
+*.webm
+*.mpeg
+*.mpg
+*.m4v
+*.3gp
+*.3g2
+
+# Ignore common document file types
+*.doc
+*.docx
+*.xls
+*.xlsx
+*.ppt
+*.pptx
+*.pdf
+*.txt
+*.rtf
+*.odt
+*.ods
+*.odp
+*.csv
+*.tsv
\ No newline at end of file
diff --git a/src/AIAssistant/AIAssistant.csproj b/src/AIAssistant/AIAssistant.csproj
index b9a3bab..f8d7948 100644
--- a/src/AIAssistant/AIAssistant.csproj
+++ b/src/AIAssistant/AIAssistant.csproj
@@ -27,7 +27,6 @@
-
@@ -39,7 +38,6 @@
-
diff --git a/src/AIAssistant/Commands/CodeAssistCommand.cs b/src/AIAssistant/Commands/CodeAssistCommand.cs
index 2a93061..c2d660d 100644
--- a/src/AIAssistant/Commands/CodeAssistCommand.cs
+++ b/src/AIAssistant/Commands/CodeAssistCommand.cs
@@ -45,10 +45,6 @@ public sealed class Settings : CommandSettings
[Description("[grey] llm model for chatting with ai. for example llama3.1.[/].")]
public string? ChatModel { get; set; }
- [CommandOption("-t|--code-assist-type ")]
- [Description("[grey] the type of code assist. it can be `embedding` or `summary`.[/].")]
- public CodeAssistType? CodeAssistType { get; set; }
-
[CommandOption("-e|--embedding-model ")]
[Description("[grey] llm model for embedding purpose. for example mxbai_embed_large.[/].")]
public string? EmbeddingModel { get; set; }
@@ -59,10 +55,24 @@ public sealed class Settings : CommandSettings
[CommandOption("-d|--diff ")]
[Description(
- "[grey] the diff tool for showing changes. it can be `unifieddiff`, `codeblockdiff` and `mergeconflictdiff`.[/]."
+ "[grey] the diff tool for showing changes. it can be `unified-diff`, `code-block-diff` and `search-replace-diff`.[/]."
)]
public CodeDiffType? CodeDiffType { get; set; }
+ [CommandOption("-t|--code-assist-type ")]
+ [Description("[grey] the type of code assist. it can be `embedding` or `summary`.[/].")]
+ public CodeAssistType? CodeAssistType { get; set; }
+
+ [CommandOption("--threshold ")]
[Description("[grey] the chat model api key.[/].")]
public string? ChatModelApiKey { get; set; }
@@ -245,32 +255,33 @@ private void SetupOptions(Settings settings)
if (settings.CodeDiffType is not null)
{
ArgumentException.ThrowIfNullOrEmpty(_llmOptions.ChatModel);
- var model = cacheModels.GetModel(_llmOptions.ChatModel);
-
- switch (settings.CodeDiffType)
- {
- case CodeDiffType.UnifiedDiff:
- model.ModelOption.CodeDiffType = CodeDiffType.UnifiedDiff;
- break;
- case CodeDiffType.CodeBlockDiff:
- model.ModelOption.CodeDiffType = CodeDiffType.CodeBlockDiff;
- break;
- }
+ var chatModel = cacheModels.GetModel(_llmOptions.ChatModel);
+ chatModel.ModelOption.CodeDiffType = settings.CodeDiffType.Value;
}
if (settings.CodeAssistType is not null)
{
ArgumentException.ThrowIfNullOrEmpty(_llmOptions.ChatModel);
- var model = cacheModels.GetModel(_llmOptions.ChatModel);
- switch (settings.CodeAssistType)
- {
- case CodeAssistType.Embedding:
- model.ModelOption.CodeAssistType = CodeAssistType.Embedding;
- break;
- case CodeAssistType.Summary:
- model.ModelOption.CodeAssistType = CodeAssistType.Summary;
- break;
- }
+ var chatModel = cacheModels.GetModel(_llmOptions.ChatModel);
+ chatModel.ModelOption.CodeAssistType = settings.CodeAssistType.Value;
+ }
+
+ if (settings.Threshold is not null)
+ {
+ ArgumentException.ThrowIfNullOrEmpty(_llmOptions.EmbeddingsModel);
+ var embeddingsModel = cacheModels.GetModel(_llmOptions.EmbeddingsModel);
+ embeddingsModel.ModelOption.Threshold = settings.Threshold.Value;
+ }
+
+ if (settings.Temperature is not null)
+ {
+ ArgumentException.ThrowIfNullOrEmpty(_llmOptions.ChatModel);
+ var chatModel = cacheModels.GetModel(_llmOptions.ChatModel);
+ chatModel.ModelOption.Temperature = settings.Temperature.Value;
+
+ ArgumentException.ThrowIfNullOrEmpty(_llmOptions.EmbeddingsModel);
+ var embeddingsModel = cacheModels.GetModel(_llmOptions.EmbeddingsModel);
+ embeddingsModel.ModelOption.Temperature = settings.Temperature.Value;
}
}
}
diff --git a/src/AIAssistant/Contracts/IContextService.cs b/src/AIAssistant/Contracts/IContextService.cs
index e2b70f9..90cf2ed 100644
--- a/src/AIAssistant/Contracts/IContextService.cs
+++ b/src/AIAssistant/Contracts/IContextService.cs
@@ -7,6 +7,7 @@ public interface IContextService
Context GetContext();
IList GetAllFiles();
IList GetFiles(IList? filesRelativePath);
+ void ValidateLoadedFilesLimit();
void AddContextFolder(string contextFolder);
void AddOrUpdateFolder(IList? foldersRelativePath);
void AddOrUpdateFiles(IList? filesRelativePath);
diff --git a/src/AIAssistant/Contracts/ILLMClientManager.cs b/src/AIAssistant/Contracts/ILLMClientManager.cs
index ff640f1..8e053f5 100644
--- a/src/AIAssistant/Contracts/ILLMClientManager.cs
+++ b/src/AIAssistant/Contracts/ILLMClientManager.cs
@@ -13,5 +13,9 @@ public interface ILLMClientManager
string? systemPrompt,
CancellationToken cancellationToken = default
);
- Task GetEmbeddingAsync(string input, CancellationToken cancellationToken = default);
+ Task GetEmbeddingAsync(
+ string input,
+ string? path,
+ CancellationToken cancellationToken = default
+ );
}
diff --git a/src/AIAssistant/Contracts/IPromptManager.cs b/src/AIAssistant/Contracts/IPromptManager.cs
index 4b3da67..2f44a0d 100644
--- a/src/AIAssistant/Contracts/IPromptManager.cs
+++ b/src/AIAssistant/Contracts/IPromptManager.cs
@@ -15,7 +15,7 @@ public interface IPromptManager
void AddPrompt(string embeddedResourceName, CommandType commandType, CodeDiffType? diffType);
string GetPrompt(CommandType commandType, CodeDiffType? diffType, object? parameters);
string AddCodeBlock(string treeSitterCode);
- string AddEmbeddingInputString(string treeSitterCode);
+ string GetEmbeddingInputString(string treeSitterCode);
string CreateLLMContext(IEnumerable codeBlocks);
string FilesAddedToChat(IEnumerable fullFileContents);
string? GetSystemPrompt(IList? codes, CodeAssistType codeAssistType, CodeDiffType diffType);
diff --git a/src/AIAssistant/Diff/MergeConflictCodeDiffParser.cs b/src/AIAssistant/Diff/MergeConflictCodeDiffParser.cs
deleted file mode 100644
index 35df9e2..0000000
--- a/src/AIAssistant/Diff/MergeConflictCodeDiffParser.cs
+++ /dev/null
@@ -1,108 +0,0 @@
-using System.Text.RegularExpressions;
-using AIAssistant.Contracts.Diff;
-using AIAssistant.Models;
-
-namespace AIAssistant.Diff;
-
-//
-// public class MergeConflictCodeDiffParser : ICodeDiffParser
-// {
-// // private static readonly Regex _filePathRegex = new(@"^([\w\-./\\]+?\.[\w]+)$", RegexOptions.Compiled);
-// // private static readonly Regex _previousVersionStart = new(@"^<<<<<<< PREVIOUS VERSION$", RegexOptions.Compiled);
-// // private static readonly Regex _newVersionEnd = new(@"^>>>>>>> NEW VERSION$", RegexOptions.Compiled);
-// // private static readonly Regex _separator = new(@"^=======$", RegexOptions.Compiled);
-// //
-// // public IList GetFileChanges(string diff)
-// // {
-// // var changes = new List();
-// // string? currentFilePath = null;
-// // var hunks = new List>();
-// // List? currentHunk = null;
-// //
-// // bool isPreviousVersion = false;
-// // bool isNewVersion = false;
-// //
-// // var lines = diff.Split('\n');
-// //
-// // foreach (var line in lines)
-// // {
-// // // Detect a new file path, starting a new `MergeConflict` section
-// // if (_filePathRegex.IsMatch(line.Trim()))
-// // {
-// // // Finalize the previous file change if there are accumulated hunks
-// // if (currentFilePath != null && hunks.Count > 0)
-// // {
-// // var fileChangeLines = hunks.SelectMany(h => h).ToList();
-// // var fileChangeType = DetermineFileChangeType(fileChangeLines);
-// // changes.Add(new FileChange(currentFilePath, fileChangeType, fileChangeLines));
-// // hunks.Clear();
-// // }
-// //
-// // currentFilePath = line.Trim();
-// // continue;
-// // }
-// //
-// // // Start of a new `PREVIOUS VERSION/NEW VERSION` hunk
-// // if (_previousVersionStart.IsMatch(line.Trim()))
-// // {
-// // isPreviousVersion = true;
-// // isNewVersion = false;
-// // currentHunk = new List();
-// // continue;
-// // }
-// //
-// // // Separator between previous and new version
-// // if (_separator.IsMatch(line.Trim()))
-// // {
-// // isPreviousVersion = false;
-// // isNewVersion = true;
-// // continue;
-// // }
-// //
-// // // End of the hunk's new version
-// // if (_newVersionEnd.IsMatch(line.Trim()))
-// // {
-// // isNewVersion = false;
-// // if (currentHunk != null)
-// // {
-// // hunks.Add(currentHunk);
-// // currentHunk = null;
-// // }
-// // continue;
-// // }
-// //
-// // // Collect lines within each `PREVIOUS VERSION` or `NEW VERSION` as part of the current hunk
-// // if (isPreviousVersion && currentHunk != null)
-// // {
-// // currentHunk.Add(new FileChangeLine(0, line, CodeChangeType.Delete)); // 0 here because we're not tracking line numbers yet
-// // }
-// // else if (isNewVersion && currentHunk != null)
-// // {
-// // currentHunk.Add(new FileChangeLine(0, line, CodeChangeType.Add)); // 0 here because we're not tracking line numbers yet
-// // }
-// // }
-// //
-// // // Finalize the last file change if any hunks remain
-// // if (currentFilePath != null && hunks.Count > 0)
-// // {
-// // var fileChangeLines = hunks.SelectMany(h => h).ToList();
-// // var fileChangeType = DetermineFileChangeType(fileChangeLines);
-// // changes.Add(new FileChange(currentFilePath, fileChangeType, fileChangeLines));
-// // }
-// //
-// // return changes;
-// // }
-// //
-// // private CodeChangeType DetermineFileChangeType(IList changeLines)
-// // {
-// // bool allAdded = changeLines.All(line => line.LineCodeChangeType == CodeChangeType.Add);
-// // bool allDeleted = changeLines.All(line => line.LineCodeChangeType == CodeChangeType.Delete);
-// //
-// // if (allAdded)
-// // return CodeChangeType.Add; // Newly created file
-// // if (allDeleted)
-// // return CodeChangeType.Delete; // Deleted file
-// //
-// // return CodeChangeType.Update; // Modified existing file
-// // }
-// }
diff --git a/src/AIAssistant/Models/Options/AppOptions.cs b/src/AIAssistant/Models/Options/AppOptions.cs
index de3869e..87d19e0 100644
--- a/src/AIAssistant/Models/Options/AppOptions.cs
+++ b/src/AIAssistant/Models/Options/AppOptions.cs
@@ -9,4 +9,6 @@ public class AppOptions
public string ContextWorkingDirectory { get; set; } = default!;
public bool AutoContextEnabled { get; set; } = true;
public IList Files { get; set; } = new List();
+ public int NumberOfFilesLimit { get; set; } = 500;
+ public int TreeLevel { get; set; }
}
diff --git a/src/AIAssistant/Prompts/PromptManager.cs b/src/AIAssistant/Prompts/PromptManager.cs
index 0b9d8a1..49782b2 100644
--- a/src/AIAssistant/Prompts/PromptManager.cs
+++ b/src/AIAssistant/Prompts/PromptManager.cs
@@ -113,7 +113,7 @@ public string AddCodeBlock(string treeSitterCode)
return renderBlock;
}
- public string AddEmbeddingInputString(string treeSitterCode)
+ public string GetEmbeddingInputString(string treeSitterCode)
{
return RenderPromptTemplate(
AIAssistantConstants.Prompts.CodeEmbeddingTemplate,
diff --git a/src/AIAssistant/Prompts/Templates/code-assist-merge-conflict-diff.template b/src/AIAssistant/Prompts/Templates/code-assist-merge-conflict-diff.template
deleted file mode 100644
index 6952822..0000000
--- a/src/AIAssistant/Prompts/Templates/code-assist-merge-conflict-diff.template
+++ /dev/null
@@ -1,113 +0,0 @@
-You are an expert code assistant to analyze the provided code snippets and make necessary improvements, refactor or add new functionality based on the user's requests.
-Your response should be in the markdown format.
-
-For understanding context you should consider following rules:
-- Review the provided code context to understand the existing structure. Consider below `code context` for answering the user requests.
-- Code context is containing multiple `code blocks` in `tree structures` format, actually for each `file path` there is a dedicated `code blocks` in tree structure format.
-- Don't return response for `code blocks` in `tree structures` format.
-- The code files are based on a `relative path` that exists in the `root` level of tree structure for each file and your response should be based on `relativePath`.
-- You have following codes in your context:
-
-Create a Merge Conflict like format showing the specified changes to the provided code. Follow these guidelines to ensure the output is in a familiar, high-level, and flexible format:
-
-1. **MergeConflict Format:**
-- For showing changes in a file use a `MergeConflict` format, and show file changes in multiple `PREVIOUS VERSION/NEW VERSION` blocks.
-- In the **first line** of above `MergeConflict` format and before starting three backticks (```) contains a file `relative path` to the each file without any extra text just file relative path.
-- In the **second line** of `MergeConflict` contains three backticks (```) as opening fence and code block used language to indicate the start of the file changes content.
-- In the **third line** we have `<<<<<<< PREVIOUS VERSION` to indicate the start of the previous version of the code.
-- In the **forth line** until reaching `=======` we have the old code before change.
-- The line after old codes is `=======` which use to separate the previous and new versions
-- The line after `=======`, we have the new code after change until reaching `>>>>>>> NEW VERSION`.
-- The line after new code is `>>>>>>> NEW VERSION` which is end of new code.
-- If MergeConflict format contains multiple `block of changes`, each `block of change` should start with a seperated `blank line` before starting next `>>>>>>> NEW VERSION` to mark the change block.
-- The last line is three backticks (```) to close fences and end of the MergeConflict section.
-
-2. **Precise and Complete Changes:**
-
-- Include only the lines necessary to define the change, and some surrounding context if needed.
-- Ensure the `PREVIOUS VERSION/NEW VERSION` blocks exactly matches the original file content.
-- In the MergeConflict format, use multiple `block of change` with PREVIOUS VERSION/NEW VERSION pairs, separated by a blank line between blocks in a file, when changes are dispersed throughout different sections of a file. Each change block should focus on a single, specific modification.
-- Each `PREVIOUS VERSION/NEW VERSION` block should include just enough lines around the change, ensuring uniqueness.
-- For new files, leave the PREVIOUS VERSION section empty and show the full content under NEW VERSION.
-- When code is removed entirely, show it only in the PREVIOUS VERSION section and leave the NEW VERSION section empty.
-- If there are no requested changes (additions, deletions, or edits) in a file, do not create a block of change in MergeConflict section for it.
-- When possible, include the entire function, method, conditional blocks, loops and etc code block that was modified, rather than only showing individual line edits. This approach makes the MergeConflict `clearer` and more `readable`.
-- When editing an existing file, include only the specific lines to be updated or replaced.
-- To move code within a file, include two separate blocks: one to delete the original code, and one to reinsert it in the new location.
-
-Here is a example for showing changes in unified diff format. bellow is the current class in `Project/Statistics.cs` file:
-
-**Original Code Block:**
-``` csharp
-using System;
-using System.Collections.Generic;
-
-public class Statistics
-{
- public double CalculateAverage(List numbers)
- {
- int sum = Sum(numbers);
- return sum / (double)numbers.Count;
- }
-
- private int Sum(List numbers)
- {
- int total = 0;
- foreach (int number in numbers)
- {
- total += number;
- }
- return total;
- }
-}
-```
-
-Now after applying bellow changes on it, we get following MergeConflict format:
-
-1. Add a new using statement to import `System.Linq`.
-2. Modify the `CalculateAverage()` method to use LINQ for computing the average instead of a manual loop.
-3. Remove the `Sum()` method entirely, as it’s no longer needed with LINQ
-
-**MergeConflict format Output:**
-
-Project/Statistics.cs
-```csharp
-<<<<<<< PREVIOUS VERSION
-using System;
-using System.Collections.Generic;
-=======
-using System;
-using System.Collections.Generic;
-using System.Linq;
->>>>>>> NEW VERSION
-
-<<<<<<< PREVIOUS VERSION
- public double CalculateAverage(List numbers)
- {
- int sum = Sum(numbers);
- return sum / (double)numbers.Count;
- }
-=======
- public double CalculateAverage(List numbers)
- {
- return numbers.Average();
- }
->>>>>>> NEW VERSION
-
-<<<<<<< PREVIOUS VERSION
- private int Sum(List numbers)
- {
- int total = 0;
- foreach (int number in numbers)
- {
- total += number;
- }
- return total;
- }
-=======
->>>>>>> NEW VERSION
-```
-
-For explanation of the produced response you should consider following rules:
-- After providing the modified code sections in the `MergeConflict` format, include an `Explanation` section in the markdown result that summarizes each change.
-- Clearly indicate what modifications were made in each file and the reasoning behind them.
diff --git a/src/AIAssistant/Services/CodeAssistStrategies/EmbeddingCodeAssist.cs b/src/AIAssistant/Services/CodeAssistStrategies/EmbeddingCodeAssist.cs
index 45d3cd9..5c5a153 100644
--- a/src/AIAssistant/Services/CodeAssistStrategies/EmbeddingCodeAssist.cs
+++ b/src/AIAssistant/Services/CodeAssistStrategies/EmbeddingCodeAssist.cs
@@ -31,7 +31,7 @@ public async Task LoadInitCodeFiles(string contextWorkingDirectory, IList x.CodeFileMap).ToList();
- await AddOrUpdateCodeFilesToCache(codeFileMaps, session);
+ await AddOrUpdateEmbeddingsForFiles(codeFileMaps, session);
}
public async Task AddOrUpdateCodeFiles(IList? codeFiles)
@@ -44,7 +44,7 @@ public async Task AddOrUpdateCodeFiles(IList? codeFiles)
var session = chatSessionManager.GetCurrentActiveSession();
var codeFileMaps = contextService.GetFiles(codeFiles).Select(x => x.CodeFileMap).ToList();
- await AddOrUpdateCodeFilesToCache(codeFileMaps, session);
+ await AddOrUpdateEmbeddingsForFiles(codeFileMaps, session);
}
public Task> GetCodeTreeContents(IList? codeFiles)
@@ -104,15 +104,15 @@ public Task> GetCodeTreeContents(IList? codeFiles)
}
}
- private async Task AddOrUpdateCodeFilesToCache(IList codeFileMaps, ChatSession chatSession)
+ private async Task AddOrUpdateEmbeddingsForFiles(IList codeFileMaps, ChatSession chatSession)
{
// generate embeddings data with using llms embeddings apis
// https://ollama.com/blog/embedding-models
// https://github.com/microsoft/semantic-kernel/blob/main/dotnet/notebooks/06-memory-and-embeddings.ipynb
// https://github.com/chroma-core/chroma
- var relatedEmbeddingsResult = await embeddingService.AddOrUpdateEmbeddingsForFiles(codeFileMaps, chatSession);
+ var filesEmbedding = await embeddingService.AddOrUpdateEmbeddingsForFiles(codeFileMaps, chatSession);
- PrintEmbeddingCost(relatedEmbeddingsResult.TotalTokensCount, relatedEmbeddingsResult.TotalCost);
+ PrintEmbeddingCost(filesEmbedding.TotalTokensCount, filesEmbedding.TotalCost);
}
private void PrintEmbeddingCost(int totalCount, decimal totalCost)
diff --git a/src/AIAssistant/Services/ContextService.cs b/src/AIAssistant/Services/ContextService.cs
index 3556847..edb11ac 100644
--- a/src/AIAssistant/Services/ContextService.cs
+++ b/src/AIAssistant/Services/ContextService.cs
@@ -25,6 +25,8 @@ public void AddContextFolder(string contextFolder)
{
_currentContext.ContextItems.Add(folderItemContext);
}
+
+ ValidateLoadedFilesLimit();
}
public void AddOrUpdateFolder(IList? foldersRelativePath)
@@ -57,6 +59,8 @@ public void AddOrUpdateFolder(IList? foldersRelativePath)
_currentContext.ContextItems.Add(folderItemsContext);
}
}
+
+ ValidateLoadedFilesLimit();
}
public void AddOrUpdateFiles(IList? filesRelativePath)
@@ -86,6 +90,8 @@ public void AddOrUpdateFiles(IList? filesRelativePath)
_currentContext.ContextItems.Add(fileItemContext);
}
}
+
+ ValidateLoadedFilesLimit();
}
public void AddOrUpdateUrls(IList? urls)
@@ -152,6 +158,16 @@ public IList GetFiles(IList? filesRelativePath)
return matchingFiles;
}
+ public void ValidateLoadedFilesLimit()
+ {
+ if (GetAllFiles().Count == _appOptions.NumberOfFilesLimit)
+ {
+ throw new Exception(
+ $"File limit count {appOptions.Value.NumberOfFilesLimit} exceeded. You can ignore files and folders that are not necessary with adding them to '.aiassistignore' file or change the level of loading folders by setting 'AppOption.TreeLevel'"
+ );
+ }
+ }
+
private void CollectFilesFromFolder(FolderItemContext folder, List fileList)
{
// Add all files from the folder
@@ -192,11 +208,20 @@ bool useShortSummary
try
{
var validFolders = folders.Where(folder => !fileService.IsPathIgnored(folder)).ToList();
+ int treeLevel = _appOptions.TreeLevel;
foreach (var folderPath in validFolders)
{
currentFolder = folderPath;
- var subFoldersItemContext = InitSubFoldersItemContext(folderPath, contextWorkingDir, useShortSummary);
+
+ // Start recursion with current depth set to 1
+ var subFoldersItemContext = InitSubFoldersItemContext(
+ folderPath,
+ contextWorkingDir,
+ useShortSummary,
+ 1,
+ treeLevel
+ );
var filesItemsContext = InitFilesItemContext(folderPath, contextWorkingDir, useShortSummary);
var folderRelativePath = Path.GetRelativePath(contextWorkingDir, folderPath).NormalizePath();
@@ -230,7 +255,9 @@ bool useShortSummary
private IList InitSubFoldersItemContext(
string folderPath,
string contextWorkingDir,
- bool useShortSummary
+ bool useShortSummary,
+ int currentDepth,
+ int treeLevel
)
{
IList subFolders = new List();
@@ -238,6 +265,13 @@ bool useShortSummary
try
{
+ // Stop recursion if the tree level is exceeded
+ if (treeLevel > 0 && currentDepth >= treeLevel)
+ {
+ // Return empty list as no deeper levels are loaded
+ return subFolders;
+ }
+
foreach (
var subFolder in Directory
.GetDirectories(folderPath)
@@ -249,11 +283,17 @@ var subFolder in Directory
var subFolderFilesItemContext = InitFilesItemContext(subFolder, contextWorkingDir, useShortSummary);
var subFolderRelativePath = Path.GetRelativePath(contextWorkingDir, subFolder).NormalizePath();
- // Recursive call for each subfolder
+ // Recursive call for each subfolder, incrementing the depth
var subFolderContext = new FolderItemContext(
subFolder,
subFolderRelativePath,
- InitSubFoldersItemContext(subFolder, contextWorkingDir, useShortSummary),
+ InitSubFoldersItemContext(
+ subFolder,
+ contextWorkingDir,
+ useShortSummary,
+ currentDepth + 1,
+ treeLevel
+ ),
subFolderFilesItemContext
);
diff --git a/src/AIAssistant/Services/EmbeddingService.cs b/src/AIAssistant/Services/EmbeddingService.cs
index ca9407f..b8a1fdb 100644
--- a/src/AIAssistant/Services/EmbeddingService.cs
+++ b/src/AIAssistant/Services/EmbeddingService.cs
@@ -3,7 +3,8 @@
using AIAssistant.Data;
using AIAssistant.Dtos;
using AIAssistant.Models;
-using AIAssistant.Prompts;
+using BuildingBlocks.LLM;
+using BuildingBlocks.Utils;
using TreeSitter.Bindings.CustomTypes.TreeParser;
namespace AIAssistant.Services;
@@ -23,10 +24,11 @@ ChatSession chatSession
decimal totalCost = 0;
IList codeEmbeddings = new List();
+
foreach (var codeFileMap in codeFilesMap)
{
- var input = promptManager.AddEmbeddingInputString(codeFileMap.TreeSitterFullCode);
- var embeddingResult = await llmClientManager.GetEmbeddingAsync(input);
+ var input = promptManager.GetEmbeddingInputString(codeFileMap.TreeSitterFullCode);
+ var embeddingResult = await llmClientManager.GetEmbeddingAsync(input, codeFileMap.RelativePath);
codeEmbeddings.Add(
new CodeEmbedding
@@ -80,6 +82,6 @@ public IEnumerable QueryByFilter(
public async Task GenerateEmbeddingForUserInput(string userInput)
{
- return await llmClientManager.GetEmbeddingAsync(userInput);
+ return await llmClientManager.GetEmbeddingAsync(userInput, null);
}
}
diff --git a/src/AIAssistant/Services/LLMClientManager.cs b/src/AIAssistant/Services/LLMClientManager.cs
index 3c48098..1207300 100644
--- a/src/AIAssistant/Services/LLMClientManager.cs
+++ b/src/AIAssistant/Services/LLMClientManager.cs
@@ -88,11 +88,15 @@ ICacheModels cacheModels
);
}
- public async Task GetEmbeddingAsync(string input, CancellationToken cancellationToken = default)
+ public async Task GetEmbeddingAsync(
+ string input,
+ string? path,
+ CancellationToken cancellationToken = default
+ )
{
var llmClientStratgey = _clientFactory.CreateClient(EmbeddingModel.ModelInformation.AIProvider);
- var embeddingResponse = await llmClientStratgey.GetEmbeddingAsync(input, cancellationToken);
+ var embeddingResponse = await llmClientStratgey.GetEmbeddingAsync(input, path, cancellationToken);
// in embedding output tokens and its cost is 0
var inputTokens = embeddingResponse?.TokenUsage?.InputTokens ?? await _tokenizer.GetTokenCount(input);
diff --git a/src/Clients/AnthropicClient.cs b/src/Clients/AnthropicClient.cs
index ac50945..a376046 100644
--- a/src/Clients/AnthropicClient.cs
+++ b/src/Clients/AnthropicClient.cs
@@ -37,7 +37,7 @@ AsyncPolicyWrap combinedPolicy
CancellationToken cancellationToken = default
)
{
- await ValidateMaxInputToken(chatCompletionRequest);
+ await ValidateChatMaxInputToken(chatCompletionRequest);
ValidateRequestSizeAndContent(chatCompletionRequest);
var requestBody = new
@@ -80,7 +80,7 @@ AsyncPolicyWrap combinedPolicy
var inputCostPerToken = _chatModel.ModelInformation.InputCostPerToken;
var outputCostPerToken = _chatModel.ModelInformation.OutputCostPerToken;
- ValidateMaxToken(inputTokens + outTokens);
+ ValidateChatMaxToken(inputTokens + outTokens);
return new ChatCompletionResponse(
completionMessage,
@@ -93,7 +93,7 @@ AsyncPolicyWrap combinedPolicy
[EnumeratorCancellation] CancellationToken cancellationToken = default
)
{
- await ValidateMaxInputToken(chatCompletionRequest);
+ await ValidateChatMaxInputToken(chatCompletionRequest);
ValidateRequestSizeAndContent(chatCompletionRequest);
var requestBody = new
@@ -165,7 +165,7 @@ AsyncPolicyWrap combinedPolicy
var inputCostPerToken = _chatModel.ModelInformation.InputCostPerToken;
var outputCostPerToken = _chatModel.ModelInformation.OutputCostPerToken;
- ValidateMaxToken(inputTokens + outTokens);
+ ValidateChatMaxToken(inputTokens + outTokens);
yield return new ChatCompletionResponse(
null,
@@ -193,7 +193,11 @@ AsyncPolicyWrap combinedPolicy
}
}
- public Task GetEmbeddingAsync(string input, CancellationToken cancellationToken = default)
+ public Task GetEmbeddingAsync(
+ string input,
+ string? path,
+ CancellationToken cancellationToken = default
+ )
{
throw new NotImplementedException();
}
@@ -228,14 +232,11 @@ [NotNull] AnthropicChatResponse? anthropicChatResponse
}
}
- private Task ValidateMaxInputToken(ChatCompletionRequest chatCompletionRequest)
- {
- return ValidateMaxInputToken(string.Concat(chatCompletionRequest.Items.Select(x => x.Prompt)));
- }
-
- private async Task ValidateMaxInputToken(string input)
+ private async Task ValidateChatMaxInputToken(ChatCompletionRequest chatCompletionRequest)
{
- var inputTokenCount = await tokenizer.GetTokenCount(input);
+ var inputTokenCount = await tokenizer.GetTokenCount(
+ string.Concat(chatCompletionRequest.Items.Select(x => x.Prompt))
+ );
if (
_chatModel.ModelInformation.MaxInputTokens > 0
@@ -247,14 +248,14 @@ private async Task ValidateMaxInputToken(string input)
{
StatusCode = (int)HttpStatusCode.BadRequest,
Message =
- $"'max_input_token' count: {inputTokenCount.FormatCommas()} is larger than configured 'max_input_token' count: {_chatModel.ModelInformation.MaxInputTokens.FormatCommas()}, if you need more tokens change the configuration.",
+ $"current chat 'max_input_token' count: {inputTokenCount.FormatCommas()} is larger than configured 'max_input_token' count: {_chatModel.ModelInformation.MaxInputTokens.FormatCommas()}",
},
HttpStatusCode.BadRequest
);
}
}
- private void ValidateMaxToken(int maxTokenCount)
+ private void ValidateChatMaxToken(int maxTokenCount)
{
if (_chatModel.ModelInformation.MaxTokens > 0 && maxTokenCount > _chatModel.ModelInformation.MaxTokens)
{
@@ -263,7 +264,7 @@ private void ValidateMaxToken(int maxTokenCount)
{
StatusCode = (int)HttpStatusCode.BadRequest,
Message =
- $"'max_token' count: {maxTokenCount.FormatCommas()} is larger than configured 'max_token' count: {_chatModel.ModelInformation.MaxTokens.FormatCommas()}, if you need more tokens change the configuration.",
+ $"current chat 'max_token' count: {maxTokenCount.FormatCommas()} is larger than configured 'max_token' count: {_chatModel.ModelInformation.MaxTokens.FormatCommas()}.",
},
HttpStatusCode.BadRequest
);
diff --git a/src/Clients/AzureClient.cs b/src/Clients/AzureClient.cs
index ec81e3c..f030a63 100644
--- a/src/Clients/AzureClient.cs
+++ b/src/Clients/AzureClient.cs
@@ -39,7 +39,7 @@ AsyncPolicyWrap combinedPolicy
CancellationToken cancellationToken = default
)
{
- await ValidateMaxInputToken(chatCompletionRequest);
+ await ValidateChatMaxInputToken(chatCompletionRequest);
ValidateRequestSizeAndContent(chatCompletionRequest);
// https://platform.openai.com/docs/api-reference/chat/create
@@ -102,7 +102,7 @@ AsyncPolicyWrap combinedPolicy
var inputCostPerToken = _chatModel.ModelInformation.InputCostPerToken;
var outputCostPerToken = _chatModel.ModelInformation.OutputCostPerToken;
- ValidateMaxToken(inputTokens + outTokens);
+ ValidateChatMaxToken(inputTokens + outTokens);
return new ChatCompletionResponse(
completionMessage,
@@ -115,7 +115,7 @@ AsyncPolicyWrap combinedPolicy
[EnumeratorCancellation] CancellationToken cancellationToken = default
)
{
- await ValidateMaxInputToken(chatCompletionRequest);
+ await ValidateChatMaxInputToken(chatCompletionRequest);
ValidateRequestSizeAndContent(chatCompletionRequest);
var requestBody = new
@@ -219,7 +219,7 @@ AsyncPolicyWrap combinedPolicy
var inputCostPerToken = _chatModel.ModelInformation.InputCostPerToken;
var outputCostPerToken = _chatModel.ModelInformation.OutputCostPerToken;
- ValidateMaxToken(inputTokens + outTokens);
+ ValidateChatMaxToken(inputTokens + outTokens);
yield return new ChatCompletionResponse(
null,
@@ -240,10 +240,11 @@ AsyncPolicyWrap combinedPolicy
public async Task GetEmbeddingAsync(
string input,
+ string? path,
CancellationToken cancellationToken = default
)
{
- await ValidateMaxInputToken(input);
+ await ValidateEmbeddingMaxInputToken(input);
ValidateRequestSizeAndContent(input);
var requestBody = new { input = new[] { input }, model = _embeddingModel.Name.Trim() };
@@ -294,7 +295,7 @@ AsyncPolicyWrap combinedPolicy
var inputCostPerToken = _embeddingModel.ModelInformation.InputCostPerToken;
var outputCostPerToken = _embeddingModel.ModelInformation.OutputCostPerToken;
- ValidateMaxToken(inputTokens + outTokens);
+ ValidateEmbeddingMaxToken(inputTokens + outTokens, path);
return new EmbeddingsResponse(
embedding,
@@ -329,33 +330,57 @@ private void HandleException(HttpResponseMessage httpResponse, [NotNull] OpenAIB
}
}
- private Task ValidateMaxInputToken(ChatCompletionRequest chatCompletionRequest)
+ private async Task ValidateChatMaxInputToken(ChatCompletionRequest chatCompletionRequest)
{
- return ValidateMaxInputToken(string.Concat(chatCompletionRequest.Items.Select(x => x.Prompt)));
+ var inputTokenCount = await tokenizer.GetTokenCount(
+ string.Concat(chatCompletionRequest.Items.Select(x => x.Prompt), false)
+ );
+
+ if (
+ _chatModel.ModelInformation.MaxInputTokens > 0
+ && inputTokenCount > _chatModel.ModelInformation.MaxInputTokens
+ )
+ {
+ throw new OpenAIException(
+ new OpenAIError
+ {
+ StatusCode = (int)HttpStatusCode.BadRequest,
+ Message =
+ $"current chat 'max_input_token' count: {inputTokenCount.FormatCommas()} is larger than configured 'max_input_token' count: {_chatModel.ModelInformation.MaxInputTokens.FormatCommas()}.",
+ },
+ HttpStatusCode.BadRequest
+ );
+ }
}
- private async Task ValidateMaxInputToken(string input)
+ private async Task ValidateEmbeddingMaxInputToken(string input, string? path = null)
{
var inputTokenCount = await tokenizer.GetTokenCount(input);
if (
- _chatModel.ModelInformation.MaxInputTokens > 0
- && inputTokenCount > _chatModel.ModelInformation.MaxInputTokens
+ _embeddingModel.ModelInformation.MaxInputTokens > 0
+ && inputTokenCount > _embeddingModel.ModelInformation.MaxInputTokens
)
{
+ var moreInfo = path is not null
+ ? $"if file '{
+ path
+ }' is not required for embedding you can ignore that by adding file or folder to '.aiassistignore'"
+ : "";
+
throw new OpenAIException(
new OpenAIError
{
StatusCode = (int)HttpStatusCode.BadRequest,
Message =
- $"'max_input_token' count: {inputTokenCount.FormatCommas()} is larger than configured 'max_input_token' count: {_chatModel.ModelInformation.MaxInputTokens.FormatCommas()}, if you need more tokens change the configuration.",
+ $"embedding {path} 'max_input_token' count: {inputTokenCount.FormatCommas()} is larger than configured 'max_input_token' count: {_embeddingModel.ModelInformation.MaxInputTokens.FormatCommas()}. {moreInfo}",
},
HttpStatusCode.BadRequest
);
}
}
- private void ValidateMaxToken(int maxTokenCount)
+ private void ValidateChatMaxToken(int maxTokenCount)
{
if (_chatModel.ModelInformation.MaxTokens > 0 && maxTokenCount > _chatModel.ModelInformation.MaxTokens)
{
@@ -364,7 +389,26 @@ private void ValidateMaxToken(int maxTokenCount)
{
StatusCode = (int)HttpStatusCode.BadRequest,
Message =
- $"'max_token' count: {maxTokenCount.FormatCommas()} is larger than configured 'max_token' count: {_chatModel.ModelInformation.MaxTokens.FormatCommas()}, if you need more tokens change the configuration.",
+ $"current chat 'max_token' count: {maxTokenCount.FormatCommas()} is larger than configured 'max_token' count: {_chatModel.ModelInformation.MaxTokens.FormatCommas()}.",
+ },
+ HttpStatusCode.BadRequest
+ );
+ }
+ }
+
+ private void ValidateEmbeddingMaxToken(int maxTokenCount, string? path)
+ {
+ if (
+ _embeddingModel.ModelInformation.MaxTokens > 0
+ && maxTokenCount > _embeddingModel.ModelInformation.MaxTokens
+ )
+ {
+ throw new OpenAIException(
+ new OpenAIError
+ {
+ StatusCode = (int)HttpStatusCode.BadRequest,
+ Message =
+ $"embedding {path} 'max_token' count: {maxTokenCount.FormatCommas()} is larger than configured 'max_token' count: {_embeddingModel.ModelInformation.MaxTokens.FormatCommas()}.",
},
HttpStatusCode.BadRequest
);
diff --git a/src/Clients/Contracts/ILLMClient.cs b/src/Clients/Contracts/ILLMClient.cs
index 0b5b7e7..34dc934 100644
--- a/src/Clients/Contracts/ILLMClient.cs
+++ b/src/Clients/Contracts/ILLMClient.cs
@@ -13,5 +13,9 @@ public interface ILLMClient
ChatCompletionRequest chatCompletionRequest,
CancellationToken cancellationToken = default
);
- Task GetEmbeddingAsync(string input, CancellationToken cancellationToken = default);
+ Task GetEmbeddingAsync(
+ string input,
+ string? path,
+ CancellationToken cancellationToken = default
+ );
}
diff --git a/src/Clients/OllamaClient.cs b/src/Clients/OllamaClient.cs
index 9c5c80c..a1d6553 100644
--- a/src/Clients/OllamaClient.cs
+++ b/src/Clients/OllamaClient.cs
@@ -39,7 +39,7 @@ AsyncPolicyWrap combinedPolicy
CancellationToken cancellationToken = default
)
{
- await ValidateMaxInputToken(chatCompletionRequest);
+ await ValidateChatMaxInputToken(chatCompletionRequest);
ValidateRequestSizeAndContent(chatCompletionRequest);
// https://github.com/ollama/ollama/blob/main/docs/api.md#generate-a-chat-completion
@@ -80,7 +80,7 @@ AsyncPolicyWrap combinedPolicy
var inputCostPerToken = _chatModel.ModelInformation.InputCostPerToken;
var outputCostPerToken = _chatModel.ModelInformation.OutputCostPerToken;
- ValidateMaxToken(inputTokens + outTokens);
+ ValidateChatMaxToken(inputTokens + outTokens);
return new ChatCompletionResponse(
completionMessage,
@@ -93,7 +93,7 @@ AsyncPolicyWrap combinedPolicy
[EnumeratorCancellation] CancellationToken cancellationToken = default
)
{
- await ValidateMaxInputToken(chatCompletionRequest);
+ await ValidateChatMaxInputToken(chatCompletionRequest);
ValidateRequestSizeAndContent(chatCompletionRequest);
// https://github.com/ollama/ollama/blob/main/docs/api.md#generate-a-chat-completion
@@ -159,7 +159,7 @@ AsyncPolicyWrap combinedPolicy
var inputCostPerToken = _chatModel.ModelInformation.InputCostPerToken;
var outputCostPerToken = _chatModel.ModelInformation.OutputCostPerToken;
- ValidateMaxToken(inputTokens + outTokens);
+ ValidateChatMaxToken(inputTokens + outTokens);
yield return new ChatCompletionResponse(
completionMessage,
@@ -183,10 +183,11 @@ AsyncPolicyWrap combinedPolicy
public async Task GetEmbeddingAsync(
string input,
+ string? path,
CancellationToken cancellationToken = default
)
{
- await ValidateMaxInputToken(input);
+ await ValidateEmbeddingMaxInputToken(input, path);
ValidateRequestSizeAndContent(input);
// https://github.com/ollama/ollama/blob/main/docs/api.md#generate-embeddings
@@ -225,7 +226,7 @@ AsyncPolicyWrap combinedPolicy
var inputCostPerToken = _embeddingModel.ModelInformation.InputCostPerToken;
var outputCostPerToken = _embeddingModel.ModelInformation.OutputCostPerToken;
- ValidateMaxToken(inputTokens + outTokens);
+ ValidateEmbeddingMaxToken(inputTokens + outTokens, path);
return new EmbeddingsResponse(
embedding,
@@ -251,33 +252,66 @@ private void HandleException(HttpResponseMessage httpResponse, [NotNull] OllamaR
}
}
- private Task ValidateMaxInputToken(ChatCompletionRequest chatCompletionRequest)
+ private async Task ValidateChatMaxInputToken(ChatCompletionRequest chatCompletionRequest)
{
- return ValidateMaxInputToken(string.Concat(chatCompletionRequest.Items.Select(x => x.Prompt)));
+ var inputTokenCount = await tokenizer.GetTokenCount(
+ string.Concat(chatCompletionRequest.Items.Select(x => x.Prompt))
+ );
+
+ if (
+ _chatModel.ModelInformation.MaxInputTokens > 0
+ && inputTokenCount > _chatModel.ModelInformation.MaxInputTokens
+ )
+ {
+ throw new OllamaException(
+ $"current chat 'max_input_token' count: {inputTokenCount.FormatCommas()} is larger than configured 'max_input_token' count: {_chatModel.ModelInformation.MaxInputTokens.FormatCommas()}.",
+ HttpStatusCode.BadRequest
+ );
+ }
}
- private async Task ValidateMaxInputToken(string input)
+ private async Task ValidateEmbeddingMaxInputToken(string input, string? path = null)
{
var inputTokenCount = await tokenizer.GetTokenCount(input);
if (
- _chatModel.ModelInformation.MaxInputTokens > 0
- && inputTokenCount > _chatModel.ModelInformation.MaxInputTokens
+ _embeddingModel.ModelInformation.MaxInputTokens > 0
+ && inputTokenCount > _embeddingModel.ModelInformation.MaxInputTokens
)
{
+ var moreInfo = path is not null
+ ? $"if file '{
+ path
+ }' is not required for embedding you can ignore that by adding file or folder to '.aiassistignore'"
+ : "";
+
throw new OllamaException(
- $"'max_input_token' count: {inputTokenCount.FormatCommas()} is larger than configured 'max_input_token' count: {_chatModel.ModelInformation.MaxInputTokens.FormatCommas()}, if you need more token change the configuration.",
+ $"embedding {path} 'max_input_token' count: {inputTokenCount.FormatCommas()} is larger than configured 'max_input_token' count: {_embeddingModel.ModelInformation.MaxInputTokens.FormatCommas()}. {moreInfo}",
HttpStatusCode.BadRequest
);
}
}
- private void ValidateMaxToken(int maxTokenCount)
+ private void ValidateChatMaxToken(int maxTokenCount)
{
if (_chatModel.ModelInformation.MaxTokens > 0 && maxTokenCount > _chatModel.ModelInformation.MaxTokens)
{
throw new OllamaException(
- $"'max_token' count: {maxTokenCount.FormatCommas()} is larger than configured 'max_token' count: {_chatModel.ModelInformation.MaxTokens.FormatCommas()}, if you need more token change the configuration.",
+ $"current chat 'max_token' count: {maxTokenCount.FormatCommas()} is larger than configured 'max_token' count: {_chatModel.ModelInformation.MaxTokens.FormatCommas()}.",
+ HttpStatusCode.BadRequest
+ );
+ }
+ }
+
+ private void ValidateEmbeddingMaxToken(int maxTokenCount, string? path)
+ {
+ if (
+ _embeddingModel.ModelInformation.MaxTokens > 0
+ && maxTokenCount > _embeddingModel.ModelInformation.MaxTokens
+ )
+ {
+ throw new OllamaException(
+ $"embedding {path} 'max_token' count: {maxTokenCount.FormatCommas()} is larger than configured 'max_token' count: {_embeddingModel.ModelInformation.MaxTokens.FormatCommas()}.",
HttpStatusCode.BadRequest
);
}
diff --git a/src/Clients/OpenAiClient.cs b/src/Clients/OpenAiClient.cs
index 27b78fd..424a3f4 100644
--- a/src/Clients/OpenAiClient.cs
+++ b/src/Clients/OpenAiClient.cs
@@ -38,7 +38,7 @@ AsyncPolicyWrap combinedPolicy
CancellationToken cancellationToken = default
)
{
- await ValidateMaxInputToken(chatCompletionRequest);
+ await ValidateChatMaxInputToken(chatCompletionRequest);
ValidateRequestSizeAndContent(chatCompletionRequest);
// https://platform.openai.com/docs/api-reference/chat/create
@@ -84,7 +84,7 @@ AsyncPolicyWrap combinedPolicy
var inputCostPerToken = _chatModel.ModelInformation.InputCostPerToken;
var outputCostPerToken = _chatModel.ModelInformation.OutputCostPerToken;
- ValidateMaxToken(inputTokens + outTokens);
+ ValidateChatMaxToken(inputTokens + outTokens);
return new ChatCompletionResponse(
completionMessage,
@@ -97,7 +97,7 @@ AsyncPolicyWrap combinedPolicy
[EnumeratorCancellation] CancellationToken cancellationToken = default
)
{
- await ValidateMaxInputToken(chatCompletionRequest);
+ await ValidateChatMaxInputToken(chatCompletionRequest);
ValidateRequestSizeAndContent(chatCompletionRequest);
var requestBody = new
@@ -184,7 +184,7 @@ AsyncPolicyWrap combinedPolicy
var inputCostPerToken = _chatModel.ModelInformation.InputCostPerToken;
var outputCostPerToken = _chatModel.ModelInformation.OutputCostPerToken;
- ValidateMaxToken(inputTokens + outTokens);
+ ValidateChatMaxToken(inputTokens + outTokens);
yield return new ChatCompletionResponse(
null,
@@ -205,10 +205,11 @@ AsyncPolicyWrap combinedPolicy
public async Task GetEmbeddingAsync(
string input,
+ string? path,
CancellationToken cancellationToken = default
)
{
- await ValidateMaxInputToken(input);
+ await ValidateEmbeddingMaxInputToken(input, path);
ValidateRequestSizeAndContent(input);
var requestBody = new { input = new[] { input }, model = _embeddingModel.Name.Trim() };
@@ -242,7 +243,7 @@ AsyncPolicyWrap combinedPolicy
var inputCostPerToken = _embeddingModel.ModelInformation.InputCostPerToken;
var outputCostPerToken = _embeddingModel.ModelInformation.OutputCostPerToken;
- ValidateMaxToken(inputTokens + outTokens);
+ ValidateEmbeddingMaxToken(inputTokens + outTokens, path);
return new EmbeddingsResponse(
embedding,
@@ -277,33 +278,57 @@ private void HandleException(HttpResponseMessage httpResponse, [NotNull] OpenAIB
}
}
- private Task ValidateMaxInputToken(ChatCompletionRequest chatCompletionRequest)
+ private async Task ValidateChatMaxInputToken(ChatCompletionRequest chatCompletionRequest)
{
- return ValidateMaxInputToken(string.Concat(chatCompletionRequest.Items.Select(x => x.Prompt)));
+ var inputTokenCount = await tokenizer.GetTokenCount(
+ string.Concat(chatCompletionRequest.Items.Select(x => x.Prompt))
+ );
+
+ if (
+ _chatModel.ModelInformation.MaxInputTokens > 0
+ && inputTokenCount > _chatModel.ModelInformation.MaxInputTokens
+ )
+ {
+ throw new OpenAIException(
+ new OpenAIError
+ {
+ StatusCode = (int)HttpStatusCode.BadRequest,
+ Message =
+ $"current chat 'max_input_token' count: {inputTokenCount.FormatCommas()} is larger than configured 'max_input_token' count: {_chatModel.ModelInformation.MaxInputTokens.FormatCommas()}",
+ },
+ HttpStatusCode.BadRequest
+ );
+ }
}
- private async Task ValidateMaxInputToken(string input)
+ private async Task ValidateEmbeddingMaxInputToken(string input, string? path = null)
{
var inputTokenCount = await tokenizer.GetTokenCount(input);
if (
- _chatModel.ModelInformation.MaxInputTokens > 0
- && inputTokenCount > _chatModel.ModelInformation.MaxInputTokens
+ _embeddingModel.ModelInformation.MaxInputTokens > 0
+ && inputTokenCount > _embeddingModel.ModelInformation.MaxInputTokens
)
{
+ var moreInfo = path is not null
+ ? $"if file '{
+ path
+ }' is not required for embedding you can ignore that by adding file or folder to '.aiassistignore'"
+ : "";
+
throw new OpenAIException(
new OpenAIError
{
StatusCode = (int)HttpStatusCode.BadRequest,
Message =
- $"'max_input_token' count: {inputTokenCount.FormatCommas()} is larger than configured 'max_input_token' count: {_chatModel.ModelInformation.MaxInputTokens.FormatCommas()}, if you need more tokens change the configuration.",
+ $"embedding {path} 'max_input_token' count: {inputTokenCount.FormatCommas()} is larger than configured 'max_input_token' count: {_embeddingModel.ModelInformation.MaxInputTokens.FormatCommas()}. {moreInfo}",
},
HttpStatusCode.BadRequest
);
}
}
- private void ValidateMaxToken(int maxTokenCount)
+ private void ValidateChatMaxToken(int maxTokenCount)
{
if (_chatModel.ModelInformation.MaxTokens > 0 && maxTokenCount > _chatModel.ModelInformation.MaxTokens)
{
@@ -312,7 +337,26 @@ private void ValidateMaxToken(int maxTokenCount)
{
StatusCode = (int)HttpStatusCode.BadRequest,
Message =
- $"'max_token' count: {maxTokenCount.FormatCommas()} is larger than configured 'max_token' count: {_chatModel.ModelInformation.MaxTokens.FormatCommas()}, if you need more tokens change the configuration.",
+ $"current chat 'max_token' count: {maxTokenCount.FormatCommas()} is larger than configured 'max_token' count: {_chatModel.ModelInformation.MaxTokens.FormatCommas()}.",
+ },
+ HttpStatusCode.BadRequest
+ );
+ }
+ }
+
+ private void ValidateEmbeddingMaxToken(int maxTokenCount, string? path)
+ {
+ if (
+ _embeddingModel.ModelInformation.MaxTokens > 0
+ && maxTokenCount > _embeddingModel.ModelInformation.MaxTokens
+ )
+ {
+ throw new OpenAIException(
+ new OpenAIError
+ {
+ StatusCode = (int)HttpStatusCode.BadRequest,
+ Message =
+ $"embedding {path} 'max_token' count: {maxTokenCount.FormatCommas()} is larger than configured 'max_token' count: {_chatModel.ModelInformation.MaxTokens.FormatCommas()}.",
},
HttpStatusCode.BadRequest
);