Compare commits

...

33 Commits
0.1.9 ... 0.2.1

Author SHA1 Message Date
zyxucp
adbecb3b25 update 更新docker compose 2024-03-16 00:23:16 +08:00
zyxucp
277aacc34d add 动态添加dll 2024-03-15 23:53:53 +08:00
zyxucp
dba98f7968 add 增加上传dll功能 2024-03-15 22:55:23 +08:00
zyxucp
a2b0f3f3c2 add 插件导入 2024-03-15 22:45:36 +08:00
zyxucp
b5e527afdb add 增加函数列表 2024-03-15 22:33:39 +08:00
zyxucp
e84b05a39b fix 修改普通特性 2024-03-15 22:16:07 +08:00
zyxucp
631c563e71 fix 修改为普通特性,避免上传DLL需要引用特殊特性 2024-03-15 22:15:02 +08:00
zyxucp
47b304e46f update 升级SK到1.6.2 2024-03-15 22:08:22 +08:00
zyxucp
27ccfc5e88 add 增加分享使用 2024-03-15 21:57:21 +08:00
zyxucp
69441167d3 fix 修改高度自适应 2024-03-15 21:50:55 +08:00
zyxucp
4b97594217 fix 调整会话总结 2024-03-15 21:15:28 +08:00
zyxucp
9ee601f88c fix 首页调整 2024-03-15 21:12:31 +08:00
zyxucp
75b1a299e3 add 限制移动端屏幕缩放 2024-03-15 21:07:59 +08:00
zyxucp
2613c463a1 Merge branch 'main' of https://github.com/xuzeyu91/AntSK 2024-03-15 14:45:15 +08:00
zyxucp
78e0350d36 add 首页调整 2024-03-15 14:39:13 +08:00
zyxucp
bc2425fc3f Update README.md 2024-03-15 14:18:15 +08:00
zyxucp
3e861bc72f Update README.md 2024-03-15 13:01:35 +08:00
zyxucp
b41c464753 fix 暂时取消星火的会话拆分 2024-03-14 16:58:19 +08:00
zyxucp
2817275091 fix 暂时取消注册时间函数 2024-03-14 12:57:28 +08:00
zyxucp
e76b0cf326 fix 调整目录结构 2024-03-14 12:24:09 +08:00
zyxucp
cf34103e15 update docker-compose.yml 2024-03-14 12:07:17 +08:00
zyxucp
1588fd7d7a add 增加ErrorBoundary全局异常 2024-03-14 11:32:42 +08:00
zyxucp
4507ccde6c margin 2024-03-14 10:03:40 +08:00
zyxucp
73fffd766f fix 修复LLamaSharp给一个默认下载路径 2024-03-14 10:02:15 +08:00
zyxucp
e529146c5b fix 修改LLamaSharp文件夹给一个默认路径 2024-03-14 09:59:51 +08:00
zyxucp
7050e52009 Merge pull request #28 from ElderJames/main
Fix DI and OpenAI function calling
2024-03-13 22:25:45 +08:00
James Yeung
4f3238c4f6 Fix DI and OpenAI function calling 2024-03-13 22:22:22 +08:00
zyxucp
b7d27c5d50 fix 修复bug 2024-03-13 22:11:35 +08:00
zyxucp
fe94aa0564 fix 修复修改自身重复问题 2024-03-13 20:59:14 +08:00
zyxucp
ae60a9aced Merge branch 'main' of https://github.com/xuzeyu91/AntSK 2024-03-13 12:13:56 +08:00
zyxucp
4f686b0871 fix 修复按钮停止不了的问题 2024-03-13 10:23:52 +08:00
zyxucp
c61840b7e8 Update README.md 2024-03-13 10:17:50 +08:00
zyxucp
9adce95367 fix appsettings.json示例 2024-03-13 10:10:52 +08:00
90 changed files with 868 additions and 439 deletions

1
.gitignore vendored
View File

@@ -341,3 +341,4 @@ ASALocalRun/
/src/AntSK/appsettings.Development.json
/src/AntSK.db
/src/AntSK/llama_models
/src/AntSK/AntSK.xml

View File

