From 30678dbbb4ff05d294588e817cbe051d8e27a1d4 Mon Sep 17 00:00:00 2001 From: ccnetcore Date: Thu, 17 Jul 2025 23:52:00 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Dtos/OpenAi/ThorChatCompletionsRequest.cs | 6 ++--- .../Services/AiChatService.cs | 1 + .../Dtos/AiModelDescribe.cs | 7 ++++- .../AzureDatabricksChatCompletionsService.cs | 23 +++++++++------- .../ThorAzureOpenAI/AzureOpenAIFactory.cs | 26 +++++++++---------- .../Entities/Model/AiModelEntity.cs | 6 ++++- .../Managers/AiGateWayManager.cs | 3 ++- 7 files changed, 43 insertions(+), 29 deletions(-) diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/OpenAi/ThorChatCompletionsRequest.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/OpenAi/ThorChatCompletionsRequest.cs index 33891678..a3fb0c2c 100644 --- a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/OpenAi/ThorChatCompletionsRequest.cs +++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/OpenAi/ThorChatCompletionsRequest.cs @@ -258,7 +258,7 @@ public class ThorChatCompletionsRequest [JsonPropertyName("response_format")] public ThorResponseFormat? ResponseFormat { get; set; } - [JsonPropertyName("metadata")] public Dictionary Metadata { get; set; } + [JsonPropertyName("metadata")] public Dictionary? Metadata { get; set; } /// /// 此功能处于测试阶段。 @@ -273,9 +273,9 @@ public class ThorChatCompletionsRequest /// 代表您的最终用户的唯一标识符,可以帮助 OpenAI 监控和检测滥用行为。 /// [JsonPropertyName("user")] - public string User { get; set; } + public string? User { get; set; } - [JsonPropertyName("thinking")] public ThorChatClaudeThinking Thinking { get; set; } + [JsonPropertyName("thinking")] public ThorChatClaudeThinking? Thinking { get; set; } /// /// 参数验证 diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/AiChatService.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/AiChatService.cs index 503565ee..c4c64312 100644 --- a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/AiChatService.cs +++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/AiChatService.cs @@ -92,6 +92,7 @@ public class AiChatService : ApplicationService /// 发送消息 /// /// + /// /// public async Task PostSendAsync([FromBody] ThorChatCompletionsRequest input, [FromQuery] Guid sessionId, CancellationToken cancellationToken) diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain.Shared/Dtos/AiModelDescribe.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain.Shared/Dtos/AiModelDescribe.cs index 560a3991..636feb70 100644 --- a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain.Shared/Dtos/AiModelDescribe.cs +++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain.Shared/Dtos/AiModelDescribe.cs @@ -50,5 +50,10 @@ public class AiModelDescribe /// /// 额外url /// - public string? ExtraUrl { get; set; } + public string? AppExtraUrl { get; set; } + + /// + /// 模型额外信息 + /// + public string? ModelExtraInfo { get; set; } } \ No newline at end of file diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/AiGateWay/Impl/ThorAzureDatabricks/Chats/AzureDatabricksChatCompletionsService.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/AiGateWay/Impl/ThorAzureDatabricks/Chats/AzureDatabricksChatCompletionsService.cs index fcb53d14..4e31e1b0 100644 --- a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/AiGateWay/Impl/ThorAzureDatabricks/Chats/AzureDatabricksChatCompletionsService.cs +++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/AiGateWay/Impl/ThorAzureDatabricks/Chats/AzureDatabricksChatCompletionsService.cs @@ -12,18 +12,19 @@ namespace Yi.Framework.AiHub.Domain.AiGateWay.Impl.ThorAzureDatabricks.Chats; public class AzureDatabricksChatCompletionsService(ILogger logger) : IChatCompletionService { - private string GetAddress(AiModelDescribe? options, string model) + private string GetAddress(AiModelDescribe? options) { // This method should return the appropriate URL for the Azure Databricks API // based on the provided options and model. // For now, we will return a placeholder URL. - return $"{options?.Endpoint.TrimEnd('/')}/serving-endpoints/{model}/invocations"; + return $"{options?.Endpoint.TrimEnd('/')}/serving-endpoints/{options.ModelExtraInfo}/invocations"; } - - public async IAsyncEnumerable CompleteChatStreamAsync(AiModelDescribe options, ThorChatCompletionsRequest chatCompletionCreate, + + public async IAsyncEnumerable CompleteChatStreamAsync(AiModelDescribe options, + ThorChatCompletionsRequest chatCompletionCreate, CancellationToken cancellationToken) { - var address = GetAddress(options, chatCompletionCreate.Model); + var address = GetAddress(options); using var openai = Activity.Current?.Source.StartActivity("OpenAI 对话流式补全"); @@ -138,11 +139,12 @@ public class AzureDatabricksChatCompletionsService(ILogger CompleteChatAsync(AiModelDescribe options, ThorChatCompletionsRequest chatCompletionCreate, + public async Task CompleteChatAsync(AiModelDescribe options, + ThorChatCompletionsRequest chatCompletionCreate, CancellationToken cancellationToken) { - var address = GetAddress(options, chatCompletionCreate.Model); - + var address = GetAddress(options); + using var openai = Activity.Current?.Source.StartActivity("OpenAI 对话补全"); @@ -168,9 +170,10 @@ public class AzureDatabricksChatCompletionsService(ILogger= HttpStatusCode.BadRequest) { var error = await response.Content.ReadAsStringAsync(cancellationToken).ConfigureAwait(false); - logger.LogError("OpenAI对话异常 请求地址:{Address}, StatusCode: {StatusCode} Response: {Response}", options.Endpoint, + logger.LogError("OpenAI对话异常 请求地址:{Address}, StatusCode: {StatusCode} Response: {Response}", + options.Endpoint, response.StatusCode, error); - + throw new BusinessException("OpenAI对话异常", response.StatusCode.ToString()); } diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/AiGateWay/Impl/ThorAzureOpenAI/AzureOpenAIFactory.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/AiGateWay/Impl/ThorAzureOpenAI/AzureOpenAIFactory.cs index 330999c7..220f6dac 100644 --- a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/AiGateWay/Impl/ThorAzureOpenAI/AzureOpenAIFactory.cs +++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/AiGateWay/Impl/ThorAzureOpenAI/AzureOpenAIFactory.cs @@ -18,47 +18,47 @@ public static class AzureOpenAIFactory public static string GetAudioTranscriptionsAddress(AiModelDescribe options, string model) { - if (string.IsNullOrEmpty(options.ExtraUrl)) + if (string.IsNullOrEmpty(options.AppExtraUrl)) { - options.ExtraUrl = "2025-03-01-preview"; + options.AppExtraUrl = "2025-03-01-preview"; } - return string.Format(AudioTranscriptions, options.Endpoint.TrimEnd('/'), model, options.ExtraUrl); + return string.Format(AudioTranscriptions, options.Endpoint.TrimEnd('/'), model, options.AppExtraUrl); } public static string GetAudioSpeechAddress(AiModelDescribe options, string model) { - if (string.IsNullOrEmpty(options.ExtraUrl)) + if (string.IsNullOrEmpty(options.AppExtraUrl)) { - options.ExtraUrl = "2025-03-01-preview"; + options.AppExtraUrl = "2025-03-01-preview"; } - return string.Format(AudioSpeechTemplate, options.Endpoint.TrimEnd('/'), model, options.ExtraUrl); + return string.Format(AudioSpeechTemplate, options.Endpoint.TrimEnd('/'), model, options.AppExtraUrl); } public static string GetAddress(AiModelDescribe options, string model) { - if (string.IsNullOrEmpty(options.ExtraUrl)) + if (string.IsNullOrEmpty(options.AppExtraUrl)) { - options.ExtraUrl = "2025-03-01-preview"; + options.AppExtraUrl = "2025-03-01-preview"; } - return string.Format(AddressTemplate, options.Endpoint.TrimEnd('/'), model, options.ExtraUrl); + return string.Format(AddressTemplate, options.Endpoint.TrimEnd('/'), model, options.AppExtraUrl); } public static string GetEditImageAddress(AiModelDescribe options, string model) { - if (string.IsNullOrEmpty(options.ExtraUrl)) + if (string.IsNullOrEmpty(options.AppExtraUrl)) { - options.ExtraUrl = "2025-03-01-preview"; + options.AppExtraUrl = "2025-03-01-preview"; } - return string.Format(EditImageAddressTemplate, options.Endpoint.TrimEnd('/'), model, options.ExtraUrl); + return string.Format(EditImageAddressTemplate, options.Endpoint.TrimEnd('/'), model, options.AppExtraUrl); } public static AzureOpenAIClient CreateClient(AiModelDescribe options) { - return Clients.GetOrAdd($"{options.ApiKey}_{options.Endpoint}_{options.ExtraUrl}", (_) => + return Clients.GetOrAdd($"{options.ApiKey}_{options.Endpoint}_{options.AppExtraUrl}", (_) => { const AzureOpenAIClientOptions.ServiceVersion version = AzureOpenAIClientOptions.ServiceVersion.V2024_06_01; diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Entities/Model/AiModelEntity.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Entities/Model/AiModelEntity.cs index d77967f9..ba363fda 100644 --- a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Entities/Model/AiModelEntity.cs +++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Entities/Model/AiModelEntity.cs @@ -44,5 +44,9 @@ public class AiModelEntity : Entity, IOrderNum,ISoftDelete /// ai应用id /// public Guid AiAppId { get; set; } - + + /// + /// 额外信息 + /// + public string? ExtraInfo { get; set; } } \ No newline at end of file diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/AiGateWayManager.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/AiGateWayManager.cs index 7e8c05d2..64cfc457 100644 --- a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/AiGateWayManager.cs +++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/AiGateWayManager.cs @@ -56,7 +56,8 @@ public class AiGateWayManager : DomainService ModelId = model.ModelId, ModelName = model.Name, Description = model.Description, - ExtraUrl = app.ExtraUrl + AppExtraUrl = app.ExtraUrl, + ModelExtraInfo = model.ExtraInfo }; } }