diff --git a/Yi.Abp.Net8/framework/Yi.Framework.Core/Options/SemanticKernelOptions.cs b/Yi.Abp.Net8/framework/Yi.Framework.Core/Options/SemanticKernelOptions.cs new file mode 100644 index 00000000..23833bcb --- /dev/null +++ b/Yi.Abp.Net8/framework/Yi.Framework.Core/Options/SemanticKernelOptions.cs @@ -0,0 +1,8 @@ +namespace Yi.Framework.Core.Options; + +public class SemanticKernelOptions +{ + public List ModelIds { get; set; } + public string Endpoint { get; set; } + public string ApiKey { get; set; } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain/Managers/SemanticKernel/SemanticKernelOptions.cs b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain/Managers/SemanticKernel/SemanticKernelOptions.cs index 15ba372c..afa754d4 100644 --- a/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain/Managers/SemanticKernel/SemanticKernelOptions.cs +++ b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain/Managers/SemanticKernel/SemanticKernelOptions.cs @@ -2,7 +2,7 @@ namespace Yi.Framework.Stock.Domain.Managers.SemanticKernel { public class SemanticKernelOptions { - public string ModelId { get; set; } + public List ModelIds { get; set; } public string Endpoint { get; set; } public string ApiKey { get; set; } } diff --git a/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain/YiFrameworkStockDomainModule.cs b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain/YiFrameworkStockDomainModule.cs index 79b60b3d..35820783 100644 --- a/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain/YiFrameworkStockDomainModule.cs +++ b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain/YiFrameworkStockDomainModule.cs @@ -32,9 +32,10 @@ namespace Yi.Framework.Stock.Domain #pragma warning disable SKEXP0010 // 从配置中获取值 var options = semanticKernelSection.Get(); + //股市优先使用第一个ai模型 services.AddKernel() .AddOpenAIChatCompletion( - modelId: options.ModelId, + modelId: options.ModelIds.FirstOrDefault(), endpoint: new Uri(options.Endpoint), apiKey: options.ApiKey); #pragma warning restore SKEXP0010 diff --git a/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Domain/Managers/AiManager.cs b/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Domain/Managers/AiManager.cs index 44f3a2ca..8fdab588 100644 --- a/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Domain/Managers/AiManager.cs +++ b/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Domain/Managers/AiManager.cs @@ -1,6 +1,9 @@ using System.Collections.Generic; using System.Net; using Microsoft.Extensions.Options; +using Microsoft.SemanticKernel; +using Microsoft.SemanticKernel.ChatCompletion; +using Microsoft.SemanticKernel.Connectors.OpenAI; // using OpenAI; // using OpenAI.Managers; // using OpenAI.ObjectModels; @@ -14,61 +17,46 @@ namespace Yi.Framework.ChatHub.Domain.Managers { public class AiManager : ISingletonDependency { - public AiManager(IOptions options) + private readonly Kernel _kernel; + public AiManager(Kernel kernel) { - // this.OpenAIService = new OpenAIService(new OpenAiOptions() - // { - // ApiKey = options.Value.ApiKey, - // BaseDomain = options.Value.BaseDomain - // }); + _kernel = kernel; } - // private OpenAIService OpenAIService { get; } - public async IAsyncEnumerable ChatAsStreamAsync(string model, List aiChatContextDtos) + public async IAsyncEnumerable ChatAsStreamAsync(string model, List aiChatContextDtos) { - throw new NotImplementedException("准备sk重构"); - yield break; - // if (aiChatContextDtos.Count == 0) - // { - // yield return null; - // } - // - // List messages = aiChatContextDtos.Select(x => - // { - // if (x.AnswererType == AnswererTypeEnum.Ai) - // { - // return ChatMessage.FromSystem(x.Message); - // } - // else - // { - // return ChatMessage.FromUser(x.Message); - // } - // }).ToList(); - // var completionResult = OpenAIService.ChatCompletion.CreateCompletionAsStream(new ChatCompletionCreateRequest - // { - // Messages = messages, - // Model =model - // }); - // - // HttpStatusCode? error = null; - // await foreach (var result in completionResult) - // { - // if (result.Successful) - // { - // yield return result.Choices.FirstOrDefault()?.Message.Content ?? null; - // } - // else - // { - // error = result.HttpStatusCode; - // break; - // } - // - // } - // if (error == HttpStatusCode.PaymentRequired) - // { - // yield return "余额不足,请联系站长充值"; - // - // } + if (aiChatContextDtos.Count == 0) + { + yield return null; + } + var openSettings = new OpenAIPromptExecutionSettings() + { + MaxTokens =1000 + }; + + var chatCompletionService = this._kernel.GetRequiredService(model); + + var history =new ChatHistory(); + foreach (var aiChatContextDto in aiChatContextDtos) + { + if (aiChatContextDto.AnswererType==AnswererTypeEnum.Ai) + { + history.AddSystemMessage(aiChatContextDto.Message); + } + else if(aiChatContextDto.AnswererType==AnswererTypeEnum.User) + { + history.AddUserMessage(aiChatContextDto.Message); + } + } + + var results = chatCompletionService.GetStreamingChatMessageContentsAsync( + chatHistory: history, + executionSettings: openSettings, + kernel: _kernel); + await foreach (var result in results) + { + yield return result.Content; + } } } } diff --git a/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Domain/Yi.Framework.ChatHub.Domain.csproj b/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Domain/Yi.Framework.ChatHub.Domain.csproj index de7bf76d..b158ec5e 100644 --- a/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Domain/Yi.Framework.ChatHub.Domain.csproj +++ b/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Domain/Yi.Framework.ChatHub.Domain.csproj @@ -8,7 +8,7 @@ - + diff --git a/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Domain/YiFrameworkChatHubDomainModule.cs b/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Domain/YiFrameworkChatHubDomainModule.cs index 5554c43e..02a4b90e 100644 --- a/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Domain/YiFrameworkChatHubDomainModule.cs +++ b/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Domain/YiFrameworkChatHubDomainModule.cs @@ -1,6 +1,10 @@ -using Volo.Abp.Domain; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.SemanticKernel; +using Volo.Abp.Domain; using Yi.Framework.Caching.FreeRedis; using Yi.Framework.ChatHub.Domain.Shared; +using Yi.Framework.Core.Options; namespace Yi.Framework.ChatHub.Domain @@ -13,9 +17,27 @@ namespace Yi.Framework.ChatHub.Domain )] public class YiFrameworkChatHubDomainModule : AbpModule { - public override async Task OnPostApplicationInitializationAsync(ApplicationInitializationContext context) + public override void ConfigureServices(ServiceConfigurationContext context) { - + var configuration = context.Services.GetConfiguration(); + var services = context.Services; + + // 配置绑定 + var semanticKernelSection = configuration.GetSection("SemanticKernel"); + services.Configure(configuration.GetSection("SemanticKernel")); +#pragma warning disable SKEXP0010 + // 从配置中获取值 + var options = semanticKernelSection.Get(); + foreach (var optionsModelId in options.ModelIds) + { + services.AddKernel() + .AddOpenAIChatCompletion( + serviceId: optionsModelId, + modelId: optionsModelId, + endpoint: new Uri(options.Endpoint), + apiKey: options.ApiKey); + } +#pragma warning restore SKEXP0010 } } } \ No newline at end of file diff --git a/Yi.Abp.Net8/src/Yi.Abp.Web/appsettings.json b/Yi.Abp.Net8/src/Yi.Abp.Web/appsettings.json index 15a8d63e..1b1eee0e 100644 --- a/Yi.Abp.Net8/src/Yi.Abp.Web/appsettings.json +++ b/Yi.Abp.Net8/src/Yi.Abp.Web/appsettings.json @@ -103,18 +103,10 @@ //开启定时数据库备份 "EnableDataBaseBackup": false }, - - - //OpenAi - "AiOptions": { - "ApiKey": "", - "BaseDomain": "" - }, - - + //语义内核 "SemanticKernel": { - "ModelId": "gpt-4o", + "ModelIds": ["gpt-4o"], "Endpoint": "https://xxx.com/v1", "ApiKey": "sk-xxxxxx" }