@@ -16,12 +16,14 @@
- **API插件系统**开放式API插件系统允许第三方开发者或服务商轻松将其服务集成到AntSK不断增强应用功能。
- **.Net插件系统(规划中)**开放式dll插件系统允许第三方开发者或服务商轻松将其业务功能通过标准格式的代码生成dll后集成到AntSK不断增强应用功能。
- **.Net插件系统**开放式dll插件系统允许第三方开发者或服务商轻松将其业务功能通过标准格式的代码生成dll后集成到AntSK不断增强应用功能。
- **联网搜索**AntSK实时获取最新信息确保用户接受到的资料总是最及时、最相关的。
- **模型管理**适配和管理集成不同厂商的不同模型。并且支持llama.cpp所支持的gguf类型的模型离线运行
- **国产信创**AntSK支持国产模型和国产数据库可以在信创条件下运行
## 应用场景
AntSK 适用于多种业务场景,例如:
@@ -85,7 +87,7 @@ docker-compose up -d
```
来启动AntSK
## 如何在docker中挂载本地模型
## 如何在docker中挂载本地模型,和模型下载的目录
```
# 非 host 版本, 不使用本机代理
version: '3.8'
@@ -128,7 +130,8 @@ model/xxx.gguf
"LLamaSharp": {
"RunType": "GPU",
"Chat": "D:\\Code\\AI\\AntBlazor\\model\\qwen1_5-1_8b-chat-q8_0.gguf",
"Embedding": "D:\\Code\\AI\\AntBlazor\\model\\qwen1_5-1_8b-chat-q8_0.gguf"
"Embedding": "D:\\Code\\AI\\AntBlazor\\model\\qwen1_5-1_8b-chat-q8_0.gguf",
"FileDirectory": "D:\\Code\\AI\\AntBlazor\\model\\"
},
"Login": {
"User": "admin",
@@ -156,8 +159,10 @@ LLamaSharp.RunType
LLamaSharp.Chat
//本地向量模型的模型路径 注意区分linux和windows盘符不同
LLamaSharp.Embedding
//默认管理员账号密码
//本地模型路径用于在选择llama时可以快速选择目录下的模型以及保存下载的模型
LLamaSharp.FileDirectory
//默认管理员账号密码
Login
//导入异步处理的线程数使用在线API可以高一点本地模型建议1 否则容易内存溢出崩掉
BackgroundTaskBroker.ImportKMSTask.WorkerCount

View File

@@ -3,7 +3,7 @@ version: '3.8'
services:
antsk:
container_name: antsk
image: registry.cn-hangzhou.aliyuncs.com/xuzeyu91/antsk:v0.1.8
image: registry.cn-hangzhou.aliyuncs.com/xuzeyu91/antsk:v0.2.1
ports:
- 5000:5000
networks:

View File

@@ -18,7 +18,7 @@ services:
- ./pg/data:/var/lib/postgresql/data
antsk:
container_name: antsk
image: registry.cn-hangzhou.aliyuncs.com/xuzeyu91/antsk:v0.1.8
image: registry.cn-hangzhou.aliyuncs.com/xuzeyu91/antsk:v0.2.1
ports:
- 5000:5000
networks:

View File

@@ -13,17 +13,17 @@
<PackageReference Include="AutoMapper" Version="8.1.0" />
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
<PackageReference Include="Markdig" Version="0.35.0" />
<PackageReference Include="Markdig" Version="0.36.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="SqlSugarCore" Version="5.1.4.145" />
<PackageReference Include="System.Data.SQLite.Core" Version="1.0.118" />
<PackageReference Include="RestSharp" Version="110.2.0" />
<PackageReference Include="Microsoft.SemanticKernel" Version="1.4.0" />
<PackageReference Include="Microsoft.SemanticKernel.Core" Version="1.4.0" />
<PackageReference Include="Microsoft.SemanticKernel.Plugins.Core" Version="1.4.0-alpha" />
<PackageReference Include="Microsoft.KernelMemory.Core" Version="0.32.240308.1" />
<PackageReference Include="Microsoft.KernelMemory.MemoryDb.Postgres" Version="0.32.240308.1" />
<PackageReference Include="Microsoft.SemanticKernel" Version="1.6.2" />
<PackageReference Include="Microsoft.SemanticKernel.Core" Version="1.6.2" />
<PackageReference Include="Microsoft.SemanticKernel.Plugins.Core" Version="1.6.2-alpha" />
<PackageReference Include="Microsoft.KernelMemory.Core" Version="0.34.240313.1" />
<PackageReference Include="Microsoft.KernelMemory.MemoryDb.Postgres" Version="0.34.240313.1" />
<PackageReference Include="LLamaSharp" Version="0.10.0" />
<PackageReference Include="LLamaSharp.Backend.Cpu" Version="0.10.0" />

View File

@@ -48,6 +48,36 @@
<param name="value"></param>
<returns></returns>
</member>
<member name="T:AntSK.Domain.Domain.Model.Enum.AIType">
<summary>
AI类型
</summary>
</member>
<member name="T:AntSK.Domain.Domain.Model.Enum.AIModelType">
<summary>
模型类型
</summary>
</member>
<member name="P:AntSK.Domain.Domain.Model.MessageInfo.IsSend">
<summary>
发送是true 接收是false
</summary>
</member>
<member name="P:AntSK.Domain.Domain.Model.PageList`1.PageIndex">
<summary>
当前页从1开始
</summary>
</member>
<member name="P:AntSK.Domain.Domain.Model.PageList`1.PageSize">
<summary>
每页数量
</summary>
</member>
<member name="P:AntSK.Domain.Domain.Model.PageList`1.TotalCount">
<summary>
总数
</summary>
</member>
<member name="F:AntSK.Domain.Domain.Other.LLamaConfig.dicLLamaWeights">
<summary>
避免模型重复加载,本地缓存
@@ -97,61 +127,6 @@
<param name="history"></param>
<returns></returns>
</member>
<member name="M:AntSK.Domain.Map.MapperExtend.ToDTOList``1(System.Object)">
<summary>
Entity集合转DTO集合
</summary>
<typeparam name="T"></typeparam>
<param name="value"></param>
<returns></returns>
</member>
<member name="M:AntSK.Domain.Map.MapperExtend.ToDTO``1(System.Object)">
<summary>
Entity转DTO
</summary>
<typeparam name="T"></typeparam>
<param name="value"></param>
<returns></returns>
</member>
<member name="M:AntSK.Domain.Map.MapperExtend.MapTo``1(System.Object,``0)">
<summary>
给已有对象map,适合update场景如需过滤空值需要在AutoMapProfile 设置
</summary>
<typeparam name="T"></typeparam>
<param name="self"></param>
<param name="result"></param>
<returns></returns>
</member>
<member name="T:AntSK.Domain.Model.Enum.AIType">
<summary>
AI类型
</summary>
</member>
<member name="T:AntSK.Domain.Model.Enum.AIModelType">
<summary>
模型类型
</summary>
</member>
<member name="P:AntSK.Domain.Model.MessageInfo.IsSend">
<summary>
发送是true 接收是false
</summary>
</member>
<member name="P:AntSK.Domain.Model.PageList`1.PageIndex">
<summary>
当前页从1开始
</summary>
</member>
<member name="P:AntSK.Domain.Model.PageList`1.PageSize">
<summary>
每页数量
</summary>
</member>
<member name="P:AntSK.Domain.Model.PageList`1.TotalCount">
<summary>
总数
</summary>
</member>
<member name="P:AntSK.Domain.Options.DBConnectionOption.DbType">
<summary>
sqlite连接字符串
@@ -272,6 +247,11 @@
API调用秘钥
</summary>
</member>
<member name="P:AntSK.Domain.Repositories.Funs.Path">
<summary>
接口描述
</summary>
</member>
<member name="P:AntSK.Domain.Repositories.KmsDetails.FileName">
<summary>
文件名称

View File

@@ -1,4 +1,4 @@
using AntSK.Domain.Domain.Dto;
using AntSK.Domain.Domain.Model.Dto;
using AntSK.Domain.Repositories;
using Microsoft.SemanticKernel;
using System;

View File

@@ -1,4 +1,4 @@
using AntSK.Domain.Model;
using AntSK.Domain.Domain.Model;
namespace AntSK.Domain.Domain.Interface
{

View File

@@ -1,4 +1,4 @@
using AntSK.Domain.Domain.Dto;
using AntSK.Domain.Domain.Model.Dto;
using Microsoft.KernelMemory;
namespace AntSK.Domain.Domain.Interface

View File

@@ -1,4 +1,4 @@
namespace AntSK.Domain.Domain.Dto
namespace AntSK.Domain.Domain.Model.Dto
{
public class KMFile
{

View File

@@ -1,4 +1,4 @@
namespace AntSK.Domain.Domain.Dto
namespace AntSK.Domain.Domain.Model.Dto.OpenAPI
{
public class OpenAIModel
{

View File

@@ -1,6 +1,6 @@
using Newtonsoft.Json;
namespace AntSK.Domain.Domain.Dto
namespace AntSK.Domain.Domain.Model.Dto.OpenAPI
{
public class OpenAIResult
{

View File

@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AntSK.Domain.Domain.Dto
namespace AntSK.Domain.Domain.Model.Dto
{
public class RelevantSource
{

View File

@@ -1,4 +1,4 @@
namespace AntSK.Domain.Model.Enum
namespace AntSK.Domain.Domain.Model.Enum
{
/// <summary>
/// AI类型
@@ -7,9 +7,9 @@
{
OpenAI = 1,
AzureOpenAI = 2,
LLamaSharp=3,
SparkDesk=4,
Mock=5,
LLamaSharp = 3,
SparkDesk = 4,
Mock = 5,
}
/// <summary>

View File

@@ -4,11 +4,11 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AntSK.Domain.Model.Enum
namespace AntSK.Domain.Domain.Model.Enum
{
public enum AppType
{
chat=1,
kms=2
chat = 1,
kms = 2
}
}

View File

@@ -1,4 +1,4 @@
namespace AntSK.Domain.Model
namespace AntSK.Domain.Domain.Model.Enum
{
public enum HttpMethodType
{

View File

@@ -1,4 +1,4 @@
namespace AntSK.Domain.Model.Enum
namespace AntSK.Domain.Domain.Model.Enum
{
public enum ImportKmsStatus
{

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AntSK.Domain.Domain.Model.Fun
{
public class FunDto
{
public string Name { get; set; }
public string Description { get; set; }
}
}

View File

@@ -1,6 +1,6 @@
using AntSK.Domain.Repositories;
namespace AntSK.Domain.Model
namespace AntSK.Domain.Domain.Model
{
public class ImportKMSTaskDTO
{

View File

@@ -1,4 +1,4 @@
namespace AntSK.Domain.Model
namespace AntSK.Domain.Domain.Model
{
public class MessageInfo
{

View File

@@ -1,4 +1,4 @@
namespace AntSK.Domain.Model
namespace AntSK.Domain.Domain.Model
{
public class PageList<T>
{

View File

@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AntSK.Domain.Model.hfmirror
namespace AntSK.Domain.Domain.Model.hfmirror
{
public class HfModel
{

View File

@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AntSK.Domain.Model.hfmirror
namespace AntSK.Domain.Domain.Model.hfmirror
{
public class HfModelDetail
{

View File

@@ -1,6 +1,6 @@
using AntSK.BackgroundTask;
using AntSK.Domain.Domain.Interface;
using AntSK.Domain.Model;
using AntSK.Domain.Domain.Model;
using Microsoft.Extensions.DependencyInjection;
namespace AntSK.Domain.Domain.Other

View File

@@ -10,9 +10,9 @@ using System.Text;
using System.Threading.Tasks;
using AntSK.Domain.Utils;
using Microsoft.KernelMemory;
using AntSK.Domain.Model;
using AntSK.Domain.Domain.Dto;
using Markdig;
using AntSK.Domain.Domain.Model;
using AntSK.Domain.Domain.Model.Dto;
namespace AntSK.Domain.Domain.Service
{

View File

@@ -1,17 +1,21 @@
using System.Reflection;
using System.ComponentModel;
using System.Reflection;
using System.Runtime.Loader;
using System.Xml;
using AntSK.Domain.Common;
using AntSK.Domain.Utils;
using System.Text.RegularExpressions;
namespace AntSK.Domain.Domain.Service
{
public class FunctionService
{
private readonly Dictionary<string, Func<object[], object>> _methodCache;
private readonly Dictionary<string, MethodInfo> _methodCache;
private readonly Dictionary<string, (string Description, (Type ParameterType, string Description) ReturnType, (string ParameterName, Type ParameterType, string Description)[] Parameters)> _methodInfos;
private readonly IServiceProvider _serviceProvider;
private readonly Assembly[] _assemblies;
private Assembly[] _assemblies;
private readonly AssemblyLoadContext loadContext;
public FunctionService(IServiceProvider serviceProvider, Assembly[] assemblies)
{
@@ -19,9 +23,10 @@ namespace AntSK.Domain.Domain.Service
_methodInfos = [];
_serviceProvider = serviceProvider;
_assemblies = assemblies;
loadContext = new AssemblyLoadContext("AntSKLoadContext", true);
}
public Dictionary<string, Func<object[], object>> Functions => _methodCache;
public Dictionary<string, MethodInfo> Functions => _methodCache;
public Dictionary<string, (string Description, (Type ParameterType, string Description) ReturnType, (string ParameterName, Type ParameterType, string Description)[] Parameters)> MethodInfos => _methodInfos;
/// <summary>
@@ -39,7 +44,26 @@ namespace AntSK.Domain.Domain.Service
// 从缓存中获取标记了ActionAttribute的方法
foreach (var type in assembly.GetTypes())
{
markedMethods.AddRange(type.GetMethods().Where(m => m.GetCustomAttributes(typeof(AntSkFunctionAttribute), true).Length > 0));
markedMethods.AddRange(type.GetMethods().Where(m =>
{
DescriptionAttribute da = (DescriptionAttribute)m.GetCustomAttributes(typeof(DescriptionAttribute), true).FirstOrDefault();
return da != null && da.Description == "AntSK";
}));
}
}
//动态加载部分
var loadedAssemblies = loadContext.Assemblies.ToList();
foreach (var assembly in loadedAssemblies)
{
// 从缓存中获取标记了ActionAttribute的方法
foreach (var type in assembly.GetTypes())
{
markedMethods.AddRange(type.GetMethods().Where(m =>
{
DescriptionAttribute da = (DescriptionAttribute)m.GetCustomAttributes(typeof(DescriptionAttribute), true).FirstOrDefault();
return da != null && da.Description == "AntSK";
}));
}
}
@@ -47,11 +71,10 @@ namespace AntSK.Domain.Domain.Service
foreach (var method in markedMethods)
{
var key = $"{method.DeclaringType.Assembly.GetName().Name}_{method.DeclaringType.Name}_{method.Name}";
_methodCache.TryAdd(key, arguments =>
{
var instance = _serviceProvider.GetService(method.DeclaringType);
return method.Invoke(instance, arguments);
});
string pattern = "[^a-zA-Z0-9_]";
// 使用 '-' 替换非ASCII的正则表达式的字符
key = Regex.Replace(key, pattern, "_");
_methodCache.TryAdd(key, method);
var xmlCommentHelper = new XmlCommentHelper();
xmlCommentHelper.LoadAll();
@@ -62,8 +85,44 @@ namespace AntSK.Domain.Domain.Service
var parameters = method.GetParameters().Select(x => (x.Name, x.ParameterType, dict[x.Name])).ToArray();
var returnType = xmlCommentHelper.GetMethodReturnComment(method);
if (string.IsNullOrEmpty(description))
{
description = "导入插件";
}
_methodInfos.TryAdd(key, (description, (method.ReflectedType, returnType), parameters));
}
}
public void FuncLoad(string pluginPath)
{
try
{
if (File.Exists(pluginPath))
{
string directory = Path.GetDirectoryName(pluginPath);
string fileName = Path.GetFileName(pluginPath);
var resolver = new AssemblyDependencyResolver(directory);
// Create a custom AssemblyLoadContext
loadContext.Resolving += (context, assemblyName) =>
{
string assemblyPath = resolver.ResolveAssemblyToPath(assemblyName);
if (assemblyPath != null)
{
return context.LoadFromAssemblyPath(assemblyPath);
}
return null;
};
// Load your assembly
Assembly pluginAssembly = loadContext.LoadFromAssemblyPath(pluginPath);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message + " ---- " + ex.StackTrace);
}
}
}
}

View File

@@ -1,6 +1,6 @@
using AntSK.Domain.Common.DependencyInjection;
using AntSK.Domain.Domain.Interface;
using AntSK.Domain.Model;
using AntSK.Domain.Domain.Model;
using AntSK.Domain.Repositories;
using Microsoft.KernelMemory;

View File

@@ -1,6 +1,6 @@
using AntSK.Domain.Common.DependencyInjection;
using AntSK.Domain.Domain.Dto;
using AntSK.Domain.Domain.Interface;
using AntSK.Domain.Domain.Model.Dto;
using AntSK.Domain.Domain.Other;
using AntSK.Domain.Repositories;
using AntSK.Domain.Utils;

View File

@@ -2,7 +2,6 @@
using AntSK.Domain.Common.DependencyInjection;
using AntSK.Domain.Domain.Interface;
using AntSK.Domain.Domain.Other;
using AntSK.Domain.Model;
using AntSK.Domain.Repositories;
using AntSK.Domain.Utils;
using LLama;
@@ -15,6 +14,7 @@ using RestSharp;
using System;
using ServiceLifetime = AntSK.Domain.Common.DependencyInjection.ServiceLifetime;
using AntSK.LLM.Mock;
using AntSK.Domain.Domain.Model.Enum;
namespace AntSK.Domain.Domain.Service
{
@@ -24,20 +24,21 @@ namespace AntSK.Domain.Domain.Service
private readonly IApis_Repositories _apis_Repositories;
private readonly IAIModels_Repositories _aIModels_Repositories;
private readonly FunctionService _functionService;
private readonly IServiceProvider _serviceProvider;
private Kernel _kernel;
public KernelService(
IApis_Repositories apis_Repositories,
IAIModels_Repositories aIModels_Repositories,
FunctionService functionService)
FunctionService functionService,
IServiceProvider serviceProvider)
{
_apis_Repositories = apis_Repositories;
_aIModels_Repositories = aIModels_Repositories;
_functionService = functionService;
_serviceProvider = serviceProvider;
}
private Kernel _kernel;
/// <summary>
/// 获取kernel实例依赖注入不好按每个用户去Import不同的插件所以每次new一个新的kernel
/// </summary>
@@ -133,7 +134,7 @@ namespace AntSK.Domain.Domain.Service
Console.WriteLine(msg);
RestClient client = new RestClient();
RestRequest request = new RestRequest(api.Url, Method.Get);
foreach (var header in api.Header.Split("\n"))
foreach (var header in api.Header.ConvertToString().Split("\n"))
{
var headerArray = header.Split(":");
if (headerArray.Length == 2)
@@ -142,7 +143,7 @@ namespace AntSK.Domain.Domain.Service
}
}
//这里应该还要处理一次参数提取,等后面再迭代
foreach (var query in api.Query.Split("\n"))
foreach (var query in api.Query.ConvertToString().Split("\n"))
{
var queryArray = query.Split("=");
if (queryArray.Length == 2)
@@ -168,7 +169,7 @@ namespace AntSK.Domain.Domain.Service
Console.WriteLine(msg);
RestClient client = new RestClient();
RestRequest request = new RestRequest(api.Url, Method.Post);
foreach (var header in api.Header.Split("\n"))
foreach (var header in api.Header.ConvertToString().Split("\n"))
{
var headerArray = header.Split(":");
if (headerArray.Length == 2)
@@ -177,7 +178,7 @@ namespace AntSK.Domain.Domain.Service
}
}
//这里应该还要处理一次参数提取,等后面再迭代
request.AddJsonBody(api.JsonBody);
request.AddJsonBody(api.JsonBody.ConvertToString());
var result = client.Execute(request);
return result.Content;
}
@@ -197,6 +198,8 @@ namespace AntSK.Domain.Domain.Service
var nativeIdList = app.NativeFunctionList.Split(",");
_functionService.SearchMarkedMethods();
using var scope= _serviceProvider.CreateScope();
foreach (var func in _functionService.Functions)
{
if (nativeIdList.Contains(func.Key))
@@ -204,7 +207,8 @@ namespace AntSK.Domain.Domain.Service
var methodInfo = _functionService.MethodInfos[func.Key];
var parameters = methodInfo.Parameters.Select(x => new KernelParameterMetadata(x.ParameterName) { ParameterType = x.ParameterType, Description = x.Description });
var returnType = new KernelReturnParameterMetadata() { ParameterType = methodInfo.ReturnType.ParameterType, Description = methodInfo.ReturnType.Description };
apiFunctions.Add(_kernel.CreateFunctionFromMethod((object[] args) => func.Value(args), func.Key, methodInfo.Description, parameters, returnType));
var target = ActivatorUtilities.CreateInstance(scope.ServiceProvider, func.Value.DeclaringType);
apiFunctions.Add(_kernel.CreateFunctionFromMethod(func.Value, target, func.Key, methodInfo.Description, parameters, returnType));
}
}
}
@@ -218,7 +222,7 @@ namespace AntSK.Domain.Domain.Service
private void RegisterPluginsWithKernel(Kernel kernel)
{
kernel.ImportPluginFromObject(new ConversationSummaryPlugin(), "ConversationSummaryPlugin");
kernel.ImportPluginFromObject(new TimePlugin(), "TimePlugin");
//kernel.ImportPluginFromObject(new TimePlugin(), "TimePlugin");
kernel.ImportPluginFromPromptDirectory(Path.Combine(RepoFiles.SamplePluginsPath(), "KMSPlugin"));
}
@@ -234,7 +238,7 @@ namespace AntSK.Domain.Domain.Service
KernelFunction sunFun = _kernel.Plugins.GetFunction("ConversationSummaryPlugin", "SummarizeConversation");
var summary = await _kernel.InvokeAsync(sunFun, new() { ["input"] = $"内容是:{history.ToString()} {Environment.NewLine} 请注意用中文总结" });
string his = summary.GetValue<string>();
var msg = $"history{history.ToString()}{Environment.NewLine} user{questions}"; ;
var msg = $"history{Environment.NewLine}{history.ToString()}{Environment.NewLine} user{questions}{Environment.NewLine}"; ;
return msg;
}
}

View File

@@ -1,13 +0,0 @@
using AutoMapper;
namespace AntSK.Domain.Map
{
public class AutoMapProfile : Profile
{
public AutoMapProfile()
{
}
}
}

View File

@@ -1,48 +0,0 @@
using AutoMapper;
namespace AntSK.Domain.Map
{
public static class MapperExtend
{
/// <summary>
/// Entity集合转DTO集合
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static List<T> ToDTOList<T>(this object value)
{
if (value == null)
return new List<T>();
return Mapper.Map<List<T>>(value);
}
/// <summary>
/// Entity转DTO
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T ToDTO<T>(this object value)
{
if (value == null)
return default(T);
return Mapper.Map<T>(value);
}
/// <summary>
/// 给已有对象map,适合update场景如需过滤空值需要在AutoMapProfile 设置
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="self"></param>
/// <param name="result"></param>
/// <returns></returns>
public static T MapTo<T>(this object self, T result)
{
if (self == null)
return default(T);
return (T)Mapper.Map(self, result, self.GetType(), typeof(T));
}
}
}

View File

@@ -1,30 +0,0 @@
using AutoMapper;
using Microsoft.Extensions.DependencyInjection;
namespace AntSK.Domain.Map
{
public static class MapperRegister
{
public static void AddMapper(this IServiceCollection services)
{
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMissingTypeMaps = true;
cfg.ValidateInlineMaps = false;
cfg.ShouldMapMethod = m => false;
cfg.AddProfile<AutoMapProfile>();
});
IMapper mapper = config.CreateMapper();
//启动实体映射
Mapper.Initialize(cfg =>
{
cfg.CreateMissingTypeMaps = true;
cfg.ValidateInlineMaps = false;
cfg.ShouldMapMethod = m => false;
cfg.AddProfile<AutoMapProfile>();
});
}
}
}

View File

@@ -7,6 +7,6 @@
public static string Embedding { get; set; }
public static string FileDirectory { get; set; }
public static string FileDirectory { get; set; } = Directory.GetCurrentDirectory();
}
}

View File

@@ -1,4 +1,4 @@
using AntSK.Domain.Model;
using AntSK.Domain.Domain.Model.Enum;
using SqlSugar;
using System.ComponentModel.DataAnnotations;

View File

@@ -0,0 +1,20 @@
using AntSK.Domain.Domain.Model.Enum;
using SqlSugar;
using System.ComponentModel.DataAnnotations;
namespace AntSK.Domain.Repositories
{
[SugarTable("Funs")]
public partial class Funs
{
[SugarColumn(IsPrimaryKey = true)]
public string Id { get; set; }
/// <summary>
/// 接口描述
/// </summary>
[Required]
public string Path { get; set; }
}
}

View File

@@ -0,0 +1,11 @@

using AntSK.Domain.Common.DependencyInjection;
using AntSK.Domain.Repositories.Base;
namespace AntSK.Domain.Repositories
{
[ServiceDescription(typeof(IFuns_Repositories), ServiceLifetime.Scoped)]
public class Funs_Repositories : Repository<Funs>, IFuns_Repositories
{
}
}

View File

@@ -0,0 +1,8 @@
using AntSK.Domain.Repositories.Base;
namespace AntSK.Domain.Repositories
{
public interface IFuns_Repositories : IRepository<Funs>
{
}
}

View File

@@ -1,4 +1,4 @@
using AntSK.Domain.Model.Enum;
using AntSK.Domain.Domain.Model.Enum;
using SqlSugar;
namespace AntSK.Domain.Repositories

View File

@@ -1,4 +1,4 @@
using AntSK.Domain.Model;
using AntSK.Domain.Domain.Model;
using SqlSugar;
using System.Linq.Expressions;

View File

@@ -1,5 +1,6 @@
using AntSK.Domain.Map;
using AntSK.Domain.Model;
using AntSK.Domain.Common.Map;
using AntSK.Domain.Domain.Model;
using SqlSugar;
using System.Linq.Expressions;

View File

@@ -1,4 +1,4 @@
using AntSK.Domain.Model.Enum;
using AntSK.Domain.Domain.Model.Enum;
using SqlSugar;
using System.ComponentModel.DataAnnotations;

View File

@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

24
src/AntSK.Test/Class1.cs Normal file
View File

@@ -0,0 +1,24 @@
using System.ComponentModel;
namespace AntSK.Test
{
/// <summary>
/// 测试插件导入
/// </summary>
public class TestFunctionImport
{
/// <summary>
/// 获取名称
/// </summary>
/// <returns>返回名称</returns>
[Description("AntSK")]
public string GetName()
{
return $"""
我的名字是AntSK,
我的作者是许泽宇
我是一个AI 知识库/智能体项目
""";
}
}
}

View File

@@ -20,6 +20,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AntSK.BackgroundTask", "Mid
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AntSK.LLM", "AntSk.LLM\AntSK.LLM.csproj", "{19529BFA-152F-4A8C-8254-F2D4896AB739}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AntSK.Test", "AntSK.Test\AntSK.Test.csproj", "{6AD71410-127F-4C83-95A8-F699C39B44FF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -42,6 +44,10 @@ Global
{19529BFA-152F-4A8C-8254-F2D4896AB739}.Debug|Any CPU.Build.0 = Debug|Any CPU
{19529BFA-152F-4A8C-8254-F2D4896AB739}.Release|Any CPU.ActiveCfg = Release|Any CPU
{19529BFA-152F-4A8C-8254-F2D4896AB739}.Release|Any CPU.Build.0 = Release|Any CPU
{6AD71410-127F-4C83-95A8-F699C39B44FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6AD71410-127F-4C83-95A8-F699C39B44FF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6AD71410-127F-4C83-95A8-F699C39B44FF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6AD71410-127F-4C83-95A8-F699C39B44FF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -1,155 +0,0 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>AntSK</name>
</assembly>
<members>
<member name="M:AntSK.Controllers.FileController.UploadFile(Microsoft.AspNetCore.Http.IFormFile)">
<summary>
Upload FileName
</summary>
<returns></returns>
</member>
<member name="M:AntSK.Controllers.InitController.InitTable">
<summary>
初始化DB 和表
</summary>
<returns></returns>
</member>
<member name="T:AntSK.Controllers.KMSController">
<summary>
</summary>
<param name="_taskBroker"></param>
</member>
<member name="M:AntSK.Controllers.LLamaSharpController.chat(AntSK.Domain.Domain.Dto.OpenAIModel)">
<summary>
本地会话接口
</summary>
<returns></returns>
</member>
<member name="M:AntSK.Controllers.LLamaSharpController.embedding(AntSK.Domain.Domain.Dto.OpenAIEmbeddingModel)">
<summary>
本地嵌入接口
</summary>
<param name="model"></param>
<returns></returns>
</member>
<member name="T:AntSK.Controllers.OpenController">
<summary>
对外接口
</summary>
</member>
<member name="M:AntSK.Controllers.OpenController.#ctor(AntSK.Services.OpenApi.IOpenApiService)">
<summary>
对外接口
</summary>
</member>
<member name="M:AntSK.Controllers.OpenController.chat(AntSK.Domain.Domain.Dto.OpenAIModel)">
<summary>
对话接口
</summary>
<returns></returns>
</member>
<member name="M:AntSK.Pages.ChatPage.Chat.SendKms(System.String,System.String,AntSK.Domain.Repositories.Apps)">
<summary>
发送知识库问答
</summary>
<param name="questions"></param>
<param name="msg"></param>
<param name="app"></param>
<returns></returns>
</member>
<member name="M:AntSK.Pages.ChatPage.Chat.SendChat(System.String,System.String,AntSK.Domain.Repositories.Apps)">
<summary>
发送普通对话
</summary>
<param name="questions"></param>
<param name="history"></param>
<param name="app"></param>
<returns></returns>
</member>
<member name="M:AntSK.Pages.ChatPage.Chat.HistorySummarize(AntSK.Domain.Repositories.Apps,System.String)">
<summary>
历史会话的会话总结
</summary>
<param name="questions"></param>
<returns></returns>
</member>
<member name="M:AntSK.Pages.ChatPage.OpenChat.SendKms(System.String,System.String,AntSK.Domain.Repositories.Apps)">
<summary>
发送知识库问答
</summary>
<param name="questions"></param>
<param name="msg"></param>
<param name="app"></param>
<returns></returns>
</member>
<member name="M:AntSK.Pages.ChatPage.OpenChat.SendChat(System.String,System.String,AntSK.Domain.Repositories.Apps)">
<summary>
发送普通对话
</summary>
<param name="questions"></param>
<param name="history"></param>
<param name="app"></param>
<returns></returns>
</member>
<member name="M:AntSK.Pages.ChatPage.OpenChat.HistorySummarize(AntSK.Domain.Repositories.Apps,System.String)">
<summary>
历史会话的会话总结
</summary>
<param name="questions"></param>
<returns></returns>
</member>
<member name="T:AntSK.Pages.KmsPage.KmsDetail.UrlModel">
<summary>
根据文档ID获取文档
</summary>
<param name="fileid"></param>
<returns></returns>
</member>
<member name="M:AntSK.plugins.Functions.FunctionTest.GetOrder(System.Int32)">
<summary>
获取订单信息
</summary>
<param name="id">订单号</param>
<returns>订单信息</returns>
</member>
<member name="T:AntSK.Services.LLamaSharp.LLamaChatService">
<summary>
</summary>
</member>
<member name="T:AntSK.Services.LLamaSharp.LLamaEmbeddingService">
<summary>
本地Embedding
</summary>
</member>
<member name="M:AntSK.Services.OpenApi.OpenApiService.SendChat(System.String,AntSK.Domain.Repositories.Apps)">
<summary>
发送普通对话
</summary>
<param name="questions"></param>
<param name="msg"></param>
<param name="app"></param>
<returns></returns>
</member>
<member name="M:AntSK.Services.OpenApi.OpenApiService.SendKms(System.String,AntSK.Domain.Repositories.Apps)">
<summary>
发送知识库问答
</summary>
<param name="questions"></param>
<param name="msg"></param>
<param name="app"></param>
<returns></returns>
</member>
<member name="M:AntSK.Services.OpenApi.OpenApiService.HistorySummarize(AntSK.Domain.Repositories.Apps,AntSK.Domain.Domain.Dto.OpenAIModel)">
<summary>
历史会话的会话总结
</summary>
<param name="questions"></param>
<param name="msg"></param>
<returns></returns>
</member>
</members>
</doc>

View File

@@ -3,7 +3,7 @@
@inherits AntDomComponentBase
<Space Class="@ClassMapper.Class" Size="@("26")">
<Image Src="https://img.shields.io/github/stars/xuzeyu91/antsk?style=social" Width="88px" Height="20px;"></Image>
<Image Src="http://img.shields.io/github/stars/aidotnet/antsk?style=social" Width="88px" Height="20px;"></Image>
<SpaceItem Style="margin-left:20px;">
<AvatarDropdown Name="@context.Identity.Name"
Avatar="@_currentUser.Avatar"

View File

@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc;
using AntSK.Domain.Options;
using Microsoft.AspNetCore.Mvc;
namespace AntSK.Controllers
{
@@ -20,7 +21,7 @@ namespace AntSK.Controllers
}
// 创建文件存储的路径
var uploadsFolderPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "files"); // 给定的文件夹名称
var uploadsFolderPath = Path.Combine(Path.Combine(Directory.GetCurrentDirectory(), LLamaSharpOption.FileDirectory), "files");// 给定的文件夹名称
// 如果路径不存在,则创建一个新的目录
if (!Directory.Exists(uploadsFolderPath))

View File

@@ -1,8 +1,8 @@
using AntSK.BackgroundTask;
using AntSK.Domain.Common.Map;
using AntSK.Domain.Domain.Interface;
using AntSK.Domain.Map;
using AntSK.Domain.Model;
using AntSK.Domain.Model.Enum;
using AntSK.Domain.Domain.Model;
using AntSK.Domain.Domain.Model.Enum;
using AntSK.Domain.Repositories;
using Microsoft.AspNetCore.Mvc;

View File

@@ -1,4 +1,4 @@
using AntSK.Domain.Domain.Dto;
using AntSK.Domain.Domain.Model.Dto.OpenAPI;
using AntSK.Services.LLamaSharp;
using Microsoft.AspNetCore.Mvc;

View File

@@ -1,4 +1,4 @@
using AntSK.Domain.Domain.Dto;
using AntSK.Domain.Domain.Model.Dto.OpenAPI;
using AntSK.Domain.Utils;
using AntSK.Services.OpenApi;
using Microsoft.AspNetCore.Mvc;

View File

@@ -5,16 +5,25 @@
@using AntSK.Domain.Options
@using AntSK.Domain.Repositories
@using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage
@inject INotificationService _notice
@inherits LayoutComponentBase
<AntDesign.ProLayout.BasicLayout
Logo="@("https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg")"
MenuData="_menuData">
<AntDesign.ProLayout.BasicLayout Logo="@("https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg")"
MenuData="_menuData">
<RightContentRender>
<AntSK.Components.RightContent />
</RightContentRender>
<ChildContent>
@Body
<ErrorBoundary @ref="errorBoundary">
<ChildContent>
@Body
</ChildContent>
<ErrorContent Context="ex">
@{
ShowNotification(ex);
}
</ErrorContent>
</ErrorBoundary>
</ChildContent>
<FooterRender>
<FooterView Copyright="2024 许泽宇的技术分享" Links="Links"></FooterView>
@@ -24,6 +33,7 @@
@code
{
ErrorBoundary errorBoundary;
private MenuDataItem[] _menuData = { };
[Inject] public HttpClient HttpClient { get; set; }
@@ -36,7 +46,7 @@
{
await base.OnInitializedAsync();
//菜单权限控制
var menuList = await HttpClient.GetFromJsonAsync<MenuDataItem[]>("data/menu.json");
var menuList = await HttpClient.GetFromJsonAsync<MenuDataItem[]>("data/menu.json");
var userSessionStorageResult = await _protectedSessionStore.GetAsync<UserSession>("UserSession");
var userSession = userSessionStorageResult.Success ? userSessionStorageResult.Value : null;
@@ -54,7 +64,7 @@
}
if (username == LoginOption.User )
if (username == LoginOption.User)
{
_menuData = menuList;
}
@@ -68,6 +78,17 @@
}
void ShowNotification(Exception ex)
{
_ = _notice.Error(new()
{
Message = ex.Message,
Description = ex.StackTrace
});
errorBoundary.Recover();
}
public LinkItem[] Links { get; set; } =
{
new LinkItem
@@ -81,9 +102,9 @@
{
Key = "github",
Title = (RenderFragment)(@<Icon Type="github" />),
Href = "https://github.com/xuzeyu91/Xzy.AntSK.KnowledgeBase",
Href = "https://github.com/AIDotNet/AntSK",
BlankTarget = true,
}
};
}

View File

@@ -1,6 +1,7 @@
@namespace AntSK
@inherits LayoutComponentBase
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
@Body
@code {

View File

@@ -36,7 +36,7 @@
{
Key = "github",
Title = (RenderFragment)(@<Icon Type="github" />),
Href = "https://github.com/xuzeyu91/Xzy.AntSK.KnowledgeBase",
Href = "https://github.com/AIDotNet/AntSK",
BlankTarget = true,
}
};

View File

@@ -1,7 +1,7 @@
@namespace AntSK.Pages.AppPage
@using AntSK.Domain.Repositories
@using AntSK.Models
@using AntSK.Domain.Model.Enum
@using AntSK.Domain.Domain.Model.Enum
@page "/App/Add"
@page "/App/Add/{AppId}"
@using AntSK.Services.Auth

View File

@@ -1,7 +1,8 @@
using AntDesign;
using AntSK.Domain.Domain.Model.Enum;
using AntSK.Domain.Domain.Service;
using AntSK.Domain.Model.Enum;
using AntSK.Domain.Repositories;
using AntSK.Domain.Utils;
using Microsoft.AspNetCore.Components;
using Microsoft.SemanticKernel;
@@ -26,7 +27,7 @@ namespace AntSK.Pages.AppPage
protected MessageService? Message { get; set; }
[Inject]
protected IAIModels_Repositories _aimodels_Repositories { get; set; }
[Inject]
[Inject]
protected FunctionService _functionService { get; set; }
private Apps _appModel = new Apps();
@@ -35,11 +36,11 @@ namespace AntSK.Pages.AppPage
private List<Kmss> _kmsList = new List<Kmss>();
IEnumerable<string> apiIds=[];
IEnumerable<string> apiIds = [];
private List<Apis> _apiList = new List<Apis>();
IEnumerable<string> funIds=[];
IEnumerable<string> funIds = [];
public Dictionary<string, string> _funList = new Dictionary<string, string>();
@@ -55,10 +56,10 @@ namespace AntSK.Pages.AppPage
_functionService.SearchMarkedMethods();
foreach (var func in _functionService.Functions)
{
var methodInfo = _functionService.MethodInfos[func.Key];
var methodInfo = _functionService.MethodInfos[func.Key];
_funList.Add(func.Key, methodInfo.Description);
}
if (!string.IsNullOrEmpty(AppId))
{
@@ -66,7 +67,7 @@ namespace AntSK.Pages.AppPage
_appModel = _apps_Repositories.GetFirst(p => p.Id == AppId);
kmsIds = _appModel.KmsIdList?.Split(",");
apiIds = _appModel.ApiFunctionList?.Split(",");
funIds= _appModel.NativeFunctionList?.Split(",");
funIds = _appModel.NativeFunctionList?.Split(",");
}
@@ -85,9 +86,15 @@ namespace AntSK.Pages.AppPage
_appModel.KmsIdList = string.Join(",", kmsIds);
}
_appModel.ApiFunctionList = string.Join(",", apiIds);
if (apiIds.IsNotNull())
{
_appModel.ApiFunctionList = string.Join(",", apiIds);
}
if (funIds.IsNotNull())
{
_appModel.NativeFunctionList = string.Join(",", funIds);
_appModel.NativeFunctionList = string.Join(",", funIds);
}
if (string.IsNullOrEmpty(AppId))
{

View File

@@ -1,6 +1,6 @@
@namespace AntSK.Pages.AppPage
@using AntSK.Domain.Repositories
@using AntSK.Domain.Model.Enum
@using AntSK.Domain.Domain.Model.Enum
@page "/AppList"
@inject NavigationManager NavigationManager
@using AntSK.Services.Auth

View File

@@ -1,5 +1,5 @@
using AntDesign;
using AntSK.Domain.Domain.Dto;
using AntSK.Domain.Domain.Model.Dto.OpenAPI;
using AntSK.Domain.Repositories;
using AntSK.Models;
using Microsoft.AspNetCore.Components;

View File

@@ -10,7 +10,7 @@
<GridRow Gutter="(16, 16)">
<GridCol Span="12">
<Spin Size="large" Tip="请稍等..." Spinning="@(_loading)">
<Card Style="height:700px;overflow: auto;">
<Card Style="height:75vh;overflow: auto;">
<TitleTemplate>
<Icon Type="setting" /> 选择应用
<Select DataSource="@_list"
@@ -20,9 +20,10 @@
LabelProperty="c=>c.Name"
Style="width:200px">
</Select>
<a href="@( NavigationManager.BaseUri + "openchat/" + AppId)" target="_blank">分享使用</a>
</TitleTemplate>
<Body>
<div id="scrollDiv" style="height: 530px; overflow-y: auto; overflow-x: hidden;">
<div id="scrollDiv" style="height: calc(75vh - 170px); overflow-y: auto; overflow-x: hidden;">
<GridRow Gutter="(8, 8)" Style="margin:0">
<Virtualize Items="@(MessageList.OrderBy(o => o.CreateTime).ToList())" Context="item">
@if (item.IsSend)
@@ -69,7 +70,7 @@
</Spin>
</GridCol>
<GridCol Span="12">
<Card Style="height: 700px;overflow: auto;">
<Card Style="height: 75vh;overflow: auto;">
<TitleTemplate>
<Icon Type="search" /> 调试结果
</TitleTemplate>
@@ -95,7 +96,6 @@
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 10px;
justify-content: center;
align-items: flex-start;
height: 100vh;

View File

@@ -1,7 +1,5 @@
using AntDesign;
using AntSK.Domain.Domain.Dto;
using AntSK.Domain.Domain.Interface;
using AntSK.Domain.Model;
using AntSK.Domain.Repositories;
using AntSK.Domain.Utils;
using Microsoft.AspNetCore.Components;
@@ -13,6 +11,8 @@ using RestSharp;
using System.Text;
using AntSK.Domain.Utils;
using Markdig;
using AntSK.Domain.Domain.Model;
using AntSK.Domain.Domain.Model.Dto;
namespace AntSK.Pages.ChatPage
{
@@ -262,7 +262,7 @@ namespace AntSK.Pages.ChatPage
}
else
{
var msg = $"history{history.ToString()}{Environment.NewLine}";
var msg = $"history{Environment.NewLine}{history.ToString()}{Environment.NewLine}{Environment.NewLine}";
return msg;
}
}

View File

@@ -1,6 +1,5 @@
using AntDesign;
using AntSK.Domain.Domain.Interface;
using AntSK.Domain.Model;
using AntSK.Domain.Repositories;
using AntSK.Domain.Utils;
using Microsoft.AspNetCore.Components;
@@ -12,6 +11,7 @@ using System.Text;
using AntSK.Domain.Utils;
using Microsoft.JSInterop;
using Markdig;
using AntSK.Domain.Domain.Model;
namespace AntSK.Pages.ChatPage
{

View File

@@ -1,4 +1,4 @@
using AntSK.Domain.Model.Enum;
using AntSK.Domain.Domain.Model.Enum;
using AntSK.Domain.Repositories;
using AntSK.Domain.Utils;
using Microsoft.AspNetCore.Components;

View File

@@ -67,5 +67,100 @@
</div>
</AntDesign.Col>
</Row>
</GridContent>
<Divider><Title Level="3">功能特性</Title></Divider>
<Space Size=@(("10", "10" )) Wrap Align="start" Style="padding:10px">
<SpaceItem>
<Card Bordered="true" Title=@("🍬语义内核") Hoverable="true" Style="height:260px;width:300px">
<Body>
<Text>1、采用遥遥领先的自然语言处理技术</Text>
<br>
<Text>2、准确理解、处理和响应复杂的语义查询</Text>
<br>
<Text>3、为用户提供精确的信息检索和推荐服务</Text>
<br>
</Body>
</Card>
</SpaceItem>
<SpaceItem>
<Card Bordered="true" Title=@("🏁知识库") Hoverable="true" Style="height:260px;width:300px">
<Body>
<Text>1、通过文档Word、PDF、Excel、Txt、Markdown、Json、PPT等形式导入知识库</Text>
<br>
<Text>2、可以进行知识库文档搜索问答</Text>
<br>
</Body>
</Card>
</SpaceItem>
<SpaceItem>
<Card Bordered="true" Title=@("🌈GPTs 生成") Hoverable="true" Style="height:260px;width:300px">
<Body>
<Text>1、支持创建个性化的GPTs</Text>
<br>
<Text>2、构建您自己的GPTs</Text>
<br>
<Text>3、可以尽情发挥你的想象力</Text>
<br>
</Body>
</Card>
</SpaceItem>
<SpaceItem>
<Card Bordered="true" Title=@("🎁插件生态") Hoverable="true" Style="height:260px;width:300px">
<Body>
<Text>1、开放式API插件系统允许第三方开发者或服务商轻松将其接口集成到AntSK不断增强应用功能</Text>
<br>
<Text>2、开放式函数插件系统标准格式的函数代码以及dll后集成到AntSK不断增强应用功能</Text>
<br>
<Text>3、支持二次开发Function</Text>
<br>
</Body>
</Card>
</SpaceItem>
<SpaceItem>
<Card Bordered="true" Title=@("📱模型管理") Hoverable="true" Style="height:260px;width:300px">
<Body>
<Text>1、适配和管理集成不同厂商的不同模型</Text>
<br>
<Text>
2、并且支持llama.cpp所支持的gguf类型的模型离线运行
</Text>
<br>
<Text>
3、未来将实现模型的训练、微调、部署一站式服务
</Text>
<br>
</Body>
</Card>
</SpaceItem>
<SpaceItem>
<Card Bordered="true" Title=@("🔗国产信创") Hoverable="true" Style="height:260px;width:300px">
<Body>
<Text>1、支持国产本地化模型</Text>
<br>
<Text>
2、支持国产信创数据库
</Text>
<br
<Text>
3、支持信创环境运行
</Text>
<br>
</Body>
</Card>
</SpaceItem>
<SpaceItem>
<Card Bordered="true" Title=@("🥤如果本项目帮助到了您") Hoverable="true" Style="height:260px;width:300px">
<Body>
<Image Height="170" Src="./assets/zfb.png" />
</Body>
</Card>
</SpaceItem>
<SpaceItem>
<Card Bordered="true" Title=@("您可用以下方式支持~🥤") Hoverable="true" Style="height:260px;width:300px">
<Body>
<Image Height="170" Src="./assets/wx.png" />
</Body>
</Card>
</SpaceItem>
</Space>
</GridContent>

View File

@@ -1,5 +1,5 @@
using AntDesign;
using AntSK.Domain.Model.Enum;
using AntSK.Domain.Domain.Model.Enum;
using AntSK.Domain.Repositories;
using Microsoft.AspNetCore.Components;

View File

@@ -1,7 +1,7 @@
using AntDesign;
using AntSK.BackgroundTask;
using AntSK.Domain.Domain.Interface;
using AntSK.Domain.Model;
using AntSK.Domain.Domain.Model;
using AntSK.Domain.Repositories;
using AntSK.Models;
using DocumentFormat.OpenXml.Drawing.Diagrams;

View File

@@ -1,6 +1,6 @@
@namespace AntSK.Pages.KmsPage
@using AntSK.Domain.Repositories
@using AntSK.Domain.Domain.Dto
@using AntSK.Domain.Domain.Model.Dto
@page "/Kms/DetailList/{KmsID}/{FileId}"
@inject NavigationManager NavigationManager
@using AntSK.Services.Auth

View File

@@ -1,5 +1,5 @@
using AntSK.Domain.Domain.Dto;
using AntSK.Domain.Domain.Interface;
using AntSK.Domain.Domain.Interface;
using AntSK.Domain.Domain.Model.Dto;
using Microsoft.AspNetCore.Components;
namespace AntSK.Pages.KmsPage

View File

@@ -1,7 +1,7 @@
@namespace AntSK.Pages.ApiPage
@using AntSK.Domain.Repositories
@using AntSK.Models
@using AntSK.Domain.Model
@using AntSK.Domain.Domain.Model.Enum
@page "/plugins/api/add"
@page "/plugins/api/add/{ApiId}"
@using AntSK.Services.Auth

View File

@@ -1,6 +1,6 @@
@namespace AntSK.Pages.ApiPage
@using AntSK.Domain.Repositories
@using AntSK.Domain.Model
@using AntSK.Domain.Domain.Model.Enum
@page "/plugins/apilist"
@inject NavigationManager NavigationManager
@using AntSK.Services.Auth

View File

@@ -0,0 +1,83 @@
@namespace AntSK.Pages.ApiPage
@using AntSK.Domain.Repositories
@using AntSK.Domain.Domain.Model.Enum
@using AntSK.Domain.Domain.Model.Fun
@page "/plugins/funlist"
@inject NavigationManager NavigationManager
@using AntSK.Services.Auth
@inherits AuthComponentBase
<PageContainer Title="函数列表">
<Content>
<div style="text-align: center;">
<Search Placeholder="输入回车"
EnterButton="@("搜索")"
Size="large"
Style="max-width: 522px; width: 100%;"
OnSearch="Search" />
</div>
</Content>
<ChildContent>
<div class="cardList">
<AntList TItem="FunDto"
DataSource="_data"
ItemLayout="ListItemLayout.Horizontal"
Grid="LayoutModel._listGridType">
<ListItem NoFlex>
@if (string.IsNullOrEmpty(context.Name))
{
<Button Type="dashed" class="newButton" @onclick="AddFun">
<Icon Type="plus" Theme="outline" /> 创建函数
</Button>
}
else
{
<Card Hoverable Bordered Class="card" Style="max-height:247px;">
<CardMeta>
<AvatarTemplate>
</AvatarTemplate>
<TitleTemplate>
<a>@context.Name</a>
</TitleTemplate>
<DescriptionTemplate>
<Paragraph class="item" Ellipsis>
<!--todo: Ellipsis not working-->
@context.Description
</Paragraph>
</DescriptionTemplate>
</CardMeta>
</Card>
}
</ListItem>
</AntList>
</div>
</ChildContent>
</PageContainer>
<Modal Title="插件导入"
Visible="@_fileVisible"
OnOk="@FileHandleOk"
OnCancel="@FileHandleCancel"
ConfirmLoading="@_fileConfirmLoading">
<Upload Action="@("api/File/UploadFile")"
Name="file"
Drag
Multiple
Accept="*/*"
BeforeUpload="BeforeUpload"
OnSingleCompleted="OnSingleCompleted">
<p class="ant-upload-drag-icon">
<Icon Type="inbox" />
</p>
<p class="ant-upload-text">单击或拖动文件到此区域进行上传</p>
<p class="ant-upload-hint">
请上传dll文件
</p>
</Upload>
</Modal>
@code
{
}

View File

@@ -0,0 +1,130 @@
using AntDesign;
using AntSK.Domain.Domain.Model.Fun;
using AntSK.Domain.Domain.Service;
using AntSK.Domain.Repositories;
using AntSK.Models;
using HtmlAgilityPack;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.SemanticKernel;
namespace AntSK.Pages.ApiPage
{
public partial class FunList
{
private FunDto[] _data = { };
[Inject]
FunctionService _functionService { get; set; }
[Inject]
IServiceProvider _serviceProvider { get; set; }
[Inject]
IConfirmService _confirmService { get; set; }
[Inject]
IFuns_Repositories _funs_Repositories { get; set; }
[Inject]
protected MessageService? _message { get; set; }
bool _fileVisible = false;
bool _fileConfirmLoading = false;
List<FileInfoModel> fileList = new List<FileInfoModel>();
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
await InitData("");
}
private async Task InitData(string searchKey)
{
var list = new List<FunDto> { new FunDto() };
_functionService.SearchMarkedMethods();
using var scope = _serviceProvider.CreateScope();
var funList = _functionService.Functions;
if (!string.IsNullOrEmpty(searchKey))
{
funList = funList.Where(x => x.Key.Contains(searchKey)).ToDictionary(x => x.Key, x => x.Value);
}
foreach (var func in funList)
{
var methodInfo = _functionService.MethodInfos[func.Key];
list.Add(new FunDto() { Name = func.Key, Description = methodInfo.Description });
}
_data = list.ToArray();
await InvokeAsync(StateHasChanged);
}
private void NavigateToAddApp()
{
NavigationManager.NavigateTo("/plugins/fun/add");
}
private async Task Search(string searchKey)
{
await InitData(searchKey);
}
private async Task AddFun() {
_fileVisible = true;
}
private async Task FileHandleOk(MouseEventArgs e)
{
try
{
foreach (var file in fileList)
{
_funs_Repositories.Insert(new Funs() { Id = Guid.NewGuid().ToString(), Path = file.FilePath });
_functionService.FuncLoad(file.FilePath);
}
_message.Info("上传成功");
await InitData("");
_fileVisible = false;
}
catch (System.Exception ex)
{
Console.WriteLine(ex.Message + " ---- " + ex.StackTrace);
}
}
private void FileHandleCancel(MouseEventArgs e)
{
_fileVisible = false;
}
private void FileShowModal()
{
_fileVisible = true;
}
bool BeforeUpload(UploadFileItem file)
{
if (file.Ext != ".dll")
{
_message.Error("请上传dll文件!");
}
var IsLt500K = file.Size < 1024 * 1024 * 100;
if (!IsLt500K)
{
_message.Error("文件需不大于100MB!");
}
return IsLt500K;
}
private void OnSingleCompleted(UploadInfo fileinfo)
{
if (fileinfo.File.State == UploadState.Success)
{
//文件列表
fileList.Add(new FileInfoModel()
{
FileName = fileinfo.File.FileName,
FilePath = fileinfo.File.Url = fileinfo.File.Response
});
}
}
}
}

View File

@@ -0,0 +1,132 @@
/* stylelint-disable at-rule-empty-line-before,at-rule-name-space-after,at-rule-no-unknown */
/* stylelint-disable no-duplicate-selectors */
/* stylelint-disable */
/* stylelint-disable declaration-bang-space-before,no-duplicate-selectors,string-no-newline */
.cardList .card .ant-card-meta-title {
margin-bottom: 12px;
}
.cardList .card .ant-card-meta-title > a {
display: inline-block;
max-width: 100%;
color: rgba(0, 0, 0, 0.85);
}
.cardList .card .ant-card-body:hover .ant-card-meta-title > a {
color: #1890ff;
}
.cardList .item {
height: 64px;
}
.cardList .ant-list .ant-list-item-content-single {
max-width: 100%;
}
.extraImg {
width: 155px;
margin-top: -20px;
text-align: center;
}
.extraImg img {
width: 100%;
}
.newButton {
width: 100%;
height: 201px;
color: rgba(0, 0, 0, 0.45);
background-color: #fff;
border-color: #d9d9d9;
}
.cardAvatar {
width: 48px;
height: 48px;
border-radius: 48px;
}
.cardDescription {
position: relative;
max-height: 4.5em;
margin-right: -1em;
padding-right: 1em;
overflow: hidden;
line-height: 1.5em;
text-align: justify;
}
.cardDescription::before {
position: absolute;
right: 14px;
bottom: 0;
padding: 0 1px;
background: #fff;
content: '...';
}
.cardDescription::after {
position: absolute;
right: 14px;
width: 1em;
height: 1em;
margin-top: 0.2em;
background: white;
content: '';
}
.pageHeaderContent__b__1 {
position: relative;
}
.contentLink {
margin-top: 16px;
}
.contentLink a {
margin-right: 32px;
}
.contentLink a img {
width: 24px;
}
.contentLink img {
margin-right: 8px;
vertical-align: middle;
}
@media screen and (max-width: 992px) {
.contentLink a {
margin-right: 16px;
}
}
@media screen and (max-width: 768px) {
.extraImg {
display: none;
}
}
@media screen and (max-width: 576px) {
.pageHeaderContent__b__1 {
padding-bottom: 30px;
}
.contentLink {
position: absolute;
bottom: -4px;
left: 0;
width: 1000px;
}
.contentLink a {
margin-right: 16px;
}
.contentLink img {
margin-right: 4px;
}
}

View File

@@ -1,7 +1,7 @@
@namespace AntSK.Pages.Setting.AIModel
@using AntSK.Domain.Repositories
@using AntSK.Models
@using AntSK.Domain.Model.Enum
@using AntSK.Domain.Domain.Model.Enum
@page "/setting/model/add"
@page "/setting/model/add/{ModelId}"
@page "/setting/model/addbypath/{ModelPath}"

View File

@@ -1,5 +1,6 @@
using AntDesign;
using AntDesign.ProLayout;
using AntSK.Domain.Domain.Model.Enum;
using AntSK.Domain.Options;
using AntSK.Domain.Repositories;
using AntSK.Domain.Utils;
@@ -50,7 +51,7 @@ namespace AntSK.Pages.Setting.AIModel
if (!string.IsNullOrEmpty(ModelPath))
{
//下载页跳入
_aiModel.AIType = Domain.Model.Enum.AIType.LLamaSharp;
_aiModel.AIType = AIType.LLamaSharp;
_downloadModalVisible = true;
_downloadUrl = $"https://hf-mirror.com{ModelPath.Replace("---","/")}";
@@ -64,7 +65,7 @@ namespace AntSK.Pages.Setting.AIModel
private void HandleSubmit()
{
if (_aimodels_Repositories.IsAny(p => p.AIModelType == _aiModel.AIModelType && p.EndPoint == _aiModel.EndPoint.ConvertToString() && p.ModelKey == _aiModel.ModelKey && p.ModelName == _aiModel.ModelName))
if (_aimodels_Repositories.IsAny(p => p.Id!=_aiModel.Id.ConvertToString()&& p.AIModelType == _aiModel.AIModelType && p.EndPoint == _aiModel.EndPoint.ConvertToString() && p.ModelKey == _aiModel.ModelKey && p.ModelName == _aiModel.ModelName))
{
_ = Message.Error("模型已存在!", 2);
return;
@@ -165,6 +166,7 @@ namespace AntSK.Pages.Setting.AIModel
{
_downloadStarted=false;
_download?.Stop();
InvokeAsync(StateHasChanged);
}
}
}

View File

@@ -3,7 +3,8 @@
@using AntSK.Services.Auth
@inherits AuthComponentBase
@using Microsoft.AspNetCore.Authorization
@using AntSK.Domain.Model.hfmirror
@using AntSK.Domain.Domain.Model.hfmirror;
using AntSK.Domain.Domain.Model.hfmirror
@attribute [Authorize(Roles = "AntSKAdmin")]

View File

@@ -1,5 +1,4 @@
using AntDesign;
using AntSK.Domain.Model.hfmirror;
using AntSK.Models;
using AntSK.Services;
using DocumentFormat.OpenXml.Office2010.Excel;
@@ -7,6 +6,7 @@ using Microsoft.AspNetCore.Components;
using Newtonsoft.Json;
using RestSharp;
using AntSK.Domain.Utils;
using AntSK.Domain.Domain.Model.hfmirror;
namespace AntSK.Pages.Setting.AIModel
{

View File

@@ -3,7 +3,8 @@
@using AntSK.Services.Auth
@inherits AuthComponentBase
@using Microsoft.AspNetCore.Authorization
@using AntSK.Domain.Model.hfmirror
@using AntSK.Domain.Domain.Model.hfmirror;
using AntSK.Domain.Domain.Model.hfmirror
@attribute [Authorize(Roles = "AntSKAdmin")]

View File

@@ -1,4 +1,4 @@
using AntSK.Domain.Model.hfmirror;
using AntSK.Domain.Domain.Model.hfmirror;
using DocumentFormat.OpenXml.EMMA;
using DocumentFormat.OpenXml.Spreadsheet;
using HtmlAgilityPack;

View File

@@ -1,6 +1,6 @@
@namespace AntSK.Pages.Setting.AIModel
@using AntSK.Domain.Repositories
@using AntSK.Domain.Model.Enum
@using AntSK.Domain.Domain.Model.Enum
@page "/setting/modellist"
@inject NavigationManager NavigationManager
@using AntSK.Services.Auth

View File

@@ -1,9 +1,9 @@
using AntDesign.ProLayout;
using AntSK.Domain.Common.DependencyInjection;
using AntSK.Domain.Common.Map;
using AntSK.Domain.Domain.Model;
using AntSK.Domain.Domain.Other;
using AntSK.Domain.Domain.Service;
using AntSK.Domain.Model;
using AntSK.Domain.Options;
using AntSK.Domain.Repositories;
using AntSK.Domain.Utils;
@@ -44,8 +44,8 @@ builder.Services.AddScoped(sp => new HttpClient
builder.Services.Configure<ProSettings>(builder.Configuration.GetSection("ProSettings"));
builder.Services.AddServicesFromAssemblies("AntSK");
builder.Services.AddServicesFromAssemblies("AntSK.Domain");
builder.Services.AddSingleton(sp => new FunctionService(sp, [typeof(AntSK.App).Assembly, typeof(AntSK.Domain.Common.AntSkFunctionAttribute).Assembly]));
builder.Services.AddSingleton<FunctionTest>();
builder.Services.AddSingleton(sp => new FunctionService(sp, [typeof(AntSK.App).Assembly]));
builder.Services.AddScoped<FunctionTest>();
builder.Services.AddSwaggerGen(c =>
{
@@ -111,6 +111,7 @@ if (!app.Environment.IsDevelopment())
app.UseStaticFiles();
InitDB(app);
LoadFun(app);
app.UseRouting();
@@ -140,7 +141,30 @@ void InitDB(WebApplication app)
_repository.GetDB().CodeFirst.InitTables(typeof(Users));
_repository.GetDB().CodeFirst.InitTables(typeof(Apis));
_repository.GetDB().CodeFirst.InitTables(typeof(AIModels));
_repository.GetDB().CodeFirst.InitTables(typeof(Funs));
//创建vector插件如果数据库没有则需要提供支持向量的数据库
_repository.GetDB().Ado.ExecuteCommandAsync($"CREATE EXTENSION IF NOT EXISTS vector;");
}
}
void LoadFun(WebApplication app)
{
try
{
using (var scope = app.Services.CreateScope())
{
//codefirst 创建表
var funRep = scope.ServiceProvider.GetRequiredService<IFuns_Repositories>();
var functionService = scope.ServiceProvider.GetRequiredService<FunctionService>();
var funs= funRep.GetList();
foreach (var fun in funs)
{
functionService.FuncLoad(fun.Path);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message + " ---- " + ex.StackTrace);
}
}

View File

@@ -1,5 +1,5 @@
using AntSK.Domain.Common.DependencyInjection;
using AntSK.Domain.Domain.Dto;
using AntSK.Domain.Domain.Model.Dto.OpenAPI;
using AntSK.Domain.Utils;
using Newtonsoft.Json;
using System.Text;

View File

@@ -1,6 +1,6 @@
using AntSK.Domain.Common.DependencyInjection;
using AntSK.Domain.Domain.Dto;
using AntSK.Domain.Domain.Interface;
using AntSK.Domain.Domain.Model.Dto.OpenAPI;
using AntSK.Domain.Repositories;
using AntSK.Domain.Utils;
using Microsoft.KernelMemory;

View File

@@ -36,7 +36,7 @@
"RunType": "GPU",
"Chat": "D:\\Code\\AI\\AntBlazor\\model\\qwen1_5-1_8b-chat-q8_0.gguf",
"Embedding": "D:\\Code\\AI\\AntBlazor\\model\\qwen1_5-1_8b-chat-q8_0.gguf",
"FileDirectory": "./llama_models"
"FileDirectory": "D:\\Code\\AI\\AntBlazor\\model\\"
},
"Login": {
"User": "admin",

View File

@@ -1,15 +1,17 @@
using AntSK.Domain.Common;
using AntSK.Domain.Repositories;
using System.ComponentModel;
namespace AntSK.plugins.Functions
{
public class FunctionTest
public class FunctionTest(IAIModels_Repositories Repository)
{
/// <summary>
/// 获取订单信息
/// </summary>
/// <param name="id">订单号</param>
/// <returns>订单信息</returns>
[AntSkFunction]
[Description("AntSK")]
public string GetOrder(int id)
{
return $"""
@@ -20,5 +22,16 @@ namespace AntSK.plugins.Functions
收货地址:上海市黄浦区
""";
}
/// <summary>
/// 获取模型
/// </summary>
/// <returns>模型列表</returns>
[Description("AntSK")]
public string GetModels()
{
var models = Repository.GetList();
return string.Join(",", models.Select(x => x.ModelName));
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

View File

@@ -27,6 +27,11 @@
"path": "/plugins/apilist",
"name": "Api管理",
"key": "plugins.apilist"
},
{
"path": "/plugins/funlist",
"name": "函数管理",
"key": "plugins.funlist"
}
]
},

View File

@@ -70,7 +70,8 @@ namespace AntSK.LLM.SparkDesk
IList<KernelFunctionMetadata> functions = kernel?.Plugins.GetFunctionsMetadata().Where(x => x.PluginName == "AntSkFunctions").ToList() ?? [];
var functionDefs = functions.Select(func => new FunctionDef(func.Name, func.Description, func.Parameters.Select(p => new FunctionParametersDef(p.Name, p.ParameterType?.IsClass == true ? "object" : "string", func.Description, p.IsRequired)).ToList())).ToList();
var messages = GetHistories(prompt);
//var messages = GetHistories(prompt);
var messages = new ChatMessage[] { new ChatMessage("user", prompt) };
return GetStreamingMessageAsync(messages, parameters, functionDefs, cancellationToken);
@@ -82,24 +83,39 @@ namespace AntSK.LLM.SparkDesk
{
var func = functions.Where(x => x.Name == msg.FunctionCall.Name).FirstOrDefault();
if (func == null)
{
yield return new($"插件{msg.FunctionCall.Name}未注册");
yield break;
}
if (kernel.Plugins.TryGetFunction(func.PluginName, func.Name, out var function))
{
var funcArgs = new Dictionary<string, object?>();
var arguments = new KernelArguments();
var JsonElement = JsonDocument.Parse(msg.FunctionCall.Arguments).RootElement;
foreach (var parameter in func.Parameters)
{
if (JsonElement.TryGetProperty(parameter.Name, out var property))
var error = "";
try
{
funcArgs.Add(parameter.Name, property.Deserialize(parameter.ParameterType!, _jsonSerializerOptions));
if (JsonElement.TryGetProperty(parameter.Name, out var property))
{
arguments.Add(parameter.Name, property.Deserialize(parameter.ParameterType!, _jsonSerializerOptions));
}
}
catch (Exception ex)
{
error = $"参数{parameter.Name}解析错误:{ex.Message}";
}
if (!string.IsNullOrEmpty(error))
{
yield return new(error);
yield break;
}
}
var arguments = new KernelArguments
{
{ "args", funcArgs.Values.ToArray() }
};
var result = (await function.InvokeAsync(kernel, arguments, cancellationToken)).GetValue<object>() ?? string.Empty;
var stringResult = ProcessFunctionResult(result, chatExecutionSettings.ToolCallBehavior);
messages = [.. messages, ChatMessage.FromUser($"""