diff --git a/app/MindWork AI Studio/Chat/ListContentBlockExtensions.cs b/app/MindWork AI Studio/Chat/ListContentBlockExtensions.cs index 5c9883e7..5776ce51 100644 --- a/app/MindWork AI Studio/Chat/ListContentBlockExtensions.cs +++ b/app/MindWork AI Studio/Chat/ListContentBlockExtensions.cs @@ -1,4 +1,5 @@ using AIStudio.Provider; +using AIStudio.Provider.OpenAI; namespace AIStudio.Chat; @@ -8,19 +9,44 @@ public static class ListContentBlockExtensions /// Processes a list of content blocks by transforming them into a collection of message results asynchronously. /// /// The list of content blocks to process. - /// A function that transforms each content block into a message result asynchronously. + /// A function that transforms each content block into a message result asynchronously. /// An asynchronous task that resolves to a list of transformed results. - public static async Task> BuildMessages(this List blocks, Func> transformer) + public static async Task> BuildMessages(this List blocks, Func roleTransformer) { var messages = blocks .Where(n => n.ContentType is ContentType.TEXT && !string.IsNullOrWhiteSpace((n.Content as ContentText)?.Text)) - .Select(transformer) + .Select(async n => new TextMessage + { + Role = roleTransformer(n.Role), + Content = n.Content switch + { + ContentText text => await text.PrepareTextContentForAI(), + _ => string.Empty, + } + }) .ToList(); // Await all messages: await Task.WhenAll(messages); // Select all results: - return messages.Select(n => n.Result).ToList(); + return messages.Select(n => n.Result).Cast().ToList(); } + + /// + /// Processes a list of content blocks using standard role transformations to create message results asynchronously. + /// + /// The list of content blocks to process. + /// >An asynchronous task that resolves to a list of transformed message results. + public static async Task> BuildMessagesUsingStandardRoles(this List blocks) => await blocks.BuildMessages(StandardRoleTransformer); + + private static string StandardRoleTransformer(ChatRole role) => role switch + { + ChatRole.USER => "user", + ChatRole.AI => "assistant", + ChatRole.AGENT => "assistant", + ChatRole.SYSTEM => "system", + + _ => "user", + }; } \ No newline at end of file diff --git a/app/MindWork AI Studio/Provider/AlibabaCloud/ProviderAlibabaCloud.cs b/app/MindWork AI Studio/Provider/AlibabaCloud/ProviderAlibabaCloud.cs index 258fb309..92a13689 100644 --- a/app/MindWork AI Studio/Provider/AlibabaCloud/ProviderAlibabaCloud.cs +++ b/app/MindWork AI Studio/Provider/AlibabaCloud/ProviderAlibabaCloud.cs @@ -40,24 +40,7 @@ public sealed class ProviderAlibabaCloud() : BaseProvider(LLMProviders.ALIBABA_C var apiParameters = this.ParseAdditionalApiParameters(); // Build the list of messages: - var messages = await chatThread.Blocks.BuildMessages(async n => new TextMessage - { - Role = n.Role switch - { - ChatRole.USER => "user", - ChatRole.AI => "assistant", - ChatRole.AGENT => "assistant", - ChatRole.SYSTEM => "system", - - _ => "user", - }, - - Content = n.Content switch - { - ContentText text => await text.PrepareTextContentForAI(), - _ => string.Empty, - } - }); + var messages = await chatThread.Blocks.BuildMessagesUsingStandardRoles(); // Prepare the AlibabaCloud HTTP chat request: var alibabaCloudChatRequest = JsonSerializer.Serialize(new ChatCompletionAPIRequest diff --git a/app/MindWork AI Studio/Provider/Anthropic/ChatRequest.cs b/app/MindWork AI Studio/Provider/Anthropic/ChatRequest.cs index d6df3990..7489c503 100644 --- a/app/MindWork AI Studio/Provider/Anthropic/ChatRequest.cs +++ b/app/MindWork AI Studio/Provider/Anthropic/ChatRequest.cs @@ -9,14 +9,11 @@ namespace AIStudio.Provider.Anthropic; /// The chat messages. /// The maximum number of tokens to generate. /// Whether to stream the chat completion. -/// The system prompt for the chat completion. public readonly record struct ChatRequest( string Model, IList Messages, int MaxTokens, - bool Stream, - string System -) + bool Stream) { // Attention: The "required" modifier is not supported for [JsonExtensionData]. [JsonExtensionData] diff --git a/app/MindWork AI Studio/Provider/Anthropic/ProviderAnthropic.cs b/app/MindWork AI Studio/Provider/Anthropic/ProviderAnthropic.cs index 632609b0..d5fd9e15 100644 --- a/app/MindWork AI Studio/Provider/Anthropic/ProviderAnthropic.cs +++ b/app/MindWork AI Studio/Provider/Anthropic/ProviderAnthropic.cs @@ -27,27 +27,18 @@ public sealed class ProviderAnthropic() : BaseProvider(LLMProviders.ANTHROPIC, " if(!requestedSecret.Success) yield break; + // Prepare the system prompt: + var systemPrompt = new TextMessage + { + Role = "system", + Content = chatThread.PrepareSystemPrompt(settingsManager, chatThread), + }; + // Parse the API parameters: var apiParameters = this.ParseAdditionalApiParameters("system"); // Build the list of messages: - var messages = await chatThread.Blocks.BuildMessages(async n => new TextMessage - { - Role = n.Role switch - { - ChatRole.USER => "user", - ChatRole.AI => "assistant", - ChatRole.AGENT => "assistant", - - _ => "user", - }, - - Content = n.Content switch - { - ContentText text => await text.PrepareTextContentForAI(), - _ => string.Empty, - } - }); + var messages = await chatThread.Blocks.BuildMessagesUsingStandardRoles(); // Prepare the Anthropic HTTP chat request: var chatRequest = JsonSerializer.Serialize(new ChatRequest @@ -55,9 +46,8 @@ public sealed class ProviderAnthropic() : BaseProvider(LLMProviders.ANTHROPIC, " Model = chatModel.Id, // Build the messages: - Messages = [..messages], + Messages = [systemPrompt, ..messages], - System = chatThread.PrepareSystemPrompt(settingsManager, chatThread), MaxTokens = apiParameters.TryGetValue("max_tokens", out var value) && value is int intValue ? intValue : 4_096, // Right now, we only support streaming completions: diff --git a/app/MindWork AI Studio/Provider/DeepSeek/ProviderDeepSeek.cs b/app/MindWork AI Studio/Provider/DeepSeek/ProviderDeepSeek.cs index 77c32867..697d4045 100644 --- a/app/MindWork AI Studio/Provider/DeepSeek/ProviderDeepSeek.cs +++ b/app/MindWork AI Studio/Provider/DeepSeek/ProviderDeepSeek.cs @@ -40,24 +40,7 @@ public sealed class ProviderDeepSeek() : BaseProvider(LLMProviders.DEEP_SEEK, "h var apiParameters = this.ParseAdditionalApiParameters(); // Build the list of messages: - var messages = await chatThread.Blocks.BuildMessages(async n => new TextMessage - { - Role = n.Role switch - { - ChatRole.USER => "user", - ChatRole.AI => "assistant", - ChatRole.AGENT => "assistant", - ChatRole.SYSTEM => "system", - - _ => "user", - }, - - Content = n.Content switch - { - ContentText text => await text.PrepareTextContentForAI(), - _ => string.Empty, - } - }); + var messages = await chatThread.Blocks.BuildMessagesUsingStandardRoles(); // Prepare the DeepSeek HTTP chat request: var deepSeekChatRequest = JsonSerializer.Serialize(new ChatCompletionAPIRequest diff --git a/app/MindWork AI Studio/Provider/Fireworks/ProviderFireworks.cs b/app/MindWork AI Studio/Provider/Fireworks/ProviderFireworks.cs index 2dc724d7..e423f009 100644 --- a/app/MindWork AI Studio/Provider/Fireworks/ProviderFireworks.cs +++ b/app/MindWork AI Studio/Provider/Fireworks/ProviderFireworks.cs @@ -40,24 +40,7 @@ public class ProviderFireworks() : BaseProvider(LLMProviders.FIREWORKS, "https:/ var apiParameters = this.ParseAdditionalApiParameters(); // Build the list of messages: - var messages = await chatThread.Blocks.BuildMessages(async n => new TextMessage - { - Role = n.Role switch - { - ChatRole.USER => "user", - ChatRole.AI => "assistant", - ChatRole.AGENT => "assistant", - ChatRole.SYSTEM => "system", - - _ => "user", - }, - - Content = n.Content switch - { - ContentText text => await text.PrepareTextContentForAI(), - _ => string.Empty, - } - }); + var messages = await chatThread.Blocks.BuildMessagesUsingStandardRoles(); // Prepare the Fireworks HTTP chat request: var fireworksChatRequest = JsonSerializer.Serialize(new ChatRequest diff --git a/app/MindWork AI Studio/Provider/GWDG/ProviderGWDG.cs b/app/MindWork AI Studio/Provider/GWDG/ProviderGWDG.cs index da390e05..9d822f8c 100644 --- a/app/MindWork AI Studio/Provider/GWDG/ProviderGWDG.cs +++ b/app/MindWork AI Studio/Provider/GWDG/ProviderGWDG.cs @@ -40,24 +40,7 @@ public sealed class ProviderGWDG() : BaseProvider(LLMProviders.GWDG, "https://ch var apiParameters = this.ParseAdditionalApiParameters(); // Build the list of messages: - var messages = await chatThread.Blocks.BuildMessages(async n => new TextMessage - { - Role = n.Role switch - { - ChatRole.USER => "user", - ChatRole.AI => "assistant", - ChatRole.AGENT => "assistant", - ChatRole.SYSTEM => "system", - - _ => "user", - }, - - Content = n.Content switch - { - ContentText text => await text.PrepareTextContentForAI(), - _ => string.Empty, - } - }); + var messages = await chatThread.Blocks.BuildMessagesUsingStandardRoles(); // Prepare the GWDG HTTP chat request: var gwdgChatRequest = JsonSerializer.Serialize(new ChatCompletionAPIRequest diff --git a/app/MindWork AI Studio/Provider/Google/ProviderGoogle.cs b/app/MindWork AI Studio/Provider/Google/ProviderGoogle.cs index 1954af00..7a8f64b9 100644 --- a/app/MindWork AI Studio/Provider/Google/ProviderGoogle.cs +++ b/app/MindWork AI Studio/Provider/Google/ProviderGoogle.cs @@ -40,24 +40,7 @@ public class ProviderGoogle() : BaseProvider(LLMProviders.GOOGLE, "https://gener var apiParameters = this.ParseAdditionalApiParameters(); // Build the list of messages: - var messages = await chatThread.Blocks.BuildMessages(async n => new TextMessage - { - Role = n.Role switch - { - ChatRole.USER => "user", - ChatRole.AI => "assistant", - ChatRole.AGENT => "assistant", - ChatRole.SYSTEM => "system", - - _ => "user", - }, - - Content = n.Content switch - { - ContentText text => await text.PrepareTextContentForAI(), - _ => string.Empty, - } - }); + var messages = await chatThread.Blocks.BuildMessagesUsingStandardRoles(); // Prepare the Google HTTP chat request: var geminiChatRequest = JsonSerializer.Serialize(new ChatRequest diff --git a/app/MindWork AI Studio/Provider/Groq/ProviderGroq.cs b/app/MindWork AI Studio/Provider/Groq/ProviderGroq.cs index 08bdd53b..e04de535 100644 --- a/app/MindWork AI Studio/Provider/Groq/ProviderGroq.cs +++ b/app/MindWork AI Studio/Provider/Groq/ProviderGroq.cs @@ -40,24 +40,7 @@ public class ProviderGroq() : BaseProvider(LLMProviders.GROQ, "https://api.groq. var apiParameters = this.ParseAdditionalApiParameters(); // Build the list of messages: - var messages = await chatThread.Blocks.BuildMessages(async n => new TextMessage - { - Role = n.Role switch - { - ChatRole.USER => "user", - ChatRole.AI => "assistant", - ChatRole.AGENT => "assistant", - ChatRole.SYSTEM => "system", - - _ => "user", - }, - - Content = n.Content switch - { - ContentText text => await text.PrepareTextContentForAI(), - _ => string.Empty, - } - }); + var messages = await chatThread.Blocks.BuildMessagesUsingStandardRoles(); // Prepare the OpenAI HTTP chat request: var groqChatRequest = JsonSerializer.Serialize(new ChatRequest diff --git a/app/MindWork AI Studio/Provider/Helmholtz/ProviderHelmholtz.cs b/app/MindWork AI Studio/Provider/Helmholtz/ProviderHelmholtz.cs index e5d0414e..d22abbd2 100644 --- a/app/MindWork AI Studio/Provider/Helmholtz/ProviderHelmholtz.cs +++ b/app/MindWork AI Studio/Provider/Helmholtz/ProviderHelmholtz.cs @@ -40,24 +40,7 @@ public sealed class ProviderHelmholtz() : BaseProvider(LLMProviders.HELMHOLTZ, " var apiParameters = this.ParseAdditionalApiParameters(); // Build the list of messages: - var messages = await chatThread.Blocks.BuildMessages(async n => new TextMessage - { - Role = n.Role switch - { - ChatRole.USER => "user", - ChatRole.AI => "assistant", - ChatRole.AGENT => "assistant", - ChatRole.SYSTEM => "system", - - _ => "user", - }, - - Content = n.Content switch - { - ContentText text => await text.PrepareTextContentForAI(), - _ => string.Empty, - } - }); + var messages = await chatThread.Blocks.BuildMessagesUsingStandardRoles(); // Prepare the Helmholtz HTTP chat request: var helmholtzChatRequest = JsonSerializer.Serialize(new ChatCompletionAPIRequest diff --git a/app/MindWork AI Studio/Provider/HuggingFace/ProviderHuggingFace.cs b/app/MindWork AI Studio/Provider/HuggingFace/ProviderHuggingFace.cs index 3883b775..1ce7609f 100644 --- a/app/MindWork AI Studio/Provider/HuggingFace/ProviderHuggingFace.cs +++ b/app/MindWork AI Studio/Provider/HuggingFace/ProviderHuggingFace.cs @@ -45,24 +45,7 @@ public sealed class ProviderHuggingFace : BaseProvider var apiParameters = this.ParseAdditionalApiParameters(); // Build the list of messages: - var message = await chatThread.Blocks.BuildMessages(async n => new TextMessage - { - Role = n.Role switch - { - ChatRole.USER => "user", - ChatRole.AI => "assistant", - ChatRole.AGENT => "assistant", - ChatRole.SYSTEM => "system", - - _ => "user", - }, - - Content = n.Content switch - { - ContentText text => await text.PrepareTextContentForAI(), - _ => string.Empty, - } - }); + var message = await chatThread.Blocks.BuildMessagesUsingStandardRoles(); // Prepare the HuggingFace HTTP chat request: var huggingfaceChatRequest = JsonSerializer.Serialize(new ChatCompletionAPIRequest diff --git a/app/MindWork AI Studio/Provider/Mistral/ProviderMistral.cs b/app/MindWork AI Studio/Provider/Mistral/ProviderMistral.cs index 165a35a5..28562719 100644 --- a/app/MindWork AI Studio/Provider/Mistral/ProviderMistral.cs +++ b/app/MindWork AI Studio/Provider/Mistral/ProviderMistral.cs @@ -38,24 +38,7 @@ public sealed class ProviderMistral() : BaseProvider(LLMProviders.MISTRAL, "http var apiParameters = this.ParseAdditionalApiParameters(); // Build the list of messages: - var messages = await chatThread.Blocks.BuildMessages(async n => new TextMessage - { - Role = n.Role switch - { - ChatRole.USER => "user", - ChatRole.AI => "assistant", - ChatRole.AGENT => "assistant", - ChatRole.SYSTEM => "system", - - _ => "user", - }, - - Content = n.Content switch - { - ContentText text => await text.PrepareTextContentForAI(), - _ => string.Empty, - } - }); + var messages = await chatThread.Blocks.BuildMessagesUsingStandardRoles(); // Prepare the Mistral HTTP chat request: var mistralChatRequest = JsonSerializer.Serialize(new ChatRequest diff --git a/app/MindWork AI Studio/Provider/OpenAI/ProviderOpenAI.cs b/app/MindWork AI Studio/Provider/OpenAI/ProviderOpenAI.cs index ebdf4bb0..44480d3f 100644 --- a/app/MindWork AI Studio/Provider/OpenAI/ProviderOpenAI.cs +++ b/app/MindWork AI Studio/Provider/OpenAI/ProviderOpenAI.cs @@ -90,23 +90,14 @@ public sealed class ProviderOpenAI() : BaseProvider(LLMProviders.OPEN_AI, "https var apiParameters = this.ParseAdditionalApiParameters("input", "store", "tools"); // Build the list of messages: - var messages = await chatThread.Blocks.BuildMessages(async n => new TextMessage + var messages = await chatThread.Blocks.BuildMessages(role => role switch { - Role = n.Role switch - { - ChatRole.USER => "user", - ChatRole.AI => "assistant", - ChatRole.AGENT => "assistant", - ChatRole.SYSTEM => systemPromptRole, + ChatRole.USER => "user", + ChatRole.AI => "assistant", + ChatRole.AGENT => "assistant", + ChatRole.SYSTEM => systemPromptRole, - _ => "user", - }, - - Content = n.Content switch - { - ContentText text => await text.PrepareTextContentForAI(), - _ => string.Empty, - } + _ => "user", }); // diff --git a/app/MindWork AI Studio/Provider/OpenRouter/ProviderOpenRouter.cs b/app/MindWork AI Studio/Provider/OpenRouter/ProviderOpenRouter.cs index 0f919b37..38267b6c 100644 --- a/app/MindWork AI Studio/Provider/OpenRouter/ProviderOpenRouter.cs +++ b/app/MindWork AI Studio/Provider/OpenRouter/ProviderOpenRouter.cs @@ -43,24 +43,7 @@ public sealed class ProviderOpenRouter() : BaseProvider(LLMProviders.OPEN_ROUTER var apiParameters = this.ParseAdditionalApiParameters(); // Build the list of messages: - var messages = await chatThread.Blocks.BuildMessages(async n => new TextMessage - { - Role = n.Role switch - { - ChatRole.USER => "user", - ChatRole.AI => "assistant", - ChatRole.AGENT => "assistant", - ChatRole.SYSTEM => "system", - - _ => "user", - }, - - Content = n.Content switch - { - ContentText text => await text.PrepareTextContentForAI(), - _ => string.Empty, - } - }); + var messages = await chatThread.Blocks.BuildMessagesUsingStandardRoles(); // Prepare the OpenRouter HTTP chat request: var openRouterChatRequest = JsonSerializer.Serialize(new ChatCompletionAPIRequest diff --git a/app/MindWork AI Studio/Provider/Perplexity/ProviderPerplexity.cs b/app/MindWork AI Studio/Provider/Perplexity/ProviderPerplexity.cs index a4ab35c6..92a19cb1 100644 --- a/app/MindWork AI Studio/Provider/Perplexity/ProviderPerplexity.cs +++ b/app/MindWork AI Studio/Provider/Perplexity/ProviderPerplexity.cs @@ -49,24 +49,7 @@ public sealed class ProviderPerplexity() : BaseProvider(LLMProviders.PERPLEXITY, var apiParameters = this.ParseAdditionalApiParameters(); // Build the list of messages: - var messages = await chatThread.Blocks.BuildMessages(async n => new TextMessage() - { - Role = n.Role switch - { - ChatRole.USER => "user", - ChatRole.AI => "assistant", - ChatRole.AGENT => "assistant", - ChatRole.SYSTEM => "system", - - _ => "user", - }, - - Content = n.Content switch - { - ContentText text => await text.PrepareTextContentForAI(), - _ => string.Empty, - } - }); + var messages = await chatThread.Blocks.BuildMessagesUsingStandardRoles(); // Prepare the Perplexity HTTP chat request: var perplexityChatRequest = JsonSerializer.Serialize(new ChatCompletionAPIRequest diff --git a/app/MindWork AI Studio/Provider/SelfHosted/ProviderSelfHosted.cs b/app/MindWork AI Studio/Provider/SelfHosted/ProviderSelfHosted.cs index 5a142090..b4849978 100644 --- a/app/MindWork AI Studio/Provider/SelfHosted/ProviderSelfHosted.cs +++ b/app/MindWork AI Studio/Provider/SelfHosted/ProviderSelfHosted.cs @@ -36,24 +36,7 @@ public sealed class ProviderSelfHosted(Host host, string hostname) : BaseProvide var apiParameters = this.ParseAdditionalApiParameters(); // Build the list of messages: - var messages = await chatThread.Blocks.BuildMessages(async n => new TextMessage - { - Role = n.Role switch - { - ChatRole.USER => "user", - ChatRole.AI => "assistant", - ChatRole.AGENT => "assistant", - ChatRole.SYSTEM => "system", - - _ => "user", - }, - - Content = n.Content switch - { - ContentText text => await text.PrepareTextContentForAI(), - _ => string.Empty, - } - }); + var messages = await chatThread.Blocks.BuildMessagesUsingStandardRoles(); // Prepare the OpenAI HTTP chat request: var providerChatRequest = JsonSerializer.Serialize(new ChatRequest diff --git a/app/MindWork AI Studio/Provider/X/ProviderX.cs b/app/MindWork AI Studio/Provider/X/ProviderX.cs index 67ea9f01..d1cc4544 100644 --- a/app/MindWork AI Studio/Provider/X/ProviderX.cs +++ b/app/MindWork AI Studio/Provider/X/ProviderX.cs @@ -40,24 +40,7 @@ public sealed class ProviderX() : BaseProvider(LLMProviders.X, "https://api.x.ai var apiParameters = this.ParseAdditionalApiParameters(); // Build the list of messages: - var messages = await chatThread.Blocks.BuildMessages(async n => new TextMessage - { - Role = n.Role switch - { - ChatRole.USER => "user", - ChatRole.AI => "assistant", - ChatRole.AGENT => "assistant", - ChatRole.SYSTEM => "system", - - _ => "user", - }, - - Content = n.Content switch - { - ContentText text => await text.PrepareTextContentForAI(), - _ => string.Empty, - } - }); + var messages = await chatThread.Blocks.BuildMessagesUsingStandardRoles(); // Prepare the xAI HTTP chat request: var xChatRequest = JsonSerializer.Serialize(new ChatCompletionAPIRequest