diff --git a/app/MindWork AI Studio/Assistants/AssistantBase.razor.cs b/app/MindWork AI Studio/Assistants/AssistantBase.razor.cs index f6582c3..fc9fcff 100644 --- a/app/MindWork AI Studio/Assistants/AssistantBase.razor.cs +++ b/app/MindWork AI Studio/Assistants/AssistantBase.razor.cs @@ -293,7 +293,7 @@ public abstract partial class AssistantBase : ComponentBase, IMessageBusReceiver // Use the selected provider to get the AI response. // By awaiting this line, we wait for the entire // content to be streamed. - await aiText.CreateFromProviderAsync(this.providerSettings.CreateProvider(this.Logger), this.providerSettings.Model, this.lastUserPrompt, this.chatThread); + this.chatThread = await aiText.CreateFromProviderAsync(this.providerSettings.CreateProvider(this.Logger), this.providerSettings.Model, this.lastUserPrompt, this.chatThread); this.isProcessing = false; this.StateHasChanged(); diff --git a/app/MindWork AI Studio/Chat/ChatRole.cs b/app/MindWork AI Studio/Chat/ChatRole.cs index d4e61e4..339be97 100644 --- a/app/MindWork AI Studio/Chat/ChatRole.cs +++ b/app/MindWork AI Studio/Chat/ChatRole.cs @@ -12,7 +12,6 @@ public enum ChatRole USER, AI, AGENT, - RAG, } /// diff --git a/app/MindWork AI Studio/Chat/ChatThread.cs b/app/MindWork AI Studio/Chat/ChatThread.cs index d7dbf9a..73182e7 100644 --- a/app/MindWork AI Studio/Chat/ChatThread.cs +++ b/app/MindWork AI Studio/Chat/ChatThread.cs @@ -40,6 +40,11 @@ public sealed record ChatThread /// public IReadOnlyList AISelectedDataSources { get; set; } = []; + /// + /// The augmented data for this chat thread. Will be inserted into the system prompt. + /// + public string AugmentedData { get; set; } = string.Empty; + /// /// The name of the chat thread. Usually generated by an AI model or manually edited by the user. /// @@ -74,31 +79,48 @@ public sealed record ChatThread /// The prepared system prompt. public string PrepareSystemPrompt(SettingsManager settingsManager, ChatThread chatThread, ILogger logger) { + var isAugmentedDataAvailable = !string.IsNullOrWhiteSpace(chatThread.AugmentedData); + var systemPromptWithAugmentedData = isAugmentedDataAvailable switch + { + true => $""" + {chatThread.SystemPrompt} + + {chatThread.AugmentedData} + """, + + false => chatThread.SystemPrompt, + }; + + if(isAugmentedDataAvailable) + logger.LogInformation("Augmented data is available for the chat thread."); + else + logger.LogInformation("No augmented data is available for the chat thread."); + // // Prepare the system prompt: // string systemPromptText; var logMessage = $"Using no profile for chat thread '{chatThread.Name}'."; if (string.IsNullOrWhiteSpace(chatThread.SelectedProfile)) - systemPromptText = chatThread.SystemPrompt; + systemPromptText = systemPromptWithAugmentedData; else { if(!Guid.TryParse(chatThread.SelectedProfile, out var profileId)) - systemPromptText = chatThread.SystemPrompt; + systemPromptText = systemPromptWithAugmentedData; else { if(chatThread.SelectedProfile == Profile.NO_PROFILE.Id || profileId == Guid.Empty) - systemPromptText = chatThread.SystemPrompt; + systemPromptText = systemPromptWithAugmentedData; else { var profile = settingsManager.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == chatThread.SelectedProfile); if(profile == default) - systemPromptText = chatThread.SystemPrompt; + systemPromptText = systemPromptWithAugmentedData; else { logMessage = $"Using profile '{profile.Name}' for chat thread '{chatThread.Name}'."; systemPromptText = $""" - {chatThread.SystemPrompt} + {systemPromptWithAugmentedData} {profile.ToSystemPrompt()} """; diff --git a/app/MindWork AI Studio/Chat/ContentImage.cs b/app/MindWork AI Studio/Chat/ContentImage.cs index 9f09e87..c7e785e 100644 --- a/app/MindWork AI Studio/Chat/ContentImage.cs +++ b/app/MindWork AI Studio/Chat/ContentImage.cs @@ -28,7 +28,7 @@ public sealed class ContentImage : IContent, IImageSource public Func StreamingEvent { get; set; } = () => Task.CompletedTask; /// - public Task CreateFromProviderAsync(IProvider provider, Model chatModel, IContent? lastPrompt, ChatThread? chatChatThread, CancellationToken token = default) + public Task CreateFromProviderAsync(IProvider provider, Model chatModel, IContent? lastPrompt, ChatThread? chatChatThread, CancellationToken token = default) { throw new NotImplementedException(); } diff --git a/app/MindWork AI Studio/Chat/ContentText.cs b/app/MindWork AI Studio/Chat/ContentText.cs index 82b5334..0dccd26 100644 --- a/app/MindWork AI Studio/Chat/ContentText.cs +++ b/app/MindWork AI Studio/Chat/ContentText.cs @@ -36,10 +36,10 @@ public sealed class ContentText : IContent public Func StreamingEvent { get; set; } = () => Task.CompletedTask; /// - public async Task CreateFromProviderAsync(IProvider provider, Model chatModel, IContent? lastPrompt, ChatThread? chatThread, CancellationToken token = default) + public async Task CreateFromProviderAsync(IProvider provider, Model chatModel, IContent? lastPrompt, ChatThread? chatThread, CancellationToken token = default) { if(chatThread is null) - return; + return new(); // Call the RAG process. Right now, we only have one RAG process: if (lastPrompt is not null) @@ -115,6 +115,7 @@ public sealed class ContentText : IContent // Inform the UI that the streaming is done: await this.StreamingDone(); + return chatThread; } #endregion diff --git a/app/MindWork AI Studio/Chat/IContent.cs b/app/MindWork AI Studio/Chat/IContent.cs index 8ca9402..be3bf09 100644 --- a/app/MindWork AI Studio/Chat/IContent.cs +++ b/app/MindWork AI Studio/Chat/IContent.cs @@ -41,7 +41,7 @@ public interface IContent /// /// Uses the provider to create the content. /// - public Task CreateFromProviderAsync(IProvider provider, Model chatModel, IContent? lastPrompt, ChatThread? chatChatThread, CancellationToken token = default); + public Task CreateFromProviderAsync(IProvider provider, Model chatModel, IContent? lastPrompt, ChatThread? chatChatThread, CancellationToken token = default); /// /// Returns the corresponding ERI content type. diff --git a/app/MindWork AI Studio/Components/ChatComponent.razor.cs b/app/MindWork AI Studio/Components/ChatComponent.razor.cs index 67d805d..2e05c0f 100644 --- a/app/MindWork AI Studio/Components/ChatComponent.razor.cs +++ b/app/MindWork AI Studio/Components/ChatComponent.razor.cs @@ -475,7 +475,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable // Use the selected provider to get the AI response. // By awaiting this line, we wait for the entire // content to be streamed. - await aiText.CreateFromProviderAsync(this.Provider.CreateProvider(this.Logger), this.Provider.Model, lastUserPrompt, this.ChatThread, this.cancellationTokenSource.Token); + this.ChatThread = await aiText.CreateFromProviderAsync(this.Provider.CreateProvider(this.Logger), this.Provider.Model, lastUserPrompt, this.ChatThread, this.cancellationTokenSource.Token); } this.cancellationTokenSource = null; diff --git a/app/MindWork AI Studio/Pages/Writer.razor.cs b/app/MindWork AI Studio/Pages/Writer.razor.cs index 76409c3..42b23ab 100644 --- a/app/MindWork AI Studio/Pages/Writer.razor.cs +++ b/app/MindWork AI Studio/Pages/Writer.razor.cs @@ -139,7 +139,7 @@ public partial class Writer : MSGComponentBase, IAsyncDisposable this.isStreaming = true; this.StateHasChanged(); - await aiText.CreateFromProviderAsync(this.providerSettings.CreateProvider(this.Logger), this.providerSettings.Model, lastUserPrompt, this.chatThread); + this.chatThread = await aiText.CreateFromProviderAsync(this.providerSettings.CreateProvider(this.Logger), this.providerSettings.Model, lastUserPrompt, this.chatThread); this.suggestion = aiText.Text; this.isStreaming = false; diff --git a/app/MindWork AI Studio/Provider/Anthropic/ProviderAnthropic.cs b/app/MindWork AI Studio/Provider/Anthropic/ProviderAnthropic.cs index a900095..7693d21 100644 --- a/app/MindWork AI Studio/Provider/Anthropic/ProviderAnthropic.cs +++ b/app/MindWork AI Studio/Provider/Anthropic/ProviderAnthropic.cs @@ -38,7 +38,6 @@ public sealed class ProviderAnthropic(ILogger logger) : BaseProvider("https://ap ChatRole.USER => "user", ChatRole.AI => "assistant", ChatRole.AGENT => "assistant", - ChatRole.RAG => "assistant", _ => "user", }, diff --git a/app/MindWork AI Studio/Provider/DeepSeek/ProviderDeepSeek.cs b/app/MindWork AI Studio/Provider/DeepSeek/ProviderDeepSeek.cs index c58e914..b4ce57a 100644 --- a/app/MindWork AI Studio/Provider/DeepSeek/ProviderDeepSeek.cs +++ b/app/MindWork AI Studio/Provider/DeepSeek/ProviderDeepSeek.cs @@ -49,7 +49,6 @@ public sealed class ProviderDeepSeek(ILogger logger) : BaseProvider("https://api ChatRole.USER => "user", ChatRole.AI => "assistant", ChatRole.AGENT => "assistant", - ChatRole.RAG => "assistant", ChatRole.SYSTEM => "system", _ => "user", diff --git a/app/MindWork AI Studio/Provider/Fireworks/ProviderFireworks.cs b/app/MindWork AI Studio/Provider/Fireworks/ProviderFireworks.cs index 88801a1..66817fc 100644 --- a/app/MindWork AI Studio/Provider/Fireworks/ProviderFireworks.cs +++ b/app/MindWork AI Studio/Provider/Fireworks/ProviderFireworks.cs @@ -49,7 +49,6 @@ public class ProviderFireworks(ILogger logger) : BaseProvider("https://api.firew ChatRole.AI => "assistant", ChatRole.AGENT => "assistant", ChatRole.SYSTEM => "system", - ChatRole.RAG => "assistant", _ => "user", }, diff --git a/app/MindWork AI Studio/Provider/GWDG/ProviderGWDG.cs b/app/MindWork AI Studio/Provider/GWDG/ProviderGWDG.cs index 40054cf..c0562a6 100644 --- a/app/MindWork AI Studio/Provider/GWDG/ProviderGWDG.cs +++ b/app/MindWork AI Studio/Provider/GWDG/ProviderGWDG.cs @@ -49,7 +49,6 @@ public sealed class ProviderGWDG(ILogger logger) : BaseProvider("https://chat-ai ChatRole.USER => "user", ChatRole.AI => "assistant", ChatRole.AGENT => "assistant", - ChatRole.RAG => "assistant", ChatRole.SYSTEM => "system", _ => "user", diff --git a/app/MindWork AI Studio/Provider/Google/ProviderGoogle.cs b/app/MindWork AI Studio/Provider/Google/ProviderGoogle.cs index 4fd12ab..942cb24 100644 --- a/app/MindWork AI Studio/Provider/Google/ProviderGoogle.cs +++ b/app/MindWork AI Studio/Provider/Google/ProviderGoogle.cs @@ -50,7 +50,6 @@ public class ProviderGoogle(ILogger logger) : BaseProvider("https://generativela ChatRole.AI => "assistant", ChatRole.AGENT => "assistant", ChatRole.SYSTEM => "system", - ChatRole.RAG => "assistant", _ => "user", }, diff --git a/app/MindWork AI Studio/Provider/Groq/ProviderGroq.cs b/app/MindWork AI Studio/Provider/Groq/ProviderGroq.cs index 10e8899..f32a31b 100644 --- a/app/MindWork AI Studio/Provider/Groq/ProviderGroq.cs +++ b/app/MindWork AI Studio/Provider/Groq/ProviderGroq.cs @@ -50,7 +50,6 @@ public class ProviderGroq(ILogger logger) : BaseProvider("https://api.groq.com/o ChatRole.AI => "assistant", ChatRole.AGENT => "assistant", ChatRole.SYSTEM => "system", - ChatRole.RAG => "assistant", _ => "user", }, diff --git a/app/MindWork AI Studio/Provider/Helmholtz/ProviderHelmholtz.cs b/app/MindWork AI Studio/Provider/Helmholtz/ProviderHelmholtz.cs index 005475e..b845050 100644 --- a/app/MindWork AI Studio/Provider/Helmholtz/ProviderHelmholtz.cs +++ b/app/MindWork AI Studio/Provider/Helmholtz/ProviderHelmholtz.cs @@ -49,7 +49,6 @@ public sealed class ProviderHelmholtz(ILogger logger) : BaseProvider("https://ap ChatRole.USER => "user", ChatRole.AI => "assistant", ChatRole.AGENT => "assistant", - ChatRole.RAG => "assistant", ChatRole.SYSTEM => "system", _ => "user", diff --git a/app/MindWork AI Studio/Provider/Mistral/ProviderMistral.cs b/app/MindWork AI Studio/Provider/Mistral/ProviderMistral.cs index 4395920..024f60d 100644 --- a/app/MindWork AI Studio/Provider/Mistral/ProviderMistral.cs +++ b/app/MindWork AI Studio/Provider/Mistral/ProviderMistral.cs @@ -48,7 +48,6 @@ public sealed class ProviderMistral(ILogger logger) : BaseProvider("https://api. ChatRole.AI => "assistant", ChatRole.AGENT => "assistant", ChatRole.SYSTEM => "system", - ChatRole.RAG => "assistant", _ => "user", }, diff --git a/app/MindWork AI Studio/Provider/OpenAI/ProviderOpenAI.cs b/app/MindWork AI Studio/Provider/OpenAI/ProviderOpenAI.cs index f901925..ed09217 100644 --- a/app/MindWork AI Studio/Provider/OpenAI/ProviderOpenAI.cs +++ b/app/MindWork AI Studio/Provider/OpenAI/ProviderOpenAI.cs @@ -76,7 +76,6 @@ public sealed class ProviderOpenAI(ILogger logger) : BaseProvider("https://api.o ChatRole.USER => "user", ChatRole.AI => "assistant", ChatRole.AGENT => "assistant", - ChatRole.RAG => "assistant", ChatRole.SYSTEM => systemPromptRole, _ => "user", diff --git a/app/MindWork AI Studio/Provider/SelfHosted/ProviderSelfHosted.cs b/app/MindWork AI Studio/Provider/SelfHosted/ProviderSelfHosted.cs index 73c101a..4ba45c6 100644 --- a/app/MindWork AI Studio/Provider/SelfHosted/ProviderSelfHosted.cs +++ b/app/MindWork AI Studio/Provider/SelfHosted/ProviderSelfHosted.cs @@ -46,7 +46,6 @@ public sealed class ProviderSelfHosted(ILogger logger, Host host, string hostnam ChatRole.AI => "assistant", ChatRole.AGENT => "assistant", ChatRole.SYSTEM => "system", - ChatRole.RAG => "assistant", _ => "user", }, diff --git a/app/MindWork AI Studio/Provider/X/ProviderX.cs b/app/MindWork AI Studio/Provider/X/ProviderX.cs index df927d7..a8334c8 100644 --- a/app/MindWork AI Studio/Provider/X/ProviderX.cs +++ b/app/MindWork AI Studio/Provider/X/ProviderX.cs @@ -50,7 +50,6 @@ public sealed class ProviderX(ILogger logger) : BaseProvider("https://api.x.ai/v ChatRole.AI => "assistant", ChatRole.AGENT => "assistant", ChatRole.SYSTEM => "system", - ChatRole.RAG => "assistant", _ => "user", }, diff --git a/app/MindWork AI Studio/Settings/DataModel/DataSourceERI_V1.cs b/app/MindWork AI Studio/Settings/DataModel/DataSourceERI_V1.cs index a9e4023..d02c6bf 100644 --- a/app/MindWork AI Studio/Settings/DataModel/DataSourceERI_V1.cs +++ b/app/MindWork AI Studio/Settings/DataModel/DataSourceERI_V1.cs @@ -97,7 +97,7 @@ public readonly record struct DataSourceERI_V1 : IERIDataSource Links = eriContext.Links, Category = eriContext.Type.ToRetrievalContentCategory(), MatchedText = eriContext.MatchedContent, - DataSourceName = eriContext.Name, + DataSourceName = this.Name, SurroundingContent = eriContext.SurroundingContent, }); break; @@ -111,7 +111,7 @@ public readonly record struct DataSourceERI_V1 : IERIDataSource Source = eriContext.MatchedContent, Category = eriContext.Type.ToRetrievalContentCategory(), SourceType = ContentImageSource.BASE64, - DataSourceName = eriContext.Name, + DataSourceName = this.Name, }); break; diff --git a/app/MindWork AI Studio/Tools/RAG/AugmentationProcesses/AugmentationOne.cs b/app/MindWork AI Studio/Tools/RAG/AugmentationProcesses/AugmentationOne.cs index fd6e30a..fff9125 100644 --- a/app/MindWork AI Studio/Tools/RAG/AugmentationProcesses/AugmentationOne.cs +++ b/app/MindWork AI Studio/Tools/RAG/AugmentationProcesses/AugmentationOne.cs @@ -66,22 +66,8 @@ public sealed class AugmentationOne : IAugmentationProcess // Let's convert all retrieval contexts to Markdown: await retrievalContexts.AsMarkdown(sb, token); - // - // Append the entire augmentation to the chat thread, - // just before the user prompt: - // - chatThread.Blocks.Insert(chatThread.Blocks.Count - 1, new() - { - Role = ChatRole.RAG, - Time = DateTimeOffset.UtcNow, - ContentType = ContentType.TEXT, - HideFromUser = true, - Content = new ContentText - { - Text = sb.ToString(), - } - }); - + // Add the augmented data to the chat thread: + chatThread.AugmentedData = sb.ToString(); return chatThread; } diff --git a/app/MindWork AI Studio/Tools/RAG/RAGProcesses/AISrcSelWithRetCtxVal.cs b/app/MindWork AI Studio/Tools/RAG/RAGProcesses/AISrcSelWithRetCtxVal.cs index 13e3250..ae7c078 100644 --- a/app/MindWork AI Studio/Tools/RAG/RAGProcesses/AISrcSelWithRetCtxVal.cs +++ b/app/MindWork AI Studio/Tools/RAG/RAGProcesses/AISrcSelWithRetCtxVal.cs @@ -38,6 +38,30 @@ public sealed class AISrcSelWithRetCtxVal : IRagProcess // makes sense to proceed with the RAG process: var proceedWithRAG = true; + // + // We read the last block in the chat thread. We need to re-arrange + // the order of blocks later, after the augmentation process takes + // place: + // + if(chatThread.Blocks.Count == 0) + { + logger.LogError("The chat thread is empty. Skipping the RAG process."); + return chatThread; + } + + if (chatThread.Blocks.Last().Role != ChatRole.AI) + { + logger.LogError("The last block in the chat thread is not the AI block. There is something wrong with the chat thread. Skipping the RAG process."); + return chatThread; + } + + // + // At this point in time, the chat thread contains already the + // last block, which is the waiting AI block. We need to remove + // this block before we call some parts of the RAG process: + // + var chatThreadWithoutWaitingAIBlock = chatThread with { Blocks = chatThread.Blocks[..^1] }; + // // When the user wants to bind data sources to the chat, we // have to check if the data sources are available for the @@ -84,7 +108,7 @@ public sealed class AISrcSelWithRetCtxVal : IRagProcess // var retrievalTasks = new List>>(selectedDataSources.Count); foreach (var dataSource in selectedDataSources) - retrievalTasks.Add(dataSource.RetrieveDataAsync(lastPrompt, chatThread, token)); + retrievalTasks.Add(dataSource.RetrieveDataAsync(lastPrompt, chatThreadWithoutWaitingAIBlock, token)); // // Wait for all retrieval tasks to finish: diff --git a/app/MindWork AI Studio/wwwroot/changelog/v0.9.32.md b/app/MindWork AI Studio/wwwroot/changelog/v0.9.32.md index 5cdac4d..007b7d7 100644 --- a/app/MindWork AI Studio/wwwroot/changelog/v0.9.32.md +++ b/app/MindWork AI Studio/wwwroot/changelog/v0.9.32.md @@ -3,4 +3,8 @@ - Improved the ERI client to expect JSON responses and send JSON requests using camel case. - Improved the ERI client to raise an error when the server responds with additional JSON data that is not expected. - Improved the error handling in the ERI data source info dialog in cases where servers respond with an invalid message. -- Improved the error handling for the entire RAG process. \ No newline at end of file +- Improved the error handling for the entire RAG process. +- Improved chat thread persistence after modifications through the RAG process. +- Improved the augmentation and generation part of RAG by passing the augmented data into the system prompt. +- Fixed the chat thread we use for the data retrieval by removing the last block, which is meant to be for the final AI answer. +- Fixed the data source name for ERI data sources when performing data retrieval. \ No newline at end of file