diff --git a/Admin.NET/Admin.NET.Application/Configuration/Ai.json b/Admin.NET/Admin.NET.Application/Configuration/Ai.json index f029ad39..1c86a47f 100644 --- a/Admin.NET/Admin.NET.Application/Configuration/Ai.json +++ b/Admin.NET/Admin.NET.Application/Configuration/Ai.json @@ -1,191 +1,191 @@ { - "LLM": { - "ModelProvider": "DeepSeek", //当前使用模型,取值为下面Providers的ProductName - "InitSystemChatMessage": "你是一个经验丰富的Admin.pro人工智能助手,请根据用户的问题给出准确的回答。- **回答请以markdown格式输出**;- **适当加入emoji表达人类情感,使内容更易于理解与传播。**", - "UserCanSwitchLLM": true, //是否可以切换模型 - "TargetCount": 10, //用于消息截取配置,当消息超过TargetCount+ThresholdCount数量时,会进行截取操作,以避免token超出限制 - "ThresholdCount": 3, //用于消息截取配置,当消息超过TargetCount+ThresholdCount数量时,会进行截取操作,以避免token超出限制 - "IsUserProxy": false, //如果使用的是openai,claude等国内未授权的模型,并且在国内运行,请设置为true,否则设置为false,避免这些LLM被国内防火墙拦截 - "ProxyUrl": "http://127.0.0.1:10809", //如果IsUserProxy为true,请设置代理地址,否则设置为空 - "LogEnabled": false, //是否开启日志,如果开启,会记录用户与大模型交互的日志,以http协议的形式展示. - "Providers": [ - { - "ProductName": "OpenAI", //LLM产品名称 - "LLMType": "OpenAI_Compatible", - "ApiKey": "sk-proj-88vztr-6Tf6LwmtpvqAYQR-5q4XJaLW-6vmeeVunhycpsUuKMLGLJAhDGyodovkVJqXLba-HV_ST3BlbkFJghWQCgwt68t5Fv4AZSwoY0MX2K2c-HQPbBQLQYOrGcWfhX4yM9OJtqMYAmPedko4RRolifks8A", - "ApiEndpoint": "https://api.openai.com/v1", - "ChatCompletion": { - "ModelId": "gpt-4o", - "SupportModelIds": [ - "gpt-4o", - "gpt-4o-mini" - ] - }, - "Embedding": { - "ModelId": "text-embedding-ada-002", - "SupportModelIds": [ - "text-embedding-ada-002", - "text-embedding-3-small" - ] - } - }, - { - "ProductName": "Azure", - "LLMType": "AzureOpenAI", - "ApiKey": "sk-proj-88vztr-6Tf6LwmtpvqAYQR-5q4XJaLW-6vmeeVunhycpsUuKMLGLJAhDGyodovkVJqXLba-HV_ST3BlbkFJghWQCgwt68t5Fv4AZSwoY0MX2K2c-HQPbBQLQYOrGcWfhX4yM9OJtqMYAmPedko4RRolifks8A", - "ApiEndpoint": "https://my-openapi.openai.azure.com/", - "ChatCompletion": { - "ModelId": "gpt-4o", - "SupportModelIds": [ - "gpt-4o", - "gpt-4o-mini" - ] - }, - "Embedding": { - "ModelId": "text-embedding-ada-002", - "SupportModelIds": [ - "text-embedding-ada-002", - "text-embedding-3-small" - ] - } - }, - { - "ProductName": "DeepSeek", - "LLMType": "OpenAI_Compatible", - "ApiKey": "sk-c1f8ca9b3b524d65a817200681f3241e", - "ApiEndpoint": "https://api.deepseek.com/v1", - "ChatCompletion": { - "ModelId": "deepseek-chat", - "SupportModelIds": [ - "deepseek-chat", - "deepseek-reasoner" - ] - } - }, - { - "ProductName": "google", - "LLMType": "google", - "ApiKey": "sk-proj-88vztr-6Tf6LwmtpvqAYQR-5q4XJaLW-6vmeeVunhycpsUuKMLGLJAhDGyodovkVJqXLba-HV_ST3BlbkFJghWQCgwt68t5Fv4AZSwoY0MX2K2c-HQPbBQLQYOrGcWfhX4yM9OJtqMYAmPedko4RRolifks8A", - "ApiEndpoint": "https://api.openai.com", - "ChatCompletion": { - "ModelId": "gemini-1.5-flash", - "SupportModelIds": [ - "gemini-1.5-flash", - "gemini-1.5-pro" - ] - }, - "Embedding": { - "ModelId": "text-embedding-3-small", - "SupportModelIds": [ - "text-embedding-3-small", - "text-embedding-3-large" - ] - } - }, - { - "ProductName": "Ollama", - "LLMType": "Ollama", - "ApiKey": "sk-proj-88vztr-6Tf6LwmtpvqAYQR-5q4XJaLW-6vmeeVunhycpsUuKMLGLJAhDGyodovkVJqXLba-HV_ST3BlbkFJghWQCgwt68t5Fv4AZSwoY0MX2K2c-HQPbBQLQYOrGcWfhX4yM9OJtqMYAmPedko4RRolifks8A", - "ApiEndpoint": "http://127.0.0.1:11434", - "ChatCompletion": { - "ModelId": "llama3.1", - "SupportModelIds": [ - "llama3.1", - "llama3.1:8b", - "llama3.1:70b" - ] - } - }, - { - "ProductName": "OpenRouter", - "LLMType": "OpenAI_Compatible", - "ApiKey": "sk-proj-88vztr-6Tf6LwmtpvqAYQR-5q4XJaLW-6vmeeVunhycpsUuKMLGLJAhDGyodovkVJqXLba-HV_ST3BlbkFJghWQCgwt68t5Fv4AZSwoY0MX2K2c-HQPbBQLQYOrGcWfhX4yM9OJtqMYAmPedko4RRolifks8A", - "ApiEndpoint": "https://openrouter.ai/api/v1", - "ChatCompletion": { - "ModelId": "deepseek/deepseek-r1:free", - "SupportModelIds": [ - "deepseek/deepseek-chat-v3-0324:free", - "deepseek/deepseek-r1:free", - "google/gemini-2.0-flash-exp:free", - "google/gemma-3-27b-it:free" - ] - } - }, - { - "ProductName": "Claude", - "LLMType": "Claude", - "ApiKey": "sk-ant-api03-0000000000000000000000000000000000000000000000000000000000000000", - "ApiEndpoint": "https://api.anthropic.com/v1", - "Region": "us-east-1", - "ApiSecret": "sk-ant-api03-0000000000000000000000000000000000000000000000000000000000000000", - "ChatCompletion": { - "ModelId": "claude-3-7-sonnet-20250219", - "SupportModelIds": [ - "claude-3-5-sonnet-20240620", - "claude-3-7-sonnet-20250219", - "claude-opus-4-20250514", - "claude-sonnet-4-20250514" - ] - } - }, - { - "ProductName": "智谱", - "LLMType": "OpenAI_Compatible", - "ApiKey": "cxxxxxxxxxx", - "ApiEndpoint": "https://open.bigmodel.cn/api/paas/v4", - "ChatCompletion": { - "ModelId": "glm-4", - "SupportModelIds": [ - "glm-4", - "glm-4-6b" - ] - } - }, - { - "ProductName": "月之暗面", - "LLMType": "OpenAI_Compatible", - "ApiKey": "sk-ant-api03-0000000000000000000000000000000000000000000000000000000000000000", - "ApiEndpoint": "https://api.moonshot.cn/v1", - "ChatCompletion": { - "ModelId": "moonshot-v1-8k", - "SupportModelIds": [ - "moonshot-v1-8k", - "moonshot-v1-16k", - "moonshot-v1-128k" - ] - } - } - ] - }, - "LLMCustom": { - "LLMType": "openrouter", - "ApiKey": "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", - "BaseUrl": "https://openrouter.ai/api/v1/chat/completions", - "InitSystemChatMessage": "你是一个经验丰富的AI助手,请根据用户的问题给出最准确的回答,每个回答都以markdown格式输出", - "InitSystemPromptMessage": "你是一个经验丰富的AI助手,请根据用户的问题给出最准确的回答", - "CanUserSwitchLLM": false, - "ModelProvider": "DeepSeek: R1", - "MaxHistory": 10, - "Timeout": 30, - "IsUserProxy": true, - "ProxyUrl": "http://127.0.0.1:10809", - "SupportLLMList": [ - { - "Desciption": "OpenAI: GPT-3.5 Turbo", - "Model": "openai/gpt-3.5-turbo" - }, - { - "Desciption": "Google: LearnLM 1.5 Pro", - "Model": "google/learnlm-1.5-pro-experimental:free" - }, - { - "Desciption": "Meta: Llama 3.2 11B", - "Model": "meta-llama/llama-3.2-11b-vision-instruct:free" - }, - { - "Desciption": "DeepSeek: R1", - "Model": "deepseek/deepseek-r1-distill-llama-70b:free" - } - ] - } + "LLM": { + "ModelProvider": "DeepSeek", //当前使用模型,取值为下面Providers的ProductName + "InitSystemChatMessage": "你是一个经验丰富的Admin.pro人工智能助手,请根据用户的问题给出准确的回答。- **回答请以markdown格式输出**;- **适当加入emoji表达人类情感,使内容更易于理解与传播。**", + "UserCanSwitchLLM": true, //是否可以切换模型 + "TargetCount": 10, //用于消息截取配置,当消息超过TargetCount+ThresholdCount数量时,会进行截取操作,以避免token超出限制 + "ThresholdCount": 3, //用于消息截取配置,当消息超过TargetCount+ThresholdCount数量时,会进行截取操作,以避免token超出限制 + "IsUserProxy": false, //如果使用的是openai,claude等国内未授权的模型,并且在国内运行,请设置为true,否则设置为false,避免这些LLM被国内防火墙拦截 + "ProxyUrl": "http://127.0.0.1:10809", //如果IsUserProxy为true,请设置代理地址,否则设置为空 + "LogEnabled": false, //是否开启日志,如果开启,会记录用户与大模型交互的日志,以http协议的形式展示. + "Providers": [ + { + "ProductName": "OpenAI", //LLM产品名称 + "LLMType": "OpenAI_Compatible", + "ApiKey": "sk-proj-88vztr-6Tf6LwmtpvqAYQR-5q4XJaLW-6vmeeVunhycpsUuKMLGLJAhDGyodovkVJqXLba-HV_ST3BlbkFJghWQCgwt68t5Fv4AZSwoY0MX2K2c-HQPbBQLQYOrGcWfhX4yM9OJtqMYAmPedko4RRolifks8A", + "ApiEndpoint": "https://api.openai.com/v1", + "ChatCompletion": { + "ModelId": "gpt-4o", + "SupportModelIds": [ + "gpt-4o", + "gpt-4o-mini" + ] + }, + "Embedding": { + "ModelId": "text-embedding-ada-002", + "SupportModelIds": [ + "text-embedding-ada-002", + "text-embedding-3-small" + ] + } + }, + { + "ProductName": "Azure", + "LLMType": "AzureOpenAI", + "ApiKey": "sk-proj-88vztr-6Tf6LwmtpvqAYQR-5q4XJaLW-6vmeeVunhycpsUuKMLGLJAhDGyodovkVJqXLba-HV_ST3BlbkFJghWQCgwt68t5Fv4AZSwoY0MX2K2c-HQPbBQLQYOrGcWfhX4yM9OJtqMYAmPedko4RRolifks8A", + "ApiEndpoint": "https://my-openapi.openai.azure.com/", + "ChatCompletion": { + "ModelId": "gpt-4o", + "SupportModelIds": [ + "gpt-4o", + "gpt-4o-mini" + ] + }, + "Embedding": { + "ModelId": "text-embedding-ada-002", + "SupportModelIds": [ + "text-embedding-ada-002", + "text-embedding-3-small" + ] + } + }, + { + "ProductName": "DeepSeek", + "LLMType": "OpenAI_Compatible", + "ApiKey": "sk-c1f8ca9b3b524d65a817200681f3241e", + "ApiEndpoint": "https://api.deepseek.com/v1", + "ChatCompletion": { + "ModelId": "deepseek-chat", + "SupportModelIds": [ + "deepseek-chat", + "deepseek-reasoner" + ] + } + }, + { + "ProductName": "google", + "LLMType": "google", + "ApiKey": "sk-proj-88vztr-6Tf6LwmtpvqAYQR-5q4XJaLW-6vmeeVunhycpsUuKMLGLJAhDGyodovkVJqXLba-HV_ST3BlbkFJghWQCgwt68t5Fv4AZSwoY0MX2K2c-HQPbBQLQYOrGcWfhX4yM9OJtqMYAmPedko4RRolifks8A", + "ApiEndpoint": "https://api.openai.com", + "ChatCompletion": { + "ModelId": "gemini-1.5-flash", + "SupportModelIds": [ + "gemini-1.5-flash", + "gemini-1.5-pro" + ] + }, + "Embedding": { + "ModelId": "text-embedding-3-small", + "SupportModelIds": [ + "text-embedding-3-small", + "text-embedding-3-large" + ] + } + }, + { + "ProductName": "Ollama", + "LLMType": "Ollama", + "ApiKey": "sk-proj-88vztr-6Tf6LwmtpvqAYQR-5q4XJaLW-6vmeeVunhycpsUuKMLGLJAhDGyodovkVJqXLba-HV_ST3BlbkFJghWQCgwt68t5Fv4AZSwoY0MX2K2c-HQPbBQLQYOrGcWfhX4yM9OJtqMYAmPedko4RRolifks8A", + "ApiEndpoint": "http://127.0.0.1:11434", + "ChatCompletion": { + "ModelId": "llama3.1", + "SupportModelIds": [ + "llama3.1", + "llama3.1:8b", + "llama3.1:70b" + ] + } + }, + { + "ProductName": "OpenRouter", + "LLMType": "OpenAI_Compatible", + "ApiKey": "sk-proj-88vztr-6Tf6LwmtpvqAYQR-5q4XJaLW-6vmeeVunhycpsUuKMLGLJAhDGyodovkVJqXLba-HV_ST3BlbkFJghWQCgwt68t5Fv4AZSwoY0MX2K2c-HQPbBQLQYOrGcWfhX4yM9OJtqMYAmPedko4RRolifks8A", + "ApiEndpoint": "https://openrouter.ai/api/v1", + "ChatCompletion": { + "ModelId": "deepseek/deepseek-r1:free", + "SupportModelIds": [ + "deepseek/deepseek-chat-v3-0324:free", + "deepseek/deepseek-r1:free", + "google/gemini-2.0-flash-exp:free", + "google/gemma-3-27b-it:free" + ] + } + }, + { + "ProductName": "Claude", + "LLMType": "Claude", + "ApiKey": "sk-ant-api03-0000000000000000000000000000000000000000000000000000000000000000", + "ApiEndpoint": "https://api.anthropic.com/v1", + "Region": "us-east-1", + "ApiSecret": "sk-ant-api03-0000000000000000000000000000000000000000000000000000000000000000", + "ChatCompletion": { + "ModelId": "claude-3-7-sonnet-20250219", + "SupportModelIds": [ + "claude-3-5-sonnet-20240620", + "claude-3-7-sonnet-20250219", + "claude-opus-4-20250514", + "claude-sonnet-4-20250514" + ] + } + }, + { + "ProductName": "智谱", + "LLMType": "OpenAI_Compatible", + "ApiKey": "cxxxxxxxxxx", + "ApiEndpoint": "https://open.bigmodel.cn/api/paas/v4", + "ChatCompletion": { + "ModelId": "glm-4", + "SupportModelIds": [ + "glm-4", + "glm-4-6b" + ] + } + }, + { + "ProductName": "月之暗面", + "LLMType": "OpenAI_Compatible", + "ApiKey": "sk-ant-api03-0000000000000000000000000000000000000000000000000000000000000000", + "ApiEndpoint": "https://api.moonshot.cn/v1", + "ChatCompletion": { + "ModelId": "moonshot-v1-8k", + "SupportModelIds": [ + "moonshot-v1-8k", + "moonshot-v1-16k", + "moonshot-v1-128k" + ] + } + } + ] + }, + "LLMCustom": { + "LLMType": "openrouter", + "ApiKey": "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", + "BaseUrl": "https://openrouter.ai/api/v1/chat/completions", + "InitSystemChatMessage": "你是一个经验丰富的AI助手,请根据用户的问题给出最准确的回答,每个回答都以markdown格式输出", + "InitSystemPromptMessage": "你是一个经验丰富的AI助手,请根据用户的问题给出最准确的回答", + "CanUserSwitchLLM": false, + "ModelProvider": "DeepSeek: R1", + "MaxHistory": 10, + "Timeout": 30, + "IsUserProxy": true, + "ProxyUrl": "http://127.0.0.1:10809", + "SupportLLMList": [ + { + "Desciption": "OpenAI: GPT-3.5 Turbo", + "Model": "openai/gpt-3.5-turbo" + }, + { + "Desciption": "Google: LearnLM 1.5 Pro", + "Model": "google/learnlm-1.5-pro-experimental:free" + }, + { + "Desciption": "Meta: Llama 3.2 11B", + "Model": "meta-llama/llama-3.2-11b-vision-instruct:free" + }, + { + "Desciption": "DeepSeek: R1", + "Model": "deepseek/deepseek-r1-distill-llama-70b:free" + } + ] + } } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Application/Configuration/Database.json b/Admin.NET/Admin.NET.Application/Configuration/Database.json index 15bb20bf..7ea0723b 100644 --- a/Admin.NET/Admin.NET.Application/Configuration/Database.json +++ b/Admin.NET/Admin.NET.Application/Configuration/Database.json @@ -34,7 +34,7 @@ }, "TableSettings": { "EnableInitTable": true, // 启用表初始化(若实体没有变化建议关闭) - "EnableIncreTable": true // 启用表增量更新(只更新贴了特性[IncreTable]的实体表) + "EnableIncreTable": false // 启用表增量更新(只更新贴了特性[IncreTable]的实体表) }, "SeedSettings": { "EnableInitSeed": true, // 启用种子初始化(若种子没有变化建议关闭) diff --git a/Admin.NET/Admin.NET.Application/GlobalUsings.cs b/Admin.NET/Admin.NET.Application/GlobalUsings.cs index fb21ba13..a70e3c4f 100644 --- a/Admin.NET/Admin.NET.Application/GlobalUsings.cs +++ b/Admin.NET/Admin.NET.Application/GlobalUsings.cs @@ -16,13 +16,11 @@ global using Mapster; global using Microsoft.AspNetCore.Authorization; global using Microsoft.AspNetCore.Mvc; global using Microsoft.Extensions.DependencyInjection; +global using Microsoft.SemanticKernel; global using SqlSugar; global using System; global using System.Collections.Generic; global using System.ComponentModel; global using System.ComponentModel.DataAnnotations; global using System.Threading.Tasks; -global using System.Linq; - -global using Microsoft.SemanticKernel; -global using Microsoft.SemanticKernel.PromptTemplates.Handlebars; +global using System.Linq; \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Application/Service/LLM/LLMChangeModelTestService.cs b/Admin.NET/Admin.NET.Application/Service/LLM/LLMChangeModelTestService.cs index b6cfa3fd..211c5bcd 100644 --- a/Admin.NET/Admin.NET.Application/Service/LLM/LLMChangeModelTestService.cs +++ b/Admin.NET/Admin.NET.Application/Service/LLM/LLMChangeModelTestService.cs @@ -1,5 +1,8 @@ -using Admin.NET.Core.Ai.Interface; -using Admin.NET.Core.Ai.Models; +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! namespace Admin.NET.Application.Service.LLM; @@ -7,10 +10,12 @@ namespace Admin.NET.Application.Service.LLM; public class LLMChangeModelTestService : IDynamicApiController, ITransient { private readonly ILLMFactory _llmFactory; + public LLMChangeModelTestService(ILLMFactory llmFactory) { _llmFactory = llmFactory; } + /// /// 演示大模型的使用,可以切换模型。 /// 例如:可以切换到不同的模型,如:OpenAI、Azure OpenAI、Google Gemini等。 @@ -25,5 +30,4 @@ public class LLMChangeModelTestService : IDynamicApiController, ITransient var result = await kernel.InvokePromptAsync("请介绍自己"); return result.ToString(); } -} - +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Application/Service/LLM/LLMTestService.cs b/Admin.NET/Admin.NET.Application/Service/LLM/LLMTestService.cs index 00009d85..beb0c9dc 100644 --- a/Admin.NET/Admin.NET.Application/Service/LLM/LLMTestService.cs +++ b/Admin.NET/Admin.NET.Application/Service/LLM/LLMTestService.cs @@ -1,5 +1,8 @@ - -using Microsoft.SemanticKernel.ChatCompletion; +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! namespace Admin.NET.Application.Service.LLM; @@ -7,6 +10,7 @@ namespace Admin.NET.Application.Service.LLM; public class LLMTestService : IDynamicApiController, ITransient { private readonly Kernel _kernel; + public LLMTestService(Kernel kernel) { _kernel = kernel; diff --git a/Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj b/Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj index db237191..c3eb9a10 100644 --- a/Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj +++ b/Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj @@ -28,9 +28,9 @@ - - - + + + @@ -59,15 +59,15 @@ - - + + - - + + diff --git a/Admin.NET/Admin.NET.Core/Ai/Entitys/LLMChatHistory.cs b/Admin.NET/Admin.NET.Core/Ai/Entity/LLMChatHistory.cs similarity index 56% rename from Admin.NET/Admin.NET.Core/Ai/Entitys/LLMChatHistory.cs rename to Admin.NET/Admin.NET.Core/Ai/Entity/LLMChatHistory.cs index 6e207990..5469c266 100644 --- a/Admin.NET/Admin.NET.Core/Ai/Entitys/LLMChatHistory.cs +++ b/Admin.NET/Admin.NET.Core/Ai/Entity/LLMChatHistory.cs @@ -1,12 +1,17 @@ -namespace Admin.NET.Core.Ai.Entitys; +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core; /// -/// 聊天历史 +/// 聊天历史表 /// -[SugarTable("LLMChatHistory")] -[IncreTable] -[SugarIndex("index_UserId_{table}", nameof(UserId), OrderByType.Asc)] -[SugarIndex("index_SummaryId_{table}", nameof(SummaryId), OrderByType.Asc)] +[SugarTable(null, "AI聊天历史表")] +[SugarIndex("i_{table}_u", nameof(UserId), OrderByType.Asc)] +[SugarIndex("i_{table}_s", nameof(SummaryId), OrderByType.Asc)] public class LLMChatHistory : EntityBaseId { /// @@ -44,4 +49,4 @@ public class LLMChatHistory : EntityBaseId /// [SugarColumn(ColumnDescription = "创建时间")] public long UtcCreateTime { get; set; } = DateTime.UtcNow.ToLong(); -} +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Ai/Entity/LLMChatSummaryHistory.cs b/Admin.NET/Admin.NET.Core/Ai/Entity/LLMChatSummaryHistory.cs new file mode 100644 index 00000000..577ec3fd --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Ai/Entity/LLMChatSummaryHistory.cs @@ -0,0 +1,46 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core; + +/// +/// 聊天摘要历史表 +/// +[SugarTable(null, "AI聊天摘要历史表")] +[SugarIndex("i_{table}_us", nameof(UserId), OrderByType.Asc)] +[SugarIndex("i_{table}_un", nameof(UniqueToken), OrderByType.Asc)] +public class LLMChatSummaryHistory : EntityBaseId +{ + /// + /// 用户ID + /// + [SugarColumn(ColumnDescription = "用户ID")] + public long UserId { get; set; } + + /// + /// 唯一标识 + /// + [SugarColumn(ColumnDescription = "唯一标识")] + public string UniqueToken { get; set; } + + /// + /// 摘要 + /// + [SugarColumn(ColumnDescription = "摘要", Length = 4000)] + public string? Summary { get; set; } + + /// + /// 创建时间 + /// + [SugarColumn(ColumnDescription = "创建时间")] + public long UtcCreateTime { get; set; } = DateTime.UtcNow.ToLong(); + + /// + /// 聊天历史 + /// + [Navigate(NavigateType.OneToMany, nameof(LLMChatHistory.SummaryId))] + public List? Histories { get; set; } +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Ai/Entitys/LLMChatSummaryHistory.cs b/Admin.NET/Admin.NET.Core/Ai/Entitys/LLMChatSummaryHistory.cs deleted file mode 100644 index a4d384f5..00000000 --- a/Admin.NET/Admin.NET.Core/Ai/Entitys/LLMChatSummaryHistory.cs +++ /dev/null @@ -1,40 +0,0 @@ -namespace Admin.NET.Core.Ai.Entitys; - -/// -/// 聊天摘要历史 -/// -[SugarTable("LLMChatSummaryHistory")] -[IncreTable] -[SugarIndex("index_UserId_{table}", nameof(UserId), OrderByType.Asc)] -[SugarIndex("index_UniqueToken_{table}", nameof(UniqueToken), OrderByType.Asc)] -public class LLMChatSummaryHistory:EntityBaseId -{ - /// - /// 用户ID - /// - [SugarColumn(ColumnDescription = "用户ID")] - public long UserId { get; set; } - - /// - /// 唯一标识 - /// - [SugarColumn(ColumnDescription = "唯一标识")] - public string UniqueToken {get;set;} - - /// - /// 摘要 - /// - [SugarColumn(ColumnDescription = "摘要",Length = 4000)] - public string? Summary { get; set; } - /// - /// 创建时间 - /// - [SugarColumn(ColumnDescription = "创建时间")] - public long UtcCreateTime {get;set;} = DateTime.UtcNow.ToLong(); - - /// - /// 聊天历史 - /// - [Navigate(NavigateType.OneToMany, nameof(LLMChatHistory.SummaryId))] - public List? Histories { get; set; } -} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Ai/Enum/ChatActionEnum.cs b/Admin.NET/Admin.NET.Core/Ai/Enum/ChatActionEnum.cs new file mode 100644 index 00000000..b20f6732 --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Ai/Enum/ChatActionEnum.cs @@ -0,0 +1,43 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core; + +/// +/// 保存数据库的动作枚举 +/// +public enum ChatActionEnum +{ + /// + /// 无 + /// + None = 0, + + /// + /// 追加 + /// + Append, + + /// + /// 追加明细 + /// + AppendItem, + + /// + /// 删除所有 + /// + DeleteAll, + + /// + /// 删除指定明细 + /// + DeleteItem, + + /// + /// 重命名摘要 + /// + RenameSummary, +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Ai/Enums/ChatActionEnums.cs b/Admin.NET/Admin.NET.Core/Ai/Enums/ChatActionEnums.cs deleted file mode 100644 index d4e85ff2..00000000 --- a/Admin.NET/Admin.NET.Core/Ai/Enums/ChatActionEnums.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace Admin.NET.Core.Ai.Enums; - -/// -/// 保存数据库的动作枚举 -/// -public enum ChatActionEnums -{ - /// - /// 无 - /// - None = 0, - /// - /// 追加 - /// - Append, - /// - /// 追加明细 - /// - AppendItem, - /// - /// 删除所有 - /// - DeleteAll, - /// - /// 删除指定明细 - /// - DeleteItem, - /// - /// 重命名摘要 - /// - RenameSummary, -} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Ai/Extention/LLMFactoryExtention.cs b/Admin.NET/Admin.NET.Core/Ai/Extention/LLMFactoryExtention.cs new file mode 100644 index 00000000..601a5bd9 --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Ai/Extention/LLMFactoryExtention.cs @@ -0,0 +1,23 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +using Admin.NET.Core.Ai.Service; + +namespace Admin.NET.Core; + +public static class LLMFactoryExtention +{ + /// + /// 注册LLM模型工厂 + /// + /// + /// + public static IServiceCollection AddLLMFactory(this IServiceCollection services) + { + services.AddTransient(); + return services; + } +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Ai/Extentions/LLMRegisterExtention.cs b/Admin.NET/Admin.NET.Core/Ai/Extention/LLMRegisterExtention.cs similarity index 65% rename from Admin.NET/Admin.NET.Core/Ai/Extentions/LLMRegisterExtention.cs rename to Admin.NET/Admin.NET.Core/Ai/Extention/LLMRegisterExtention.cs index 3a5e7ca5..3c971ab3 100644 --- a/Admin.NET/Admin.NET.Core/Ai/Extentions/LLMRegisterExtention.cs +++ b/Admin.NET/Admin.NET.Core/Ai/Extention/LLMRegisterExtention.cs @@ -1,20 +1,10 @@ -using Microsoft.SemanticKernel; -using Microsoft.SemanticKernel.Connectors.Google; -using Microsoft.SemanticKernel.Connectors.AzureOpenAI; -using Microsoft.SemanticKernel.Connectors.OpenAI; -using Microsoft.SemanticKernel.Connectors.HuggingFace; -using Microsoft.SemanticKernel.Connectors.Ollama; -using Microsoft.SemanticKernel.Connectors.Qdrant; - -using Admin.NET.Core.Ai.Option; -using System.Net; -using Admin.NET.Core.Ai.Handlers; -using OllamaSharp; -using Admin.NET.Core.Ai.Interface; -using Admin.NET.Core.Ai.Models; - -namespace Admin.NET.Core.Ai.Extentions; +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! +namespace Admin.NET.Core; /// /// LLM注册扩展类 @@ -47,4 +37,4 @@ public static class LLMRegisterExtention }); return services; } -} +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Ai/Extentions/LLMFactoryExtention.cs b/Admin.NET/Admin.NET.Core/Ai/Extentions/LLMFactoryExtention.cs deleted file mode 100644 index 3d3b9a28..00000000 --- a/Admin.NET/Admin.NET.Core/Ai/Extentions/LLMFactoryExtention.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Admin.NET.Core.Ai.Interface; -using Admin.NET.Core.Ai.Services; -using Admin.NET.Core.Ai.Services.Infrastructure; - - -namespace Admin.NET.Core.Ai.Extentions; - -public static class LLMFactoryExtention -{ - /// - /// 注册LLM模型工厂 - /// - /// - /// - public static IServiceCollection AddLLMFactory(this IServiceCollection services) - { - services.AddTransient(); - return services; - } -} - diff --git a/Admin.NET/Admin.NET.Core/Ai/Handler/LLMDelegatingHandler.cs b/Admin.NET/Admin.NET.Core/Ai/Handler/LLMDelegatingHandler.cs new file mode 100644 index 00000000..4bf2711b --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Ai/Handler/LLMDelegatingHandler.cs @@ -0,0 +1,26 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +using System.Net.Http.Headers; + +namespace Admin.NET.Core; + +public class LLMDelegatingHandler : DelegatingHandler +{ + private readonly LLMCustomOptions _options; + + public LLMDelegatingHandler(IOptions options) + { + _options = options.Value; + } + + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + //设置header + request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _options.ApiKey); + return await base.SendAsync(request, cancellationToken); + } +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Ai/Handlers/LoggingHandler.cs b/Admin.NET/Admin.NET.Core/Ai/Handler/LoggingHandler.cs similarity index 92% rename from Admin.NET/Admin.NET.Core/Ai/Handlers/LoggingHandler.cs rename to Admin.NET/Admin.NET.Core/Ai/Handler/LoggingHandler.cs index 112ae1cd..aabd2782 100644 --- a/Admin.NET/Admin.NET.Core/Ai/Handlers/LoggingHandler.cs +++ b/Admin.NET/Admin.NET.Core/Ai/Handler/LoggingHandler.cs @@ -1,14 +1,18 @@ -using System.Text.Json; -using System.Text.RegularExpressions; -using System.Text; -using System.Text.Encodings.Web; -using System.Text.Json.Serialization; +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! -namespace Admin.NET.Core.Ai.Handlers; +using System.Text.Encodings.Web; +using System.Text.Json; + +namespace Admin.NET.Core; public class LoggingHandler : DelegatingHandler { private readonly ILogger _logger; + public LoggingHandler(HttpMessageHandler innerHandler) { InnerHandler = innerHandler ?? new HttpClientHandler(); @@ -143,6 +147,7 @@ public class LoggingStream : Stream public override bool CanSeek => _innerStream.CanSeek; public override bool CanWrite => _innerStream.CanWrite; public override long Length => _innerStream.Length; + public override long Position { get => _innerStream.Position; @@ -188,8 +193,11 @@ public class LoggingStream : Stream } public override void Flush() => _innerStream.Flush(); + public override long Seek(long offset, SeekOrigin origin) => _innerStream.Seek(offset, origin); + public override void SetLength(long value) => _innerStream.SetLength(value); + public override void Write(byte[] buffer, int offset, int count) => _innerStream.Write(buffer, offset, count); protected override void Dispose(bool disposing) diff --git a/Admin.NET/Admin.NET.Core/Ai/Handlers/LLMDelegatingHandler.cs b/Admin.NET/Admin.NET.Core/Ai/Handlers/LLMDelegatingHandler.cs deleted file mode 100644 index d143b160..00000000 --- a/Admin.NET/Admin.NET.Core/Ai/Handlers/LLMDelegatingHandler.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Net.Http.Headers; -using Admin.NET.Core.Ai.Option; - -namespace Admin.NET.Core.Ai.Handlers; - -public class LLMDelegatingHandler: DelegatingHandler -{ - private readonly LLMCustomOptions _options; - - public LLMDelegatingHandler(IOptions options) - { - _options = options.Value; - } - - protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) - { - //设置header - request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _options.ApiKey); - return await base.SendAsync(request, cancellationToken); - } -} - - diff --git a/Admin.NET/Admin.NET.Core/Ai/Interface/ILLMFactory.cs b/Admin.NET/Admin.NET.Core/Ai/Interface/ILLMFactory.cs index 8fdf8c1c..11d13779 100644 --- a/Admin.NET/Admin.NET.Core/Ai/Interface/ILLMFactory.cs +++ b/Admin.NET/Admin.NET.Core/Ai/Interface/ILLMFactory.cs @@ -1,6 +1,10 @@ -using Admin.NET.Core.Ai.Models; +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! -namespace Admin.NET.Core.Ai.Interface; +namespace Admin.NET.Core; /// /// LLM工厂接口 @@ -13,5 +17,4 @@ public interface ILLMFactory /// 模型输入 /// Kernel CreateKernel(LLMModelInput modelInput); -} - +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Ai/Interface/ISseChannelManager.cs b/Admin.NET/Admin.NET.Core/Ai/Interface/ISseChannelManager.cs index c89d4e6e..36d1c5d6 100644 --- a/Admin.NET/Admin.NET.Core/Ai/Interface/ISseChannelManager.cs +++ b/Admin.NET/Admin.NET.Core/Ai/Interface/ISseChannelManager.cs @@ -1,6 +1,12 @@ -// 1. 定义接口 +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + using System.Threading.Channels; -namespace Admin.NET.Core.Ai.Interface; + +namespace Admin.NET.Core; /// /// SSE通道管理接口 @@ -11,11 +17,13 @@ public interface ISseChannelManager /// 注册 /// ChannelReader Register(long userId); + /// /// 注销 /// /// void Unregister(long userId); + /// /// 发送消息 /// diff --git a/Admin.NET/Admin.NET.Core/Ai/Model/LLMInputBody.cs b/Admin.NET/Admin.NET.Core/Ai/Model/LLMInputBody.cs new file mode 100644 index 00000000..0932d42d --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Ai/Model/LLMInputBody.cs @@ -0,0 +1,32 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core; + +/// +/// LLM请求体 +/// +public class LLMInputBody +{ + public string Model { get; set; } + public List Messages { get; set; } +} + +/// +/// LLM请求体消息 +/// +public class LLMInputMessage +{ + /// + /// 角色,system、user、assistant + /// + public string Role { get; set; } + + /// + /// 内容 + /// + public string Content { get; set; } +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Ai/Model/LLMModelInput.cs b/Admin.NET/Admin.NET.Core/Ai/Model/LLMModelInput.cs new file mode 100644 index 00000000..c11dad41 --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Ai/Model/LLMModelInput.cs @@ -0,0 +1,24 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core; + +/// +/// LLM模型输入 +/// 用途:切换模型 +/// +public class LLMModelInput +{ + /// + /// 产品名称 + /// + public string ProductName { get; set; } + + /// + /// 模型ID + /// + public string ModelId { get; set; } +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Ai/Models/LLMOutput.cs b/Admin.NET/Admin.NET.Core/Ai/Model/LLMOutput.cs similarity index 59% rename from Admin.NET/Admin.NET.Core/Ai/Models/LLMOutput.cs rename to Admin.NET/Admin.NET.Core/Ai/Model/LLMOutput.cs index 22223b20..dbfe9a60 100644 --- a/Admin.NET/Admin.NET.Core/Ai/Models/LLMOutput.cs +++ b/Admin.NET/Admin.NET.Core/Ai/Model/LLMOutput.cs @@ -1,11 +1,18 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + using Newtonsoft.Json; -namespace Admin.NET.Core.Ai.Models; +namespace Admin.NET.Core; /// /// LLM输出 /// -public class LLMOutput { +public class LLMOutput +{ public string Id { get; set; } public string Provider { get; set; } public string Model { get; set; } @@ -18,9 +25,11 @@ public class LLMOutput { /// /// LLM输出机会 /// -public class ChoicesItem { +public class ChoicesItem +{ [JsonProperty("logprobs")] public string? Logprobs { get; set; } + public string? FinishReason { get; set; } public string? NativeFinishReason { get; set; } public int Index { get; set; } @@ -30,10 +39,12 @@ public class ChoicesItem { /// /// LLM输出消息 /// -public class OutPutMessage { +public class OutPutMessage +{ public string Role { get; set; } public string Content { get; set; } public Object Refusal { get; set; } + [JsonProperty("reasoning")] public string? Reasoning { get; set; } } @@ -41,10 +52,9 @@ public class OutPutMessage { /// /// LLM的消耗 /// -public class Usage { +public class Usage +{ public int PromptTokens { get; set; } public int CompletionTokens { get; set; } public int TotalTokens { get; set; } -} - - +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Ai/Models/LLMInputBody.cs b/Admin.NET/Admin.NET.Core/Ai/Models/LLMInputBody.cs deleted file mode 100644 index 9c0c983a..00000000 --- a/Admin.NET/Admin.NET.Core/Ai/Models/LLMInputBody.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace Admin.NET.Core.Ai.Models; - -/// -/// LLM请求体 -/// -public class LLMInputBody { - public string Model { get; set; } - public List Messages { get; set; } -} - -/// -/// LLM请求体消息 -/// -public class LLMInputMessage { - /// - /// 角色,system、user、assistant - /// - public string Role { get; set; } - /// - /// 内容 - /// - public string Content { get; set; } -} - - diff --git a/Admin.NET/Admin.NET.Core/Ai/Models/LLMModelInput.cs b/Admin.NET/Admin.NET.Core/Ai/Models/LLMModelInput.cs deleted file mode 100644 index 95cc282b..00000000 --- a/Admin.NET/Admin.NET.Core/Ai/Models/LLMModelInput.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace Admin.NET.Core.Ai.Models; - -/// -/// LLM模型输入 -/// 用途:切换模型 -/// -public class LLMModelInput -{ - /// - /// 产品名称 - /// - public string ProductName { get; set; } - /// - /// 模型ID - /// - public string ModelId { get; set; } -} - diff --git a/Admin.NET/Admin.NET.Core/Ai/Option/LLMCustomOptions.cs b/Admin.NET/Admin.NET.Core/Ai/Option/LLMCustomOptions.cs index f77d0925..2f826bf6 100644 --- a/Admin.NET/Admin.NET.Core/Ai/Option/LLMCustomOptions.cs +++ b/Admin.NET/Admin.NET.Core/Ai/Option/LLMCustomOptions.cs @@ -1,9 +1,15 @@ -namespace Admin.NET.Core.Ai.Option; +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core; /// /// 手动实现LLM接口配置选项 /// -public class LLMCustomOptions: IConfigurableOptions +public class LLMCustomOptions : IConfigurableOptions { public string LLMType { get; set; } = "openrouter"; public string ApiKey { get; set; } @@ -26,4 +32,4 @@ public class LLMItem { public string Desciption { get; set; } public string Model { get; set; } -} +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Ai/Option/LLMOptions.cs b/Admin.NET/Admin.NET.Core/Ai/Option/LLMOptions.cs index ddc07a4b..1bbb8c2a 100644 --- a/Admin.NET/Admin.NET.Core/Ai/Option/LLMOptions.cs +++ b/Admin.NET/Admin.NET.Core/Ai/Option/LLMOptions.cs @@ -1,4 +1,10 @@ -namespace Admin.NET.Core.Ai.Option; +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core; /// /// LLM配置选项 @@ -48,5 +54,4 @@ public class EmbeddingOptions { public string ModelId { get; set; } public List SupportModelIds { get; set; } -} - +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Ai/Services/Chat/Dto/ChatInput.cs b/Admin.NET/Admin.NET.Core/Ai/Service/Chat/Dto/ChatInput.cs similarity index 53% rename from Admin.NET/Admin.NET.Core/Ai/Services/Chat/Dto/ChatInput.cs rename to Admin.NET/Admin.NET.Core/Ai/Service/Chat/Dto/ChatInput.cs index 6e265299..ae80f127 100644 --- a/Admin.NET/Admin.NET.Core/Ai/Services/Chat/Dto/ChatInput.cs +++ b/Admin.NET/Admin.NET.Core/Ai/Service/Chat/Dto/ChatInput.cs @@ -1,4 +1,10 @@ -namespace Admin.NET.Core.Ai.Services.Chat.Dto; +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core.Ai.Service; public class ChatInput { @@ -6,14 +12,17 @@ public class ChatInput /// 摘要id /// public long SummaryId { get; set; } + /// /// 摘要 /// public string? Summary { get; set; } + /// /// 摘要唯一标识 /// public string? UniqueToken { get; set; } = ""; + /// /// 消息 /// @@ -24,14 +33,13 @@ public class ChatInput /// public string ProviderName { get; set; } - /// /// 模型id /// public string ModelId { get; set; } + /// /// 深度思考 /// public bool DeepThinking { get; set; } = false; -} - +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Ai/Service/Chat/Dto/ChatListInput.cs b/Admin.NET/Admin.NET.Core/Ai/Service/Chat/Dto/ChatListInput.cs new file mode 100644 index 00000000..62ef92cf --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Ai/Service/Chat/Dto/ChatListInput.cs @@ -0,0 +1,11 @@ +// Admin.NET ĿİȨ̱ꡢרȨӦɷıʹñĿӦطɷ֤Ҫ +// +// ĿҪѭ MIT ֤ Apache ֤汾 2.0зַʹá֤λԴĿ¼е LICENSE-MIT LICENSE-APACHE ļ +// +// ñĿΣҰȫַ˺ϷȨȷɷֹĻκλڱĿοһзɾ׺ΣDzеκΣ + +namespace Admin.NET.Core.Ai.Service; + +public class ChatListInput : BasePageInput +{ +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Ai/Service/Chat/Dto/ChatListOutput.cs b/Admin.NET/Admin.NET.Core/Ai/Service/Chat/Dto/ChatListOutput.cs new file mode 100644 index 00000000..f9b701c5 --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Ai/Service/Chat/Dto/ChatListOutput.cs @@ -0,0 +1,14 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core.Ai.Service; + +/// +/// 聊天列表输出 +/// +public class ChatListOutput : LLMChatSummaryHistory +{ +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Ai/Service/Chat/Dto/ChatOutput.cs b/Admin.NET/Admin.NET.Core/Ai/Service/Chat/Dto/ChatOutput.cs new file mode 100644 index 00000000..c88c2e98 --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Ai/Service/Chat/Dto/ChatOutput.cs @@ -0,0 +1,35 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core.Ai.Service; + +public class ChatOutput +{ + /// + /// 唯一标识 + /// + public string? UniqueToken { get; set; } + + /// + /// 备注 + /// + public string? Note { get; set; } + + /// + /// 状态 + /// + public bool State { get; set; } = true; + + /// + /// 摘要 + /// + public string? Summary { get; set; } = ""; + + /// + /// 摘要ID + /// + public long? SummaryId { get; set; } +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Ai/Service/Chat/Dto/ModelListChangeInput.cs b/Admin.NET/Admin.NET.Core/Ai/Service/Chat/Dto/ModelListChangeInput.cs new file mode 100644 index 00000000..8e65f398 --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Ai/Service/Chat/Dto/ModelListChangeInput.cs @@ -0,0 +1,11 @@ +// Admin.NET ĿİȨ̱ꡢרȨӦɷıʹñĿӦطɷ֤Ҫ +// +// ĿҪѭ MIT ֤ Apache ֤汾 2.0зַʹá֤λԴĿ¼е LICENSE-MIT LICENSE-APACHE ļ +// +// ñĿΣҰȫַ˺ϷȨȷɷֹĻκλڱĿοһзɾ׺ΣDzеκΣ + +namespace Admin.NET.Core.Ai.Service; + +public class ModelListChangeInput : ModelListOutputItem +{ +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Ai/Services/Chat/Dto/ModelListOutput.cs b/Admin.NET/Admin.NET.Core/Ai/Service/Chat/Dto/ModelListOutput.cs similarity index 55% rename from Admin.NET/Admin.NET.Core/Ai/Services/Chat/Dto/ModelListOutput.cs rename to Admin.NET/Admin.NET.Core/Ai/Service/Chat/Dto/ModelListOutput.cs index c38c9fb3..42b47777 100644 --- a/Admin.NET/Admin.NET.Core/Ai/Services/Chat/Dto/ModelListOutput.cs +++ b/Admin.NET/Admin.NET.Core/Ai/Service/Chat/Dto/ModelListOutput.cs @@ -1,4 +1,10 @@ -namespace Admin.NET.Core.Ai.Services.Chat.Dto; +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core.Ai.Service; /// /// 模型列表输出 @@ -33,11 +39,8 @@ public class ModelListOutputItem /// public string ProviderName { get; set; } - /// /// 模型名称 /// public string ModelName { get; set; } - - -} +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Ai/Services/Chat/LLMChatCoreService.cs b/Admin.NET/Admin.NET.Core/Ai/Service/Chat/LLMChatCoreService.cs similarity index 94% rename from Admin.NET/Admin.NET.Core/Ai/Services/Chat/LLMChatCoreService.cs rename to Admin.NET/Admin.NET.Core/Ai/Service/Chat/LLMChatCoreService.cs index cbe5ef9a..b7fb7037 100644 --- a/Admin.NET/Admin.NET.Core/Ai/Services/Chat/LLMChatCoreService.cs +++ b/Admin.NET/Admin.NET.Core/Ai/Service/Chat/LLMChatCoreService.cs @@ -1,17 +1,13 @@ -using Admin.NET.Core.Ai.Enums; -using Admin.NET.Core.Ai.Option; -using Admin.NET.Core.Ai.Services.Chat.Dto; -using Admin.NET.Core.Ai.Services.DataBase; -using Admin.NET.Core.Ai.Services.DataBase.Dto; -using Microsoft.SemanticKernel.ChatCompletion; -using Admin.NET.Core.Ai.Services.SSE; -using LLMChatHistory = Admin.NET.Core.Ai.Entitys.LLMChatHistory; -using LLMChatSummaryHistory = Admin.NET.Core.Ai.Entitys.LLMChatSummaryHistory; -using Admin.NET.Core.Ai.Interface; -using Admin.NET.Core.Ai.Models; -using NewLife.Reflection; +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +using Microsoft.SemanticKernel.ChatCompletion; + +namespace Admin.NET.Core.Ai.Service; -namespace Admin.NET.Core.Ai.Services.Chat; /// /// 聊天补全核心服务 /// @@ -19,8 +15,10 @@ public class LLMChatCoreService : ITransient { private readonly ILogger _logger; private readonly IChatHistoryReducer _chatHistoryTruncationReducer; //截取器 + // private readonly IChatHistoryReducer _chatHistorySummarizationReducer; //摘要器 private readonly ILLMFactory _llmFactory; + private readonly SseChannelManager _sseChannelManager; //给sse服务发送消息 private readonly SseDeepThinkingChannelManager _sseDeepThinkingChannelManager; //给sse服务发送深度思考消息 private readonly ChatChannelManager _dbAction; //操作数据库 @@ -29,6 +27,7 @@ public class LLMChatCoreService : ITransient private readonly UserManager _userManager; private Kernel _kernel; private readonly SysCacheService _sysCacheService; + public LLMChatCoreService(ILogger logger, ILLMFactory llmFactory, SseChannelManager sseChannelManager, @@ -75,6 +74,7 @@ public class LLMChatCoreService : ITransient } #region 新聊天 + /// /// 新聊天 /// @@ -93,6 +93,7 @@ public class LLMChatCoreService : ITransient return await NormalNewChatCore(input, kernel, cancellationToken); } } + /// /// 深度思考新聊天 /// @@ -103,7 +104,9 @@ public class LLMChatCoreService : ITransient private async Task DeepThinkingNewChatCore(ChatInput input, Kernel kernel, CancellationToken cancellationToken) { ChatHistory chatHistory = []; + #region 深度思考过程 + var deepThinkingPrompt = $""" 你是一个逻辑严谨的AI助手,请在回答前,先梳理出完整的推理路径,用户的问题是: ``` @@ -131,7 +134,9 @@ public class LLMChatCoreService : ITransient await _sseDeepThinkingChannelManager.SendMessageAsync(_userManager.UserId, streamInput, cancellationToken); } await _sseDeepThinkingChannelManager.SendMessageAsync(_userManager.UserId, "[DONE]", cancellationToken); - #endregion + + #endregion 深度思考过程 + //生成最终答案 return await NormalNewChatCore(input, kernel, cancellationToken, thinkingMessage); } @@ -215,7 +220,7 @@ public class LLMChatCoreService : ITransient }; DataActionInput dataActionInput = new DataActionInput { - ActionType = ChatActionEnums.Append, + ActionType = ChatActionEnum.Append, Item = chatSummaryHistory }; await _dbAction.ActionWriter.WriteAsync(dataActionInput); @@ -227,7 +232,8 @@ public class LLMChatCoreService : ITransient Summary = "New Chat" }; } - #endregion + + #endregion 新聊天 #region 续聊 @@ -251,6 +257,7 @@ public class LLMChatCoreService : ITransient return await NormalContinueChatCoreAsync(input, kernel, uniqueToken, chatHistory, cancellationToken); } } + /// /// 深度思考续聊 /// @@ -263,6 +270,7 @@ public class LLMChatCoreService : ITransient private async Task DeepThinkingContinueChatCoreAsync(ChatInput input, Kernel kernel, string uniqueToken, ChatHistory chatHistory, CancellationToken cancellationToken) { #region 深度思考过程 + var deepThinkChatHistory = new ChatHistory(chatHistory); var deepThinkingPrompt = $""" 你是一个逻辑严谨的AI助手,请在回答前,先梳理出完整的推理路径,请你一步步进行推理,不要给出最终答案,仅展示思考过程,适当加入emoji表达人类情感,**用第一人称描述**。 @@ -288,10 +296,12 @@ public class LLMChatCoreService : ITransient } await _sseDeepThinkingChannelManager.SendMessageAsync(_userManager.UserId, "[DONE]", cancellationToken); - #endregion + #endregion 深度思考过程 + //生成最终答案 return await NormalContinueChatCoreAsync(input, kernel, uniqueToken, chatHistory, cancellationToken, thinkingMessage); } + /// /// 普通续聊 /// @@ -329,7 +339,7 @@ public class LLMChatCoreService : ITransient message += chunk.Content ?? ""; var streamInput = chunk.Content ?? ""; streamInput = streamInput.Replace("\n", "\\x0A"); - //发送消息到SSE通道 + //发送消息到SSE通道 await _sseChannelManager.SendMessageAsync(_userManager.UserId, streamInput, cancellationToken); } await _sseChannelManager.SendMessageAsync(_userManager.UserId, "[DONE]", cancellationToken); @@ -368,6 +378,7 @@ public class LLMChatCoreService : ITransient } input.SummaryId = chatSummaryHistory.Id; } + private async Task _UpdateSummaryToDatabase(string summary, ChatInput input) { //更新摘要至数据库 @@ -375,7 +386,7 @@ public class LLMChatCoreService : ITransient { await _dbAction.ActionWriter.WriteAsync(new DataActionInput { - ActionType = ChatActionEnums.RenameSummary, + ActionType = ChatActionEnum.RenameSummary, Item = new LLMChatSummaryHistory { Id = input.SummaryId, @@ -410,6 +421,7 @@ public class LLMChatCoreService : ITransient ); return result.Content ?? ""; } + /// /// 获取聊天历史,并截取 /// @@ -432,12 +444,15 @@ public class LLMChatCoreService : ITransient case "user": chatHistory.AddUserMessage(history.Content); break; + case "assistant": chatHistory.AddAssistantMessage(history.Content); break; + case "system": chatHistory.AddSystemMessage(history.Content); break; + default: break; } @@ -453,6 +468,7 @@ public class LLMChatCoreService : ITransient } return chatHistory; } + private async Task _SaveChatItemToDatabase(ChatHistory chatHistory, string uniqueToken) { var chatSummaryHistory = await _chatSummaryHistoryService.AsQueryable().Where(u => u.UniqueToken == uniqueToken).FirstAsync(); @@ -474,14 +490,16 @@ public class LLMChatCoreService : ITransient } DataActionInput dataActionInput = new DataActionInput { - ActionType = ChatActionEnums.AppendItem, + ActionType = ChatActionEnum.AppendItem, Item = chatSummaryHistory }; await _dbAction.ActionWriter.WriteAsync(dataActionInput); } - #endregion + + #endregion 续聊 #region 删除所属摘要的所有聊天记录 + /// /// 删除所属摘要的所有聊天记录 /// @@ -496,15 +514,17 @@ public class LLMChatCoreService : ITransient } DataActionInput dataActionInput = new DataActionInput { - ActionType = ChatActionEnums.DeleteAll, + ActionType = ChatActionEnum.DeleteAll, Item = chatSummaryHistory }; await _dbAction.ActionWriter.WriteAsync(dataActionInput); return true; } - #endregion + + #endregion 删除所属摘要的所有聊天记录 #region 重命名所属摘要的标签 + /// /// 重命名所属摘要的标签 /// @@ -520,12 +540,12 @@ public class LLMChatCoreService : ITransient chatSummaryHistory.Summary = input.Summary; DataActionInput dataActionInput = new DataActionInput { - ActionType = ChatActionEnums.RenameSummary, + ActionType = ChatActionEnum.RenameSummary, Item = chatSummaryHistory }; await _dbAction.ActionWriter.WriteAsync(dataActionInput); return true; } - #endregion -} + #endregion 重命名所属摘要的标签 +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Ai/Services/Chat/LLMChatService.cs b/Admin.NET/Admin.NET.Core/Ai/Service/Chat/LLMChatService.cs similarity index 86% rename from Admin.NET/Admin.NET.Core/Ai/Services/Chat/LLMChatService.cs rename to Admin.NET/Admin.NET.Core/Ai/Service/Chat/LLMChatService.cs index 151a00d0..4ea1c48a 100644 --- a/Admin.NET/Admin.NET.Core/Ai/Services/Chat/LLMChatService.cs +++ b/Admin.NET/Admin.NET.Core/Ai/Service/Chat/LLMChatService.cs @@ -1,10 +1,10 @@ -using Admin.NET.Core.Ai.Entitys; -using Admin.NET.Core.Ai.Option; -using Admin.NET.Core.Ai.Services.Chat.Dto; -using Admin.NET.Core.Ai.Services.DataBase; -using Admin.NET.Core.Ai.Services.SSE; +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! -namespace Admin.NET.Core.Ai.Services.Chat; +namespace Admin.NET.Core.Ai.Service; /// /// LLM聊天补全服务 @@ -55,7 +55,7 @@ public class LLMChatService : IDynamicApiController, ITransient [HttpPost] [ApiDescriptionSettings(Description = "删除所属摘要的所有聊天记录", Name = "DeleteSummaryAll")] public async Task DeleteSummaryAllAsync(ChatInput message) => await _chatCoreService.DeleteSummaryAllAsync(message); - + /// /// 重命名所属摘要的标签 /// @@ -95,7 +95,6 @@ public class LLMChatService : IDynamicApiController, ITransient [ApiDescriptionSettings(Description = "获取模型列表", Name = "ModelList")] public async Task GetModelListAsync() => await _llmOptionService.GetModelListAsync(); - /// /// 切换模型 /// @@ -104,4 +103,4 @@ public class LLMChatService : IDynamicApiController, ITransient /// [ApiDescriptionSettings(Description = "切换模型", Name = "ChangeModel"), HttpPost] public async Task ChangeModelAsync(ModelListChangeInput input) => await _llmOptionService.ChangeModelAsync(input); -} +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Ai/Services/Chat/LLMOptionService.cs b/Admin.NET/Admin.NET.Core/Ai/Service/Chat/LLMOptionService.cs similarity index 91% rename from Admin.NET/Admin.NET.Core/Ai/Services/Chat/LLMOptionService.cs rename to Admin.NET/Admin.NET.Core/Ai/Service/Chat/LLMOptionService.cs index 1f682b6a..0364449e 100644 --- a/Admin.NET/Admin.NET.Core/Ai/Services/Chat/LLMOptionService.cs +++ b/Admin.NET/Admin.NET.Core/Ai/Service/Chat/LLMOptionService.cs @@ -1,7 +1,10 @@ -using Admin.NET.Core.Ai.Option; -using Admin.NET.Core.Ai.Services.Chat.Dto; +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! -namespace Admin.NET.Core.Ai.Services.Chat; +namespace Admin.NET.Core.Ai.Service; public class LLMOptionService : ITransient { @@ -9,6 +12,7 @@ public class LLMOptionService : ITransient private readonly UserManager _userManager; private readonly IOptions _llmOptions; private readonly SysCacheService _sysCacheService; + public LLMOptionService(ILogger logger, UserManager userManager, IOptions llmOptions, @@ -19,6 +23,7 @@ public class LLMOptionService : ITransient _llmOptions = llmOptions; _sysCacheService = sysCacheService; } + /// /// 获取模型列表 /// 步骤: @@ -55,6 +60,7 @@ public class LLMOptionService : ITransient _sysCacheService.Set(key, output); return await Task.FromResult(output); } + /// /// 可能存在用户手动修改了配置文件,如删除、添加、修改模型,此时需要更新缓存中的模型列表 /// @@ -134,6 +140,7 @@ public class LLMOptionService : ITransient } return await _UpdateModelList(input, cache, key); } + private async Task _SetNewModelList(ModelListChangeInput input, string key) { var currentModel = _llmOptions.Value.Providers.FirstOrDefault(it => it.ProductName == input.ProviderName); @@ -170,5 +177,4 @@ public class LLMOptionService : ITransient _sysCacheService.Set(key, cache); return await Task.FromResult(true); } -} - +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Ai/Services/DataBase/ChatChannelActionService.cs b/Admin.NET/Admin.NET.Core/Ai/Service/DataBase/ChatChannelActionService.cs similarity index 80% rename from Admin.NET/Admin.NET.Core/Ai/Services/DataBase/ChatChannelActionService.cs rename to Admin.NET/Admin.NET.Core/Ai/Service/DataBase/ChatChannelActionService.cs index 2f2ebbc1..cf48074f 100644 --- a/Admin.NET/Admin.NET.Core/Ai/Services/DataBase/ChatChannelActionService.cs +++ b/Admin.NET/Admin.NET.Core/Ai/Service/DataBase/ChatChannelActionService.cs @@ -1,8 +1,10 @@ -namespace Admin.NET.Core.Ai.Services.DataBase; +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! -using Admin.NET.Core.Ai.Entitys; -using Admin.NET.Core.Ai.Enums; -using Admin.NET.Core.Ai.Services.DataBase.Dto; +namespace Admin.NET.Core.Ai.Service; /// /// 异步对数据库进行操作 @@ -75,4 +77,4 @@ public class ChatChannelActionService : IScoped .Updateable(oldChatSummaryHistory) .ExecuteCommandAsync(); } -} +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Ai/Services/DataBase/ChatChannelManager.cs b/Admin.NET/Admin.NET.Core/Ai/Service/DataBase/ChatChannelManager.cs similarity index 70% rename from Admin.NET/Admin.NET.Core/Ai/Services/DataBase/ChatChannelManager.cs rename to Admin.NET/Admin.NET.Core/Ai/Service/DataBase/ChatChannelManager.cs index 09ed293c..9a5011d8 100644 --- a/Admin.NET/Admin.NET.Core/Ai/Services/DataBase/ChatChannelManager.cs +++ b/Admin.NET/Admin.NET.Core/Ai/Service/DataBase/ChatChannelManager.cs @@ -1,9 +1,12 @@ -using System.Threading.Channels; -using Admin.NET.Core.Ai.Services.DataBase.Dto; -using Admin.NET.Core.Ai.Enums; -using Microsoft.Extensions.DependencyInjection; +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! -namespace Admin.NET.Core.Ai.Services.DataBase; +using System.Threading.Channels; + +namespace Admin.NET.Core.Ai.Service; public class ChatChannelManager : ISingleton { @@ -35,16 +38,19 @@ public class ChatChannelManager : ISingleton switch (action.ActionType) { - case ChatActionEnums.Append: + case ChatActionEnum.Append: await chatChannelActionService.AppendAsync(action.Item); break; - case ChatActionEnums.AppendItem: + + case ChatActionEnum.AppendItem: await chatChannelActionService.AppendItemAsync(action.Item); break; - case ChatActionEnums.DeleteAll: + + case ChatActionEnum.DeleteAll: await chatChannelActionService.DeleteAllAsync(action.Item); break; - case ChatActionEnums.RenameSummary: + + case ChatActionEnum.RenameSummary: await chatChannelActionService.RenameSummaryAsync(action.Item); break; } @@ -59,4 +65,4 @@ public class ChatChannelManager : ISingleton public ChannelReader ActionReader => _channel.Reader; public ChannelWriter ActionWriter => _channel.Writer; -} +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Ai/Service/DataBase/Dto/DataActionInput.cs b/Admin.NET/Admin.NET.Core/Ai/Service/DataBase/Dto/DataActionInput.cs new file mode 100644 index 00000000..f0f98884 --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Ai/Service/DataBase/Dto/DataActionInput.cs @@ -0,0 +1,13 @@ +// Admin.NET ĿİȨ̱ꡢרȨӦɷıʹñĿӦطɷ֤Ҫ +// +// ĿҪѭ MIT ֤ Apache ֤汾 2.0зַʹá֤λԴĿ¼е LICENSE-MIT LICENSE-APACHE ļ +// +// ñĿΣҰȫַ˺ϷȨȷɷֹĻκλڱĿοһзɾ׺ΣDzеκΣ + +namespace Admin.NET.Core.Ai.Service; + +public class DataActionInput +{ + public ChatActionEnum ActionType { get; set; } + public LLMChatSummaryHistory Item { get; set; } +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Ai/Services/Infrastructure/ChangeModelFactory.cs b/Admin.NET/Admin.NET.Core/Ai/Service/Infrastructure/ChangeModelFactory.cs similarity index 87% rename from Admin.NET/Admin.NET.Core/Ai/Services/Infrastructure/ChangeModelFactory.cs rename to Admin.NET/Admin.NET.Core/Ai/Service/Infrastructure/ChangeModelFactory.cs index 749a3bc5..22d29814 100644 --- a/Admin.NET/Admin.NET.Core/Ai/Services/Infrastructure/ChangeModelFactory.cs +++ b/Admin.NET/Admin.NET.Core/Ai/Service/Infrastructure/ChangeModelFactory.cs @@ -1,14 +1,15 @@ -using System.Net; -using Admin.NET.Core.Ai.Handlers; -using Admin.NET.Core.Ai.Interface; -using Admin.NET.Core.Ai.Models; -using Admin.NET.Core.Ai.Option; -using Microsoft.SemanticKernel.Connectors.Ollama; -using OllamaSharp; +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + using Amazon.BedrockRuntime; using Amazon.Runtime; +using OllamaSharp; +using System.Net; -namespace Admin.NET.Core.Ai.Services.Infrastructure; +namespace Admin.NET.Core.Ai.Service; /// /// 模型切换工厂 @@ -17,10 +18,12 @@ namespace Admin.NET.Core.Ai.Services.Infrastructure; public class ChangeModelFactory : ILLMFactory, ITransient { private readonly IServiceProvider _serviceProvider; + public ChangeModelFactory(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } + /// /// 创建Kernel实例 /// @@ -31,6 +34,7 @@ public class ChangeModelFactory : ILLMFactory, ITransient var builder = Kernel.CreateBuilder(); return GetKernel(builder, modelInput); } + /// /// 获取Kernel实例 /// @@ -62,6 +66,7 @@ public class ChangeModelFactory : ILLMFactory, ITransient } ConfigureKernelCore(builder, httpClient, provider, modelInput.ModelId); } + /// /// 配置Kernel核心代码 /// @@ -85,8 +90,7 @@ public class ChangeModelFactory : ILLMFactory, ITransient ); if (provider.ProductName == "OpenAI") { - - #pragma warning disable SKEXP0010 // 禁用预览API的警告 +#pragma warning disable SKEXP0010 // 禁用预览API的警告 // 如果模型是OpenAI,则添加音频转文字服务 builder.AddOpenAIAudioToText( modelId: modelId, @@ -105,9 +109,10 @@ public class ChangeModelFactory : ILLMFactory, ITransient apiKey: apiKey, httpClient: httpClient ); - #pragma warning restore +#pragma warning restore } break; + case "AzureOpenAI": builder.AddAzureOpenAIChatCompletion( deploymentName: modelId, @@ -115,7 +120,7 @@ public class ChangeModelFactory : ILLMFactory, ITransient apiKey: apiKey, httpClient: httpClient ); - #pragma warning disable SKEXP0010 // 禁用预览API的警告 +#pragma warning disable SKEXP0010 // 禁用预览API的警告 builder.AddAzureOpenAIAudioToText( deploymentName: modelId, endpoint: provider.ApiEndpoint, @@ -134,36 +139,40 @@ public class ChangeModelFactory : ILLMFactory, ITransient apiKey: apiKey, httpClient: httpClient ); - #pragma warning restore SKEXP0010 // 禁用预览API的警告 +#pragma warning restore SKEXP0010 // 禁用预览API的警告 break; + case "Ollama": var ollamaClient = new OllamaApiClient( uriString: provider.ApiEndpoint, defaultModel: modelId ); - #pragma warning disable SKEXP0070// 禁用预览API的警告 +#pragma warning disable SKEXP0070// 禁用预览API的警告 builder.AddOllamaChatCompletion( ollamaClient: ollamaClient ); - #pragma warning restore SKEXP0070// 禁用预览API的警告 +#pragma warning restore SKEXP0070// 禁用预览API的警告 break; + case "Claude": var credentials = new BasicAWSCredentials(provider.ApiKey, provider.ApiSecret); var amazonBedrockRuntime = new AmazonBedrockRuntimeClient(credentials, new AmazonBedrockRuntimeConfig { RegionEndpoint = Amazon.RegionEndpoint.GetBySystemName(provider.Region) }); - #pragma warning disable SKEXP0070 +#pragma warning disable SKEXP0070 builder.AddBedrockChatCompletionService( modelId: modelId, bedrockRuntime: amazonBedrockRuntime ); - #pragma warning restore SKEXP0070 +#pragma warning restore SKEXP0070 break; + default: throw new Exception($"未找到{provider.LLMType}模型提供者"); } } + /// /// 获取HttpClient实例,可能为null /// @@ -203,5 +212,4 @@ public class ChangeModelFactory : ILLMFactory, ITransient } return httpMessageHandler == null ? null : new HttpClient(httpMessageHandler); } -} - +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Ai/Services/Infrastructure/LLMOpenRouterClient.cs b/Admin.NET/Admin.NET.Core/Ai/Service/Infrastructure/LLMOpenRouterClient.cs similarity index 83% rename from Admin.NET/Admin.NET.Core/Ai/Services/Infrastructure/LLMOpenRouterClient.cs rename to Admin.NET/Admin.NET.Core/Ai/Service/Infrastructure/LLMOpenRouterClient.cs index 62bd8679..48e02c29 100644 --- a/Admin.NET/Admin.NET.Core/Ai/Services/Infrastructure/LLMOpenRouterClient.cs +++ b/Admin.NET/Admin.NET.Core/Ai/Service/Infrastructure/LLMOpenRouterClient.cs @@ -1,12 +1,15 @@ -using Admin.NET.Core.Ai.Models; -using Admin.NET.Core.Ai.Option; -using Admin.NET.Core.Ai.Utils; +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + using Newtonsoft.Json; -namespace Admin.NET.Core.Ai.Services.Infrastructure; +namespace Admin.NET.Core.Ai.Service; /// -/// OpenRouter 客户端 +/// OpenRouter 客户端 /// public class LLMOpenRouterClient { @@ -19,6 +22,7 @@ public class LLMOpenRouterClient _options = options.Value; _httpClient.Timeout = TimeSpan.FromSeconds(_options.Timeout); } + /// /// 获取提示词的LLM的回答 /// @@ -41,6 +45,7 @@ public class LLMOpenRouterClient } }); } + /// /// 获取聊天记录的LLM的回答 /// @@ -62,6 +67,7 @@ public class LLMOpenRouterClient } }); } + /// /// 获取LLM的回答 /// @@ -71,7 +77,7 @@ public class LLMOpenRouterClient /// 消息列表不能为空 /// 网络请求错误 /// JSON解析错误 - private async Task GetLLMResponseAsync(List messages,Action> beforeSendAction = null) + private async Task GetLLMResponseAsync(List messages, Action> beforeSendAction = null) { try { @@ -89,7 +95,7 @@ public class LLMOpenRouterClient var inputBody = new LLMInputBody(); inputBody.Model = defaultLLM.Model; inputBody.Messages = messages; - var strBody = LLMJsonTools.SerializeObject(inputBody); + var strBody = LLMJsonTool.SerializeObject(inputBody); beforeSendAction?.Invoke(messages); // 在发送请求之前,可以对消息进行修改 using (var content = new StringContent(strBody, Encoding.UTF8, "application/json")) using (var response = await _httpClient.PostAsync(_options.BaseUrl, content)) @@ -97,7 +103,7 @@ public class LLMOpenRouterClient if (response.StatusCode == System.Net.HttpStatusCode.OK) { var strResponse = await response.Content.ReadAsStringAsync(); - var output = LLMJsonTools.DeserializeObject(strResponse); + var output = LLMJsonTool.DeserializeObject(strResponse); return output.Choices[0].Message.Content; } else diff --git a/Admin.NET/Admin.NET.Core/Ai/Services/SSE/BaseSseChannelManager.cs b/Admin.NET/Admin.NET.Core/Ai/Service/SSE/BaseSseChannelManager.cs similarity index 68% rename from Admin.NET/Admin.NET.Core/Ai/Services/SSE/BaseSseChannelManager.cs rename to Admin.NET/Admin.NET.Core/Ai/Service/SSE/BaseSseChannelManager.cs index 83efd6f8..1cbba827 100644 --- a/Admin.NET/Admin.NET.Core/Ai/Services/SSE/BaseSseChannelManager.cs +++ b/Admin.NET/Admin.NET.Core/Ai/Service/SSE/BaseSseChannelManager.cs @@ -1,7 +1,12 @@ -using System.Threading.Channels; -using Admin.NET.Core.Ai.Interface; +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! -namespace Admin.NET.Core.Ai.Services.SSE; +using System.Threading.Channels; + +namespace Admin.NET.Core.Ai.Service; /// /// SSE通道管理 @@ -50,4 +55,4 @@ public class BaseSseChannelManager : ISseChannelManager await channel.Writer.WriteAsync(message, cancellationToken); } } -} +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Ai/Service/SSE/SseChannelManager.cs b/Admin.NET/Admin.NET.Core/Ai/Service/SSE/SseChannelManager.cs new file mode 100644 index 00000000..896f784a --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Ai/Service/SSE/SseChannelManager.cs @@ -0,0 +1,14 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core.Ai.Service; + +/// +/// 聊天通道管理 +/// +public class SseChannelManager : BaseSseChannelManager, ISingleton +{ +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Ai/Service/SSE/SseDeepThinkingChannelManager.cs b/Admin.NET/Admin.NET.Core/Ai/Service/SSE/SseDeepThinkingChannelManager.cs new file mode 100644 index 00000000..9262e92a --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Ai/Service/SSE/SseDeepThinkingChannelManager.cs @@ -0,0 +1,14 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core.Ai.Service; + +/// +/// 深度思考通道管理 +/// +public class SseDeepThinkingChannelManager : BaseSseChannelManager, ISingleton +{ +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Ai/Services/SSE/SseService.cs b/Admin.NET/Admin.NET.Core/Ai/Service/SSE/SseService.cs similarity index 82% rename from Admin.NET/Admin.NET.Core/Ai/Services/SSE/SseService.cs rename to Admin.NET/Admin.NET.Core/Ai/Service/SSE/SseService.cs index a653d17b..46e7697f 100644 --- a/Admin.NET/Admin.NET.Core/Ai/Services/SSE/SseService.cs +++ b/Admin.NET/Admin.NET.Core/Ai/Service/SSE/SseService.cs @@ -1,4 +1,10 @@ -namespace Admin.NET.Core.Ai.Services.SSE; +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core.Ai.Service; /// /// SSE服务 @@ -71,5 +77,4 @@ public class SseService : ControllerBase _sseDeepThinkingChannelManager.Unregister(id); } } -} - +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Ai/Services/Chat/Dto/ChatListInput.cs b/Admin.NET/Admin.NET.Core/Ai/Services/Chat/Dto/ChatListInput.cs deleted file mode 100644 index 5efd41ba..00000000 --- a/Admin.NET/Admin.NET.Core/Ai/Services/Chat/Dto/ChatListInput.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Admin.NET.Core.Ai.Services.Chat.Dto; - -public class ChatListInput : BasePageInput -{ - -} - diff --git a/Admin.NET/Admin.NET.Core/Ai/Services/Chat/Dto/ChatListOutput.cs b/Admin.NET/Admin.NET.Core/Ai/Services/Chat/Dto/ChatListOutput.cs deleted file mode 100644 index 93a80ec6..00000000 --- a/Admin.NET/Admin.NET.Core/Ai/Services/Chat/Dto/ChatListOutput.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Admin.NET.Core.Ai.Entitys; - -namespace Admin.NET.Core.Ai.Services.Chat.Dto; - -/// -/// 聊天列表输出 -/// -public class ChatListOutput:LLMChatSummaryHistory -{ -} diff --git a/Admin.NET/Admin.NET.Core/Ai/Services/Chat/Dto/ChatOutput.cs b/Admin.NET/Admin.NET.Core/Ai/Services/Chat/Dto/ChatOutput.cs deleted file mode 100644 index d70399be..00000000 --- a/Admin.NET/Admin.NET.Core/Ai/Services/Chat/Dto/ChatOutput.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace Admin.NET.Core.Ai.Services.Chat.Dto; - -public class ChatOutput -{ - /// - /// 唯一标识 - /// - public string? UniqueToken { get; set; } - - /// - /// 备注 - /// - public string? Note { get; set; } - - /// - /// 状态 - /// - public bool State { get; set; } = true; - - /// - /// 摘要 - /// - public string? Summary { get; set; } = ""; - - /// - /// 摘要ID - /// - public long? SummaryId { get; set; } -} - diff --git a/Admin.NET/Admin.NET.Core/Ai/Services/Chat/Dto/ModelListChangeInput.cs b/Admin.NET/Admin.NET.Core/Ai/Services/Chat/Dto/ModelListChangeInput.cs deleted file mode 100644 index 333e3511..00000000 --- a/Admin.NET/Admin.NET.Core/Ai/Services/Chat/Dto/ModelListChangeInput.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Admin.NET.Core.Ai.Services.Chat.Dto; - -public class ModelListChangeInput:ModelListOutputItem -{ - -} - diff --git a/Admin.NET/Admin.NET.Core/Ai/Services/DataBase/Dto/DataActionInput.cs b/Admin.NET/Admin.NET.Core/Ai/Services/DataBase/Dto/DataActionInput.cs deleted file mode 100644 index 0859130a..00000000 --- a/Admin.NET/Admin.NET.Core/Ai/Services/DataBase/Dto/DataActionInput.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Admin.NET.Core.Ai.Entitys; -using Admin.NET.Core.Ai.Enums; - -namespace Admin.NET.Core.Ai.Services.DataBase.Dto; - -public class DataActionInput -{ - public ChatActionEnums ActionType { get; set; } - public LLMChatSummaryHistory Item { get; set; } -} - diff --git a/Admin.NET/Admin.NET.Core/Ai/Services/SSE/SseChannelManager.cs b/Admin.NET/Admin.NET.Core/Ai/Services/SSE/SseChannelManager.cs deleted file mode 100644 index 9d64a68c..00000000 --- a/Admin.NET/Admin.NET.Core/Ai/Services/SSE/SseChannelManager.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Threading.Channels; - -namespace Admin.NET.Core.Ai.Services.SSE; - -/// -/// 聊天通道管理 -/// -public class SseChannelManager: BaseSseChannelManager,ISingleton -{ -} diff --git a/Admin.NET/Admin.NET.Core/Ai/Services/SSE/SseDeepThinkingChannelManager.cs b/Admin.NET/Admin.NET.Core/Ai/Services/SSE/SseDeepThinkingChannelManager.cs deleted file mode 100644 index a12fef36..00000000 --- a/Admin.NET/Admin.NET.Core/Ai/Services/SSE/SseDeepThinkingChannelManager.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Threading.Channels; - -namespace Admin.NET.Core.Ai.Services.SSE; - -/// -/// 深度思考通道管理 -/// -public class SseDeepThinkingChannelManager: BaseSseChannelManager,ISingleton -{ -} diff --git a/Admin.NET/Admin.NET.Core/Ai/Utils/LLMJsonTools.cs b/Admin.NET/Admin.NET.Core/Ai/Utils/LLMJsonTool.cs similarity index 64% rename from Admin.NET/Admin.NET.Core/Ai/Utils/LLMJsonTools.cs rename to Admin.NET/Admin.NET.Core/Ai/Utils/LLMJsonTool.cs index 40a8da15..04393c3d 100644 --- a/Admin.NET/Admin.NET.Core/Ai/Utils/LLMJsonTools.cs +++ b/Admin.NET/Admin.NET.Core/Ai/Utils/LLMJsonTool.cs @@ -1,12 +1,18 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + using Newtonsoft.Json; using Newtonsoft.Json.Serialization; -namespace Admin.NET.Core.Ai.Utils; +namespace Admin.NET.Core; /// /// LLM JSON 工具类 /// -public class LLMJsonTools +public class LLMJsonTool { /// /// 序列化对象 @@ -42,4 +48,4 @@ public class LLMJsonTools }; return JsonConvert.DeserializeObject(json, settings); } -} +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/GlobalUsings.cs b/Admin.NET/Admin.NET.Core/GlobalUsings.cs index 6c9bb416..6ca68b7a 100644 --- a/Admin.NET/Admin.NET.Core/GlobalUsings.cs +++ b/Admin.NET/Admin.NET.Core/GlobalUsings.cs @@ -34,6 +34,7 @@ global using Microsoft.Extensions.DependencyInjection; global using Microsoft.Extensions.Hosting; global using Microsoft.Extensions.Logging; global using Microsoft.Extensions.Options; +global using Microsoft.SemanticKernel; global using NewLife; global using NewLife.Caching; global using Newtonsoft.Json.Linq; @@ -59,7 +60,4 @@ global using System.Text; global using System.Text.RegularExpressions; global using System.Web; global using UAParser; -global using Yitter.IdGenerator; - -global using Microsoft.SemanticKernel; -global using Microsoft.SemanticKernel.PromptTemplates.Handlebars; \ No newline at end of file +global using Yitter.IdGenerator; \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Utils/System/CodeGenHelper.cs b/Admin.NET/Admin.NET.Core/Utils/System/CodeGenHelper.cs index e905ae50..aa71b300 100644 --- a/Admin.NET/Admin.NET.Core/Utils/System/CodeGenHelper.cs +++ b/Admin.NET/Admin.NET.Core/Utils/System/CodeGenHelper.cs @@ -157,13 +157,13 @@ public static class CodeGenHelper { return dataType.ToLower() switch { - "tinytext" or "mediumtext" or "longtext" or "mid" or "text" or "varchar" or "char" or "nvarchar" or "nchar" or "timestamp" => "string", - "int" or "integer" => "int", + "tinytext" or "mediumtext" or "longtext" or "mid" or "text" or "varchar" or "char" or "nvarchar" or "nchar" or "string" or "timestamp" => "string", + "int" or "integer" or "int32" => "int", "smallint" => "Int16", //"tinyint" => "byte", - "tinyint" => "bool", // MYSQL - "bigint" => "long", - "bit" => "bool", + "tinyint" => "bool", // MYSQL + "bigint" or "int64" => "long", + "bit" or "boolean" => "bool", "money" or "smallmoney" or "numeric" or "decimal" => "decimal", "real" => "Single", "datetime" or "datetime2" or "smalldatetime" => "DateTime", diff --git a/Admin.NET/Admin.NET.Web.Core/ProjectOptions.cs b/Admin.NET/Admin.NET.Web.Core/ProjectOptions.cs index f1244200..dbdbe152 100644 --- a/Admin.NET/Admin.NET.Web.Core/ProjectOptions.cs +++ b/Admin.NET/Admin.NET.Web.Core/ProjectOptions.cs @@ -5,7 +5,6 @@ // 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! using Admin.NET.Core; -using Admin.NET.Core.Ai.Option; using AspNetCoreRateLimit; using Furion; using Microsoft.Extensions.DependencyInjection; @@ -44,9 +43,8 @@ public static class ProjectOptions services.Configure(App.Configuration.GetSection("ClientRateLimiting")); services.Configure(App.Configuration.GetSection("ClientRateLimitPolicies")); - services.AddConfigurableOptions(); //手动实现LLM接口配置选项 - services.AddConfigurableOptions(); //基于Microsoft Semantic Kernel实现,也是本应用的默认实现 - + services.AddConfigurableOptions(); // 手动实现LLM接口配置选项 + services.AddConfigurableOptions(); // 基于Microsoft Semantic Kernel实现,也是本应用的默认实现 return services; } diff --git a/Admin.NET/Admin.NET.Web.Core/Startup.cs b/Admin.NET/Admin.NET.Web.Core/Startup.cs index fe07cb90..74005d85 100644 --- a/Admin.NET/Admin.NET.Web.Core/Startup.cs +++ b/Admin.NET/Admin.NET.Web.Core/Startup.cs @@ -5,7 +5,6 @@ // 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! using Admin.NET.Core; -using Admin.NET.Core.Ai.Extentions; using Admin.NET.Core.Service; using AspNetCoreRateLimit; using Furion; @@ -137,10 +136,9 @@ public class Startup : AppStartup // SqlSugar services.AddSqlSugar(); - #region 注册LLM大模型 + // 注册LLM大模型 services.AddLLMFactory(); // 注册LLM模型工厂,如果需要切换模型,请引入ILLMFactory接口,调用CreateKernel方法获取Kernel实例 services.AddLLM(); // 注册LLM大模型,注意:此扩展不能切换模型,只能使用一个模型 - #endregion // 三方授权登录OAuth services.AddOAuth(); @@ -421,12 +419,14 @@ public class Startup : AppStartup options.EnableDirectoryBrowsing = false; // 是否启用目录浏览 options.Title = "定时任务看板"; // 自定义看板标题 - options.LoginHandle = async (username, password, httpContext) => + options.LoginConfig.OnLoging = async (username, password, httpContext) => { var res = await httpContext.RequestServices.GetRequiredService().SwaggerSubmitUrl(new SpecificationAuth { UserName = username, Password = password }); return res == 200; }; - options.LoginSessionKey = "schedule_session_key"; // 登录客户端存储的 Session 键 + options.LoginConfig.DefaultUsername = ""; + options.LoginConfig.DefaultPassword = ""; + options.LoginConfig.SessionKey = "schedule_session_key"; // 登录客户端存储的 Session 键 }); // 配置Swagger-Knife4UI(路由前缀一致代表独立,不同则代表共存) diff --git a/Admin.NET/Plugins/Admin.NET.Plugin.ReZero/Admin.NET.Plugin.ReZero.csproj b/Admin.NET/Plugins/Admin.NET.Plugin.ReZero/Admin.NET.Plugin.ReZero.csproj index 609a12c3..c6b3ff82 100644 --- a/Admin.NET/Plugins/Admin.NET.Plugin.ReZero/Admin.NET.Plugin.ReZero.csproj +++ b/Admin.NET/Plugins/Admin.NET.Plugin.ReZero/Admin.NET.Plugin.ReZero.csproj @@ -26,7 +26,7 @@ - + diff --git a/Web/package.json b/Web/package.json index 106cecba..2b515b2a 100644 --- a/Web/package.json +++ b/Web/package.json @@ -2,7 +2,7 @@ "name": "admin.net.pro", "type": "module", "version": "2.4.33", - "lastBuildTime": "2025.06.17", + "lastBuildTime": "2025.06.19", "description": "Admin.NET 站在巨人肩膀上的 .NET 通用权限开发框架", "author": "zuohuaijun", "license": "MIT", @@ -70,7 +70,7 @@ "uuid": "^11.1.0", "vcrontab-3": "^3.3.22", "vform3-builds": "^3.0.10", - "vue": "^3.5.16", + "vue": "^3.5.17", "vue-clipboard3": "^2.0.0", "vue-demi": "0.14.10", "vue-draggable-plus": "^0.6.0", @@ -83,15 +83,14 @@ "vue-router": "^4.5.1", "vue-signature-pad": "^3.0.2", "vue3-tree-org": "^4.2.2", - "vxe-pc-ui": "^4.6.24", - "vxe-table": "^4.13.40", + "vxe-pc-ui": "^4.6.26", + "vxe-table": "^4.13.42", "xe-utils": "^3.7.5", "xlsx-js-style": "^1.2.0" }, "devDependencies": { "@iconify/vue": "^5.0.0", "@plugin-web-update-notification/vite": "^2.0.0", - "@types/franc": "^6.0.0", "@types/lodash-es": "^4.17.12", "@types/node": "^22.15.32", "@types/nprogress": "^0.2.3", @@ -100,7 +99,7 @@ "@typescript-eslint/parser": "^8.34.1", "@vitejs/plugin-vue": "^5.2.4", "@vitejs/plugin-vue-jsx": "^4.2.0", - "@vue/compiler-sfc": "^3.5.16", + "@vue/compiler-sfc": "^3.5.17", "code-inspector-plugin": "^0.20.12", "eslint": "^9.29.0", "eslint-plugin-vue": "^10.2.0", @@ -109,7 +108,7 @@ "prettier": "^3.5.3", "rollup-plugin-visualizer": "^6.0.3", "sass": "^1.89.2", - "terser": "^5.42.0", + "terser": "^5.43.0", "typescript": "^5.8.3", "vite": "^6.3.5", "vite-plugin-cdn-import": "^1.0.1", diff --git a/Web/src/api-services/models/llmchat-history.ts b/Web/src/api-services/models/llmchat-history.ts index f76cce9e..be7d6bad 100644 --- a/Web/src/api-services/models/llmchat-history.ts +++ b/Web/src/api-services/models/llmchat-history.ts @@ -14,7 +14,7 @@ import { LLMChatSummaryHistory } from './llmchat-summary-history'; /** - * 聊天历史 + * 聊天历史表 * * @export * @interface LLMChatHistory diff --git a/Web/src/api-services/models/llmchat-summary-history.ts b/Web/src/api-services/models/llmchat-summary-history.ts index c6d0f90f..dcb7ce71 100644 --- a/Web/src/api-services/models/llmchat-summary-history.ts +++ b/Web/src/api-services/models/llmchat-summary-history.ts @@ -14,7 +14,7 @@ import { LLMChatHistory } from './llmchat-history'; /** - * 聊天摘要历史 + * 聊天摘要历史表 * * @export * @interface LLMChatSummaryHistory diff --git a/Web/src/main.ts b/Web/src/main.ts index 02bc33df..42856e8e 100644 --- a/Web/src/main.ts +++ b/Web/src/main.ts @@ -26,13 +26,12 @@ import JwChat from 'jwchat'; import 'jwchat/lib/style.css'; // 自定义字典组件 import sysDict from '/@/components/sysDict/sysDict.vue'; +// AI组件 import ElementPlusX from 'vue-element-plus-x'; import 'vue-markdown-shiki/style' -import markdownPlugin from 'vue-markdown-shiki' //markodwn渲染组件,由于element-plus-x的thinking不支持markdown,所以需要单独引入,未来element-plus-x组成成熟应该会被移转 +import markdownPlugin from 'vue-markdown-shiki' // 关闭自动打印 import { disAutoConnect } from 'vue-plugin-hiprint'; - - disAutoConnect(); const app = createApp(App); diff --git a/Web/src/router/route.ts b/Web/src/router/route.ts index ad97a8f9..40a86e08 100644 --- a/Web/src/router/route.ts +++ b/Web/src/router/route.ts @@ -50,13 +50,13 @@ export const dynamicRoutes: Array = [ children: [], }, { - path: '/llm/chat', - name: 'chat', - component: () => import('/@/views/chat/index.vue'), + path: '/llm/aiChat', + name: 'aiChat', + component: () => import('/@/views/aiChat/index.vue'), meta: { title: 'AI对话', isKeepAlive: true, - } + }, }, { path: '/platform/job/dashboard', diff --git a/Web/src/types/franc.d.ts b/Web/src/types/franc.d.ts index fb217e93..1f9d93f9 100644 --- a/Web/src/types/franc.d.ts +++ b/Web/src/types/franc.d.ts @@ -1,3 +1,3 @@ declare module 'franc' { - export function franc(text: string): string; -} \ No newline at end of file + export function franc(text: string): string; +} diff --git a/Web/src/types/vue-element-plus-x.d.ts b/Web/src/types/vue-element-plus-x.d.ts index efbb8c5a..f72e92e3 100644 --- a/Web/src/types/vue-element-plus-x.d.ts +++ b/Web/src/types/vue-element-plus-x.d.ts @@ -1 +1 @@ -declare module 'vue-element-plus-x'; \ No newline at end of file +declare module 'vue-element-plus-x'; diff --git a/Web/src/utils/useInfo.ts b/Web/src/utils/useInfo.ts index 7b54cc96..1dc5f9f5 100644 --- a/Web/src/utils/useInfo.ts +++ b/Web/src/utils/useInfo.ts @@ -1,19 +1,18 @@ import { useUserInfo } from '/@/stores/userInfo'; -const {userInfos} = useUserInfo(); +const { userInfos } = useUserInfo(); /** * 判断是否是超级管理员 - * @returns + * @returns */ export const isSupperAdmin = (): boolean => { return userInfos?.accountType === 999; }; - /** * 判断是否是租户管理员 - * @returns + * @returns */ export const isTenantAdmin = (): boolean => { return userInfos?.accountType === 888; @@ -21,7 +20,7 @@ export const isTenantAdmin = (): boolean => { /** * 判断是否是管理员 - * @returns + * @returns */ export const isAdmin = (): boolean => { return isSupperAdmin() || isTenantAdmin(); @@ -29,92 +28,91 @@ export const isAdmin = (): boolean => { /** * 判断是否是普通用户 - * @returns + * @returns */ export const isNormalUser = (): boolean => { return userInfos?.accountType === 777; }; - /** * 判断是否是会员 - * @returns + * @returns */ export const isMember = (): boolean => { return userInfos?.accountType === 666; -}; +}; /** * 获取邮件 * @returns 获取邮件 */ -export const userEmail = ():string => { +export const userEmail = (): string => { return userInfos?.email; -} +}; /** * 获取用户id * @returns 获取用户id */ -export const userName = ():string => { +export const userName = (): string => { return userInfos?.userName; -} +}; /** * 获取用户好友名称 * @returns 获取用户好友名称 */ -export const userFriendName = ():string => ( - userInfos?.realName ? userInfos?.realName : userInfos?.account ? userInfos?.account : userInfos?.email -) +export const userFriendName = (): string => (userInfos?.realName ? userInfos?.realName : userInfos?.account ? userInfos?.account : userInfos?.email); /** * 获取租户id * @returns 获取租户id */ -export const tenantId = ():number => { +export const tenantId = (): number => { return userInfos?.tenantId; -} +}; /*** * 获取用户账户. */ -export const userAccount = ():string => userInfos?.account; +export const userAccount = (): string => userInfos?.account; /** * 获取用户手机 * @returns 获取用户手机 */ -export const userPhone = ():string => userInfos?.phone; +export const userPhone = (): string => userInfos?.phone; /** * 获取用户id * @returns 获取用户id. */ -export const userId = ():number => userInfos?.id; +export const userId = (): number => userInfos?.id; /** * 获取组织id * @returns 获取组织id */ -export const orgId = ():number => userInfos?.orgId; +export const orgId = (): number => userInfos?.orgId; /** * 获取组织名称 * @returns 获取组织名称 */ -export const orgName = ():string => userInfos?.orgName; +export const orgName = (): string => userInfos?.orgName; + /** * 获取职位id * @returns 获取职位id. */ -export const posId = ():number => userInfos?.posId; +export const posId = (): number => userInfos?.posId; + /** * 获取部位名称 * @returns 获取职位名称 */ -export const posName = ():string => userInfos?.posName; +export const posName = (): string => userInfos?.posName; -export const hasPrivilege = (privilege: string):boolean => { +export const hasPrivilege = (privilege: string): boolean => { return userInfos.authApiList.includes(privilege); -} +}; diff --git a/Web/src/views/aiChat/index.vue b/Web/src/views/aiChat/index.vue new file mode 100644 index 00000000..b17791b5 --- /dev/null +++ b/Web/src/views/aiChat/index.vue @@ -0,0 +1,1118 @@ + + + + + diff --git a/Web/src/views/chat/index.vue b/Web/src/views/chat/index.vue deleted file mode 100644 index c5e138fb..00000000 --- a/Web/src/views/chat/index.vue +++ /dev/null @@ -1,1090 +0,0 @@ - - - - - diff --git a/Web/vite.config.ts b/Web/vite.config.ts index 059f77c3..1b7e72ba 100644 --- a/Web/vite.config.ts +++ b/Web/vite.config.ts @@ -9,10 +9,10 @@ import { CodeInspectorPlugin } from 'code-inspector-plugin'; import fs from 'fs'; import { visualizer } from 'rollup-plugin-visualizer'; import { webUpdateNotice } from '@plugin-web-update-notification/vite'; +import { copyPublicPlugin } from 'vite-plugin-forvmsc'; // monaco 菜单汉化 https://wf0.github.io/example/plugins/I18n.html import monacoZhHans from './public/monaco/zh-hans.json'; import nlsPlugin, { Languages, esbuildPluginMonacoEditorNls } from './public/monaco/vite-plugin-i18n-nls'; -import { copyPublicPlugin } from 'vite-plugin-forvmsc' const pathResolve = (dir: string) => { return resolve(__dirname, '.', dir);