diff --git a/src/BE/Chats.BE.csproj b/src/BE/Chats.BE.csproj
index 22774063..97cb4b4f 100644
--- a/src/BE/Chats.BE.csproj
+++ b/src/BE/Chats.BE.csproj
@@ -9,7 +9,7 @@
-
+
@@ -26,12 +26,12 @@
-
+
-
-
+
+
diff --git a/src/BE/DB/Enums/DBModelProvider.cs b/src/BE/DB/Enums/DBModelProvider.cs
index c5f47d14..2c2f90bc 100644
--- a/src/BE/DB/Enums/DBModelProvider.cs
+++ b/src/BE/DB/Enums/DBModelProvider.cs
@@ -13,4 +13,6 @@ public enum DBModelProvider
Sparkdesk = 8,
ZhiPuAI = 9,
DeepSeek = 10,
+ xAI = 11,
+ GithubModels = 12,
}
diff --git a/src/BE/DB/Init/BasicData.cs b/src/BE/DB/Init/BasicData.cs
index 34f1388a..57fdb52d 100644
--- a/src/BE/DB/Init/BasicData.cs
+++ b/src/BE/DB/Init/BasicData.cs
@@ -247,22 +247,22 @@ private static void InsertModelReferences(ChatsDB db)
private static void InsertModelProviders(ChatsDB db)
{
- // Generated from data, hash: 918110f3f52c51c8fdebe00ca4e2e9dac5d2f2e7f892ed5c7197be6a7fbcfbdf
+ // Generated from data, hash: 615290985867eb3467e7889a31c4edf5dcdbd113930d67df8e19b6cd27c955ca
db.ModelProviders.AddRange(
[
- new(){ Id=0, Name="Test", InitialHost=null, InitialSecret=null, },
- new(){ Id=1, Name="Azure OpenAI", InitialHost="https://.openai.azure.com/", InitialSecret="", },
- new(){ Id=2, Name="Tencent Hunyuan", InitialHost="hunyuan.tencentcloudapi.com", InitialSecret="""{"secretId":"", "secretKey":""}""", },
- new(){ Id=3, Name="01.ai", InitialHost=null, InitialSecret="", },
- new(){ Id=4, Name="Moonshot", InitialHost=null, InitialSecret="", },
- new(){ Id=5, Name="OpenAI", InitialHost="https://api.openai.com/v1", InitialSecret="", },
- new(){ Id=6, Name="Wenxin Qianfan", InitialHost=null, InitialSecret="""{"apiKey":"", "secret":""}""", },
- new(){ Id=7, Name="DashScope", InitialHost=null, InitialSecret="", },
- new(){ Id=8, Name="Xunfei SparkDesk", InitialHost=null, InitialSecret="""{"appId": "", "apiKey":"", "secret":""}""", },
- new(){ Id=9, Name="Zhipu AI", InitialHost=null, InitialSecret="", },
- new(){ Id=10, Name="DeepSeek", InitialHost=null, InitialSecret="", },
- new(){ Id=11, Name="x.ai", InitialHost=null, InitialSecret="xai-yourkey", },
- new(){ Id=12, Name="Github Models", InitialHost=null, InitialSecret="ghp_yourkey", }
+ new(){ Id=0, Name="Test", InitialHost=null, InitialSecret=null, },
+ new(){ Id=1, Name="Azure OpenAI", InitialHost="https://.openai.azure.com/", InitialSecret="", },
+ new(){ Id=2, Name="Tencent Hunyuan", InitialHost="hunyuan.tencentcloudapi.com", InitialSecret="""{"secretId":"", "secretKey":""}""", },
+ new(){ Id=3, Name="01.ai", InitialHost=null, InitialSecret="", },
+ new(){ Id=4, Name="Moonshot", InitialHost=null, InitialSecret="", },
+ new(){ Id=5, Name="OpenAI", InitialHost="https://api.openai.com/v1", InitialSecret="", },
+ new(){ Id=6, Name="Wenxin Qianfan", InitialHost=null, InitialSecret="""{"apiKey":"", "secret":""}""", },
+ new(){ Id=7, Name="DashScope", InitialHost=null, InitialSecret="", },
+ new(){ Id=8, Name="Xunfei SparkDesk", InitialHost=null, InitialSecret="", },
+ new(){ Id=9, Name="Zhipu AI", InitialHost=null, InitialSecret="", },
+ new(){ Id=10, Name="DeepSeek", InitialHost=null, InitialSecret="", },
+ new(){ Id=11, Name="x.ai", InitialHost=null, InitialSecret="xai-yourkey", },
+ new(){ Id=12, Name="Github Models", InitialHost=null, InitialSecret="ghp_yourkey", }
]);
}
};
\ No newline at end of file
diff --git a/src/BE/Services/ChatServices/ChatFactory.cs b/src/BE/Services/ChatServices/ChatFactory.cs
index 611642f1..a08ab5e7 100644
--- a/src/BE/Services/ChatServices/ChatFactory.cs
+++ b/src/BE/Services/ChatServices/ChatFactory.cs
@@ -1,12 +1,7 @@
using Chats.BE.DB;
using Chats.BE.DB.Enums;
-using Chats.BE.Services.ChatServices.Implementations.Azure;
using Chats.BE.Services.ChatServices.Implementations.DashScope;
-using Chats.BE.Services.ChatServices.Implementations.DeepSeek;
-using Chats.BE.Services.ChatServices.Implementations.GLM;
using Chats.BE.Services.ChatServices.Implementations.Hunyuan;
-using Chats.BE.Services.ChatServices.Implementations.Kimi;
-using Chats.BE.Services.ChatServices.Implementations.LingYi;
using Chats.BE.Services.ChatServices.Implementations.OpenAI;
using Chats.BE.Services.ChatServices.Implementations.QianFan;
using Chats.BE.Services.ChatServices.Implementations.Test;
@@ -29,9 +24,11 @@ public ChatService CreateConversationService(Model model)
DBModelProvider.ZhiPuAI => new GLMChatService(model),
DBModelProvider.Moonshot => new KimiChatService(model),
DBModelProvider.HunYuan => new HunyuanChatService(model),
- DBModelProvider.Sparkdesk => throw new NotImplementedException("Spark model is not implemented"),
+ DBModelProvider.Sparkdesk => new SparkDeskChatService(model),
DBModelProvider.LingYi => new LingYiChatService(model),
DBModelProvider.DeepSeek => new DeepSeekChatService(model),
+ DBModelProvider.xAI => new XAIChatService(model),
+ DBModelProvider.GithubModels => new GithubModelsChatService(model),
_ => throw new NotSupportedException($"Unknown model provider: {modelProvider}")
};
return cs;
diff --git a/src/BE/Services/ChatServices/ChatServiceExtensions.cs b/src/BE/Services/ChatServices/ChatServiceExtensions.cs
index dc61f33f..5dcc9c11 100644
--- a/src/BE/Services/ChatServices/ChatServiceExtensions.cs
+++ b/src/BE/Services/ChatServices/ChatServiceExtensions.cs
@@ -9,7 +9,7 @@ public abstract partial class ChatService
{
public async IAsyncEnumerable ChatStreamedFEProcessed(IReadOnlyList messages, ChatCompletionOptions options, [EnumeratorCancellation] CancellationToken cancellationToken)
{
- ChatMessage[] filteredMessage = FEProcessMessages(messages, options);
+ ChatMessage[] filteredMessage = FEPreprocess(messages, options);
await foreach (InternalChatSegment seg in ChatStreamedSimulated(suggestedStreaming: true, filteredMessage, options, cancellationToken))
{
@@ -48,7 +48,7 @@ public async IAsyncEnumerable ChatStreamedSimulated(bool su
}
}
- private ChatMessage[] FEProcessMessages(IReadOnlyList messages, ChatCompletionOptions options)
+ protected virtual ChatMessage[] FEPreprocess(IReadOnlyList messages, ChatCompletionOptions options)
{
if (!Model.ModelReference.AllowSystemPrompt)
{
@@ -66,10 +66,6 @@ private ChatMessage[] FEProcessMessages(IReadOnlyList messages, Cha
}
ChatMessage[] filteredMessage = messages.Select(m => FilterVision(Model.ModelReference.AllowVision, m)).ToArray();
- if (Model.ModelReference.AllowVision)
- {
- options.MaxOutputTokenCount ??= Model.ModelReference.MaxResponseTokens;
- }
if (!Model.ModelReference.AllowSearch)
{
options.RemoveAllowSearch();
diff --git a/src/BE/Services/ChatServices/Implementations/Azure/JsonAzureConfig.cs b/src/BE/Services/ChatServices/Implementations/Azure/JsonAzureConfig.cs
deleted file mode 100644
index f3d80fb5..00000000
--- a/src/BE/Services/ChatServices/Implementations/Azure/JsonAzureConfig.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using System.Text.Json;
-using System.Text.Json.Serialization;
-
-namespace Chats.BE.Services.ChatServices.Implementations.Azure;
-
-public record JsonAzureApiConfig
-{
- [JsonPropertyName("host")]
- public required string Host { get; init; }
-
- [JsonPropertyName("apiKey")]
- public required string ApiKey { get; init; }
-
- public static JsonAzureApiConfig Parse(string json)
- {
- return JsonSerializer.Deserialize(json)!;
- }
-}
\ No newline at end of file
diff --git a/src/BE/Services/ChatServices/Implementations/Azure/JsonAzureModelConfig.cs b/src/BE/Services/ChatServices/Implementations/Azure/JsonAzureModelConfig.cs
deleted file mode 100644
index 15f77097..00000000
--- a/src/BE/Services/ChatServices/Implementations/Azure/JsonAzureModelConfig.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using System.Text.Json.Serialization;
-
-namespace Chats.BE.Services.ChatServices.Implementations.Azure;
-
-public record JsonAzureModelConfig
-{
- [JsonPropertyName("prompt")]
- public required string Prompt { get; init; }
-
- [JsonPropertyName("temperature")]
- public float? Temperature { get; init; }
-
- [JsonPropertyName("version")]
- public string? Version { get; init; }
-
- [JsonPropertyName("deploymentName")]
- public required string DeploymentName { get; init; }
-}
\ No newline at end of file
diff --git a/src/BE/Services/ChatServices/Implementations/GLM/JsonGLMModelConfig.cs b/src/BE/Services/ChatServices/Implementations/GLM/JsonGLMModelConfig.cs
deleted file mode 100644
index 818a9498..00000000
--- a/src/BE/Services/ChatServices/Implementations/GLM/JsonGLMModelConfig.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using System.Text.Json.Serialization;
-
-namespace Chats.BE.Services.ChatServices.Implementations.GLM;
-
-public record JsonGLMModelConfig
-{
- [JsonPropertyName("prompt")]
- public required string Prompt { get; init; }
-
- [JsonPropertyName("temperature")]
- public required double Temperature { get; init; }
-
- [JsonPropertyName("model")]
- public required string Model { get; init; }
-}
diff --git a/src/BE/Services/ChatServices/Implementations/Hunyuan/JsonHunyuanModelConfig.cs b/src/BE/Services/ChatServices/Implementations/Hunyuan/JsonHunyuanModelConfig.cs
deleted file mode 100644
index bb9853e5..00000000
--- a/src/BE/Services/ChatServices/Implementations/Hunyuan/JsonHunyuanModelConfig.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using System.Text.Json.Serialization;
-
-namespace Chats.BE.Services.ChatServices.Implementations.Hunyuan;
-
-public record JsonHunyuanModelConfig
-{
- [JsonPropertyName("prompt")]
- public required string Prompt { get; init; }
-
- [JsonPropertyName("temperature")]
- public required float? Temperature { get; init; }
-
- [JsonPropertyName("model")]
- public required string Model { get; init; }
-}
\ No newline at end of file
diff --git a/src/BE/Services/ChatServices/Implementations/Kimi/JsonKimiModelConfig.cs b/src/BE/Services/ChatServices/Implementations/Kimi/JsonKimiModelConfig.cs
deleted file mode 100644
index 9e3e13df..00000000
--- a/src/BE/Services/ChatServices/Implementations/Kimi/JsonKimiModelConfig.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using System.Text.Json.Serialization;
-
-namespace Chats.BE.Services.ChatServices.Implementations.Kimi;
-
-public record JsonKimiModelConfig
-{
- [JsonPropertyName("prompt")]
- public required string Prompt { get; init; }
-
- [JsonPropertyName("temperature")]
- public required float Temperature { get; init; }
-}
diff --git a/src/BE/Services/ChatServices/Implementations/Azure/AzureChatService.cs b/src/BE/Services/ChatServices/Implementations/OpenAI/AzureChatService.cs
similarity index 83%
rename from src/BE/Services/ChatServices/Implementations/Azure/AzureChatService.cs
rename to src/BE/Services/ChatServices/Implementations/OpenAI/AzureChatService.cs
index 027532f6..d9c911d9 100644
--- a/src/BE/Services/ChatServices/Implementations/Azure/AzureChatService.cs
+++ b/src/BE/Services/ChatServices/Implementations/OpenAI/AzureChatService.cs
@@ -1,11 +1,10 @@
using Azure.AI.OpenAI;
using Chats.BE.DB;
-using Chats.BE.Services.ChatServices.Implementations.OpenAI;
using OpenAI;
using OpenAI.Chat;
using System.ClientModel;
-namespace Chats.BE.Services.ChatServices.Implementations.Azure;
+namespace Chats.BE.Services.ChatServices.Implementations.OpenAI;
public class AzureChatService(Model model) : OpenAIChatService(model, CreateChatClient(model))
{
diff --git a/src/BE/Services/ChatServices/Implementations/DeepSeek/DeepSeekChatService.cs b/src/BE/Services/ChatServices/Implementations/OpenAI/DeepSeekChatService.cs
similarity index 51%
rename from src/BE/Services/ChatServices/Implementations/DeepSeek/DeepSeekChatService.cs
rename to src/BE/Services/ChatServices/Implementations/OpenAI/DeepSeekChatService.cs
index e178ebda..893faa92 100644
--- a/src/BE/Services/ChatServices/Implementations/DeepSeek/DeepSeekChatService.cs
+++ b/src/BE/Services/ChatServices/Implementations/OpenAI/DeepSeekChatService.cs
@@ -1,6 +1,5 @@
using Chats.BE.DB;
-using Chats.BE.Services.ChatServices.Implementations.OpenAI;
-namespace Chats.BE.Services.ChatServices.Implementations.DeepSeek;
+namespace Chats.BE.Services.ChatServices.Implementations.OpenAI;
public class DeepSeekChatService(Model model) : OpenAIChatService(model, new Uri("https://api.deepseek.com/v1"));
\ No newline at end of file
diff --git a/src/BE/Services/ChatServices/Implementations/GLM/GLMChatService.cs b/src/BE/Services/ChatServices/Implementations/OpenAI/GLMChatService.cs
similarity index 54%
rename from src/BE/Services/ChatServices/Implementations/GLM/GLMChatService.cs
rename to src/BE/Services/ChatServices/Implementations/OpenAI/GLMChatService.cs
index 088451e0..0e62e4dc 100644
--- a/src/BE/Services/ChatServices/Implementations/GLM/GLMChatService.cs
+++ b/src/BE/Services/ChatServices/Implementations/OpenAI/GLMChatService.cs
@@ -1,7 +1,6 @@
using Chats.BE.DB;
-using Chats.BE.Services.ChatServices.Implementations.OpenAI;
-namespace Chats.BE.Services.ChatServices.Implementations.GLM;
+namespace Chats.BE.Services.ChatServices.Implementations.OpenAI;
public class GLMChatService(Model model) : OpenAIChatService(model, new Uri("https://open.bigmodel.cn/api/paas/v4/"))
{
diff --git a/src/BE/Services/ChatServices/Implementations/OpenAI/GithubModelsChatService.cs b/src/BE/Services/ChatServices/Implementations/OpenAI/GithubModelsChatService.cs
new file mode 100644
index 00000000..6a948c36
--- /dev/null
+++ b/src/BE/Services/ChatServices/Implementations/OpenAI/GithubModelsChatService.cs
@@ -0,0 +1,5 @@
+using Chats.BE.DB;
+
+namespace Chats.BE.Services.ChatServices.Implementations.OpenAI;
+
+public class GithubModelsChatService(Model model) : OpenAIChatService(model, new Uri("https://models.inference.ai.azure.com"));
\ No newline at end of file
diff --git a/src/BE/Services/ChatServices/Implementations/OpenAI/JsonOpenAIModelConfig.cs b/src/BE/Services/ChatServices/Implementations/OpenAI/JsonOpenAIModelConfig.cs
deleted file mode 100644
index 44e4d4a1..00000000
--- a/src/BE/Services/ChatServices/Implementations/OpenAI/JsonOpenAIModelConfig.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using System.Text.Json.Serialization;
-
-namespace Chats.BE.Services.ChatServices.Implementations.OpenAI;
-
-public record JsonOpenAIModelConfig
-{
- [JsonPropertyName("prompt")]
- public required string Prompt { get; init; }
-
- [JsonPropertyName("temperature")]
- public float? Temperature { get; init; }
-
- [JsonPropertyName("model")]
- public required string DeploymentName { get; init; }
-}
\ No newline at end of file
diff --git a/src/BE/Services/ChatServices/Implementations/Kimi/KimiChatService.cs b/src/BE/Services/ChatServices/Implementations/OpenAI/KimiChatService.cs
similarity index 51%
rename from src/BE/Services/ChatServices/Implementations/Kimi/KimiChatService.cs
rename to src/BE/Services/ChatServices/Implementations/OpenAI/KimiChatService.cs
index c0a6c907..b909ee68 100644
--- a/src/BE/Services/ChatServices/Implementations/Kimi/KimiChatService.cs
+++ b/src/BE/Services/ChatServices/Implementations/OpenAI/KimiChatService.cs
@@ -1,6 +1,5 @@
using Chats.BE.DB;
-using Chats.BE.Services.ChatServices.Implementations.OpenAI;
-namespace Chats.BE.Services.ChatServices.Implementations.Kimi;
+namespace Chats.BE.Services.ChatServices.Implementations.OpenAI;
public class KimiChatService(Model model) : OpenAIChatService(model, new Uri("https://api.moonshot.cn/v1"));
\ No newline at end of file
diff --git a/src/BE/Services/ChatServices/Implementations/LingYi/LingYiChatService.cs b/src/BE/Services/ChatServices/Implementations/OpenAI/LingYiChatService.cs
similarity index 52%
rename from src/BE/Services/ChatServices/Implementations/LingYi/LingYiChatService.cs
rename to src/BE/Services/ChatServices/Implementations/OpenAI/LingYiChatService.cs
index d777fd27..7380a7fd 100644
--- a/src/BE/Services/ChatServices/Implementations/LingYi/LingYiChatService.cs
+++ b/src/BE/Services/ChatServices/Implementations/OpenAI/LingYiChatService.cs
@@ -1,6 +1,5 @@
using Chats.BE.DB;
-using Chats.BE.Services.ChatServices.Implementations.OpenAI;
-namespace Chats.BE.Services.ChatServices.Implementations.LingYi;
+namespace Chats.BE.Services.ChatServices.Implementations.OpenAI;
public class LingYiChatService(Model model) : OpenAIChatService(model, new Uri("https://api.lingyiwanwu.com/v1"));
diff --git a/src/BE/Services/ChatServices/Implementations/OpenAI/SparkDeskChatService.cs b/src/BE/Services/ChatServices/Implementations/OpenAI/SparkDeskChatService.cs
new file mode 100644
index 00000000..99167ed5
--- /dev/null
+++ b/src/BE/Services/ChatServices/Implementations/OpenAI/SparkDeskChatService.cs
@@ -0,0 +1,18 @@
+using Chats.BE.DB;
+using OpenAI.Chat;
+
+namespace Chats.BE.Services.ChatServices.Implementations.OpenAI;
+
+public class SparkDeskChatService(Model model) : OpenAIChatService(model, new Uri("https://spark-api-open.xf-yun.com/v1"))
+{
+ protected override ChatMessage[] FEPreprocess(IReadOnlyList messages, ChatCompletionOptions options)
+ {
+ ChatMessage[] toReturn = base.FEPreprocess(messages, options);
+ // spark desk enable search is set via tool https://www.xfyun.cn/doc/spark/HTTP%E8%B0%83%E7%94%A8%E6%96%87%E6%A1%A3.html#_3-%E8%AF%B7%E6%B1%82%E8%AF%B4%E6%98%8E
+ // however unfortunately the tool is not available in OpenAI SDK
+ // otherwise, the code should be:
+ // bool enableSearch = options.IsSearchEnabled();
+ // options.Tools.Add(MakeSparkDeskSearchTool(enableSearch));
+ return toReturn;
+ }
+}
\ No newline at end of file
diff --git a/src/BE/Services/ChatServices/Implementations/OpenAI/XAIChatService.cs b/src/BE/Services/ChatServices/Implementations/OpenAI/XAIChatService.cs
new file mode 100644
index 00000000..338018ab
--- /dev/null
+++ b/src/BE/Services/ChatServices/Implementations/OpenAI/XAIChatService.cs
@@ -0,0 +1,5 @@
+using Chats.BE.DB;
+
+namespace Chats.BE.Services.ChatServices.Implementations.OpenAI;
+
+public class XAIChatService(Model model) : OpenAIChatService(model, new Uri("https://api.x.ai/v1"));
\ No newline at end of file
diff --git a/src/scripts/db-migration/2024/20241211-xai-githubmodels.sql b/src/scripts/db-migration/2024/20241211-xai-githubmodels.sql
index b40fc861..f9e00fb9 100644
--- a/src/scripts/db-migration/2024/20241211-xai-githubmodels.sql
+++ b/src/scripts/db-migration/2024/20241211-xai-githubmodels.sql
@@ -1,5 +1,6 @@
insert into ModelProvider values(11, 'x.ai', NULL, 'xai-yourkey');
insert into ModelProvider values(12, 'Github Models', NULL, 'ghp_yourkey');
+update ModelProvider set InitialSecret = '' where id = 8;
insert into ModelReference values
(1100, 11, 'grok-beta', 'grok', 0, 0, 2, 0, 0, 1, 1, 131072, 4096, NULL, 5, 15, 'USD'),