feat: 完成功能

This commit is contained in:
ccnetcore
2025-07-17 23:52:00 +08:00
parent c5b0f69b51
commit 30678dbbb4
7 changed files with 43 additions and 29 deletions

View File

@@ -258,7 +258,7 @@ public class ThorChatCompletionsRequest
[JsonPropertyName("response_format")] [JsonPropertyName("response_format")]
public ThorResponseFormat? ResponseFormat { get; set; } public ThorResponseFormat? ResponseFormat { get; set; }
[JsonPropertyName("metadata")] public Dictionary<string, string> Metadata { get; set; } [JsonPropertyName("metadata")] public Dictionary<string, string>? Metadata { get; set; }
/// <summary> /// <summary>
/// 此功能处于测试阶段。 /// 此功能处于测试阶段。
@@ -273,9 +273,9 @@ public class ThorChatCompletionsRequest
/// 代表您的最终用户的唯一标识符,可以帮助 OpenAI 监控和检测滥用行为。 /// 代表您的最终用户的唯一标识符,可以帮助 OpenAI 监控和检测滥用行为。
/// </summary> /// </summary>
[JsonPropertyName("user")] [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; }
/// <summary> /// <summary>
/// 参数验证 /// 参数验证

View File

@@ -92,6 +92,7 @@ public class AiChatService : ApplicationService
/// 发送消息 /// 发送消息
/// </summary> /// </summary>
/// <param name="input"></param> /// <param name="input"></param>
/// <param name="sessionId"></param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
public async Task PostSendAsync([FromBody] ThorChatCompletionsRequest input, [FromQuery] Guid sessionId, public async Task PostSendAsync([FromBody] ThorChatCompletionsRequest input, [FromQuery] Guid sessionId,
CancellationToken cancellationToken) CancellationToken cancellationToken)

View File

@@ -50,5 +50,10 @@ public class AiModelDescribe
/// <summary> /// <summary>
/// 额外url /// 额外url
/// </summary> /// </summary>
public string? ExtraUrl { get; set; } public string? AppExtraUrl { get; set; }
/// <summary>
/// 模型额外信息
/// </summary>
public string? ModelExtraInfo { get; set; }
} }

View File

@@ -12,18 +12,19 @@ namespace Yi.Framework.AiHub.Domain.AiGateWay.Impl.ThorAzureDatabricks.Chats;
public class AzureDatabricksChatCompletionsService(ILogger<AzureDatabricksChatCompletionsService> logger) public class AzureDatabricksChatCompletionsService(ILogger<AzureDatabricksChatCompletionsService> logger)
: IChatCompletionService : 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 // This method should return the appropriate URL for the Azure Databricks API
// based on the provided options and model. // based on the provided options and model.
// For now, we will return a placeholder URL. // 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<ThorChatCompletionsResponse> CompleteChatStreamAsync(AiModelDescribe options, ThorChatCompletionsRequest chatCompletionCreate, public async IAsyncEnumerable<ThorChatCompletionsResponse> CompleteChatStreamAsync(AiModelDescribe options,
ThorChatCompletionsRequest chatCompletionCreate,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
var address = GetAddress(options, chatCompletionCreate.Model); var address = GetAddress(options);
using var openai = using var openai =
Activity.Current?.Source.StartActivity("OpenAI 对话流式补全"); Activity.Current?.Source.StartActivity("OpenAI 对话流式补全");
@@ -138,10 +139,11 @@ public class AzureDatabricksChatCompletionsService(ILogger<AzureDatabricksChatCo
} }
} }
public async Task<ThorChatCompletionsResponse> CompleteChatAsync(AiModelDescribe options, ThorChatCompletionsRequest chatCompletionCreate, public async Task<ThorChatCompletionsResponse> CompleteChatAsync(AiModelDescribe options,
ThorChatCompletionsRequest chatCompletionCreate,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
var address = GetAddress(options, chatCompletionCreate.Model); var address = GetAddress(options);
using var openai = using var openai =
Activity.Current?.Source.StartActivity("OpenAI 对话补全"); Activity.Current?.Source.StartActivity("OpenAI 对话补全");
@@ -168,7 +170,8 @@ public class AzureDatabricksChatCompletionsService(ILogger<AzureDatabricksChatCo
if (response.StatusCode >= HttpStatusCode.BadRequest) if (response.StatusCode >= HttpStatusCode.BadRequest)
{ {
var error = await response.Content.ReadAsStringAsync(cancellationToken).ConfigureAwait(false); 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); response.StatusCode, error);
throw new BusinessException("OpenAI对话异常", response.StatusCode.ToString()); throw new BusinessException("OpenAI对话异常", response.StatusCode.ToString());

View File

@@ -18,47 +18,47 @@ public static class AzureOpenAIFactory
public static string GetAudioTranscriptionsAddress(AiModelDescribe options, string model) 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) 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) 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) 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) 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; const AzureOpenAIClientOptions.ServiceVersion version = AzureOpenAIClientOptions.ServiceVersion.V2024_06_01;

View File

@@ -45,4 +45,8 @@ public class AiModelEntity : Entity<Guid>, IOrderNum,ISoftDelete
/// </summary> /// </summary>
public Guid AiAppId { get; set; } public Guid AiAppId { get; set; }
/// <summary>
/// 额外信息
/// </summary>
public string? ExtraInfo { get; set; }
} }

View File

@@ -56,7 +56,8 @@ public class AiGateWayManager : DomainService
ModelId = model.ModelId, ModelId = model.ModelId,
ModelName = model.Name, ModelName = model.Name,
Description = model.Description, Description = model.Description,
ExtraUrl = app.ExtraUrl AppExtraUrl = app.ExtraUrl,
ModelExtraInfo = model.ExtraInfo
}; };
} }
} }