fix(llm): 将自定义接入LLM模式删除,全部改成微软官方接入方式
This commit is contained in:
commit
dd43e3a7a7
@ -156,5 +156,36 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"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"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -34,7 +34,7 @@
|
||||
},
|
||||
"TableSettings": {
|
||||
"EnableInitTable": true, // 启用表初始化(若实体没有变化建议关闭)
|
||||
"EnableIncreTable": true // 启用表增量更新(只更新贴了特性[IncreTable]的实体表)
|
||||
"EnableIncreTable": false // 启用表增量更新(只更新贴了特性[IncreTable]的实体表)
|
||||
},
|
||||
"SeedSettings": {
|
||||
"EnableInitSeed": true, // 启用种子初始化(若种子没有变化建议关闭)
|
||||
|
||||
@ -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;
|
||||
@ -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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 演示大模型的使用,可以切换模型。
|
||||
/// 例如:可以切换到不同的模型,如:OpenAI、Azure OpenAI、Google Gemini等。
|
||||
@ -25,5 +30,4 @@ public class LLMChangeModelTestService : IDynamicApiController, ITransient
|
||||
var result = await kernel.InvokePromptAsync("请介绍自己");
|
||||
return result.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
|
||||
@ -28,9 +28,9 @@
|
||||
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
|
||||
<PackageReference Include="BouncyCastle.Cryptography" Version="2.6.1" Aliases="BouncyCastleV2" />
|
||||
<PackageReference Include="Elastic.Clients.Elasticsearch" Version="9.0.6" />
|
||||
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.7.87" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.87" />
|
||||
<PackageReference Include="Furion.Pure" Version="4.9.7.87" />
|
||||
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.7.88" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.88" />
|
||||
<PackageReference Include="Furion.Pure" Version="4.9.7.88" />
|
||||
<PackageReference Include="Hardware.Info" Version="101.0.1.1" />
|
||||
<PackageReference Include="Hashids.net" Version="1.7.0" />
|
||||
<PackageReference Include="IPTools.China" Version="1.6.0" />
|
||||
@ -59,15 +59,15 @@
|
||||
<PackageReference Include="TencentCloudSDK.Sms" Version="3.0.1259" />
|
||||
<PackageReference Include="UAParser" Version="3.1.47" />
|
||||
<PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />
|
||||
<PackageReference Include="microsoft.semantickernel" Version="1.54.0" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.Agents.Core" Version="1.54.0" />
|
||||
<PackageReference Include="microsoft.semantickernel" Version="1.57.0" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.Agents.Core" Version="1.57.0" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.Connectors.Amazon" Version="1.56.0-alpha" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.Connectors.Google" Version="1.54.0-alpha" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.Connectors.HuggingFace" Version="1.56.0-preview" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.Connectors.Ollama" Version="1.54.0-alpha" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.Connectors.Qdrant" Version="1.54.0-preview" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.PromptTemplates.Handlebars" Version="1.54.0" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.Yaml" Version="1.54.0" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.PromptTemplates.Handlebars" Version="1.57.0" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.Yaml" Version="1.57.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net8.0' ">
|
||||
|
||||
@ -1,12 +1,17 @@
|
||||
namespace Admin.NET.Core.Ai.Entitys;
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
namespace Admin.NET.Core;
|
||||
|
||||
/// <summary>
|
||||
/// 聊天历史
|
||||
/// 聊天历史表
|
||||
/// </summary>
|
||||
[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
|
||||
{
|
||||
/// <summary>
|
||||
@ -44,4 +49,4 @@ public class LLMChatHistory : EntityBaseId
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDescription = "创建时间")]
|
||||
public long UtcCreateTime { get; set; } = DateTime.UtcNow.ToLong();
|
||||
}
|
||||
}
|
||||
46
Admin.NET/Admin.NET.Core/Ai/Entity/LLMChatSummaryHistory.cs
Normal file
46
Admin.NET/Admin.NET.Core/Ai/Entity/LLMChatSummaryHistory.cs
Normal file
@ -0,0 +1,46 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
namespace Admin.NET.Core;
|
||||
|
||||
/// <summary>
|
||||
/// 聊天摘要历史表
|
||||
/// </summary>
|
||||
[SugarTable(null, "AI聊天摘要历史表")]
|
||||
[SugarIndex("i_{table}_us", nameof(UserId), OrderByType.Asc)]
|
||||
[SugarIndex("i_{table}_un", nameof(UniqueToken), OrderByType.Asc)]
|
||||
public class LLMChatSummaryHistory : EntityBaseId
|
||||
{
|
||||
/// <summary>
|
||||
/// 用户ID
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDescription = "用户ID")]
|
||||
public long UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 唯一标识
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDescription = "唯一标识")]
|
||||
public string UniqueToken { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 摘要
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDescription = "摘要", Length = 4000)]
|
||||
public string? Summary { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDescription = "创建时间")]
|
||||
public long UtcCreateTime { get; set; } = DateTime.UtcNow.ToLong();
|
||||
|
||||
/// <summary>
|
||||
/// 聊天历史
|
||||
/// </summary>
|
||||
[Navigate(NavigateType.OneToMany, nameof(LLMChatHistory.SummaryId))]
|
||||
public List<LLMChatHistory>? Histories { get; set; }
|
||||
}
|
||||
@ -1,40 +0,0 @@
|
||||
namespace Admin.NET.Core.Ai.Entitys;
|
||||
|
||||
/// <summary>
|
||||
/// 聊天摘要历史
|
||||
/// </summary>
|
||||
[SugarTable("LLMChatSummaryHistory")]
|
||||
[IncreTable]
|
||||
[SugarIndex("index_UserId_{table}", nameof(UserId), OrderByType.Asc)]
|
||||
[SugarIndex("index_UniqueToken_{table}", nameof(UniqueToken), OrderByType.Asc)]
|
||||
public class LLMChatSummaryHistory:EntityBaseId
|
||||
{
|
||||
/// <summary>
|
||||
/// 用户ID
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDescription = "用户ID")]
|
||||
public long UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 唯一标识
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDescription = "唯一标识")]
|
||||
public string UniqueToken {get;set;}
|
||||
|
||||
/// <summary>
|
||||
/// 摘要
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDescription = "摘要",Length = 4000)]
|
||||
public string? Summary { get; set; }
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDescription = "创建时间")]
|
||||
public long UtcCreateTime {get;set;} = DateTime.UtcNow.ToLong();
|
||||
|
||||
/// <summary>
|
||||
/// 聊天历史
|
||||
/// </summary>
|
||||
[Navigate(NavigateType.OneToMany, nameof(LLMChatHistory.SummaryId))]
|
||||
public List<LLMChatHistory>? Histories { get; set; }
|
||||
}
|
||||
43
Admin.NET/Admin.NET.Core/Ai/Enum/ChatActionEnum.cs
Normal file
43
Admin.NET/Admin.NET.Core/Ai/Enum/ChatActionEnum.cs
Normal file
@ -0,0 +1,43 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
namespace Admin.NET.Core;
|
||||
|
||||
/// <summary>
|
||||
/// 保存数据库的动作枚举
|
||||
/// </summary>
|
||||
public enum ChatActionEnum
|
||||
{
|
||||
/// <summary>
|
||||
/// 无
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// 追加
|
||||
/// </summary>
|
||||
Append,
|
||||
|
||||
/// <summary>
|
||||
/// 追加明细
|
||||
/// </summary>
|
||||
AppendItem,
|
||||
|
||||
/// <summary>
|
||||
/// 删除所有
|
||||
/// </summary>
|
||||
DeleteAll,
|
||||
|
||||
/// <summary>
|
||||
/// 删除指定明细
|
||||
/// </summary>
|
||||
DeleteItem,
|
||||
|
||||
/// <summary>
|
||||
/// 重命名摘要
|
||||
/// </summary>
|
||||
RenameSummary,
|
||||
}
|
||||
@ -1,32 +0,0 @@
|
||||
namespace Admin.NET.Core.Ai.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// 保存数据库的动作枚举
|
||||
/// </summary>
|
||||
public enum ChatActionEnums
|
||||
{
|
||||
/// <summary>
|
||||
/// 无
|
||||
/// </summary>
|
||||
None = 0,
|
||||
/// <summary>
|
||||
/// 追加
|
||||
/// </summary>
|
||||
Append,
|
||||
/// <summary>
|
||||
/// 追加明细
|
||||
/// </summary>
|
||||
AppendItem,
|
||||
/// <summary>
|
||||
/// 删除所有
|
||||
/// </summary>
|
||||
DeleteAll,
|
||||
/// <summary>
|
||||
/// 删除指定明细
|
||||
/// </summary>
|
||||
DeleteItem,
|
||||
/// <summary>
|
||||
/// 重命名摘要
|
||||
/// </summary>
|
||||
RenameSummary,
|
||||
}
|
||||
23
Admin.NET/Admin.NET.Core/Ai/Extention/LLMFactoryExtention.cs
Normal file
23
Admin.NET/Admin.NET.Core/Ai/Extention/LLMFactoryExtention.cs
Normal file
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// 注册LLM模型工厂
|
||||
/// </summary>
|
||||
/// <param name="services"></param>
|
||||
/// <returns></returns>
|
||||
public static IServiceCollection AddLLMFactory(this IServiceCollection services)
|
||||
{
|
||||
services.AddTransient<ILLMFactory, ChangeModelFactory>();
|
||||
return services;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// LLM注册扩展类
|
||||
@ -47,4 +37,4 @@ public static class LLMRegisterExtention
|
||||
});
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// 注册LLM模型工厂
|
||||
/// </summary>
|
||||
/// <param name="services"></param>
|
||||
/// <returns></returns>
|
||||
public static IServiceCollection AddLLMFactory(this IServiceCollection services)
|
||||
{
|
||||
services.AddTransient<ILLMFactory, ChangeModelFactory>();
|
||||
return services;
|
||||
}
|
||||
}
|
||||
|
||||
26
Admin.NET/Admin.NET.Core/Ai/Handler/LLMDelegatingHandler.cs
Normal file
26
Admin.NET/Admin.NET.Core/Ai/Handler/LLMDelegatingHandler.cs
Normal file
@ -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<LLMCustomOptions> options)
|
||||
{
|
||||
_options = options.Value;
|
||||
}
|
||||
|
||||
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||
{
|
||||
//设置header
|
||||
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _options.ApiKey);
|
||||
return await base.SendAsync(request, cancellationToken);
|
||||
}
|
||||
}
|
||||
@ -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<LoggingHandler> _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)
|
||||
@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// LLM工厂接口
|
||||
@ -13,5 +17,4 @@ public interface ILLMFactory
|
||||
/// <param name="modelInput">模型输入</param>
|
||||
/// <returns></returns>
|
||||
Kernel CreateKernel(LLMModelInput modelInput);
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// SSE通道管理接口
|
||||
@ -11,11 +17,13 @@ public interface ISseChannelManager
|
||||
/// 注册
|
||||
/// </summary>
|
||||
ChannelReader<string> Register(long userId);
|
||||
|
||||
/// <summary>
|
||||
/// 注销
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
void Unregister(long userId);
|
||||
|
||||
/// <summary>
|
||||
/// 发送消息
|
||||
/// </summary>
|
||||
|
||||
32
Admin.NET/Admin.NET.Core/Ai/Model/LLMInputBody.cs
Normal file
32
Admin.NET/Admin.NET.Core/Ai/Model/LLMInputBody.cs
Normal file
@ -0,0 +1,32 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
namespace Admin.NET.Core;
|
||||
|
||||
/// <summary>
|
||||
/// LLM请求体
|
||||
/// </summary>
|
||||
public class LLMInputBody
|
||||
{
|
||||
public string Model { get; set; }
|
||||
public List<LLMInputMessage> Messages { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// LLM请求体消息
|
||||
/// </summary>
|
||||
public class LLMInputMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// 角色,system、user、assistant
|
||||
/// </summary>
|
||||
public string Role { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 内容
|
||||
/// </summary>
|
||||
public string Content { get; set; }
|
||||
}
|
||||
24
Admin.NET/Admin.NET.Core/Ai/Model/LLMModelInput.cs
Normal file
24
Admin.NET/Admin.NET.Core/Ai/Model/LLMModelInput.cs
Normal file
@ -0,0 +1,24 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
namespace Admin.NET.Core;
|
||||
|
||||
/// <summary>
|
||||
/// LLM模型输入
|
||||
/// 用途:切换模型
|
||||
/// </summary>
|
||||
public class LLMModelInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 产品名称
|
||||
/// </summary>
|
||||
public string ProductName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型ID
|
||||
/// </summary>
|
||||
public string ModelId { get; set; }
|
||||
}
|
||||
@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// LLM输出
|
||||
/// </summary>
|
||||
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 {
|
||||
/// <summary>
|
||||
/// LLM输出机会
|
||||
/// </summary>
|
||||
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 {
|
||||
/// <summary>
|
||||
/// LLM输出消息
|
||||
/// </summary>
|
||||
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 {
|
||||
/// <summary>
|
||||
/// LLM的消耗
|
||||
/// </summary>
|
||||
public class Usage {
|
||||
public class Usage
|
||||
{
|
||||
public int PromptTokens { get; set; }
|
||||
public int CompletionTokens { get; set; }
|
||||
public int TotalTokens { get; set; }
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -1,25 +0,0 @@
|
||||
namespace Admin.NET.Core.Ai.Models;
|
||||
|
||||
/// <summary>
|
||||
/// LLM请求体
|
||||
/// </summary>
|
||||
public class LLMInputBody {
|
||||
public string Model { get; set; }
|
||||
public List<LLMInputMessage> Messages { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// LLM请求体消息
|
||||
/// </summary>
|
||||
public class LLMInputMessage {
|
||||
/// <summary>
|
||||
/// 角色,system、user、assistant
|
||||
/// </summary>
|
||||
public string Role { get; set; }
|
||||
/// <summary>
|
||||
/// 内容
|
||||
/// </summary>
|
||||
public string Content { get; set; }
|
||||
}
|
||||
|
||||
|
||||
@ -1,18 +0,0 @@
|
||||
namespace Admin.NET.Core.Ai.Models;
|
||||
|
||||
/// <summary>
|
||||
/// LLM模型输入
|
||||
/// 用途:切换模型
|
||||
/// </summary>
|
||||
public class LLMModelInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 产品名称
|
||||
/// </summary>
|
||||
public string ProductName { get; set; }
|
||||
/// <summary>
|
||||
/// 模型ID
|
||||
/// </summary>
|
||||
public string ModelId { get; set; }
|
||||
}
|
||||
|
||||
35
Admin.NET/Admin.NET.Core/Ai/Option/LLMCustomOptions.cs
Normal file
35
Admin.NET/Admin.NET.Core/Ai/Option/LLMCustomOptions.cs
Normal file
@ -0,0 +1,35 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
namespace Admin.NET.Core;
|
||||
|
||||
/// <summary>
|
||||
/// 手动实现LLM接口配置选项
|
||||
/// </summary>
|
||||
public class LLMCustomOptions : IConfigurableOptions
|
||||
{
|
||||
public string LLMType { get; set; } = "openrouter";
|
||||
public string ApiKey { get; set; }
|
||||
public string BaseUrl { get; set; } = "https://openrouter.ai/api/v1/chat/completions";
|
||||
public string InitSystemChatMessage { get; set; } = "你是一个经验丰富的AI助手,请根据用户的问题给出最准确的回答,每个回答都以markdown格式输出";
|
||||
public string InitSystemPromptMessage { get; set; } = "你是一个经验丰富的AI助手,请根据用户的问题给出最准确的回答";
|
||||
public bool CanUserSwitchLLM { get; set; } = false;
|
||||
public string ModelProvider { get; set; }
|
||||
public int MaxHistory { get; set; } = 10;
|
||||
public bool IsUserProxy { get; set; } = false;
|
||||
public string ProxyUrl { get; set; } = "";
|
||||
public int Timeout { get; set; } = 30;
|
||||
public List<LLMItem> SupportLLMList { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// LLM配置选项
|
||||
/// </summary>
|
||||
public class LLMItem
|
||||
{
|
||||
public string Desciption { get; set; }
|
||||
public string Model { get; set; }
|
||||
}
|
||||
@ -1,4 +1,10 @@
|
||||
namespace Admin.NET.Core.Ai.Option;
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
namespace Admin.NET.Core;
|
||||
|
||||
/// <summary>
|
||||
/// LLM配置选项
|
||||
@ -48,5 +54,4 @@ public class EmbeddingOptions
|
||||
{
|
||||
public string ModelId { get; set; }
|
||||
public List<string> SupportModelIds { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
@ -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
|
||||
/// </summary>
|
||||
public long SummaryId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 摘要
|
||||
/// </summary>
|
||||
public string? Summary { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 摘要唯一标识
|
||||
/// </summary>
|
||||
public string? UniqueToken { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// 消息
|
||||
/// </summary>
|
||||
@ -24,14 +33,13 @@ public class ChatInput
|
||||
/// </summary>
|
||||
public string ProviderName { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 模型id
|
||||
/// </summary>
|
||||
public string ModelId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 深度思考
|
||||
/// </summary>
|
||||
public bool DeepThinking { get; set; } = false;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
namespace Admin.NET.Core.Ai.Service;
|
||||
|
||||
public class ChatListInput : BasePageInput
|
||||
{
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
namespace Admin.NET.Core.Ai.Service;
|
||||
|
||||
/// <summary>
|
||||
/// 聊天列表输出
|
||||
/// </summary>
|
||||
public class ChatListOutput : LLMChatSummaryHistory
|
||||
{
|
||||
}
|
||||
35
Admin.NET/Admin.NET.Core/Ai/Service/Chat/Dto/ChatOutput.cs
Normal file
35
Admin.NET/Admin.NET.Core/Ai/Service/Chat/Dto/ChatOutput.cs
Normal file
@ -0,0 +1,35 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
namespace Admin.NET.Core.Ai.Service;
|
||||
|
||||
public class ChatOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// 唯一标识
|
||||
/// </summary>
|
||||
public string? UniqueToken { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string? Note { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 状态
|
||||
/// </summary>
|
||||
public bool State { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 摘要
|
||||
/// </summary>
|
||||
public string? Summary { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// 摘要ID
|
||||
/// </summary>
|
||||
public long? SummaryId { get; set; }
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
namespace Admin.NET.Core.Ai.Service;
|
||||
|
||||
public class ModelListChangeInput : ModelListOutputItem
|
||||
{
|
||||
}
|
||||
@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// 模型列表输出
|
||||
@ -33,11 +39,8 @@ public class ModelListOutputItem
|
||||
/// </summary>
|
||||
public string ProviderName { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 模型名称
|
||||
/// </summary>
|
||||
public string ModelName { get; set; }
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
/// <summary>
|
||||
/// 聊天补全核心服务
|
||||
/// </summary>
|
||||
@ -19,8 +15,10 @@ public class LLMChatCoreService : ITransient
|
||||
{
|
||||
private readonly ILogger<LLMChatCoreService> _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<LLMChatCoreService> logger,
|
||||
ILLMFactory llmFactory,
|
||||
SseChannelManager sseChannelManager,
|
||||
@ -75,6 +74,7 @@ public class LLMChatCoreService : ITransient
|
||||
}
|
||||
|
||||
#region 新聊天
|
||||
|
||||
/// <summary>
|
||||
/// 新聊天
|
||||
/// </summary>
|
||||
@ -93,6 +93,7 @@ public class LLMChatCoreService : ITransient
|
||||
return await NormalNewChatCore(input, kernel, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 深度思考新聊天
|
||||
/// </summary>
|
||||
@ -103,7 +104,9 @@ public class LLMChatCoreService : ITransient
|
||||
private async Task<ChatOutput> 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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 深度思考续聊
|
||||
/// </summary>
|
||||
@ -263,6 +270,7 @@ public class LLMChatCoreService : ITransient
|
||||
private async Task<ChatOutput> 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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 普通续聊
|
||||
/// </summary>
|
||||
@ -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 ?? "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取聊天历史,并截取
|
||||
/// </summary>
|
||||
@ -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 删除所属摘要的所有聊天记录
|
||||
|
||||
/// <summary>
|
||||
/// 删除所属摘要的所有聊天记录
|
||||
/// </summary>
|
||||
@ -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 重命名所属摘要的标签
|
||||
|
||||
/// <summary>
|
||||
/// 重命名所属摘要的标签
|
||||
/// </summary>
|
||||
@ -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 重命名所属摘要的标签
|
||||
}
|
||||
@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// LLM聊天补全服务
|
||||
@ -55,7 +55,7 @@ public class LLMChatService : IDynamicApiController, ITransient
|
||||
[HttpPost]
|
||||
[ApiDescriptionSettings(Description = "删除所属摘要的所有聊天记录", Name = "DeleteSummaryAll")]
|
||||
public async Task<bool> DeleteSummaryAllAsync(ChatInput message) => await _chatCoreService.DeleteSummaryAllAsync(message);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 重命名所属摘要的标签
|
||||
/// </summary>
|
||||
@ -95,7 +95,6 @@ public class LLMChatService : IDynamicApiController, ITransient
|
||||
[ApiDescriptionSettings(Description = "获取模型列表", Name = "ModelList")]
|
||||
public async Task<ModelListOutput> GetModelListAsync() => await _llmOptionService.GetModelListAsync();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 切换模型
|
||||
/// </summary>
|
||||
@ -104,4 +103,4 @@ public class LLMChatService : IDynamicApiController, ITransient
|
||||
/// <exception cref="Exception"></exception>
|
||||
[ApiDescriptionSettings(Description = "切换模型", Name = "ChangeModel"), HttpPost]
|
||||
public async Task<bool> ChangeModelAsync(ModelListChangeInput input) => await _llmOptionService.ChangeModelAsync(input);
|
||||
}
|
||||
}
|
||||
@ -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> _llmOptions;
|
||||
private readonly SysCacheService _sysCacheService;
|
||||
|
||||
public LLMOptionService(ILogger<LLMOptionService> logger,
|
||||
UserManager userManager,
|
||||
IOptions<LLMOptions> llmOptions,
|
||||
@ -19,6 +23,7 @@ public class LLMOptionService : ITransient
|
||||
_llmOptions = llmOptions;
|
||||
_sysCacheService = sysCacheService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取模型列表
|
||||
/// 步骤:
|
||||
@ -55,6 +60,7 @@ public class LLMOptionService : ITransient
|
||||
_sysCacheService.Set(key, output);
|
||||
return await Task.FromResult(output);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 可能存在用户手动修改了配置文件,如删除、添加、修改模型,此时需要更新缓存中的模型列表
|
||||
/// </summary>
|
||||
@ -134,6 +140,7 @@ public class LLMOptionService : ITransient
|
||||
}
|
||||
return await _UpdateModelList(input, cache, key);
|
||||
}
|
||||
|
||||
private async Task<bool> _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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// 异步对数据库进行操作
|
||||
@ -75,4 +77,4 @@ public class ChatChannelActionService : IScoped
|
||||
.Updateable(oldChatSummaryHistory)
|
||||
.ExecuteCommandAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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<DataActionInput> ActionReader => _channel.Reader;
|
||||
public ChannelWriter<DataActionInput> ActionWriter => _channel.Writer;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
namespace Admin.NET.Core.Ai.Service;
|
||||
|
||||
public class DataActionInput
|
||||
{
|
||||
public ChatActionEnum ActionType { get; set; }
|
||||
public LLMChatSummaryHistory Item { get; set; }
|
||||
}
|
||||
@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// 模型切换工厂
|
||||
@ -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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建Kernel实例
|
||||
/// </summary>
|
||||
@ -31,6 +34,7 @@ public class ChangeModelFactory : ILLMFactory, ITransient
|
||||
var builder = Kernel.CreateBuilder();
|
||||
return GetKernel(builder, modelInput);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取Kernel实例
|
||||
/// </summary>
|
||||
@ -62,6 +66,7 @@ public class ChangeModelFactory : ILLMFactory, ITransient
|
||||
}
|
||||
ConfigureKernelCore(builder, httpClient, provider, modelInput.ModelId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 配置Kernel核心代码
|
||||
/// </summary>
|
||||
@ -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}模型提供者");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取HttpClient实例,可能为null
|
||||
/// </summary>
|
||||
@ -203,5 +212,4 @@ public class ChangeModelFactory : ILLMFactory, ITransient
|
||||
}
|
||||
return httpMessageHandler == null ? null : new HttpClient(httpMessageHandler);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,128 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Admin.NET.Core.Ai.Service;
|
||||
|
||||
/// <summary>
|
||||
/// OpenRouter 客户端
|
||||
/// </summary>
|
||||
public class LLMOpenRouterClient
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
private readonly LLMCustomOptions _options;
|
||||
|
||||
public LLMOpenRouterClient(HttpClient httpClient, IOptions<LLMCustomOptions> options)
|
||||
{
|
||||
_httpClient = httpClient;
|
||||
_options = options.Value;
|
||||
_httpClient.Timeout = TimeSpan.FromSeconds(_options.Timeout);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取提示词的LLM的回答
|
||||
/// </summary>
|
||||
/// <param name="messages">提示词</param>
|
||||
/// <returns>提示词的LLM的回答</returns>
|
||||
/// <exception cref="ArgumentException">消息列表不能为空</exception>
|
||||
/// <exception cref="Exception">网络请求错误</exception>
|
||||
/// <exception cref="JsonException">JSON解析错误</exception>
|
||||
public async Task<string> GetPromptAsync(List<LLMInputMessage> messages)
|
||||
{
|
||||
return await GetLLMResponseAsync(messages, (messages) =>
|
||||
{
|
||||
if (!messages.Any(m => m.Role.Equals("system")))
|
||||
{
|
||||
messages.Insert(0, new LLMInputMessage()
|
||||
{
|
||||
Role = "system",
|
||||
Content = _options.InitSystemPromptMessage
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取聊天记录的LLM的回答
|
||||
/// </summary>
|
||||
/// <param name="messages">聊天记录</param>
|
||||
/// <returns>聊天记录的LLM的回答</returns>
|
||||
/// <exception cref="ArgumentException">消息列表不能为空</exception>
|
||||
/// <exception cref="Exception">网络请求错误</exception>
|
||||
public async Task<string> GetChatAsync(List<LLMInputMessage> messages)
|
||||
{
|
||||
return await GetLLMResponseAsync(messages, (messages) =>
|
||||
{
|
||||
if (!messages.Any(m => m.Role.Equals("system")))
|
||||
{
|
||||
messages.Insert(0, new LLMInputMessage()
|
||||
{
|
||||
Role = "system",
|
||||
Content = _options.InitSystemChatMessage
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取LLM的回答
|
||||
/// </summary>
|
||||
/// <param name="messages">消息列表</param>
|
||||
/// <param name="beforeSendAction">在发送请求之前,可以对消息进行修改</param>
|
||||
/// <returns>LLM的回答</returns>
|
||||
/// <exception cref="ArgumentException">消息列表不能为空</exception>
|
||||
/// <exception cref="Exception">网络请求错误</exception>
|
||||
/// <exception cref="JsonException">JSON解析错误</exception>
|
||||
private async Task<string> GetLLMResponseAsync(List<LLMInputMessage> messages, Action<List<LLMInputMessage>> beforeSendAction = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (messages == null || !messages.Any())
|
||||
throw new ArgumentException("Message list cannot be empty");
|
||||
|
||||
if (messages.Any(m => m.Content.Length > 2000))
|
||||
throw new ArgumentException("Message content exceeds the maximum length limit");
|
||||
|
||||
var defaultLLM = _options.SupportLLMList.Find(item => item.Desciption.Equals(_options.ModelProvider));
|
||||
if (defaultLLM == null)
|
||||
{
|
||||
throw new Exception("Default LLM not found, please check if the ModelProvider in ai.json is set incorrectly?");
|
||||
}
|
||||
var inputBody = new LLMInputBody();
|
||||
inputBody.Model = defaultLLM.Model;
|
||||
inputBody.Messages = messages;
|
||||
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))
|
||||
{
|
||||
if (response.StatusCode == System.Net.HttpStatusCode.OK)
|
||||
{
|
||||
var strResponse = await response.Content.ReadAsStringAsync();
|
||||
var output = LLMJsonTool.DeserializeObject<LLMOutput>(strResponse);
|
||||
return output.Choices[0].Message.Content;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Failed to get LLM response: " + $"Status code: {response.StatusCode}" + " " + $"Error message: {response.ReasonPhrase}" + " " + $"Error content: {await response.Content.ReadAsStringAsync()}");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
throw new Exception($"Network request error: {ex.Message}");
|
||||
}
|
||||
catch (JsonException ex)
|
||||
{
|
||||
throw new Exception($"JSON parsing error: {ex.Message}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception($"Unknown error: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// SSE通道管理
|
||||
@ -50,4 +55,4 @@ public class BaseSseChannelManager : ISseChannelManager
|
||||
await channel.Writer.WriteAsync(message, cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
14
Admin.NET/Admin.NET.Core/Ai/Service/SSE/SseChannelManager.cs
Normal file
14
Admin.NET/Admin.NET.Core/Ai/Service/SSE/SseChannelManager.cs
Normal file
@ -0,0 +1,14 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
namespace Admin.NET.Core.Ai.Service;
|
||||
|
||||
/// <summary>
|
||||
/// 聊天通道管理
|
||||
/// </summary>
|
||||
public class SseChannelManager : BaseSseChannelManager, ISingleton
|
||||
{
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
namespace Admin.NET.Core.Ai.Service;
|
||||
|
||||
/// <summary>
|
||||
/// 深度思考通道管理
|
||||
/// </summary>
|
||||
public class SseDeepThinkingChannelManager : BaseSseChannelManager, ISingleton
|
||||
{
|
||||
}
|
||||
@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// SSE服务
|
||||
@ -71,5 +77,4 @@ public class SseService : ControllerBase
|
||||
_sseDeepThinkingChannelManager.Unregister(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,7 +0,0 @@
|
||||
namespace Admin.NET.Core.Ai.Services.Chat.Dto;
|
||||
|
||||
public class ChatListInput : BasePageInput
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@ -1,10 +0,0 @@
|
||||
using Admin.NET.Core.Ai.Entitys;
|
||||
|
||||
namespace Admin.NET.Core.Ai.Services.Chat.Dto;
|
||||
|
||||
/// <summary>
|
||||
/// 聊天列表输出
|
||||
/// </summary>
|
||||
public class ChatListOutput:LLMChatSummaryHistory
|
||||
{
|
||||
}
|
||||
@ -1,30 +0,0 @@
|
||||
namespace Admin.NET.Core.Ai.Services.Chat.Dto;
|
||||
|
||||
public class ChatOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// 唯一标识
|
||||
/// </summary>
|
||||
public string? UniqueToken { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string? Note { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 状态
|
||||
/// </summary>
|
||||
public bool State { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 摘要
|
||||
/// </summary>
|
||||
public string? Summary { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// 摘要ID
|
||||
/// </summary>
|
||||
public long? SummaryId { get; set; }
|
||||
}
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
namespace Admin.NET.Core.Ai.Services.Chat.Dto;
|
||||
|
||||
public class ModelListChangeInput:ModelListOutputItem
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@ -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; }
|
||||
}
|
||||
|
||||
@ -1,10 +0,0 @@
|
||||
using System.Threading.Channels;
|
||||
|
||||
namespace Admin.NET.Core.Ai.Services.SSE;
|
||||
|
||||
/// <summary>
|
||||
/// 聊天通道管理
|
||||
/// </summary>
|
||||
public class SseChannelManager: BaseSseChannelManager,ISingleton
|
||||
{
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
using System.Threading.Channels;
|
||||
|
||||
namespace Admin.NET.Core.Ai.Services.SSE;
|
||||
|
||||
/// <summary>
|
||||
/// 深度思考通道管理
|
||||
/// </summary>
|
||||
public class SseDeepThinkingChannelManager: BaseSseChannelManager,ISingleton
|
||||
{
|
||||
}
|
||||
51
Admin.NET/Admin.NET.Core/Ai/Utils/LLMJsonTool.cs
Normal file
51
Admin.NET/Admin.NET.Core/Ai/Utils/LLMJsonTool.cs
Normal file
@ -0,0 +1,51 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace Admin.NET.Core;
|
||||
|
||||
/// <summary>
|
||||
/// LLM JSON 工具类
|
||||
/// </summary>
|
||||
public class LLMJsonTool
|
||||
{
|
||||
/// <summary>
|
||||
/// 序列化对象
|
||||
/// </summary>
|
||||
/// <param name="obj">对象</param>
|
||||
/// <returns>JSON字符串</returns>
|
||||
public static string SerializeObject(object obj)
|
||||
{
|
||||
var settings = new JsonSerializerSettings
|
||||
{
|
||||
ContractResolver = new DefaultContractResolver
|
||||
{
|
||||
NamingStrategy = new SnakeCaseNamingStrategy()
|
||||
}
|
||||
};
|
||||
return JsonConvert.SerializeObject(obj, settings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 反序列化JSON字符串
|
||||
/// </summary>
|
||||
/// <typeparam name="T">对象类型</typeparam>
|
||||
/// <param name="json">JSON字符串</param>
|
||||
/// <returns>对象</returns>
|
||||
public static T DeserializeObject<T>(string json)
|
||||
{
|
||||
var settings = new JsonSerializerSettings
|
||||
{
|
||||
ContractResolver = new DefaultContractResolver
|
||||
{
|
||||
NamingStrategy = new SnakeCaseNamingStrategy()
|
||||
}
|
||||
};
|
||||
return JsonConvert.DeserializeObject<T>(json, settings);
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
global using Yitter.IdGenerator;
|
||||
@ -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",
|
||||
|
||||
@ -5,7 +5,6 @@
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
using Admin.NET.Core;
|
||||
using Admin.NET.Core.Ai.Option;
|
||||
using AspNetCoreRateLimit;
|
||||
using Furion;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
@ -44,8 +43,13 @@ public static class ProjectOptions
|
||||
services.Configure<ClientRateLimitOptions>(App.Configuration.GetSection("ClientRateLimiting"));
|
||||
services.Configure<ClientRateLimitPolicies>(App.Configuration.GetSection("ClientRateLimitPolicies"));
|
||||
|
||||
<<<<<<< HEAD
|
||||
services.AddConfigurableOptions<LLMOptions>(); //基于Microsoft Semantic Kernel实现,也是本应用的默认实现
|
||||
|
||||
=======
|
||||
services.AddConfigurableOptions<LLMCustomOptions>(); // 手动实现LLM接口配置选项
|
||||
services.AddConfigurableOptions<LLMOptions>(); // 基于Microsoft Semantic Kernel实现,也是本应用的默认实现
|
||||
>>>>>>> f408a01a2d83c2d384dcbdb16eab344e4d437ab3
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
@ -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<SysAuthService>().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(路由前缀一致代表独立,不同则代表共存)
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DocumentFormat.OpenXml" Version="3.3.0" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.14.0" />
|
||||
<PackageReference Include="Rezero.Api" Version="1.8.23" />
|
||||
<PackageReference Include="Rezero.Api" Version="1.8.24" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
|
||||
import { LLMChatSummaryHistory } from './llmchat-summary-history';
|
||||
/**
|
||||
* 聊天历史
|
||||
* 聊天历史表
|
||||
*
|
||||
* @export
|
||||
* @interface LLMChatHistory
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
|
||||
import { LLMChatHistory } from './llmchat-history';
|
||||
/**
|
||||
* 聊天摘要历史
|
||||
* 聊天摘要历史表
|
||||
*
|
||||
* @export
|
||||
* @interface LLMChatSummaryHistory
|
||||
|
||||
@ -261,7 +261,7 @@ const onLanguageChange = (lang: string) => {
|
||||
// 聊天点击
|
||||
const onChatClick = () => {
|
||||
router.push({
|
||||
path: '/llm/chat',
|
||||
path: '/llm/aiChat',
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -50,13 +50,13 @@ export const dynamicRoutes: Array<RouteRecordRaw> = [
|
||||
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',
|
||||
|
||||
4
Web/src/types/franc.d.ts
vendored
4
Web/src/types/franc.d.ts
vendored
@ -1,3 +1,3 @@
|
||||
declare module 'franc' {
|
||||
export function franc(text: string): string;
|
||||
}
|
||||
export function franc(text: string): string;
|
||||
}
|
||||
|
||||
2
Web/src/types/vue-element-plus-x.d.ts
vendored
2
Web/src/types/vue-element-plus-x.d.ts
vendored
@ -1 +1 @@
|
||||
declare module 'vue-element-plus-x';
|
||||
declare module 'vue-element-plus-x';
|
||||
|
||||
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
1118
Web/src/views/aiChat/index.vue
Normal file
1118
Web/src/views/aiChat/index.vue
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -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);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user