mirror of
https://github.com/AIDotNet/AntSK.git
synced 2026-02-18 23:01:32 +08:00
Compare commits
163 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a1a36c3494 | ||
|
|
4f350081dd | ||
|
|
b3ea0c4e1a | ||
|
|
e72a6acd03 | ||
|
|
9bb8ab89fe | ||
|
|
e78da66d1a | ||
|
|
9ee21fd5e5 | ||
|
|
a22c04c9b2 | ||
|
|
3bb5bfaca7 | ||
|
|
c4bf5ee7e5 | ||
|
|
5e1e688f84 | ||
|
|
80d9bf68f3 | ||
|
|
65f2e3e363 | ||
|
|
68d27ff2bc | ||
|
|
034da30811 | ||
|
|
3db0cdcd19 | ||
|
|
42181a6f1d | ||
|
|
ec8cbf2550 | ||
|
|
9a1bd079da | ||
|
|
4213c4379c | ||
|
|
05cda17e2e | ||
|
|
cda6e54f0b | ||
|
|
51d8ba6408 | ||
|
|
b571c7d22d | ||
|
|
a0c91f565e | ||
|
|
280c750165 | ||
|
|
fec9337fda | ||
|
|
b84f252f2f | ||
|
|
5c998ccce2 | ||
|
|
0e3cfd2cfb | ||
|
|
4040831a23 | ||
|
|
a3a2308659 | ||
|
|
6d43c71d13 | ||
|
|
8315b6f37f | ||
|
|
7bc708e6ae | ||
|
|
e6f2c5c2fe | ||
|
|
5cab781362 | ||
|
|
02d7994bae | ||
|
|
b740957157 | ||
|
|
2480ec1272 | ||
|
|
35c98a0d14 | ||
|
|
0964a5ad5b | ||
|
|
a95131efe9 | ||
|
|
7783cdf3c4 | ||
|
|
7a65f33cb6 | ||
|
|
6efd01db3f | ||
|
|
1e2322b573 | ||
|
|
2cb2241a66 | ||
|
|
64efdd7881 | ||
|
|
be28e32803 | ||
|
|
468422baee | ||
|
|
7b1c6c8c64 | ||
|
|
7ff0ea0bfe | ||
|
|
6bed4356f0 | ||
|
|
73b65f7305 | ||
|
|
0ea52eced9 | ||
|
|
498e9ba9f6 | ||
|
|
125695665b | ||
|
|
0e08b3ae85 | ||
|
|
7cb8f99e7e | ||
|
|
d15cb527d0 | ||
|
|
9cb36174fd | ||
|
|
6265f94ef2 | ||
|
|
09d90b654c | ||
|
|
64e2bca2e6 | ||
|
|
328ece6d73 | ||
|
|
fabb8c2044 | ||
|
|
6ca75df880 | ||
|
|
3d4dfaced1 | ||
|
|
d532bf3bb6 | ||
|
|
e1fd288875 | ||
|
|
91eae9cfa8 | ||
|
|
b0059942d3 | ||
|
|
a716982878 | ||
|
|
3d4e48f9f5 | ||
|
|
1f212d3156 | ||
|
|
7d91ef6ba1 | ||
|
|
2a450b00de | ||
|
|
3a97068248 | ||
|
|
1d9d95899a | ||
|
|
7ae8e52b57 | ||
|
|
f5c195a1d0 | ||
|
|
78a6b662d3 | ||
|
|
5f814eb76c | ||
|
|
d9e5ebb464 | ||
|
|
bce0e9183c | ||
|
|
c40a7bcf22 | ||
|
|
97a7d447ab | ||
|
|
f803b9538b | ||
|
|
1ac34c1702 | ||
|
|
e07b480da1 | ||
|
|
9036af57e3 | ||
|
|
93288f9b5c | ||
|
|
f40dd8b013 | ||
|
|
c6b83d0695 | ||
|
|
592c850198 | ||
|
|
4a3930ac7b | ||
|
|
c05ba0af3e | ||
|
|
630ee51df6 | ||
|
|
d0e75e26c3 | ||
|
|
62c36c3072 | ||
|
|
baef309064 | ||
|
|
d717cbad9c | ||
|
|
5ef0624605 | ||
|
|
af2930a371 | ||
|
|
98f0f9fe84 | ||
|
|
28a23271e9 | ||
|
|
f1ba0bdf10 | ||
|
|
0d5513f374 | ||
|
|
4812cc308c | ||
|
|
584f7faded | ||
|
|
08dcef2d8b | ||
|
|
68218733a2 | ||
|
|
eb64cbf3d4 | ||
|
|
f0e8a55522 | ||
|
|
5ec5a0bde4 | ||
|
|
1cc56dd553 | ||
|
|
64e949a88b | ||
|
|
a2390a7c97 | ||
|
|
559661bb6c | ||
|
|
79326de263 | ||
|
|
3815891b28 | ||
|
|
42d474382a | ||
|
|
fe691f2d44 | ||
|
|
3ee41a8ab1 | ||
|
|
7ca41dff8a | ||
|
|
ba2e86993e | ||
|
|
13878046a2 | ||
|
|
49ff8bf54f | ||
|
|
e9cc5a3993 | ||
|
|
b213964b63 | ||
|
|
bfbed44270 | ||
|
|
9b07d88392 | ||
|
|
3f8ed109f9 | ||
|
|
3f969627a4 | ||
|
|
d92970819a | ||
|
|
23e756fa9b | ||
|
|
5f58126fbf | ||
|
|
dcfd0ffb8f | ||
|
|
17221d056c | ||
|
|
4a9dcfada4 | ||
|
|
bb6c2bb020 | ||
|
|
a8760a34de | ||
|
|
1e432a5782 | ||
|
|
cb861ef2bb | ||
|
|
7cee8fd87a | ||
|
|
8ce0e5d348 | ||
|
|
90bce7c89f | ||
|
|
b840d0bcce | ||
|
|
bfa6d28289 | ||
|
|
f6e6ca9747 | ||
|
|
75f8d39648 | ||
|
|
9a939eba5a | ||
|
|
4e93efe821 | ||
|
|
8bdbee80a0 | ||
|
|
6bdf5dcc03 | ||
|
|
0bf0a9d78a | ||
|
|
38e9fea601 | ||
|
|
d2366b3b46 | ||
|
|
3aff93083a | ||
|
|
eb998199db | ||
|
|
1dd794af1b | ||
|
|
08c9923e7e |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -324,10 +324,6 @@ ASALocalRun/
|
||||
# MSBuild Binary and Structured Log
|
||||
*.binlog
|
||||
|
||||
# NVidia Nsight GPU debugger configuration file
|
||||
*.nvuser
|
||||
*.dll
|
||||
*.pdb
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
.mfractor/
|
||||
**/bin/
|
||||
|
||||
@@ -22,4 +22,5 @@ WORKDIR /app
|
||||
COPY --from=build /app/publish .
|
||||
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
|
||||
RUN echo 'Asia/Shanghai' >/etc/timezone
|
||||
RUN apt update && apt install -y libpugixml-dev libtbb-dev
|
||||
ENTRYPOINT ["dotnet", "AntSK.dll"]
|
||||
|
||||
@@ -25,4 +25,5 @@ ENV PATH="/app:/opt/conda/bin:/usr/local/bin:${PATH}"
|
||||
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
|
||||
RUN echo 'Asia/Shanghai' >/etc/timezone
|
||||
RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
|
||||
ENTRYPOINT ["dotnet", "AntSK.dll"]
|
||||
RUN apt update && apt install -y libpugixml-dev libtbb-dev
|
||||
ENTRYPOINT ["dotnet", "AntSK.dll"]
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -186,7 +186,7 @@
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
Copyright [2024] [许泽宇]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
214
README.en.md
214
README.en.md
@@ -1,214 +0,0 @@
|
||||
[简体中文](./README.md) | English
|
||||
# AntSK
|
||||
## AI Knowledge Base/Intelligent Agent built on .Net8+AntBlazor+SemanticKernel
|
||||
|
||||
## ⭐Core Features
|
||||
|
||||
- **Semantic Kernel**: Utilizes advanced natural language processing technology to accurately understand, process, and respond to complex semantic queries, providing users with precise information retrieval and recommendation services.
|
||||
|
||||
- **Kernel Memory**: Capable of continuous learning and storing knowledge points, AntSK has long-term memory function, accumulates experience, and provides a more personalized interaction experience.
|
||||
|
||||
- **Knowledge Base**: Import knowledge base through documents (Word, PDF, Excel, Txt, Markdown, Json, PPT) and perform knowledge base Q&A.
|
||||
|
||||
- **GPT Generation**: This platform supports creating personalized GPT models, enabling users to build their own GPT models.
|
||||
|
||||
- **API Interface Publishing**: Exposes internal functions in the form of APIs, enabling developers to integrate AntSK into other applications and enhance application intelligence.
|
||||
|
||||
- **API Plugin System**: Open API plugin system that allows third-party developers or service providers to easily integrate their services into AntSK, continuously enhancing application functionality.
|
||||
|
||||
- **.Net Plugin System**: Open dll plugin system that allows third-party developers or service providers to easily integrate their business functions by generating dll in standard format code, continuously enhancing application functionality.
|
||||
|
||||
- **Online Search**: AntSK, real-time access to the latest information, ensuring users receive the most timely and relevant data.
|
||||
|
||||
- **Model Management**: Adapts and manages integration of different models from different manufacturers, including gguf types supported by **llama.cpp** and models offline running supported by **llamafactory**.
|
||||
|
||||
- **Domestic Innovation**: AntSK supports domestic models and databases and can run under domestic innovation conditions.
|
||||
|
||||
- **Model Fine-Tuning**: Planned based on llamafactory for model fine-tuning.
|
||||
|
||||
## ⛪Application Scenarios
|
||||
|
||||
AntSK is suitable for various business scenarios, such as:
|
||||
- Enterprise knowledge management system
|
||||
- Automatic customer service and chatbots
|
||||
- Enterprise search engine
|
||||
- Personalized recommendation system
|
||||
- Intelligent writing assistance
|
||||
- Education and online learning platforms
|
||||
- Other interesting AI Apps
|
||||
|
||||
## ✏️Function Examples
|
||||
### Online Demo
|
||||
```
|
||||
https://antsk.ai-dotnet.com/
|
||||
```
|
||||
```
|
||||
Default account: test
|
||||
|
||||
Default password: test
|
||||
|
||||
Due to the low configuration of the cloud server, the local model cannot be run, so the system settings permissions have been closed. You can simply view the interface. If you want to use the local model, please download and use it on your own.
|
||||
```
|
||||
|
||||
### Other Function Examples
|
||||
[Video Demonstration](https://www.bilibili.com/video/BV1zH4y1h7Y9/)
|
||||
|
||||
## ❓How to get started?
|
||||
|
||||
Here I am using Postgres as the data and vector storage because Semantic Kernel and Kernel Memory support it, but you can also use other options.
|
||||
|
||||
The model by default supports the local model of openai, azure openai, and llama. If you need to use other models, you can integrate them using one-api.
|
||||
|
||||
The Login configuration in the configuration file is the default login account and password.
|
||||
|
||||
The following configuration file needs to be configured
|
||||
|
||||
## 1️⃣Using docker-compose
|
||||
|
||||
Provided the pg version **appsettings.json** and simplified version (Sqlite+disk) **docker-compose.simple.yml**
|
||||
|
||||
Download **docker-compose.yml** from the project root directory and place the configuration file **appsettings.json** in the same directory.
|
||||
|
||||
The pg image has already been prepared. You can modify the default username and password in docker-compose.yml, and then the database connection in your **appsettings.json** needs to be consistent.
|
||||
|
||||
Then you can execute the following command in the directory to start AntSK
|
||||
```
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
## 2️⃣How to mount local models and model download directory in docker
|
||||
```
|
||||
# Non-host version, do not use local proxy
|
||||
version: '3.8'
|
||||
services:
|
||||
antsk:
|
||||
container_name: antsk
|
||||
image: registry.cn-hangzhou.aliyuncs.com/AIDotNet/antsk:v0.1.5ports:
|
||||
- 5000:5000
|
||||
networks:
|
||||
- antsk
|
||||
depends_on:
|
||||
- antskpg
|
||||
restart: always
|
||||
environment:
|
||||
- ASPNETCORE_URLS=http://*:5000
|
||||
volumes:
|
||||
- ./appsettings.json:/app/appsettings.json # Local configuration file needs to be placed in the same directory
|
||||
- D://model:/app/model
|
||||
networks:
|
||||
antsk:
|
||||
```
|
||||
Taking this as an example, it means mounting the local D://model folder of Windows into the container /app/model. If so, the model address in your appsettings.json should be configured as
|
||||
```
|
||||
model/xxx.gguf
|
||||
```
|
||||
|
||||
## 3️⃣Some meanings of configuration file
|
||||
```
|
||||
{
|
||||
"DBConnection": {
|
||||
"DbType": "Sqlite",
|
||||
"ConnectionStrings": "Data Source=AntSK.db;"
|
||||
},
|
||||
"KernelMemory": {
|
||||
"VectorDb": "Disk",
|
||||
"ConnectionString": "Host=;Port=;Database=antsk;Username=;Password=",
|
||||
"TableNamePrefix": "km-"
|
||||
},
|
||||
"LLamaSharp": {
|
||||
"RunType": "GPU",
|
||||
"FileDirectory": "D:\\Code\\AI\\AntBlazor\\model\\"
|
||||
},
|
||||
"Login": {
|
||||
"User": "admin",
|
||||
"Password": "xuzeyu"
|
||||
},
|
||||
"BackgroundTaskBroker": {
|
||||
"ImportKMSTask": {
|
||||
"WorkerCount": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
```
|
||||
// Supports various databases, you can check SqlSugar, MySql, SqlServer, Sqlite, Oracle, PostgreSQL, Dm, Kdbndp, Oscar, MySqlConnector, Access, OpenGauss, QuestDB, HG, ClickHouse, GBase, Odbc, OceanBaseForOracle, TDengine, GaussDB, OceanBase, Tidb, Vastbase, PolarDB, Custom
|
||||
DBConnection.DbType
|
||||
|
||||
// Connection string, need to use the corresponding string according to the different DB types
|
||||
DBConnection.ConnectionStrings
|
||||
|
||||
//The type of vector storage, supporting Postgres, Disk, Memory, Qdrant, Redis, AzureAISearch
|
||||
//Postgres and Redis require ConnectionString configuration
|
||||
//The ConnectionString of Qdrant and AzureAISearch uses Endpoint | APIKey
|
||||
KernelMemory.VectorDb
|
||||
|
||||
//Local model execution options: GPU and CPU. When using the online API, any option can be used.
|
||||
LLamaSharp.RunType
|
||||
|
||||
//Local model path, used for quick selection of models under llama, as well as saving downloaded models.
|
||||
LLamaSharp.FileDirectory
|
||||
|
||||
//Default admin account password
|
||||
Login
|
||||
|
||||
//Import asynchronous processing thread count. A higher count can be used for online API, but for local models, 1 is recommended to avoid memory overflow issues.
|
||||
BackgroundTaskBroker.ImportKMSTask.WorkerCount
|
||||
|
||||
```
|
||||
|
||||
## ⚠️Fixing Style Issues:
|
||||
Run the following in AntSK/src/AntSK:
|
||||
```
|
||||
dotnet clean
|
||||
dotnet build
|
||||
dotnet publish "AntSK.csproj"
|
||||
```
|
||||
Then navigate to AntSK/src/AntSK/bin/Release/net8.0/publish and run:
|
||||
```
|
||||
dotnet AntSK.dll
|
||||
```
|
||||
The styles should now be applied after starting.
|
||||
|
||||
I'm using CodeFirst mode for the database, so as long as the database connection is properly configured, the table structure will be created automatically.
|
||||
|
||||
## ✔️Using llamafactory
|
||||
```
|
||||
1. First, ensure that Python and pip are installed in your environment. This step is not necessary if using an image, such as version v0.2.3.2, which already includes the complete Python environment.
|
||||
2. Go to the model add page and select llamafactory.
|
||||
3. Click "Initialize" to check whether the 'pip install' environment setup is complete.
|
||||
4. Choose a model that you like.
|
||||
5. Click "Start" to begin downloading the model from the tower. This may involve a somewhat lengthy wait.
|
||||
6. After the model has finished downloading, enter http://localhost:8000/ in the request address. The default port is 8000.
|
||||
7. Click "Save" and start chatting.
|
||||
8. Many people ask about the difference between LLamaSharp and llamafactory. In fact, LLamaSharp is a .NET implementation of llama.cpp, but only supports local gguf models, while llamafactory supports a wider variety of models and uses Python implementation. The main difference lies here. Additionally, llamafactory has the ability to fine-tune models, which is an area we will focus on integrating in the future.
|
||||
```
|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
[](https://github.com/AIDotNet/AntSK/pulls)
|
||||
|
||||
If you would like to contribute, feel free to create a [Pull Request](https://github.com/AIDotNet/AntSK/pulls), or give us [Bug Report](https://github.com/AIDotNet/AntSK/issues/new).
|
||||
|
||||
|
||||
## 💕 Contributors
|
||||
|
||||
This project exists thanks to all the people who contribute.
|
||||
|
||||
<a href="https://github.com/AIDotNet/AntSK/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=AIDotNet/AntSK&max=1000&columns=15&anon=1" />
|
||||
</a>
|
||||
|
||||
## 🚨 Code of Conduct
|
||||
|
||||
This project has adopted the code of conduct defined by the Contributor Covenant to clarify expected behavior in our community.
|
||||
For more information see the [.NET Foundation Code of Conduct](https://dotnetfoundation.org/code-of-conduct).
|
||||
|
||||
To learn more or get started with **AntSK**, follow my official WeChat account and join the discussion group.
|
||||
|
||||
## ☎️Contact Me
|
||||
If you have any questions or suggestions, please contact me through my official WeChat account. We also have a discussion group where you can send a message to join, and then I will add you to the group.
|
||||

|
||||
|
||||
---
|
||||
|
||||
We appreciate your interest in **AntSK** and look forward to collaborating with you to create an intelligent future!
|
||||
219
README.md
219
README.md
@@ -1,96 +1,90 @@
|
||||
中文|[English](https://github.com/AIDotNet/AntSK/blob/main/README.en.md)
|
||||
[简体中文](./README.zh.md) | English
|
||||
# AntSK
|
||||
## 使用.Net8+Blazor+SemanticKernel 打造的AI知识库/智能体
|
||||
## AI Knowledge Base/Intelligent Agent built on .Net8+AntBlazor+SemanticKernel
|
||||
|
||||
## ⭐核心功能
|
||||
## ⭐Core Features
|
||||
|
||||
- **语义内核 (Semantic Kernel)**:采用领先的自然语言处理技术,准确理解、处理和响应复杂的语义查询,为用户提供精确的信息检索和推荐服务。
|
||||
- **Semantic Kernel**: Utilizes advanced natural language processing technology to accurately understand, process, and respond to complex semantic queries, providing users with precise information retrieval and recommendation services.
|
||||
|
||||
- **内存内核 (Kernel Memory)**:具备持续学习和存储知识点的能力,AntSK 拥有长期记忆功能,累积经验,提供更个性化的交互体验。
|
||||
- **Kernel Memory**: Capable of continuous learning and storing knowledge points, AntSK has long-term memory function, accumulates experience, and provides a more personalized interaction experience.
|
||||
|
||||
- **知识库**:通过文档(Word、PDF、Excel、Txt、Markdown、Json、PPT)等形式导入知识库,可以进行知识库问答。
|
||||
- **Knowledge Base**: Import knowledge base through documents (Word, PDF, Excel, Txt, Markdown, Json, PPT) and perform knowledge base Q&A.
|
||||
|
||||
- **文生图**:集成**StableDiffusion** 本地模型,可以进行文生图。
|
||||
- **GPT Generation**: This platform supports creating personalized GPT models, enabling users to build their own GPT models.
|
||||
|
||||
- **GPTs 生成**:此平台支持创建个性化的GPT模型,尝试构建您自己的GPT模型。
|
||||
- **API Interface Publishing**: Exposes internal functions in the form of APIs, enabling developers to integrate AntSK into other applications and enhance application intelligence.
|
||||
|
||||
- **API接口发布**:将内部功能以API的形式对外提供,便于开发者将AntSK 集成进其他应用,增强应用智慧。
|
||||
- **API Plugin System**: Open API plugin system that allows third-party developers or service providers to easily integrate their services into AntSK, continuously enhancing application functionality.
|
||||
|
||||
- **API插件系统**:开放式API插件系统,允许第三方开发者或服务商轻松将其服务集成到AntSK,不断增强应用功能。
|
||||
- **.Net Plugin System**: Open dll plugin system that allows third-party developers or service providers to easily integrate their business functions by generating dll in standard format code, continuously enhancing application functionality.
|
||||
|
||||
- **.Net插件系统**:开放式dll插件系统,允许第三方开发者或服务商轻松将其业务功能通过标准格式的代码生成dll后集成到AntSK,不断增强应用功能。
|
||||
- **Online Search**: AntSK, real-time access to the latest information, ensuring users receive the most timely and relevant data.
|
||||
|
||||
- **联网搜索**:AntSK,实时获取最新信息,确保用户接受到的资料总是最及时、最相关的。
|
||||
- **Model Management**: Adapts and manages integration of different models from different manufacturers, including gguf types supported by **llama.cpp** and models offline running supported by **llamafactory**.
|
||||
|
||||
- **模型管理**:适配和管理集成不同厂商的不同模型。并且支持**llama.cpp**所支持的gguf类型,以及**llamafactory**所支持的模型离线运行
|
||||
- **Domestic Innovation**: AntSK supports domestic models and databases and can run under domestic innovation conditions.
|
||||
|
||||
- **国产信创**:AntSK支持国产模型,和国产数据库,可以在信创条件下运行
|
||||
- **Model Fine-Tuning**: Planned based on llamafactory for model fine-tuning.
|
||||
|
||||
- **模型微调**:规划中,基于llamafactory进行模型微调
|
||||
|
||||
## ⛪Application Scenarios
|
||||
|
||||
## ⛪应用场景
|
||||
AntSK is suitable for various business scenarios, such as:
|
||||
- Enterprise knowledge management system
|
||||
- Automatic customer service and chatbots
|
||||
- Enterprise search engine
|
||||
- Personalized recommendation system
|
||||
- Intelligent writing assistance
|
||||
- Education and online learning platforms
|
||||
- Other interesting AI Apps
|
||||
|
||||
AntSK 适用于多种业务场景,例如:
|
||||
- 企业级知识管理系统
|
||||
- 自动客服与聊天机器人
|
||||
- 企业级搜索引擎
|
||||
- 个性化推荐系统
|
||||
- 智能辅助写作
|
||||
- 教育与在线学习平台
|
||||
- 其他有意思的AI App
|
||||
## ✏️Function Examples
|
||||
### Online Demo
|
||||
[document](http://antsk.cn/)
|
||||
|
||||
[demo](https://antsk.ai-dotnet.com/)
|
||||
|
||||
## ✏️功能示例
|
||||
### 在线演示
|
||||
```
|
||||
https://antsk.ai-dotnet.com/
|
||||
```
|
||||
```
|
||||
默认账号:test
|
||||
Default account: test
|
||||
|
||||
默认密码:test
|
||||
Default password: test
|
||||
|
||||
由于云服务器配置较低,无法运行本地模型,所以把系统设置权限关闭了,大家看看界面即可,要使用本地模型,请下载自行使用
|
||||
Due to the low configuration of the cloud server, the local model cannot be run, so the system settings permissions have been closed. You can simply view the interface. If you want to use the local model, please download and use it on your own.
|
||||
```
|
||||
|
||||
### 其他功能示例
|
||||
[视频示例](https://www.bilibili.com/video/BV1zH4y1h7Y9/)
|
||||
### Other Function Examples
|
||||
[Video Demonstration](https://www.bilibili.com/video/BV1zH4y1h7Y9/)
|
||||
|
||||
[在线文档:http://antsk.cn](http://antsk.cn)
|
||||
## ❓How to get started?
|
||||
|
||||
## ❓如何开始?
|
||||
Here I am using Postgres as the data and vector storage because Semantic Kernel and Kernel Memory support it, but you can also use other options.
|
||||
|
||||
在这里我使用的是Postgres 作为数据存储和向量存储,因为Semantic Kernel和Kernel Memory都支持他,当然你也可以换成其他的。
|
||||
The model by default supports the local model of openai, azure openai, and llama. If you need to use other models, you can integrate them using one-api.
|
||||
|
||||
模型默认支持openai、azure openai、讯飞星火、阿里云积、 和llama支持的gguf本地模型 以及llamafactory的本地模型,如果需要使用其他模型,可以使用one-api进行集成。
|
||||
The Login configuration in the configuration file is the default login account and password.
|
||||
|
||||
配置文件中的Login配置是默认的登录账号和密码
|
||||
The following configuration file needs to be configured
|
||||
|
||||
需要配置如下的配置文件
|
||||
## 1️⃣Using docker-compose
|
||||
|
||||
## 1️⃣使用docker-compose
|
||||
Provided the pg version **appsettings.json** and simplified version (Sqlite+disk) **docker-compose.simple.yml**
|
||||
|
||||
提供了pg版本 **appsettings.json** 和 简化版本(**Sqlite+disk**) **docker-compose.simple.yml**
|
||||
Download **docker-compose.yml** from the project root directory and place the configuration file **appsettings.json** in the same directory.
|
||||
|
||||
从项目根目录下载**docker-compose.yml**,然后把配置文件**appsettings.json**和它放在统一目录,
|
||||
The pg image has already been prepared. You can modify the default username and password in docker-compose.yml, and then the database connection in your **appsettings.json** needs to be consistent.
|
||||
|
||||
这里已经把pg的镜像做好了。在docker-compose.yml中可以修改默认账号密码,然后你的**appsettings.json**的数据库连接需要保持一致。
|
||||
|
||||
然后你可以进入到目录后执行
|
||||
Then you can execute the following command in the directory to start AntSK
|
||||
```
|
||||
docker-compose up -d
|
||||
```
|
||||
来启动AntSK
|
||||
|
||||
## 2️⃣如何在docker中挂载本地模型,和模型下载的目录
|
||||
## 2️⃣How to mount local models and model download directory in docker
|
||||
```
|
||||
# 非 host 版本, 不使用本机代理
|
||||
# Non-host version, do not use local proxy
|
||||
version: '3.8'
|
||||
services:
|
||||
antsk:
|
||||
container_name: antsk
|
||||
image: registry.cn-hangzhou.aliyuncs.com/AIDotNet/antsk:v0.2.3
|
||||
ports:
|
||||
image: registry.cn-hangzhou.aliyuncs.com/AIDotNet/antsk:v0.1.5ports:
|
||||
- 5000:5000
|
||||
networks:
|
||||
- antsk
|
||||
@@ -100,31 +94,35 @@ services:
|
||||
environment:
|
||||
- ASPNETCORE_URLS=http://*:5000
|
||||
volumes:
|
||||
- ./appsettings.json:/app/appsettings.json # 本地配置文件 需要放在同级目录
|
||||
- ./appsettings.json:/app/appsettings.json # Local configuration file needs to be placed in the same directory
|
||||
- D://model:/app/model
|
||||
networks:
|
||||
antsk:
|
||||
```
|
||||
以这个为示例,意思是把windows本地D://model的文件夹挂载进 容器内/app/model 如果是这样你的appsettings.json中的模型地址应该配置为
|
||||
Taking this as an example, it means mounting the local D://model folder of Windows into the container /app/model. If so, the model address in your appsettings.json should be configured as
|
||||
```
|
||||
model/xxx.gguf
|
||||
```
|
||||
|
||||
## 3️⃣配置文件的一些含义
|
||||
## 3️⃣Some meanings of configuration file
|
||||
```
|
||||
{
|
||||
"DBConnection": {
|
||||
"DbType": "Sqlite",
|
||||
"DbType": "Sqlite",
|
||||
"ConnectionStrings": "Data Source=AntSK.db;"
|
||||
},
|
||||
"KernelMemory": {
|
||||
"VectorDb": "Disk",
|
||||
"VectorDb": "Disk",
|
||||
"ConnectionString": "Host=;Port=;Database=antsk;Username=;Password=",
|
||||
"TableNamePrefix": "km-"
|
||||
},
|
||||
"FileDir": {
|
||||
"DirectoryPath": "D:\\git\\AntBlazor\\model"
|
||||
},
|
||||
"LLamaSharp": {
|
||||
"RunType": "GPU",
|
||||
"FileDirectory": "D:\\Code\\AI\\AntBlazor\\model\\"
|
||||
"RunType": "GPU",
|
||||
"ContextSize": 2048,
|
||||
"GpuLayerCount": 20
|
||||
},
|
||||
"Login": {
|
||||
"User": "admin",
|
||||
@@ -138,86 +136,85 @@ model/xxx.gguf
|
||||
}
|
||||
```
|
||||
```
|
||||
//支持多种数据库,具体可以查看SqlSugar,MySql,SqlServer,Sqlite,Oracle,PostgreSQL,Dm,Kdbndp,Oscar,MySqlConnector,Access,OpenGauss,QuestDB,HG,ClickHouse,GBase,Odbc,OceanBaseForOracle,TDengine,GaussDB,OceanBase,Tidb,Vastbase,PolarDB,Custom
|
||||
// Supports various databases, you can check SqlSugar, MySql, SqlServer, Sqlite, Oracle, PostgreSQL, Dm, Kdbndp, Oscar, MySqlConnector, Access, OpenGauss, QuestDB, HG, ClickHouse, GBase, Odbc, OceanBaseForOracle, TDengine, GaussDB, OceanBase, Tidb, Vastbase, PolarDB, Custom
|
||||
DBConnection.DbType
|
||||
//连接字符串,需要根据不同DB类型,用对应的字符串
|
||||
|
||||
// Connection string, need to use the corresponding string according to the different DB types
|
||||
DBConnection.ConnectionStrings
|
||||
|
||||
//向量存储的类型,支持 Postgres、Disk、Memory、Qdrant、Redis、AzureAISearch
|
||||
//Postgres、Redis需要配置 ConnectionString
|
||||
//Qdrant 和AzureAISearch 的 ConnectionString 使用 Endpoint|APIKey
|
||||
//The type of vector storage, supporting Postgres, Disk, Memory, Qdrant, Redis, AzureAISearch
|
||||
//Postgres and Redis require ConnectionString configuration
|
||||
//The ConnectionString of Qdrant and AzureAISearch uses Endpoint | APIKey
|
||||
KernelMemory.VectorDb
|
||||
|
||||
//本地模型使用的运行方式 GUP CPU ,如果用在线API 这个随意使用一个即可
|
||||
//Local model execution options: GPU and CPU. When using the online API, any option can be used.
|
||||
LLamaSharp.RunType
|
||||
|
||||
//本地模型路径,用于在选择llama时可以快速选择目录下的模型,以及保存下载的模型
|
||||
//Local model path, used for quick selection of models under llama, as well as saving downloaded models.
|
||||
LLamaSharp.FileDirectory
|
||||
|
||||
//默认管理员账号密码
|
||||
//Default admin account password
|
||||
Login
|
||||
//导入异步处理的线程数,使用在线API可以高一点,本地模型建议1 否则容易内存溢出崩掉
|
||||
|
||||
//Import asynchronous processing thread count. A higher count can be used for online API, but for local models, 1 is recommended to avoid memory overflow issues.
|
||||
BackgroundTaskBroker.ImportKMSTask.WorkerCount
|
||||
|
||||
```
|
||||
|
||||
## ⚠️找不到样式问题解决:
|
||||
AntSK/src/AntSK下执行:
|
||||
## ⚠️Fixing Style Issues:
|
||||
Run the following in AntSK/src/AntSK:
|
||||
```
|
||||
dotnet clean
|
||||
dotnet build
|
||||
dotnet publish "AntSK.csproj"
|
||||
```
|
||||
再去AntSK/src/AntSK/bin/Release/net8.0/publish下
|
||||
Then navigate to AntSK/src/AntSK/bin/Release/net8.0/publish and run:
|
||||
```
|
||||
dotnet AntSK.dll
|
||||
```
|
||||
然后启动就有样式了
|
||||
The styles should now be applied after starting.
|
||||
|
||||
DB我使用的是CodeFirst模式,只要配置好数据库链接,表结构是自动创建的
|
||||
I'm using CodeFirst mode for the database, so as long as the database connection is properly configured, the table structure will be created automatically.
|
||||
|
||||
## ✔️使用llamafactory
|
||||
## ✔️Using llamafactory
|
||||
```
|
||||
1、首先需要确保你的环境已经安装了python和pip,如果使用镜像,例如p0.2.4版本已经包含了 python全套环境则无需此步骤
|
||||
2、进入模型添加页面选择llamafactory
|
||||
3、点击初始化,可以检查pip install 环境是否完成
|
||||
4、选择一个喜欢的模型
|
||||
5、点击启动,这会开始从魔塔下载模型,你可能需要有一个较为漫长的等待
|
||||
6、等待模型下载完毕后,在请求地址输入 http://localhost:8000/ 这里默认是使用8000端口
|
||||
7、点击保存,然后就可以开始聊天了
|
||||
8、很多人会问 LLamaSharp与llamafactory有什么区别?其实这两者LLamaSharp是llama.cpp的 dotnet实现,但是只支持本地gguf模型, 而llamafactory 支持的模型种类更多,但使用的是python的实现,其主要差异在这里,另外llamafactory具有模型微调的能力,这也是我们下一步需要重点集成的部分。
|
||||
1. First, ensure that Python and pip are installed in your environment. This step is not necessary if using an image, such as version v0.2.3.2, which already includes the complete Python environment.
|
||||
2. Go to the model add page and select llamafactory.
|
||||
3. Click "Initialize" to check whether the 'pip install' environment setup is complete.
|
||||
4. Choose a model that you like.
|
||||
5. Click "Start" to begin downloading the model from the tower. This may involve a somewhat lengthy wait.
|
||||
6. After the model has finished downloading, enter http://localhost:8000/ in the request address. The default port is 8000.
|
||||
7. Click "Save" and start chatting.
|
||||
8. Many people ask about the difference between LLamaSharp and llamafactory. In fact, LLamaSharp is a .NET implementation of llama.cpp, but only supports local gguf models, while llamafactory supports a wider variety of models and uses Python implementation. The main difference lies here. Additionally, llamafactory has the ability to fine-tune models, which is an area we will focus on integrating in the future.
|
||||
```
|
||||
|
||||
## 🤝 贡献
|
||||
## 🤝 Contributing
|
||||
|
||||
[](https://github.com/AIDotNet/AntSK/pulls)
|
||||
|
||||
如果你想贡献,可以创建一个[拉取请求](https://github.com/AIDotNet/AntSK/pulls), 或给我们[错误报告](https://github.com/AIDotNet/AntSK/issues/new).
|
||||
|
||||
|
||||
## 💕 贡献者
|
||||
[PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)
|
||||
|
||||
If you would like to contribute, feel free to create a [Pull Request](https://github.com/AIDotNet/AntSK/pulls), or give us [Bug Report](https://github.com/AIDotNet/AntSK/issues/new).
|
||||
|
||||
|
||||
## 💕 Contributors
|
||||
|
||||
This project exists thanks to all the people who contribute.
|
||||
|
||||
这个项目的存在要感谢所有的贡献者。
|
||||
|
||||
<a href="https://github.com/AIDotNet/AntSK/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=AIDotNet/AntSK&max=1000&columns=15&anon=1" />
|
||||
</a>
|
||||
|
||||
## 🚨 行为准则
|
||||
|
||||
该项目采用了贡献者公约定义的行为准则,以阐明我们社区的预期行为。有关更多信息,请参见 .NET Foundation 行为准则。 [.NET Foundation Code of Conduct](https://dotnetfoundation.org/code-of-conduct).
|
||||
|
||||
想了解更多信息或开始使用 **AntSK**,可以关注我的公众号以及加入交流群。
|
||||
|
||||
## ☎️联系我
|
||||
如有任何问题或建议,请通过以下方式关注我的公众号,发消息与我联系,我们也有交流群,可以发送进群等消息,然后我会拉你进交流群
|
||||

|
||||
|
||||
## 🌟 Star History
|
||||
<a href="https://github.com/AIDotNet/AntSK/stargazers" target="_blank" style="display: block" align="center">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=AIDotNet/AntSK&type=Date&theme=dark" />
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=AIDotNet/AntSK&type=Date" />
|
||||
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=AIDotNet/AntSK&type=Date" />
|
||||
</picture>
|
||||
<img src="https://contrib.rocks/image?repo=AIDotNet/AntSK&max=1000&columns=15&anon=1" />
|
||||
</a>
|
||||
|
||||
## 🚨 Use Protocol
|
||||
This warehouse follows the [Apache-2.0 License](https://github.com/AIDotNet/AntSK?tab=Apache-2.0-1-ov-file) open source protocol.
|
||||
The Apache open source license allows the use of AntSK in commercial environments, provided that the license terms are followed. One of the main terms is to retain the copyright and license statements.
|
||||
If you plan to use AntSK in commercial projects, you need to ensure that you follow the following steps:
|
||||
1. Copyright statement containing Apache license. [Apache-2.0 License](https://github.com/AIDotNet/AntSK?tab=Apache-2.0-1-ov-file).
|
||||
2. If you modify the software source code, you need to clearly indicate these modifications in the source code.
|
||||
|
||||
## ☎️Contact Me
|
||||
If you have any questions or suggestions, please contact me through my official WeChat account. We also have a discussion group where you can send a message to join, and then I will add you to the group.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
We appreciate your interest in **AntSK** and look forward to collaborating with you to create an intelligent future!
|
||||
|
||||
238
README.zh.md
Normal file
238
README.zh.md
Normal file
@@ -0,0 +1,238 @@
|
||||
中文|[English](./README.md)
|
||||
# AntSK
|
||||
## 使用.Net8+Blazor+SemanticKernel 打造的AI知识库/智能体
|
||||
|
||||
## ⭐核心功能
|
||||
|
||||
- **语义内核 (Semantic Kernel)**:采用领先的自然语言处理技术,准确理解、处理和响应复杂的语义查询,为用户提供精确的信息检索和推荐服务。
|
||||
|
||||
- **内存内核 (Kernel Memory)**:具备持续学习和存储知识点的能力,AntSK 拥有长期记忆功能,累积经验,提供更个性化的交互体验。
|
||||
|
||||
- **知识库**:通过文档(Word、PDF、Excel、Txt、Markdown、Json、PPT)等形式导入知识库,可以进行知识库问答,支持本地bge-embedding 向量模型 ,以及bge-rerank 重排模型。
|
||||
|
||||
- **文生图**:集成**StableDiffusion** 本地模型,可以进行文生图。
|
||||
|
||||
- **GPTs 生成**:此平台支持创建个性化的GPT模型,尝试构建您自己的GPT模型。
|
||||
|
||||
- **API接口发布**:将内部功能以API的形式对外提供,便于开发者将AntSK 集成进其他应用,增强应用智慧。
|
||||
|
||||
- **API插件系统**:开放式API插件系统,允许第三方开发者或服务商轻松将其服务集成到AntSK,不断增强应用功能。
|
||||
|
||||
- **.Net插件系统**:开放式dll插件系统,允许第三方开发者或服务商轻松将其业务功能通过标准格式的代码生成dll后集成到AntSK,不断增强应用功能。
|
||||
|
||||
- **联网搜索**:AntSK,实时获取最新信息,确保用户接受到的资料总是最及时、最相关的。
|
||||
|
||||
- **模型管理**:适配和管理集成不同厂商的不同模型。并且支持**llama.cpp**所支持的gguf类型,以及**llamafactory**所支持的模型离线运行
|
||||
|
||||
- **国产信创**:AntSK支持国产模型,和国产数据库,可以在信创条件下运行
|
||||
|
||||
- **模型微调**:规划中,基于llamafactory进行模型微调
|
||||
|
||||
|
||||
## ⛪应用场景
|
||||
|
||||
AntSK 适用于多种业务场景,例如:
|
||||
- 企业级知识管理系统
|
||||
- 自动客服与聊天机器人
|
||||
- 企业级搜索引擎
|
||||
- 个性化推荐系统
|
||||
- 智能辅助写作
|
||||
- 教育与在线学习平台
|
||||
- 其他有意思的AI App
|
||||
|
||||
## ✏️功能示例
|
||||
### 在线演示
|
||||
|
||||
[文档地址](http://antsk.cn/)
|
||||
|
||||
[体验地址](https://antsk.ai-dotnet.com/)
|
||||
|
||||
```
|
||||
默认账号:test
|
||||
|
||||
默认密码:test
|
||||
|
||||
由于云服务器配置较低,无法运行本地模型,所以把系统设置权限关闭了,大家看看界面即可,要使用本地模型,请下载自行使用
|
||||
|
||||
请勿在演示站点上传敏感信息
|
||||
```
|
||||
|
||||
### 其他功能示例
|
||||
[视频示例](https://www.bilibili.com/video/BV1zH4y1h7Y9/)
|
||||
|
||||
[在线文档:http://antsk.cn](http://antsk.cn)
|
||||
|
||||
## ❓如何开始?
|
||||
|
||||
在这里我使用的是Postgres 作为数据存储和向量存储,因为Semantic Kernel和Kernel Memory都支持他,当然你也可以换成其他的。
|
||||
|
||||
模型默认支持openai、azure openai、讯飞星火、阿里云积、 和llama支持的gguf本地模型 以及llamafactory的本地模型,如果需要使用其他模型,可以使用one-api进行集成。
|
||||
|
||||
配置文件中的Login配置是默认的登录账号和密码
|
||||
|
||||
需要配置如下的配置文件
|
||||
|
||||
## 1️⃣使用docker-compose
|
||||
|
||||
提供了pg版本 **appsettings.json** 和 简化版本(**Sqlite+disk**) **docker-compose.simple.yml**
|
||||
|
||||
从项目根目录下载**docker-compose.yml**,然后把配置文件**appsettings.json**和它放在统一目录,
|
||||
|
||||
这里已经把pg的镜像做好了。在docker-compose.yml中可以修改默认账号密码,然后你的**appsettings.json**的数据库连接需要保持一致。
|
||||
|
||||
然后你可以进入到目录后执行
|
||||
```
|
||||
docker-compose up -d
|
||||
```
|
||||
来启动AntSK
|
||||
|
||||
## 2️⃣如何在docker中挂载本地模型,和模型下载的目录
|
||||
```
|
||||
# 非 host 版本, 不使用本机代理
|
||||
version: '3.8'
|
||||
services:
|
||||
antsk:
|
||||
container_name: antsk
|
||||
image: registry.cn-hangzhou.aliyuncs.com/AIDotNet/antsk:v0.3.1
|
||||
ports:
|
||||
- 5000:5000
|
||||
networks:
|
||||
- antsk
|
||||
depends_on:
|
||||
- antskpg
|
||||
restart: always
|
||||
environment:
|
||||
- ASPNETCORE_URLS=http://*:5000
|
||||
volumes:
|
||||
- ./appsettings.json:/app/appsettings.json # 本地配置文件 需要放在同级目录
|
||||
- D://model:/app/model
|
||||
- D://model:/root/.cache/modelscope/hub/AI-ModelScope #使用Llamafactory时需要挂载 否则初始化的环境重启后会丢失
|
||||
networks:
|
||||
antsk:
|
||||
```
|
||||
以这个为示例,意思是把windows本地D://model的文件夹挂载进 容器内/app/model 如果是这样你的appsettings.json中的模型地址应该配置为
|
||||
```
|
||||
model/xxx.gguf
|
||||
```
|
||||
|
||||
## 3️⃣配置文件的一些含义
|
||||
```
|
||||
{
|
||||
"DBConnection": {
|
||||
"DbType": "Sqlite",
|
||||
"ConnectionStrings": "Data Source=AntSK.db;"
|
||||
},
|
||||
"KernelMemory": {
|
||||
"VectorDb": "Disk",
|
||||
"ConnectionString": "Host=;Port=;Database=antsk;Username=;Password=",
|
||||
"TableNamePrefix": "km-"
|
||||
},
|
||||
"FileDir": {
|
||||
"DirectoryPath": "D:\\git\\AntBlazor\\model"
|
||||
},
|
||||
"LLamaSharp": {
|
||||
"RunType": "GPU",
|
||||
"ContextSize": 2048,
|
||||
"GpuLayerCount": 20
|
||||
},
|
||||
"Login": {
|
||||
"User": "admin",
|
||||
"Password": "xuzeyu"
|
||||
},
|
||||
"BackgroundTaskBroker": {
|
||||
"ImportKMSTask": {
|
||||
"WorkerCount": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
```
|
||||
//支持多种数据库,具体可以查看SqlSugar,MySql,SqlServer,Sqlite,Oracle,PostgreSQL,Dm,Kdbndp,Oscar,MySqlConnector,Access,OpenGauss,QuestDB,HG,ClickHouse,GBase,Odbc,OceanBaseForOracle,TDengine,GaussDB,OceanBase,Tidb,Vastbase,PolarDB,Custom
|
||||
DBConnection.DbType
|
||||
//连接字符串,需要根据不同DB类型,用对应的字符串
|
||||
DBConnection.ConnectionStrings
|
||||
|
||||
//向量存储的类型,支持 Postgres、Disk、Memory、Qdrant、Redis、AzureAISearch
|
||||
//Postgres、Redis需要配置 ConnectionString
|
||||
//Qdrant 和AzureAISearch 的 ConnectionString 使用 Endpoint|APIKey
|
||||
KernelMemory.VectorDb
|
||||
|
||||
//本地模型使用的运行方式 GUP CPU ,如果用在线API 这个随意使用一个即可
|
||||
LLamaSharp.RunType
|
||||
|
||||
//本地模型路径,用于在选择llama时可以快速选择目录下的模型,以及保存下载的模型
|
||||
LLamaSharp.FileDirectory
|
||||
|
||||
//默认管理员账号密码
|
||||
Login
|
||||
//导入异步处理的线程数,使用在线API可以高一点,本地模型建议1 否则容易内存溢出崩掉
|
||||
BackgroundTaskBroker.ImportKMSTask.WorkerCount
|
||||
```
|
||||
|
||||
## ⚠️找不到样式问题解决:
|
||||
AntSK/src/AntSK下执行:
|
||||
```
|
||||
dotnet clean
|
||||
dotnet build
|
||||
dotnet publish "AntSK.csproj"
|
||||
```
|
||||
再去AntSK/src/AntSK/bin/Release/net8.0/publish下
|
||||
```
|
||||
dotnet AntSK.dll
|
||||
```
|
||||
然后启动就有样式了
|
||||
|
||||
DB我使用的是CodeFirst模式,只要配置好数据库链接,表结构是自动创建的
|
||||
|
||||
## ✔️使用llamafactory
|
||||
```
|
||||
1、首先需要确保你的环境已经安装了python和pip,如果使用镜像,例如p0.2.4版本已经包含了 python全套环境则无需此步骤
|
||||
2、进入模型添加页面选择llamafactory
|
||||
3、点击初始化,可以检查pip install 环境是否完成
|
||||
4、选择一个喜欢的模型
|
||||
5、点击启动,这会开始从魔塔下载模型,你可能需要有一个较为漫长的等待
|
||||
6、等待模型下载完毕后,在请求地址输入 http://localhost:8000/ 这里默认是使用8000端口
|
||||
7、点击保存,然后就可以开始聊天了
|
||||
8、很多人会问 LLamaSharp与llamafactory有什么区别?其实这两者LLamaSharp是llama.cpp的 dotnet实现,但是只支持本地gguf模型, 而llamafactory 支持的模型种类更多,但使用的是python的实现,其主要差异在这里,另外llamafactory具有模型微调的能力,这也是我们下一步需要重点集成的部分。
|
||||
```
|
||||
|
||||
## 🤝 贡献
|
||||
|
||||
[](https://github.com/AIDotNet/AntSK/pulls)
|
||||
|
||||
如果你想贡献,可以创建一个[拉取请求](https://github.com/AIDotNet/AntSK/pulls), 或给我们[错误报告](https://github.com/AIDotNet/AntSK/issues/new).
|
||||
|
||||
|
||||
## 💕 贡献者
|
||||
|
||||
这个项目的存在要感谢所有的贡献者。
|
||||
|
||||
<a href="https://github.com/AIDotNet/AntSK/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=AIDotNet/AntSK&max=1000&columns=15&anon=1" />
|
||||
</a>
|
||||
|
||||
## 🚨 使用协议
|
||||
|
||||
本仓库遵循 [Apache-2.0 License](https://github.com/AIDotNet/AntSK?tab=Apache-2.0-1-ov-file) 开源协议。
|
||||
Apache开源许可证允许在商业环境中使用AntSK,前提是需要遵守许可证的条款。主要条款之一是要保留版权声明和许可证声明。
|
||||
|
||||
如果您打算在商业项目中使用AntSK,您需要确保遵守以下步骤:
|
||||
|
||||
1、包含Apache许可证的版权声明。 [Apache-2.0 License](https://github.com/AIDotNet/AntSK?tab=Apache-2.0-1-ov-file) 。
|
||||
|
||||
2、如果您修改了软件源代码,您需要在源代码中明确标明这些修改。
|
||||
|
||||
|
||||
## ☎️联系我
|
||||
如有任何问题或建议,请通过以下方式关注我的公众号《许泽宇的技术分享》,发消息与我联系,我们也有AIDotnet交流群,可以发送进群等消息,然后我会拉你进交流群
|
||||

|
||||
|
||||
## 🌟 Star History
|
||||
<a href="https://github.com/AIDotNet/AntSK/stargazers" target="_blank" style="display: block" align="center">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=AIDotNet/AntSK&type=Date&theme=dark" />
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=AIDotNet/AntSK&type=Date" />
|
||||
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=AIDotNet/AntSK&type=Date" />
|
||||
</picture>
|
||||
</a>
|
||||
|
||||
@@ -3,9 +3,9 @@ version: '3.8'
|
||||
services:
|
||||
antsk:
|
||||
container_name: antsk
|
||||
image: registry.cn-hangzhou.aliyuncs.com/xuzeyu91/antsk:v0.2.6
|
||||
image: registry.cn-hangzhou.aliyuncs.com/xuzeyu91/antsk:v0.3.6
|
||||
# 如果需要pytorch环境需要使用下面这个镜像,镜像比较大
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/xuzeyu91/antsk:p0.2.6
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/xuzeyu91/antsk:p0.3.6
|
||||
ports:
|
||||
- 5000:5000
|
||||
networks:
|
||||
@@ -15,5 +15,7 @@ services:
|
||||
- ASPNETCORE_URLS=http://*:5000
|
||||
volumes:
|
||||
- ./appsettings.json:/app/appsettings.json # 本地配置文件 需要放在同级目录
|
||||
- /AntSK/model:/app/model
|
||||
- /AntSK/model:/root/.cache/modelscope/hub/AI-ModelScope # LLamaFactory模型文件
|
||||
networks:
|
||||
antsk:
|
||||
|
||||
@@ -1,6 +1,20 @@
|
||||
# 非 host 版本, 不使用本机代理
|
||||
version: '3.8'
|
||||
services:
|
||||
aspire-dashboard:
|
||||
container_name: aspire-dashboard
|
||||
image: mcr.microsoft.com/dotnet/aspire-dashboard:8.0
|
||||
networks:
|
||||
- antsk
|
||||
environment:
|
||||
- DOTNET_DASHBOARD_UNSECURED_ALLOW_ANONYMOUS=true
|
||||
- ASPIRE_ALLOW_UNSECURED_TRANSPORT=true
|
||||
- DASHBOARD_OTLP_AUTHMODE=ApiKey
|
||||
- DASHBOARD_OTLP_PRIMARYAPIKEY=antsk
|
||||
ports:
|
||||
- 18888:18888
|
||||
- 18889:18889
|
||||
restart: unless-stopped
|
||||
antskpg:
|
||||
image: registry.cn-hangzhou.aliyuncs.com/xuzeyu91/pg:v0.5.0
|
||||
container_name: antskpg
|
||||
@@ -18,9 +32,9 @@ services:
|
||||
- ./pg/data:/var/lib/postgresql/data
|
||||
antsk:
|
||||
container_name: antsk
|
||||
image: registry.cn-hangzhou.aliyuncs.com/xuzeyu91/antsk:v0.2.6
|
||||
image: registry.cn-hangzhou.aliyuncs.com/xuzeyu91/antsk:v0.3.6
|
||||
# 如果需要pytorch环境需要使用下面这个镜像,镜像比较大
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/xuzeyu91/antsk:p0.2.6
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/xuzeyu91/antsk:p0.3.6
|
||||
ports:
|
||||
- 5000:5000
|
||||
networks:
|
||||
@@ -30,7 +44,15 @@ services:
|
||||
restart: always
|
||||
environment:
|
||||
- ASPNETCORE_URLS=http://*:5000
|
||||
- ASPNETCORE_FORWARDEDHEADERS_ENABLED=true
|
||||
- OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EXCEPTION_LOG_ATTRIBUTES=true
|
||||
- OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EVENT_LOG_ATTRIBUTES= true
|
||||
- OTEL_DOTNET_EXPERIMENTAL_OTLP_RETRY=in_memory
|
||||
- OTEL_EXPORTER_OTLP_ENDPOINT=http://aspire-dashboard:18889
|
||||
- OTEL_SERVICE_NAME=antsk
|
||||
volumes:
|
||||
- ./appsettings.json:/app/appsettings.json # 本地配置文件 需要放在同级目录
|
||||
- /AntSK/model:/app/model
|
||||
- /AntSK/model:/root/.cache/modelscope/hub/AI-ModelScope # LLamaFactory模型文件
|
||||
networks:
|
||||
antsk:
|
||||
|
||||
20
src/AntSK.AppHost/AntSK.AppHost.csproj
Normal file
20
src/AntSK.AppHost/AntSK.AppHost.csproj
Normal file
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsAspireHost>true</IsAspireHost>
|
||||
<UserSecretsId>32ac67c8-178a-4eeb-871d-879023582e06</UserSecretsId>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Aspire.Hosting.AppHost" Version="8.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\AntSK\AntSK.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
5
src/AntSK.AppHost/Program.cs
Normal file
5
src/AntSK.AppHost/Program.cs
Normal file
@@ -0,0 +1,5 @@
|
||||
var builder = DistributedApplication.CreateBuilder(args);
|
||||
|
||||
builder.AddProject<Projects.AntSK>("antsk");
|
||||
|
||||
builder.Build().Run();
|
||||
8
src/AntSK.AppHost/appsettings.Development.json
Normal file
8
src/AntSK.AppHost/appsettings.Development.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
9
src/AntSK.AppHost/appsettings.json
Normal file
9
src/AntSK.AppHost/appsettings.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning",
|
||||
"Aspire.Hosting.Dcp": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
26
src/AntSK.AppHost/aspirate-output/docker-compose.yaml
Normal file
26
src/AntSK.AppHost/aspirate-output/docker-compose.yaml
Normal file
@@ -0,0 +1,26 @@
|
||||
services:
|
||||
aspire-dashboard:
|
||||
container_name: "aspire-dashboard"
|
||||
image: "mcr.microsoft.com/dotnet/aspire-dashboard:8.0"
|
||||
environment:
|
||||
DOTNET_DASHBOARD_UNSECURED_ALLOW_ANONYMOUS: "true"
|
||||
ports:
|
||||
- target: 18888
|
||||
published: 18888
|
||||
restart: unless-stopped
|
||||
antsk:
|
||||
container_name: "antsk"
|
||||
image: "antsk:latest"
|
||||
environment:
|
||||
OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EXCEPTION_LOG_ATTRIBUTES: "true"
|
||||
OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EVENT_LOG_ATTRIBUTES: "true"
|
||||
OTEL_DOTNET_EXPERIMENTAL_OTLP_RETRY: "in_memory"
|
||||
ASPNETCORE_FORWARDEDHEADERS_ENABLED: "true"
|
||||
OTEL_EXPORTER_OTLP_ENDPOINT: "http://aspire-dashboard:18889"
|
||||
OTEL_SERVICE_NAME: "antsk"
|
||||
ports:
|
||||
- target: 8080
|
||||
published: 10000
|
||||
- target: 8443
|
||||
published: 10001
|
||||
restart: unless-stopped
|
||||
17
src/AntSK.AppHost/aspirate-state.json
Normal file
17
src/AntSK.AppHost/aspirate-state.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"projectPath": ".",
|
||||
"outputPath": "aspirate-output",
|
||||
"containerImageTags": [
|
||||
"latest"
|
||||
],
|
||||
"containerBuilder": "docker",
|
||||
"outputFormat": "compose",
|
||||
"privateRegistryEmail": "aspir8@aka.ms",
|
||||
"includeDashboard": true,
|
||||
"secrets": {
|
||||
"salt": "fjamZa3pQbM1UyY4",
|
||||
"hash": "QR\u002BSEr3p2SwD/w2oPE21vrWh/EerhNyVyTkr0atIREw=",
|
||||
"secrets": {}
|
||||
},
|
||||
"processAllComponents": true
|
||||
}
|
||||
26
src/AntSK.AppHost/manifest.json
Normal file
26
src/AntSK.AppHost/manifest.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"resources": {
|
||||
"antsk": {
|
||||
"type": "project.v0",
|
||||
"path": "../AntSK/AntSK.csproj",
|
||||
"env": {
|
||||
"OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EXCEPTION_LOG_ATTRIBUTES": "true",
|
||||
"OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EVENT_LOG_ATTRIBUTES": "true",
|
||||
"OTEL_DOTNET_EXPERIMENTAL_OTLP_RETRY": "in_memory",
|
||||
"ASPNETCORE_FORWARDEDHEADERS_ENABLED": "true"
|
||||
},
|
||||
"bindings": {
|
||||
"http": {
|
||||
"scheme": "http",
|
||||
"protocol": "tcp",
|
||||
"transport": "http"
|
||||
},
|
||||
"https": {
|
||||
"scheme": "https",
|
||||
"protocol": "tcp",
|
||||
"transport": "http"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
53
src/AntSK.Domain/AntSK - Backup.Domain.csproj
Normal file
53
src/AntSK.Domain/AntSK - Backup.Domain.csproj
Normal file
@@ -0,0 +1,53 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<DocumentationFile>AntSK.Domain.xml</DocumentationFile>
|
||||
<NoWarn>CA1050,CA1707,CA2007,VSTHRD111,CS1591,RCS1110,CA5394,SKEXP0001,SKEXP0002,SKEXP0003,SKEXP0004,SKEXP0010,SKEXP0011,,SKEXP0012,SKEXP0020,SKEXP0021,SKEXP0022,SKEXP0023,SKEXP0024,SKEXP0025,SKEXP0026,SKEXP0027,SKEXP0028,SKEXP0029,SKEXP0030,SKEXP0031,SKEXP0032,SKEXP0040,SKEXP0041,SKEXP0042,SKEXP0050,SKEXP0051,SKEXP0052,SKEXP0053,SKEXP0054,SKEXP0055,SKEXP0060,SKEXP0061,SKEXP0101,SKEXP0102</NoWarn>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AntDesign.Charts" Version="0.5.1" />
|
||||
<PackageReference Include="AntDesign.ProLayout" Version="0.18.2" />
|
||||
<PackageReference Include="BlazorComponents.Terminal" Version="0.6.0" />
|
||||
<PackageReference Include="Blazored.LocalStorage" Version="4.5.0" />
|
||||
|
||||
<PackageReference Include="pythonnet" Version="3.0.3" />
|
||||
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||
|
||||
<PackageReference Include="AutoMapper" Version="8.1.0" />
|
||||
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
|
||||
<PackageReference Include="Markdig" Version="0.37.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="SqlSugarCore" Version="5.1.4.151" />
|
||||
<PackageReference Include="System.Data.SQLite.Core" Version="1.0.118" />
|
||||
<PackageReference Include="RestSharp" Version="110.2.0" />
|
||||
<PackageReference Include="NPOI" Version="2.7.0" />
|
||||
|
||||
<PackageReference Include="Microsoft.SemanticKernel" Version="1.7.1" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.Core" Version="1.7.1" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.Plugins.Core" Version="1.7.1-alpha" />
|
||||
<PackageReference Include="Microsoft.KernelMemory.Core" Version="0.36.240415.2" />
|
||||
<PackageReference Include="Microsoft.KernelMemory.MemoryDb.Postgres" Version="0.36.240415.2" />
|
||||
<PackageReference Include="Microsoft.KernelMemory.MemoryDb.Qdrant" Version="0.36.240415.2" />
|
||||
<PackageReference Include="Microsoft.KernelMemory.MemoryDb.Redis" Version="0.36.240415.2" />
|
||||
<PackageReference Include="Microsoft.KernelMemory.MemoryDb.AzureAISearch" Version="0.36.240415.2" />
|
||||
|
||||
<PackageReference Include="LLamaSharp" Version="0.11.2" />
|
||||
<PackageReference Include="LLamaSharp.Backend.Cpu" Version="0.11.2" />
|
||||
<PackageReference Include="LLamaSharp.Backend.Cuda12" Version="0.11.2" />
|
||||
<PackageReference Include="LLamaSharp.kernel-memory" Version="0.11.2" />
|
||||
<PackageReference Include="LLamaSharp.semantic-kernel" Version="0.11.2" />
|
||||
|
||||
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\AntSK.LLamaFactory\AntSK.LLamaFactory.csproj" />
|
||||
<ProjectReference Include="..\AntSk.LLM\AntSK.LLM.csproj" />
|
||||
<ProjectReference Include="..\AntSK.OCR\AntSK.OCR.csproj" />
|
||||
<ProjectReference Include="..\MiddleWare\AntSK.BackgroundTask\AntSK.BackgroundTask.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -5,47 +5,54 @@
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<DocumentationFile>AntSK.Domain.xml</DocumentationFile>
|
||||
<NoWarn>CA1050,CA1707,CA2007,VSTHRD111,CS1591,RCS1110,CA5394,SKEXP0001,SKEXP0002,SKEXP0003,SKEXP0004,SKEXP0010,SKEXP0011,,SKEXP0012,SKEXP0020,SKEXP0021,SKEXP0022,SKEXP0023,SKEXP0024,SKEXP0025,SKEXP0026,SKEXP0027,SKEXP0028,SKEXP0029,SKEXP0030,SKEXP0031,SKEXP0032,SKEXP0040,SKEXP0041,SKEXP0042,SKEXP0050,SKEXP0051,SKEXP0052,SKEXP0053,SKEXP0054,SKEXP0055,SKEXP0060,SKEXP0061,SKEXP0101,SKEXP0102</NoWarn>
|
||||
<NoWarn>CA1050,CA1707,CA2007,VSTHRD111,CS1591,RCS1110,CA5394,SKEXP0001,SKEXP0002,SKEXP0003,SKEXP0004,SKEXP0010,SKEXP0011,,SKEXP0012,SKEXP0020,SKEXP0021,SKEXP0022,SKEXP0023,SKEXP0024,SKEXP0025,SKEXP0026,SKEXP0027,SKEXP0028,SKEXP0029,SKEXP0030,SKEXP0031,SKEXP0032,SKEXP0040,SKEXP0041,SKEXP0042,SKEXP0050,SKEXP0051,SKEXP0052,SKEXP0053,SKEXP0054,SKEXP0055,SKEXP0060,SKEXP0061,SKEXP0101,SKEXP0102,KMEXP00</NoWarn>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AntDesign.Charts" Version="0.5.1" />
|
||||
<PackageReference Include="AntDesign.ProLayout" Version="0.18.2" />
|
||||
<PackageReference Include="AntDesign.ProLayout" Version="0.19.0" />
|
||||
<PackageReference Include="BlazorComponents.Terminal" Version="0.6.0" />
|
||||
<PackageReference Include="Blazored.LocalStorage" Version="4.5.0" />
|
||||
|
||||
<PackageReference Include="pythonnet" Version="3.0.3" />
|
||||
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
|
||||
|
||||
<PackageReference Include="AutoMapper" Version="8.1.0" />
|
||||
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
|
||||
<PackageReference Include="Markdig" Version="0.36.2" />
|
||||
<PackageReference Include="Markdig" Version="0.37.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="SqlSugarCore" Version="5.1.4.151" />
|
||||
<PackageReference Include="SqlSugarCore" Version="5.1.4.158" />
|
||||
<PackageReference Include="System.Data.SQLite.Core" Version="1.0.118" />
|
||||
<PackageReference Include="RestSharp" Version="110.2.0" />
|
||||
<PackageReference Include="NPOI" Version="2.5.5" />
|
||||
<PackageReference Include="RestSharp" Version="111.2.0" />
|
||||
<PackageReference Include="NPOI" Version="2.7.0" />
|
||||
|
||||
<PackageReference Include="Microsoft.SemanticKernel" Version="1.6.3" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.Core" Version="1.6.3" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.Plugins.Core" Version="1.6.3-alpha" />
|
||||
<PackageReference Include="Microsoft.KernelMemory.Core" Version="0.35.240321.1" />
|
||||
<PackageReference Include="Microsoft.KernelMemory.MemoryDb.Postgres" Version="0.35.240321.1" />
|
||||
<PackageReference Include="Microsoft.KernelMemory.MemoryDb.Qdrant" Version="0.35.240321.1" />
|
||||
<PackageReference Include="Microsoft.KernelMemory.MemoryDb.Redis" Version="0.35.240321.1" />
|
||||
<PackageReference Include="Microsoft.KernelMemory.MemoryDb.AzureAISearch" Version="0.35.240321.1" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel" Version="1.14.1" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.Core" Version="1.14.1" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.Plugins.Core" Version="1.14.1-alpha" />
|
||||
<PackageReference Include="Microsoft.KernelMemory.Core" Version="$(KMVersion)" />
|
||||
<PackageReference Include="Microsoft.KernelMemory.MemoryDb.Postgres" Version="$(KMVersion)" />
|
||||
<PackageReference Include="Microsoft.KernelMemory.MemoryDb.Qdrant" Version="$(KMVersion)" />
|
||||
<PackageReference Include="Microsoft.KernelMemory.MemoryDb.Redis" Version="$(KMVersion)" />
|
||||
<PackageReference Include="Microsoft.KernelMemory.MemoryDb.AzureAISearch" Version="$(KMVersion)" />
|
||||
|
||||
<PackageReference Include="LLamaSharp" Version="0.11.1" />
|
||||
<PackageReference Include="LLamaSharp.Backend.Cpu" Version="0.11.1" />
|
||||
<PackageReference Include="LLamaSharp.Backend.Cuda12" Version="0.11.1" />
|
||||
<PackageReference Include="LLamaSharp.kernel-memory" Version="0.11.1" />
|
||||
<PackageReference Include="LLamaSharp.semantic-kernel" Version="0.11.1" />
|
||||
|
||||
|
||||
<PackageReference Include="LLamaSharp" Version="$(LLamaSharpVersion)" />
|
||||
<PackageReference Include="LLamaSharp.Backend.Cpu" Version="$(LLamaSharpVersion)" />
|
||||
<PackageReference Include="LLamaSharp.Backend.Cuda12" Version="$(LLamaSharpVersion)" />
|
||||
<PackageReference Include="LLamaSharp.kernel-memory" Version="$(LLamaSharpVersion)" />
|
||||
<PackageReference Include="LLamaSharp.semantic-kernel" Version="$(LLamaSharpVersion)" />
|
||||
|
||||
<PackageReference Include="Serilog" Version="4.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="5.1.0-dev-00943" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.1-dev-00972" />
|
||||
<PackageReference Include="Serilog.Extensions.Logging" Version="8.0.1-dev-10391" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="8.0.1" />
|
||||
<PackageReference Include="Serilog.Sinks.Seq" Version="8.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.OpenTelemetry" Version="3.0.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\AntSK.LLamaFactory\AntSK.LLamaFactory.csproj" />
|
||||
<ProjectReference Include="..\AntSk.LLM\AntSK.LLM.csproj" />
|
||||
<ProjectReference Include="..\AntSK.OCR\AntSK.OCR.csproj" />
|
||||
<ProjectReference Include="..\MiddleWare\AntSK.BackgroundTask\AntSK.BackgroundTask.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -157,11 +157,6 @@
|
||||
模型类型
|
||||
</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开始
|
||||
@@ -177,7 +172,12 @@
|
||||
总数
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Domain.Other.EmbeddingConfig.LoadModel(System.String,System.String)">
|
||||
<member name="M:AntSK.Domain.Domain.Other.Bge.BegRerankConfig.LoadModel(System.String,System.String)">
|
||||
<summary>
|
||||
模型写死
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Domain.Other.Bge.BgeEmbeddingConfig.LoadModel(System.String,System.String)">
|
||||
<summary>
|
||||
模型写死
|
||||
</summary>
|
||||
@@ -193,7 +193,13 @@
|
||||
避免模型重复加载,本地缓存
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Domain.Service.ChatService.SendChatByAppAsync(AntSK.Domain.Repositories.Apps,System.String,Microsoft.SemanticKernel.ChatCompletion.ChatHistory)">
|
||||
<member name="P:AntSK.Domain.Domain.Other.QAHandler.StepName">
|
||||
<inheritdoc />
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Domain.Other.QAHandler.InvokeAsync(Microsoft.KernelMemory.Pipeline.DataPipeline,System.Threading.CancellationToken)">
|
||||
<inheritdoc />
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Domain.Service.ChatService.SendChatByAppAsync(AntSK.Domain.Repositories.Apps,Microsoft.SemanticKernel.ChatCompletion.ChatHistory)">
|
||||
<summary>
|
||||
发送消息
|
||||
</summary>
|
||||
@@ -396,6 +402,36 @@
|
||||
回答最大token数
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Repositories.Chats.UserName">
|
||||
<summary>
|
||||
用户名
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Repositories.Chats.AppId">
|
||||
<summary>
|
||||
应用ID
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Repositories.Chats.Context">
|
||||
<summary>
|
||||
消息内容
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Repositories.Chats.IsSend">
|
||||
<summary>
|
||||
发送是true 接收是false
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Repositories.Chats.CreateTime">
|
||||
<summary>
|
||||
创建事件
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Repositories.Chats.FileName">
|
||||
<summary>
|
||||
文件名
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Repositories.Funs.Path">
|
||||
<summary>
|
||||
接口描述
|
||||
|
||||
@@ -5,6 +5,7 @@ using DocumentFormat.OpenXml.Office2016.Drawing.ChartDrawing;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using SqlSugar;
|
||||
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||
@@ -19,6 +20,12 @@ namespace AntSK.Domain.Common.DependencyInjection
|
||||
{
|
||||
public static class InitExtensions
|
||||
{
|
||||
private static ILogger _logger;
|
||||
|
||||
public static void InitLog(ILogger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
/// <summary>
|
||||
/// 使用codefirst创建数据库表
|
||||
/// </summary>
|
||||
@@ -50,6 +57,10 @@ namespace AntSK.Domain.Common.DependencyInjection
|
||||
_repository.GetDB().CodeFirst.InitTables(type);
|
||||
}
|
||||
}
|
||||
//安装向量插件
|
||||
_repository.GetDB().Ado.ExecuteCommandAsync($"CREATE EXTENSION IF NOT EXISTS vector;");
|
||||
|
||||
_logger.LogInformation("初始化表结构完成");
|
||||
}
|
||||
return app;
|
||||
}
|
||||
@@ -70,7 +81,7 @@ namespace AntSK.Domain.Common.DependencyInjection
|
||||
llamafactoryStart.Value = "false";
|
||||
_dic_Repository.Insert(llamafactoryStart);
|
||||
}
|
||||
|
||||
_logger.LogInformation("初始化数据库初始数据完成");
|
||||
}
|
||||
return app;
|
||||
}
|
||||
@@ -97,7 +108,7 @@ namespace AntSK.Domain.Common.DependencyInjection
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message + " ---- " + ex.StackTrace);
|
||||
_logger.LogError(ex.Message + " ---- " + ex.StackTrace);
|
||||
}
|
||||
return app;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using AntSK.Domain.Domain.Other;
|
||||
using AntSK.Domain.Domain.Other.Bge;
|
||||
|
||||
namespace AntSK.Domain.Common.Embedding
|
||||
{
|
||||
@@ -22,12 +22,12 @@ namespace AntSK.Domain.Common.Embedding
|
||||
|
||||
public HuggingfaceTextEmbeddingGenerator(string pyDllPath,string modelName)
|
||||
{
|
||||
_embedder = EmbeddingConfig.LoadModel(pyDllPath, modelName);
|
||||
_embedder = BgeEmbeddingConfig.LoadModel(pyDllPath, modelName);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
EmbeddingConfig.Dispose();
|
||||
BgeEmbeddingConfig.Dispose();
|
||||
}
|
||||
|
||||
//public async Task<IList<ReadOnlyMemory<float>>> GenerateEmbeddingAsync(IList<string> data, CancellationToken cancellationToken = default)
|
||||
@@ -44,13 +44,13 @@ namespace AntSK.Domain.Common.Embedding
|
||||
|
||||
public async Task<Microsoft.KernelMemory.Embedding> GenerateEmbeddingAsync(string text, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var embeddings = await EmbeddingConfig.GetEmbedding(text);
|
||||
var embeddings = await BgeEmbeddingConfig.GetEmbedding(text);
|
||||
return new Microsoft.KernelMemory.Embedding(embeddings);
|
||||
}
|
||||
|
||||
public int CountTokens(string text)
|
||||
{
|
||||
return EmbeddingConfig.TokenCount(text);
|
||||
return BgeEmbeddingConfig.TokenCount(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using Amazon.Runtime.Internal.Util;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
@@ -7,7 +9,7 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace AntSK.Domain.Common.LLamaFactory
|
||||
{
|
||||
public class ProcessWrapper
|
||||
public class ProcessWrapper(ILogger<ProcessWrapper> _logger)
|
||||
{
|
||||
private Process process;
|
||||
|
||||
@@ -41,7 +43,7 @@ namespace AntSK.Domain.Common.LLamaFactory
|
||||
isProcessComplete = true;
|
||||
}
|
||||
}
|
||||
Console.WriteLine(result);
|
||||
_logger.LogInformation(result);
|
||||
}
|
||||
start.WaitForExit();
|
||||
}
|
||||
|
||||
@@ -14,10 +14,10 @@ namespace AntSK.Domain.Domain.Interface
|
||||
{
|
||||
public interface IChatService
|
||||
{
|
||||
IAsyncEnumerable<StreamingKernelContent> SendChatByAppAsync(Apps app, string questions, ChatHistory history);
|
||||
IAsyncEnumerable<string> SendChatByAppAsync(Apps app, ChatHistory history);
|
||||
|
||||
IAsyncEnumerable<StreamingKernelContent> SendKmsByAppAsync(Apps app, string questions, ChatHistory history, string filePath, List<RelevantSource> relevantSources = null);
|
||||
Task<string> SendImgByAppAsync(Apps app, string questions);
|
||||
Task<ChatHistory> GetChatHistory(List<MessageInfo> MessageList);
|
||||
Task<ChatHistory> GetChatHistory(List<Chats> MessageList, ChatHistory history);
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,8 @@ namespace AntSK.Domain.Domain.Interface
|
||||
public interface IKernelService
|
||||
{
|
||||
Kernel GetKernelByApp(Apps app);
|
||||
|
||||
Kernel GetKernelByAIModelID(string modelid);
|
||||
void ImportFunctionsByApp(Apps app, Kernel _kernel);
|
||||
Task<string> HistorySummarize(Kernel _kernel, string questions, string history);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,10 @@ namespace AntSK.Domain.Domain.Model.Constant
|
||||
public class KmsConstantcs
|
||||
{
|
||||
public const string KmsIdTag = "kmsid";
|
||||
public const string FileIdTag = "fileid";
|
||||
public const string AppIdTag = "appid";
|
||||
public const string KmsIndex = "kms";
|
||||
public const string FileIndex = "kms";
|
||||
public const string KmsSearchNull="知识库未搜索到相关内容";
|
||||
|
||||
public const string KmsPrompt = @"使用<data></data>标记的内容作为你的知识:
|
||||
|
||||
@@ -8,6 +8,8 @@ namespace AntSK.Domain.Domain.Model.Dto
|
||||
public string Text { get; set; }
|
||||
public float Relevance { get; set; }
|
||||
|
||||
public double RerankScore { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"[file:{SourceName};Relevance:{(Relevance * 100):F2}%]:{Text}";
|
||||
|
||||
@@ -26,8 +26,10 @@ namespace AntSK.Domain.Domain.Model.Enum
|
||||
LLamaFactory = 6,
|
||||
[Display(Name = "Bge Embedding")]
|
||||
BgeEmbedding = 7,
|
||||
[Display(Name = "Bge Rerank")]
|
||||
BgeRerank = 8,
|
||||
[Display(Name = "StableDiffusion")]
|
||||
StableDiffusion = 8,
|
||||
StableDiffusion = 9,
|
||||
[Display(Name = "模拟输出")]
|
||||
Mock = 100,
|
||||
|
||||
@@ -41,5 +43,6 @@ namespace AntSK.Domain.Domain.Model.Enum
|
||||
Chat = 1,
|
||||
Embedding = 2,
|
||||
Image=3,
|
||||
Rerank=4
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,11 +17,14 @@ namespace AntSK.Domain.Domain.Model
|
||||
public string FilePath { get; set; } = "";
|
||||
|
||||
public string FileName { get; set; } = "";
|
||||
|
||||
public bool IsQA { get; set; } = false;
|
||||
}
|
||||
|
||||
|
||||
public class ImportKMSTaskReq : ImportKMSTaskDTO
|
||||
{
|
||||
public bool IsQA { get; set; }=false;
|
||||
public KmsDetails KmsDetail { get; set; } = new KmsDetails();
|
||||
}
|
||||
|
||||
@@ -32,4 +35,10 @@ namespace AntSK.Domain.Domain.Model
|
||||
Text = 3,
|
||||
Excel=4
|
||||
}
|
||||
|
||||
public class QAModel
|
||||
{
|
||||
public string ChatModelId { get; set; }
|
||||
public string Context { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
namespace AntSK.Domain.Domain.Model
|
||||
{
|
||||
public class MessageInfo
|
||||
{
|
||||
public string ID { get; set; } = "";
|
||||
public string Context { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// 发送是true 接收是false
|
||||
/// </summary>
|
||||
public bool IsSend { get; set; } = false;
|
||||
|
||||
public DateTime CreateTime { get; set; }
|
||||
|
||||
public string? FileName { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,27 +1,31 @@
|
||||
using AntSK.BackgroundTask;
|
||||
using Amazon.Runtime.Internal.Util;
|
||||
using AntSK.BackgroundTask;
|
||||
using AntSK.Domain.Domain.Interface;
|
||||
using AntSK.Domain.Domain.Model;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace AntSK.Domain.Domain.Other
|
||||
{
|
||||
public class BackGroundTaskHandler : IBackgroundTaskHandler<ImportKMSTaskReq>
|
||||
{
|
||||
private readonly IServiceScopeFactory _scopeFactory;
|
||||
private readonly ILogger<BackGroundTaskHandler> _logger;
|
||||
|
||||
public BackGroundTaskHandler(IServiceScopeFactory scopeFactory)
|
||||
public BackGroundTaskHandler(IServiceScopeFactory scopeFactory, ILogger<BackGroundTaskHandler> logger)
|
||||
{
|
||||
_scopeFactory = scopeFactory;
|
||||
_logger = logger;
|
||||
}
|
||||
public async Task ExecuteAsync(ImportKMSTaskReq item)
|
||||
{
|
||||
using (var scope = _scopeFactory.CreateScope())
|
||||
{
|
||||
Console.WriteLine("ExecuteAsync.开始执行后台任务");
|
||||
_logger.LogInformation("ExecuteAsync.开始执行后台任务");
|
||||
var importKMSService = scope.ServiceProvider.GetRequiredService<IImportKMSService>();
|
||||
//不能使用异步
|
||||
importKMSService.ImportKMSTask(item);
|
||||
Console.WriteLine("ExecuteAsync.后台任务执行完成");
|
||||
_logger.LogInformation("ExecuteAsync.后台任务执行完成");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
81
src/AntSK.Domain/Domain/Other/Bge/BegRerankConfig.cs
Normal file
81
src/AntSK.Domain/Domain/Other/Bge/BegRerankConfig.cs
Normal file
@@ -0,0 +1,81 @@
|
||||
using Newtonsoft.Json;
|
||||
using Python.Runtime;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static Python.Runtime.Py;
|
||||
|
||||
namespace AntSK.Domain.Domain.Other.Bge
|
||||
{
|
||||
public static class BegRerankConfig
|
||||
{
|
||||
public static dynamic model { get; set; }
|
||||
|
||||
static object lockobj = new object();
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 模型写死
|
||||
/// </summary>
|
||||
public static dynamic LoadModel(string pythondllPath, string modelName)
|
||||
{
|
||||
lock (lockobj)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(Runtime.PythonDLL))
|
||||
{
|
||||
Runtime.PythonDLL = pythondllPath;
|
||||
}
|
||||
PythonEngine.Initialize();
|
||||
try
|
||||
{
|
||||
using (GIL())// 初始化Python环境的Global Interpreter Lock)
|
||||
{
|
||||
dynamic modelscope = Py.Import("modelscope");
|
||||
dynamic flagEmbedding = Py.Import("FlagEmbedding");
|
||||
|
||||
dynamic model_dir = modelscope.snapshot_download(modelName, revision: "master");
|
||||
dynamic flagReranker = flagEmbedding.FlagReranker(model_dir, use_fp16: true);
|
||||
model = flagReranker;
|
||||
return model;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return model;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static double Rerank(List<string> list)
|
||||
{
|
||||
using (GIL())
|
||||
{
|
||||
try
|
||||
{
|
||||
PyList pyList = new PyList();
|
||||
foreach (string item in list)
|
||||
{
|
||||
pyList.Append(item.ToPython()); // 将C# string转换为Python对象并添加到PyList中
|
||||
}
|
||||
PyObject result = model.compute_score(pyList, normalize: true);
|
||||
return result.As<double>();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
using Microsoft.KernelMemory.AI.OpenAI.GPT3;
|
||||
using Microsoft.KernelMemory.AI.OpenAI;
|
||||
using Microsoft.KernelMemory.AI.OpenAI.GPT3;
|
||||
using Python.Runtime;
|
||||
using Serilog;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -7,9 +9,9 @@ using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static Python.Runtime.Py;
|
||||
|
||||
namespace AntSK.Domain.Domain.Other
|
||||
namespace AntSK.Domain.Domain.Other.Bge
|
||||
{
|
||||
public static class EmbeddingConfig
|
||||
public static class BgeEmbeddingConfig
|
||||
{
|
||||
public static dynamic model { get; set; }
|
||||
|
||||
@@ -27,18 +29,20 @@ namespace AntSK.Domain.Domain.Other
|
||||
if (model == null)
|
||||
{
|
||||
//Runtime.PythonDLL = @"D:\Programs\Python\Python311\python311.dll";
|
||||
Runtime.PythonDLL = pythondllPath;
|
||||
if (string.IsNullOrEmpty(Runtime.PythonDLL))
|
||||
{
|
||||
Runtime.PythonDLL = pythondllPath;
|
||||
}
|
||||
PythonEngine.Initialize();
|
||||
PythonEngine.BeginAllowThreads();
|
||||
|
||||
try
|
||||
{
|
||||
using (Py.GIL())// 初始化Python环境的Global Interpreter Lock)
|
||||
using (GIL())// 初始化Python环境的Global Interpreter Lock)
|
||||
{
|
||||
dynamic modelscope = Py.Import("modelscope");
|
||||
dynamic modelscope = Import("modelscope");
|
||||
//dynamic model_dir = modelscope.snapshot_download("AI-ModelScope/bge-large-zh-v1.5", revision: "master");
|
||||
dynamic model_dir = modelscope.snapshot_download(modelName, revision: "master");
|
||||
dynamic HuggingFaceBgeEmbeddingstemp = Py.Import("langchain_community.embeddings.huggingface");
|
||||
dynamic HuggingFaceBgeEmbeddingstemp = Import("langchain_community.embeddings.huggingface");
|
||||
dynamic HuggingFaceBgeEmbeddings = HuggingFaceBgeEmbeddingstemp.HuggingFaceBgeEmbeddings;
|
||||
string model_name = model_dir;
|
||||
dynamic model_kwargs = new PyDict();
|
||||
@@ -51,7 +55,7 @@ namespace AntSK.Domain.Domain.Other
|
||||
return hugginmodel;
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw ex;
|
||||
}
|
||||
@@ -63,7 +67,7 @@ namespace AntSK.Domain.Domain.Other
|
||||
|
||||
public static Task<float[]> GetEmbedding(string queryStr)
|
||||
{
|
||||
using (Py.GIL())
|
||||
using (GIL())
|
||||
{
|
||||
PyObject queryResult = model.embed_query(queryStr);
|
||||
var floatList = queryResult.As<float[]>();
|
||||
@@ -83,13 +87,13 @@ namespace AntSK.Domain.Domain.Other
|
||||
// return len;
|
||||
|
||||
//}
|
||||
var tokenCount1 = GPT3Tokenizer.Encode(queryStr).Count;
|
||||
var tokenCount1 = DefaultGPTTokenizer.StaticCountTokens(queryStr);
|
||||
return tokenCount1;
|
||||
}
|
||||
|
||||
public static void Dispose()
|
||||
{
|
||||
Console.WriteLine("python dispose");
|
||||
Log.Information("python dispose");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using AntSK.Domain.Domain.Model.Constant;
|
||||
using AntSK.Domain.Utils;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.KernelMemory.AI.OpenAI;
|
||||
using Microsoft.KernelMemory.Configuration;
|
||||
@@ -134,7 +135,7 @@ namespace AntSK.Domain.Domain.Other
|
||||
PartitionNumber = partitionNumber,
|
||||
SectionNumber = sectionNumber,
|
||||
Tags = pipeline.Tags,
|
||||
ContentSHA256 = textData.CalculateSHA256(),
|
||||
ContentSHA256 = textData.AntSKCalculateSHA256(),
|
||||
};
|
||||
newFiles.Add(destFile, destFileDetails);
|
||||
destFileDetails.MarkProcessedBy(this);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using LLama;
|
||||
using AntSK.Domain.Options;
|
||||
using LLama;
|
||||
using LLama.Common;
|
||||
using LLamaSharp.KernelMemory;
|
||||
|
||||
@@ -29,10 +30,10 @@ namespace AntSK.Domain.Domain.Other
|
||||
}
|
||||
var parameters = new ModelParams(lsConfig.ModelPath)
|
||||
{
|
||||
ContextSize = lsConfig?.ContextSize ?? 2048,
|
||||
ContextSize = LLamaSharpOption.ContextSize ?? 2048,
|
||||
Seed = lsConfig?.Seed ?? 0,
|
||||
GpuLayerCount = lsConfig?.GpuLayerCount ?? 20,
|
||||
EmbeddingMode = true
|
||||
GpuLayerCount = LLamaSharpOption.GpuLayerCount ?? 20,
|
||||
Embeddings = true
|
||||
};
|
||||
var weights = LLamaWeights.LoadFromFile(parameters);
|
||||
dicLLamaWeights.Add(modelPath, (weights, parameters));
|
||||
|
||||
173
src/AntSK.Domain/Domain/Other/QAHandler.cs
Normal file
173
src/AntSK.Domain/Domain/Other/QAHandler.cs
Normal file
@@ -0,0 +1,173 @@
|
||||
using AntSK.Domain.Domain.Interface;
|
||||
using AntSK.Domain.Domain.Model;
|
||||
using AntSK.Domain.Utils;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.KernelMemory.AI.OpenAI;
|
||||
using Microsoft.KernelMemory.Configuration;
|
||||
using Microsoft.KernelMemory.DataFormats.Text;
|
||||
using Microsoft.KernelMemory.Diagnostics;
|
||||
using Microsoft.KernelMemory.Extensions;
|
||||
using Microsoft.KernelMemory.Pipeline;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Newtonsoft.Json;
|
||||
using RestSharp;
|
||||
using System.Security.Policy;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace AntSK.Domain.Domain.Other
|
||||
{
|
||||
public class QAHandler : IPipelineStepHandler
|
||||
{
|
||||
private readonly TextPartitioningOptions _options;
|
||||
private readonly IPipelineOrchestrator _orchestrator;
|
||||
private readonly ILogger<QAHandler> _log;
|
||||
private readonly TextChunker.TokenCounter _tokenCounter;
|
||||
private readonly IKernelService _kernelService;
|
||||
public QAHandler(
|
||||
string stepName,
|
||||
IPipelineOrchestrator orchestrator,
|
||||
IKernelService kernelService,
|
||||
TextPartitioningOptions? options = null,
|
||||
ILogger<QAHandler>? log = null
|
||||
)
|
||||
{
|
||||
this.StepName = stepName;
|
||||
this._orchestrator = orchestrator;
|
||||
this._options = options ?? new TextPartitioningOptions();
|
||||
this._options.Validate();
|
||||
|
||||
this._log = log ?? DefaultLogger<QAHandler>.Instance;
|
||||
this._tokenCounter = DefaultGPTTokenizer.StaticCountTokens;
|
||||
this._kernelService = kernelService;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string StepName { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<(bool success, DataPipeline updatedPipeline)> InvokeAsync(
|
||||
DataPipeline pipeline, CancellationToken cancellationToken = default)
|
||||
{
|
||||
this._log.LogDebug("Partitioning text, pipeline '{0}/{1}'", pipeline.Index, pipeline.DocumentId);
|
||||
|
||||
if (pipeline.Files.Count == 0)
|
||||
{
|
||||
this._log.LogWarning("Pipeline '{0}/{1}': there are no files to process, moving to next pipeline step.", pipeline.Index, pipeline.DocumentId);
|
||||
return (true, pipeline);
|
||||
}
|
||||
|
||||
foreach (DataPipeline.FileDetails uploadedFile in pipeline.Files)
|
||||
{
|
||||
// Track new files being generated (cannot edit originalFile.GeneratedFiles while looping it)
|
||||
Dictionary<string, DataPipeline.GeneratedFileDetails> newFiles = new();
|
||||
|
||||
foreach (KeyValuePair<string, DataPipeline.GeneratedFileDetails> generatedFile in uploadedFile.GeneratedFiles)
|
||||
{
|
||||
var file = generatedFile.Value;
|
||||
if (file.AlreadyProcessedBy(this))
|
||||
{
|
||||
this._log.LogTrace("File {0} already processed by this handler", file.Name);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Partition only the original text
|
||||
if (file.ArtifactType != DataPipeline.ArtifactTypes.ExtractedText)
|
||||
{
|
||||
this._log.LogTrace("Skipping file {0} (not original text)", file.Name);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Use a different partitioning strategy depending on the file type
|
||||
List<string> partitions;
|
||||
List<string> sentences;
|
||||
BinaryData partitionContent = await this._orchestrator.ReadFileAsync(pipeline, file.Name, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// Skip empty partitions. Also: partitionContent.ToString() throws an exception if there are no bytes.
|
||||
if (partitionContent.ToArray().Length == 0) { continue; }
|
||||
|
||||
switch (file.MimeType)
|
||||
{
|
||||
case MimeTypes.PlainText:
|
||||
case MimeTypes.MarkDown:
|
||||
{
|
||||
this._log.LogDebug("Partitioning text file {0}", file.Name);
|
||||
string content = partitionContent.ToString();
|
||||
|
||||
var kernel = _kernelService.GetKernelByAIModelID(StepName);
|
||||
var lines = TextChunker.SplitPlainTextLines(content, 299);
|
||||
var paragraphs = TextChunker.SplitPlainTextParagraphs(lines, 3000);
|
||||
KernelFunction jsonFun = kernel.Plugins.GetFunction("KMSPlugin", "QA");
|
||||
|
||||
List<string> qaList = new List<string>();
|
||||
foreach (var para in paragraphs)
|
||||
{
|
||||
var qaresult = await kernel.InvokeAsync(function: jsonFun, new KernelArguments() { ["input"] = para });
|
||||
var qaListStr = qaresult.GetValue<string>().ConvertToString();
|
||||
|
||||
string pattern = @"Q\d+:.*?A\d+:.*?(?=(Q\d+:|$))";
|
||||
RegexOptions options = RegexOptions.Singleline;
|
||||
|
||||
foreach (Match match in Regex.Matches(qaListStr, pattern, options))
|
||||
{
|
||||
qaList.Add(match.Value.Trim()); // Trim用于删除可能的首尾空格
|
||||
}
|
||||
}
|
||||
sentences = qaList;
|
||||
partitions = qaList;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
this._log.LogWarning("File {0} cannot be partitioned, type '{1}' not supported", file.Name, file.MimeType);
|
||||
// Don't partition other files
|
||||
continue;
|
||||
}
|
||||
|
||||
if (partitions.Count == 0) { continue; }
|
||||
|
||||
this._log.LogDebug("Saving {0} file partitions", partitions.Count);
|
||||
for (int partitionNumber = 0; partitionNumber < partitions.Count; partitionNumber++)
|
||||
{
|
||||
// TODO: turn partitions in objects with more details, e.g. page number
|
||||
string text = partitions[partitionNumber];
|
||||
int sectionNumber = 0; // TODO: use this to store the page number (if any)
|
||||
BinaryData textData = new(text);
|
||||
|
||||
int tokenCount = this._tokenCounter(text);
|
||||
this._log.LogDebug("Partition size: {0} tokens", tokenCount);
|
||||
|
||||
var destFile = uploadedFile.GetPartitionFileName(partitionNumber);
|
||||
await this._orchestrator.WriteFileAsync(pipeline, destFile, textData, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var destFileDetails = new DataPipeline.GeneratedFileDetails
|
||||
{
|
||||
Id = Guid.NewGuid().ToString("N"),
|
||||
ParentId = uploadedFile.Id,
|
||||
Name = destFile,
|
||||
Size = text.Length,
|
||||
MimeType = MimeTypes.PlainText,
|
||||
ArtifactType = DataPipeline.ArtifactTypes.TextPartition,
|
||||
PartitionNumber = partitionNumber,
|
||||
SectionNumber = sectionNumber,
|
||||
Tags = pipeline.Tags,
|
||||
ContentSHA256 = textData.AntSKCalculateSHA256(),
|
||||
};
|
||||
newFiles.Add(destFile, destFileDetails);
|
||||
destFileDetails.MarkProcessedBy(this);
|
||||
}
|
||||
|
||||
file.MarkProcessedBy(this);
|
||||
}
|
||||
|
||||
// Add new files to pipeline status
|
||||
foreach (var file in newFiles)
|
||||
{
|
||||
uploadedFile.GeneratedFiles.Add(file.Key, file.Value);
|
||||
}
|
||||
}
|
||||
|
||||
return (true, pipeline);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,23 @@
|
||||
using AntSK.Domain.Common.DependencyInjection;
|
||||
using AntSK.Domain.Domain.Interface;
|
||||
using AntSK.Domain.Repositories;
|
||||
using Microsoft.SemanticKernel.Connectors.OpenAI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using System.Text;
|
||||
using AntSK.Domain.Utils;
|
||||
using AntSK.Domain.Domain.Model.Dto;
|
||||
using AntSK.Domain.Domain.Model.Constant;
|
||||
using DocumentFormat.OpenXml.Drawing;
|
||||
using System.Reflection.Metadata;
|
||||
using Microsoft.KernelMemory;
|
||||
using System.Collections.Generic;
|
||||
using Markdig;
|
||||
using ChatHistory = Microsoft.SemanticKernel.ChatCompletion.ChatHistory;
|
||||
using Microsoft.SemanticKernel.Plugins.Core;
|
||||
using Azure.Core;
|
||||
using AntSK.Domain.Domain.Model;
|
||||
using AntSK.Domain.Domain.Model.Constant;
|
||||
using AntSK.Domain.Domain.Model.Dto;
|
||||
using AntSK.Domain.Domain.Other.Bge;
|
||||
using AntSK.Domain.Repositories;
|
||||
using AntSK.Domain.Utils;
|
||||
using AntSK.LLM.StableDiffusion;
|
||||
using Markdig;
|
||||
using Microsoft.KernelMemory;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.ChatCompletion;
|
||||
using Microsoft.SemanticKernel.Connectors.OpenAI;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using ChatHistory = Microsoft.SemanticKernel.ChatCompletion.ChatHistory;
|
||||
|
||||
namespace AntSK.Domain.Domain.Service
|
||||
{
|
||||
@@ -36,45 +36,54 @@ namespace AntSK.Domain.Domain.Service
|
||||
/// <param name="questions"></param>
|
||||
/// <param name="history"></param>
|
||||
/// <returns></returns>
|
||||
public async IAsyncEnumerable<StreamingKernelContent> SendChatByAppAsync(Apps app, string questions, ChatHistory history)
|
||||
public async IAsyncEnumerable<string> SendChatByAppAsync(Apps app, ChatHistory history)
|
||||
{
|
||||
|
||||
if (string.IsNullOrEmpty(app.Prompt) || !app.Prompt.Contains("{{$input}}"))
|
||||
{
|
||||
//如果模板为空,给默认提示词
|
||||
app.Prompt = app.Prompt.ConvertToString() + "{{$input}}";
|
||||
}
|
||||
KernelArguments args =new KernelArguments();
|
||||
if (history.Count > 10)
|
||||
{
|
||||
app.Prompt = @"${{ConversationSummaryPlugin.SummarizeConversation $history}}" + app.Prompt;
|
||||
args = new() {
|
||||
{ "history", string.Join("\n", history.Select(x => x.Role + ": " + x.Content)) },
|
||||
{ "input", questions }
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
args=new()
|
||||
{
|
||||
{ "input", $"{string.Join("\n", history.Select(x => x.Role + ": " + x.Content))}{Environment.NewLine} user:{questions}" }
|
||||
};
|
||||
}
|
||||
|
||||
var _kernel = _kernelService.GetKernelByApp(app);
|
||||
var chat = _kernel.GetRequiredService<IChatCompletionService>();
|
||||
var temperature = app.Temperature / 100;//存的是0~100需要缩小
|
||||
OpenAIPromptExecutionSettings settings = new() { Temperature = temperature };
|
||||
List<string> completionList = new List<string>();
|
||||
if (!string.IsNullOrEmpty(app.ApiFunctionList) || !string.IsNullOrEmpty(app.NativeFunctionList))//这里还需要加上本地插件的
|
||||
{
|
||||
_kernelService.ImportFunctionsByApp(app, _kernel);
|
||||
settings.ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions;
|
||||
settings.ToolCallBehavior = ToolCallBehavior.EnableKernelFunctions;
|
||||
while (true)
|
||||
{
|
||||
ChatMessageContent result = await chat.GetChatMessageContentAsync(history, settings, _kernel);
|
||||
if (result.Content is not null)
|
||||
{
|
||||
string chunkCompletion = result.Content.ConvertToString();
|
||||
completionList.Add(chunkCompletion);
|
||||
foreach (var content in completionList)
|
||||
{
|
||||
yield return content.ConvertToString();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
history.Add(result);
|
||||
|
||||
IEnumerable<FunctionCallContent> functionCalls = FunctionCallContent.GetFunctionCalls(result);
|
||||
if (!functionCalls.Any())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
foreach (var functionCall in functionCalls)
|
||||
{
|
||||
FunctionResultContent resultContent = await functionCall.InvokeAsync(_kernel);
|
||||
|
||||
history.Add(resultContent.ToChatMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
var func = _kernel.CreateFunctionFromPrompt(app.Prompt, settings);
|
||||
var chatResult = _kernel.InvokeStreamingAsync(function: func,
|
||||
arguments: args);
|
||||
await foreach (var content in chatResult)
|
||||
else
|
||||
{
|
||||
yield return content;
|
||||
var chatResult = chat.GetStreamingChatMessageContentsAsync(history, settings, _kernel);
|
||||
await foreach (var content in chatResult)
|
||||
{
|
||||
yield return content.ConvertToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,40 +95,103 @@ namespace AntSK.Domain.Domain.Service
|
||||
if (!string.IsNullOrWhiteSpace(filePath))
|
||||
{
|
||||
var memory = _kMService.GetMemoryByApp(app);
|
||||
var fileId = Guid.NewGuid().ToString();
|
||||
var result = await memory.ImportDocumentAsync(new Microsoft.KernelMemory.Document(fileId).AddFile(filePath)
|
||||
.AddTag(KmsConstantcs.KmsIdTag, app.Id)
|
||||
, index: KmsConstantcs.KmsIndex);
|
||||
|
||||
var filters = new MemoryFilter().ByTag(KmsConstantcs.KmsIdTag, app.Id);
|
||||
// 匹配GUID的正则表达式
|
||||
string pattern = @"\b[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}\b";
|
||||
|
||||
var searchResult = await memory.SearchAsync(questions, index: KmsConstantcs.KmsIndex, filters: [filters]);
|
||||
relevantSourceList.AddRange(searchResult.Results.SelectMany(item => item.Partitions.Select(part => new RelevantSource()
|
||||
// 使用正则表达式找到匹配
|
||||
Match match = Regex.Match(filePath, pattern);
|
||||
if (match.Success)
|
||||
{
|
||||
SourceName = item.SourceName,
|
||||
Text = Markdown.ToHtml(part.Text),
|
||||
Relevance = part.Relevance
|
||||
})));
|
||||
var fileId = match.Value;
|
||||
|
||||
var status=await memory.IsDocumentReadyAsync(fileId, index: KmsConstantcs.KmsIndex);
|
||||
if (!status)
|
||||
{
|
||||
var result = await memory.ImportDocumentAsync(new Document(fileId).AddFile(filePath)
|
||||
.AddTag(KmsConstantcs.AppIdTag, app.Id)
|
||||
.AddTag(KmsConstantcs.FileIdTag, fileId)
|
||||
, index: KmsConstantcs.FileIndex);
|
||||
}
|
||||
|
||||
var filters = new List<MemoryFilter>() {
|
||||
new MemoryFilter().ByTag(KmsConstantcs.AppIdTag, app.Id),
|
||||
new MemoryFilter().ByTag(KmsConstantcs.FileIdTag, fileId)
|
||||
};
|
||||
|
||||
var searchResult = await memory.SearchAsync(questions, index: KmsConstantcs.FileIndex, filters: filters);
|
||||
relevantSourceList.AddRange(searchResult.Results.SelectMany(item => item.Partitions.Select(part => new RelevantSource()
|
||||
{
|
||||
SourceName = item.SourceName,
|
||||
Text = Markdown.ToHtml(part.Text),
|
||||
Relevance = part.Relevance
|
||||
})));
|
||||
app.Prompt = KmsConstantcs.KmsPrompt;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var dataMsg = new StringBuilder();
|
||||
if (relevantSourceList.Any())
|
||||
{
|
||||
bool isSearch=false;
|
||||
if (!string.IsNullOrEmpty(app.RerankModelID))
|
||||
{
|
||||
var rerankModel=_aIModels_Repositories.GetById(app.RerankModelID);
|
||||
BegRerankConfig.LoadModel(rerankModel.EndPoint, rerankModel.ModelName);
|
||||
//进行rerank
|
||||
foreach (var item in relevantSourceList)
|
||||
{
|
||||
List<string> rerank = new List<string>();
|
||||
rerank.Add(questions);
|
||||
rerank.Add(item.Text);
|
||||
item.RerankScore = BegRerankConfig.Rerank(rerank);
|
||||
|
||||
}
|
||||
relevantSourceList = relevantSourceList.OrderByDescending(p => p.RerankScore).Take(app.MaxMatchesCount).ToList();
|
||||
}
|
||||
|
||||
bool isSearch = false;
|
||||
foreach (var item in relevantSourceList)
|
||||
{
|
||||
//匹配相似度
|
||||
if (item.Relevance >= app.Relevance/100)
|
||||
if (!string.IsNullOrEmpty(app.RerankModelID))
|
||||
{
|
||||
dataMsg.AppendLine(item.ToString());
|
||||
isSearch=true;
|
||||
//匹配重排后相似度
|
||||
if (item.RerankScore >= app.Relevance / 100)
|
||||
{
|
||||
dataMsg.AppendLine(item.ToString());
|
||||
isSearch = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//匹配相似度
|
||||
if (item.Relevance >= app.Relevance / 100)
|
||||
{
|
||||
dataMsg.AppendLine(item.ToString());
|
||||
isSearch = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//处理markdown显示
|
||||
relevantSources?.AddRange(relevantSourceList);
|
||||
Dictionary<string, string> fileDic = new Dictionary<string, string>();
|
||||
foreach (var item in relevantSourceList)
|
||||
{
|
||||
if (fileDic.ContainsKey(item.SourceName))
|
||||
{
|
||||
item.SourceName = fileDic[item.SourceName];
|
||||
}
|
||||
else
|
||||
{
|
||||
var fileDetail = _kmsDetails_Repositories.GetFirst(p => p.FileGuidName == item.SourceName);
|
||||
if (fileDetail.IsNotNull())
|
||||
{
|
||||
string fileName = fileDetail.FileName;
|
||||
fileDic.Add(item.SourceName, fileName);
|
||||
item.SourceName = fileName;
|
||||
}
|
||||
}
|
||||
item.Text = Markdown.ToHtml(item.Text);
|
||||
}
|
||||
|
||||
@@ -128,7 +200,7 @@ namespace AntSK.Domain.Domain.Service
|
||||
//KernelFunction jsonFun = _kernel.Plugins.GetFunction("KMSPlugin", "Ask1");
|
||||
var temperature = app.Temperature / 100;//存的是0~100需要缩小
|
||||
OpenAIPromptExecutionSettings settings = new() { Temperature = temperature };
|
||||
var func = _kernel.CreateFunctionFromPrompt(app.Prompt, settings);
|
||||
var func = _kernel.CreateFunctionFromPrompt(app.Prompt , settings);
|
||||
|
||||
var chatResult = _kernel.InvokeStreamingAsync(function: func,
|
||||
arguments: new KernelArguments() { ["doc"] = dataMsg.ToString(), ["history"] = string.Join("\n", history.Select(x => x.Role + ": " + x.Content)), ["input"] = questions });
|
||||
@@ -138,10 +210,10 @@ namespace AntSK.Domain.Domain.Service
|
||||
yield return content;
|
||||
}
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
yield return new StreamingTextContent(KmsConstantcs.KmsSearchNull);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -163,6 +235,59 @@ namespace AntSK.Domain.Domain.Service
|
||||
var chatResult = await _kernel.InvokeAsync(function: func, arguments: args);
|
||||
if (chatResult.IsNotNull())
|
||||
{
|
||||
//Can Load stable-diffusion library in diffenert environment
|
||||
|
||||
//SDHelper.LoadLibrary()
|
||||
string versionString = string.Empty;
|
||||
string extensionString = string.Empty;
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
extensionString = ".dll";
|
||||
}
|
||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
{
|
||||
extensionString = ".so";
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException("OS Platform no support");
|
||||
}
|
||||
|
||||
ProcessStartInfo startInfo = new ProcessStartInfo("nvcc", "--version");
|
||||
startInfo.RedirectStandardOutput = true;
|
||||
startInfo.UseShellExecute = false;
|
||||
startInfo.CreateNoWindow = true;
|
||||
using (Process process = Process.Start(startInfo))
|
||||
{
|
||||
if (process != null)
|
||||
{
|
||||
string result = process.StandardOutput.ReadToEnd();
|
||||
Regex regex = new Regex(@"release (\d+).[\d]");
|
||||
Match match = regex.Match(result);
|
||||
if (match.Success)
|
||||
{
|
||||
switch (match.Groups[1].Value.ToString())
|
||||
{
|
||||
case "11":
|
||||
versionString = "Cuda11";
|
||||
break;
|
||||
case "12":
|
||||
versionString = "Cuda12";
|
||||
break;
|
||||
default:
|
||||
versionString = "CPU";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("nvcc get an error");
|
||||
}
|
||||
}
|
||||
|
||||
string libraryPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "StableDiffusion", "Backend", versionString, "stable-diffusion" + extensionString);
|
||||
NativeLibrary.TryLoad(libraryPath, out _);
|
||||
string prompt = chatResult.GetValue<string>();
|
||||
if (!SDHelper.IsInitialized)
|
||||
{
|
||||
@@ -172,7 +297,8 @@ namespace AntSK.Domain.Domain.Service
|
||||
RngType = Structs.RngType.CUDA_RNG,
|
||||
//VaePath = vaePath,
|
||||
//KeepVaeOnCpu = keepVaeOnCpu,
|
||||
//VaeTiling = vaeTiling,
|
||||
//set false can get a better image, otherwise can use lower vram
|
||||
VaeTiling = false,
|
||||
//LoraModelDir = loraModelDir,
|
||||
};
|
||||
bool result = SDHelper.Initialize(modelParams);
|
||||
@@ -181,10 +307,11 @@ namespace AntSK.Domain.Domain.Service
|
||||
Structs.TextToImageParams textToImageParams = new Structs.TextToImageParams
|
||||
{
|
||||
Prompt = prompt,
|
||||
NegativePrompt = "2d, 3d, cartoon, paintings",
|
||||
NegativePrompt = "bad quality, wrong image, worst quality",
|
||||
SampleMethod = (Structs.SampleMethod)Enum.Parse(typeof(Structs.SampleMethod), "EULER_A"),
|
||||
Width = 256,
|
||||
Height = 256,
|
||||
//the base image size in SD1.5 is 512x512
|
||||
Width = 512,
|
||||
Height = 512,
|
||||
NormalizeInput = true,
|
||||
ClipSkip = -1,
|
||||
CfgScale = 7,
|
||||
@@ -201,25 +328,20 @@ namespace AntSK.Domain.Domain.Service
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<ChatHistory> GetChatHistory(List<MessageInfo> MessageList)
|
||||
public async Task<ChatHistory> GetChatHistory(List<Chats> MessageList, ChatHistory history)
|
||||
{
|
||||
ChatHistory history = new ChatHistory();
|
||||
if (MessageList.Count > 1)
|
||||
foreach (var item in MessageList)
|
||||
{
|
||||
|
||||
foreach (var item in MessageList)
|
||||
if (item.IsSend)
|
||||
{
|
||||
if (item.IsSend)
|
||||
{
|
||||
history.AddUserMessage(item.Context);
|
||||
}
|
||||
else
|
||||
{
|
||||
history.AddAssistantMessage(item.Context);
|
||||
}
|
||||
history.AddUserMessage(item.Context);
|
||||
}
|
||||
else
|
||||
{
|
||||
history.AddAssistantMessage(item.Context);
|
||||
}
|
||||
}
|
||||
return history;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ using System.Text.RegularExpressions;
|
||||
using Microsoft.SemanticKernel;
|
||||
using HtmlAgilityPack;
|
||||
using System.Collections.Generic;
|
||||
using Serilog;
|
||||
|
||||
namespace AntSK.Domain.Domain.Service
|
||||
{
|
||||
@@ -115,7 +116,7 @@ namespace AntSK.Domain.Domain.Service
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message + " ---- " + ex.StackTrace);
|
||||
Log.Error(ex.Message + " ---- " + ex.StackTrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ using AntSK.Domain.Domain.Model.Constant;
|
||||
using AntSK.Domain.Domain.Model.Excel;
|
||||
using AntSK.Domain.Domain.Other;
|
||||
using AntSK.Domain.Repositories;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.KernelMemory;
|
||||
using Microsoft.KernelMemory.Handlers;
|
||||
using System.Text;
|
||||
@@ -15,7 +16,8 @@ namespace AntSK.Domain.Domain.Service
|
||||
public class ImportKMSService(
|
||||
IKMService _kMService,
|
||||
IKmsDetails_Repositories _kmsDetails_Repositories,
|
||||
IKmss_Repositories _kmss_Repositories
|
||||
IKmss_Repositories _kmss_Repositories,
|
||||
ILogger<ImportKMSService> _logger
|
||||
) : IImportKMSService
|
||||
{
|
||||
|
||||
@@ -24,18 +26,40 @@ namespace AntSK.Domain.Domain.Service
|
||||
try
|
||||
{
|
||||
var km = _kmss_Repositories.GetFirst(p => p.Id == req.KmsId);
|
||||
|
||||
var _memory = _kMService.GetMemoryByKMS(km.Id);
|
||||
string fileid = req.KmsDetail.Id;
|
||||
List<string> step = new List<string>();
|
||||
if (req.IsQA)
|
||||
{
|
||||
_memory.Orchestrator.AddHandler<TextExtractionHandler>("extract_text");
|
||||
_memory.Orchestrator.AddHandler<QAHandler>(km.ChatModelID);
|
||||
_memory.Orchestrator.AddHandler<GenerateEmbeddingsHandler>("generate_embeddings");
|
||||
_memory.Orchestrator.AddHandler<SaveRecordsHandler>("save_memory_records");
|
||||
step.Add("extract_text");
|
||||
step.Add(km.ChatModelID);
|
||||
step.Add("generate_embeddings");
|
||||
step.Add("save_memory_records");
|
||||
}
|
||||
|
||||
switch (req.ImportType)
|
||||
{
|
||||
case ImportType.File:
|
||||
//导入文件
|
||||
{
|
||||
var importResult = _memory.ImportDocumentAsync(new Document(fileid)
|
||||
.AddFile(req.FilePath)
|
||||
.AddTag(KmsConstantcs.KmsIdTag, req.KmsId)
|
||||
, index: KmsConstantcs.KmsIndex).Result;
|
||||
//导入文件
|
||||
if (req.IsQA)
|
||||
{
|
||||
var importResult = _memory.ImportDocumentAsync(new Document(fileid)
|
||||
.AddFile(req.FilePath)
|
||||
.AddTag(KmsConstantcs.KmsIdTag, req.KmsId)
|
||||
,index: KmsConstantcs.KmsIndex ,steps: step.ToArray()).Result;
|
||||
}
|
||||
else
|
||||
{
|
||||
var importResult = _memory.ImportDocumentAsync(new Document(fileid)
|
||||
.AddFile(req.FilePath)
|
||||
.AddTag(KmsConstantcs.KmsIdTag, req.KmsId)
|
||||
, index: KmsConstantcs.KmsIndex).Result;
|
||||
}
|
||||
//查询文档数量
|
||||
var docTextList = _kMService.GetDocumentByFileID(km.Id, fileid).Result;
|
||||
string fileGuidName = Path.GetFileName(req.FilePath);
|
||||
@@ -48,8 +72,16 @@ namespace AntSK.Domain.Domain.Service
|
||||
case ImportType.Url:
|
||||
{
|
||||
//导入url
|
||||
var importResult = _memory.ImportWebPageAsync(req.Url, fileid, new TagCollection() { { KmsConstantcs.KmsIdTag, req.KmsId } }
|
||||
, index: KmsConstantcs.KmsIndex).Result;
|
||||
if (req.IsQA)
|
||||
{
|
||||
var importResult = _memory.ImportWebPageAsync(req.Url, fileid, new TagCollection() { { KmsConstantcs.KmsIdTag, req.KmsId } }
|
||||
, index: KmsConstantcs.KmsIndex, steps: step.ToArray()).Result;
|
||||
}
|
||||
else
|
||||
{
|
||||
var importResult = _memory.ImportWebPageAsync(req.Url, fileid, new TagCollection() { { KmsConstantcs.KmsIdTag, req.KmsId } }
|
||||
, index: KmsConstantcs.KmsIndex).Result;
|
||||
}
|
||||
//查询文档数量
|
||||
var docTextList = _kMService.GetDocumentByFileID(km.Id, fileid).Result;
|
||||
req.KmsDetail.Url = req.Url;
|
||||
@@ -59,8 +91,16 @@ namespace AntSK.Domain.Domain.Service
|
||||
case ImportType.Text:
|
||||
//导入文本
|
||||
{
|
||||
var importResult = _memory.ImportTextAsync(req.Text, fileid, new TagCollection() { { KmsConstantcs.KmsIdTag, req.KmsId } }
|
||||
, index: KmsConstantcs.KmsIndex).Result;
|
||||
if (req.IsQA)
|
||||
{
|
||||
var importResult = _memory.ImportTextAsync(req.Text, fileid, new TagCollection() { { KmsConstantcs.KmsIdTag, req.KmsId } }
|
||||
, index: KmsConstantcs.KmsIndex, steps: step.ToArray()).Result;
|
||||
}
|
||||
else
|
||||
{
|
||||
var importResult = _memory.ImportTextAsync(req.Text, fileid, new TagCollection() { { KmsConstantcs.KmsIdTag, req.KmsId } }
|
||||
, index: KmsConstantcs.KmsIndex).Result;
|
||||
}
|
||||
//查询文档数量
|
||||
var docTextList = _kMService.GetDocumentByFileID(km.Id, fileid).Result;
|
||||
req.KmsDetail.Url = req.Url;
|
||||
@@ -71,8 +111,7 @@ namespace AntSK.Domain.Domain.Service
|
||||
case ImportType.Excel:
|
||||
using (var fs = File.OpenRead(req.FilePath))
|
||||
{
|
||||
var excelList= ExeclHelper.ExcelToList<KMSExcelModel>(fs);
|
||||
|
||||
var excelList= ExeclHelper.ExcelToList<KMSExcelModel>(fs);
|
||||
_memory.Orchestrator.AddHandler<TextExtractionHandler>("extract_text");
|
||||
_memory.Orchestrator.AddHandler<KMExcelHandler>("antsk_excel_split");
|
||||
_memory.Orchestrator.AddHandler<GenerateEmbeddingsHandler>("generate_embeddings");
|
||||
@@ -103,13 +142,13 @@ namespace AntSK.Domain.Domain.Service
|
||||
req.KmsDetail.Status = Model.Enum.ImportKmsStatus.Success;
|
||||
_kmsDetails_Repositories.Update(req.KmsDetail);
|
||||
//_kmsDetails_Repositories.GetList(p => p.KmsId == req.KmsId);
|
||||
Console.WriteLine("后台导入任务成功:" + req.KmsDetail.DataCount);
|
||||
_logger.LogInformation("后台导入任务成功:" + req.KmsDetail.DataCount);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
req.KmsDetail.Status = Model.Enum.ImportKmsStatus.Fail;
|
||||
_kmsDetails_Repositories.Update(req.KmsDetail);
|
||||
Console.WriteLine("后台导入任务异常:" + ex.Message);
|
||||
_logger.LogError("后台导入任务异常:" + ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ using AntSK.Domain.Domain.Other;
|
||||
using AntSK.Domain.Options;
|
||||
using AntSK.Domain.Repositories;
|
||||
using AntSK.Domain.Utils;
|
||||
using AntSK.OCR;
|
||||
using DocumentFormat.OpenXml.Drawing.Diagrams;
|
||||
using LLama;
|
||||
using LLamaSharp.KernelMemory;
|
||||
@@ -16,6 +17,7 @@ using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.KernelMemory;
|
||||
using Microsoft.KernelMemory.Configuration;
|
||||
using Microsoft.KernelMemory.DataFormats;
|
||||
using Microsoft.KernelMemory.FileSystem.DevTools;
|
||||
using Microsoft.KernelMemory.MemoryStorage;
|
||||
using Microsoft.KernelMemory.MemoryStorage.DevTools;
|
||||
@@ -27,7 +29,8 @@ namespace AntSK.Domain.Domain.Service
|
||||
public class KMService(
|
||||
IKmss_Repositories _kmss_Repositories,
|
||||
IAIModels_Repositories _aIModels_Repositories,
|
||||
IMessageService? _message
|
||||
IMessageService? _message,
|
||||
IKernelService _kernelService
|
||||
) : IKMService
|
||||
{
|
||||
private MemoryServerless _memory;
|
||||
@@ -42,14 +45,30 @@ namespace AntSK.Domain.Domain.Service
|
||||
var embedModel = _aIModels_Repositories.GetFirst(p => p.Id == app.EmbeddingModelID);
|
||||
var chatHttpClient = OpenAIHttpClientHandlerUtil.GetHttpClient(chatModel.EndPoint);
|
||||
var embeddingHttpClient = OpenAIHttpClientHandlerUtil.GetHttpClient(embedModel.EndPoint);
|
||||
|
||||
var searchClientConfig = new SearchClientConfig
|
||||
SearchClientConfig searchClientConfig;
|
||||
if (string.IsNullOrEmpty(app.RerankModelID))
|
||||
{
|
||||
MaxAskPromptSize = app.MaxAskPromptSize,
|
||||
MaxMatchesCount = app.MaxMatchesCount,
|
||||
AnswerTokens = app.AnswerTokens,
|
||||
EmptyAnswer = KmsConstantcs.KmsSearchNull
|
||||
};
|
||||
//不重排直接取查询数
|
||||
searchClientConfig = new SearchClientConfig
|
||||
{
|
||||
MaxAskPromptSize = app.MaxAskPromptSize,
|
||||
MaxMatchesCount = app.MaxMatchesCount,
|
||||
AnswerTokens = app.AnswerTokens,
|
||||
EmptyAnswer = KmsConstantcs.KmsSearchNull
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
//重排取rerank数
|
||||
searchClientConfig = new SearchClientConfig
|
||||
{
|
||||
MaxAskPromptSize = app.MaxAskPromptSize,
|
||||
MaxMatchesCount = app.RerankCount,
|
||||
AnswerTokens = app.AnswerTokens,
|
||||
EmptyAnswer = KmsConstantcs.KmsSearchNull
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
var memoryBuild = new KernelMemoryBuilder()
|
||||
.WithSearchClientConfig(searchClientConfig)
|
||||
@@ -104,14 +123,16 @@ namespace AntSK.Domain.Domain.Service
|
||||
MaxTokensPerParagraph = kms.MaxTokensPerParagraph,
|
||||
OverlappingTokens = kms.OverlappingTokens
|
||||
});
|
||||
//加载OCR
|
||||
WithOcr(memoryBuild, kms);
|
||||
//加载会话模型
|
||||
WithTextGenerationByAIType(memoryBuild, chatModel, chatHttpClient);
|
||||
//加载向量模型
|
||||
WithTextEmbeddingGenerationByAIType(memoryBuild, embedModel, embeddingHttpClient);
|
||||
//加载向量库
|
||||
WithMemoryDbByVectorDB(memoryBuild);
|
||||
|
||||
_memory = memoryBuild.Build<MemoryServerless>();
|
||||
|
||||
_memory = memoryBuild.AddSingleton<IKernelService>(_kernelService).Build<MemoryServerless>();
|
||||
return _memory;
|
||||
}
|
||||
//else {
|
||||
@@ -119,6 +140,14 @@ namespace AntSK.Domain.Domain.Service
|
||||
//}
|
||||
}
|
||||
|
||||
private static void WithOcr(IKernelMemoryBuilder memoryBuild, Kmss kms)
|
||||
{
|
||||
if (kms.IsOCR == 1)
|
||||
{
|
||||
memoryBuild.WithCustomImageOcr(new AntSKOcrEngine());
|
||||
}
|
||||
}
|
||||
|
||||
private void WithTextEmbeddingGenerationByAIType(IKernelMemoryBuilder memory, AIModels embedModel,
|
||||
HttpClient embeddingHttpClient)
|
||||
{
|
||||
@@ -193,7 +222,7 @@ namespace AntSK.Domain.Domain.Service
|
||||
|
||||
memory.WithOpenAITextGeneration(new OpenAIConfig()
|
||||
{
|
||||
APIKey = "123",
|
||||
APIKey = "NotNull",
|
||||
TextModel = chatModel.ModelName
|
||||
}, null, chatHttpClient);
|
||||
break;
|
||||
@@ -262,12 +291,12 @@ namespace AntSK.Domain.Domain.Service
|
||||
{
|
||||
foreach (var memoryDb in memoryDbs)
|
||||
{
|
||||
var items = await memoryDb.GetListAsync(memoryIndex.Name, new List<MemoryFilter>() { new MemoryFilter().ByDocument(fileId) }, 100, true).ToListAsync();
|
||||
var items = await memoryDb.GetListAsync(memoryIndex.Name, new List<MemoryFilter>() { new MemoryFilter().ByDocument(fileId) }, 1000, true).ToListAsync();
|
||||
docTextList.AddRange(items.Select(item => new KMFile()
|
||||
{
|
||||
DocumentId = item.GetDocumentId(),
|
||||
Text = item.GetPartitionText(),
|
||||
Url = item.GetWebPageUrl(),
|
||||
Url = item.GetWebPageUrl(KmsConstantcs.KmsIndex),
|
||||
LastUpdate = item.GetLastUpdate().LocalDateTime.ToString("yyyy-MM-dd HH:mm:ss"),
|
||||
File = item.GetFileName()
|
||||
}));
|
||||
@@ -319,7 +348,10 @@ namespace AntSK.Domain.Domain.Service
|
||||
"application/pdf",
|
||||
"application/json",
|
||||
"text/x-markdown",
|
||||
"text/markdown"
|
||||
"text/markdown",
|
||||
"image/jpeg",
|
||||
"image/png",
|
||||
"image/tiff"
|
||||
};
|
||||
|
||||
string[] exceptExts = [".md", ".pdf"];
|
||||
|
||||
@@ -18,6 +18,12 @@ using AntSK.Domain.Domain.Model.Enum;
|
||||
using AntSK.LLM.LLamaFactory;
|
||||
using System.Reflection;
|
||||
using DocumentFormat.OpenXml.Drawing;
|
||||
using Microsoft.KernelMemory;
|
||||
using OpenCvSharp.ML;
|
||||
using LLamaSharp.SemanticKernel.ChatCompletion;
|
||||
using Microsoft.SemanticKernel.ChatCompletion;
|
||||
using Amazon.Runtime.Internal.Util;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace AntSK.Domain.Domain.Service
|
||||
{
|
||||
@@ -29,17 +35,20 @@ namespace AntSK.Domain.Domain.Service
|
||||
private readonly FunctionService _functionService;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private Kernel _kernel;
|
||||
private readonly ILogger<KernelService> _logger;
|
||||
|
||||
public KernelService(
|
||||
IApis_Repositories apis_Repositories,
|
||||
IAIModels_Repositories aIModels_Repositories,
|
||||
FunctionService functionService,
|
||||
IServiceProvider serviceProvider)
|
||||
IServiceProvider serviceProvider,
|
||||
ILogger<KernelService> logger)
|
||||
{
|
||||
_apis_Repositories = apis_Repositories;
|
||||
_aIModels_Repositories = aIModels_Repositories;
|
||||
_functionService = functionService;
|
||||
_serviceProvider = serviceProvider;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -57,7 +66,7 @@ namespace AntSK.Domain.Domain.Service
|
||||
var chatHttpClient = OpenAIHttpClientHandlerUtil.GetHttpClient(chatModel.EndPoint);
|
||||
|
||||
var builder = Kernel.CreateBuilder();
|
||||
WithTextGenerationByAIType(builder, app, chatModel, chatHttpClient);
|
||||
WithTextGenerationByAIType(builder, chatModel, chatHttpClient);
|
||||
|
||||
_kernel = builder.Build();
|
||||
RegisterPluginsWithKernel(_kernel);
|
||||
@@ -69,7 +78,18 @@ namespace AntSK.Domain.Domain.Service
|
||||
//}
|
||||
}
|
||||
|
||||
private void WithTextGenerationByAIType(IKernelBuilder builder, Apps app, AIModels chatModel, HttpClient chatHttpClient)
|
||||
public Kernel GetKernelByAIModelID(string modelid)
|
||||
{
|
||||
var chatModel = _aIModels_Repositories.GetById(modelid);
|
||||
var chatHttpClient = OpenAIHttpClientHandlerUtil.GetHttpClient(chatModel.EndPoint);
|
||||
var builder = Kernel.CreateBuilder();
|
||||
WithTextGenerationByAIType(builder, chatModel, chatHttpClient);
|
||||
_kernel = builder.Build();
|
||||
RegisterPluginsWithKernel(_kernel);
|
||||
return _kernel;
|
||||
}
|
||||
|
||||
private void WithTextGenerationByAIType(IKernelBuilder builder,AIModels chatModel, HttpClient chatHttpClient)
|
||||
{
|
||||
switch (chatModel.AIType)
|
||||
{
|
||||
@@ -92,11 +112,13 @@ namespace AntSK.Domain.Domain.Service
|
||||
var (weights, parameters) = LLamaConfig.GetLLamaConfig(chatModel.ModelName);
|
||||
var ex = new StatelessExecutor(weights, parameters);
|
||||
builder.Services.AddKeyedSingleton<ITextGenerationService>("local-llama", new LLamaSharpTextCompletion(ex));
|
||||
builder.Services.AddKeyedSingleton<IChatCompletionService>("local-llama-chat", new LLamaSharpChatCompletion(ex));
|
||||
break;
|
||||
|
||||
case Model.Enum.AIType.SparkDesk:
|
||||
var options = new SparkDeskOptions { AppId = chatModel.EndPoint, ApiSecret = chatModel.ModelKey, ApiKey = chatModel.ModelName, ModelVersion = Sdcb.SparkDesk.ModelVersion.V3_5 };
|
||||
builder.Services.AddKeyedSingleton<ITextGenerationService>("spark-desk", new SparkDeskTextCompletion(options, app.Id));
|
||||
builder.Services.AddKeyedSingleton<ITextGenerationService>("spark-desk", new SparkDeskTextCompletion(options, chatModel.Id));
|
||||
builder.Services.AddKeyedSingleton<IChatCompletionService>("spark-desk-chat", new SparkDeskChatCompletion(options, chatModel.Id));
|
||||
break;
|
||||
|
||||
case Model.Enum.AIType.DashScope:
|
||||
@@ -105,6 +127,7 @@ namespace AntSK.Domain.Domain.Service
|
||||
|
||||
case Model.Enum.AIType.Mock:
|
||||
builder.Services.AddKeyedSingleton<ITextGenerationService>("mock", new MockTextCompletion());
|
||||
builder.Services.AddKeyedSingleton<IChatCompletionService>("mock-chat", new MockChatCompletion());
|
||||
break;
|
||||
case Model.Enum.AIType.LLamaFactory:
|
||||
builder.AddOpenAIChatCompletion(
|
||||
@@ -160,7 +183,6 @@ namespace AntSK.Domain.Domain.Service
|
||||
|
||||
var getParametes = new List<KernelParameterMetadata>() {
|
||||
new KernelParameterMetadata("jsonbody"){
|
||||
Name="json参数字符串",
|
||||
ParameterType=typeof(string),
|
||||
Description=$"背景文档:{Environment.NewLine}{api.InputPrompt} {Environment.NewLine}提取出对应的json格式字符串,参考如下格式:{Environment.NewLine}{api.Query}"
|
||||
}
|
||||
@@ -199,7 +221,6 @@ namespace AntSK.Domain.Domain.Service
|
||||
//处理json body
|
||||
var postParametes = new List<KernelParameterMetadata>() {
|
||||
new KernelParameterMetadata("jsonbody"){
|
||||
Name="json参数字符串",
|
||||
ParameterType=typeof(string),
|
||||
Description=$"背景文档:{Environment.NewLine}{api.InputPrompt} {Environment.NewLine}提取出对应的json格式字符串,参考如下格式:{Environment.NewLine}{api.JsonBody}"
|
||||
}
|
||||
@@ -208,7 +229,7 @@ namespace AntSK.Domain.Domain.Service
|
||||
{
|
||||
try
|
||||
{
|
||||
Console.WriteLine(jsonBody);
|
||||
_logger.LogInformation(jsonBody);
|
||||
RestClient client = new RestClient();
|
||||
RestRequest request = new RestRequest(api.Url, Method.Post);
|
||||
foreach (var header in api.Header.ConvertToString().Split("\n"))
|
||||
@@ -287,8 +308,8 @@ 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:{Environment.NewLine}{history.ToString()}{Environment.NewLine} user:{questions}{Environment.NewLine}"; ;
|
||||
var msg = $"history:{Environment.NewLine}{his}{Environment.NewLine} user:{questions}{Environment.NewLine}";
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
using AntSK.Domain.Common.DependencyInjection;
|
||||
using Amazon.Runtime.Internal.Util;
|
||||
using AntSK.Domain.Common.DependencyInjection;
|
||||
using AntSK.Domain.Domain.Interface;
|
||||
using AntSK.Domain.Domain.Model.Dto;
|
||||
using AntSK.Domain.Options;
|
||||
using AntSK.LLamaFactory.Model;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -17,7 +19,7 @@ using System.Threading.Tasks;
|
||||
namespace AntSK.Domain.Domain.Service
|
||||
{
|
||||
[ServiceDescription(typeof(ILLamaFactoryService), ServiceLifetime.Singleton)]
|
||||
public class LLamaFactoryService : ILLamaFactoryService
|
||||
public class LLamaFactoryService(ILogger<LLamaFactoryService> _logger) : ILLamaFactoryService
|
||||
{
|
||||
private Process process;
|
||||
|
||||
@@ -26,7 +28,7 @@ namespace AntSK.Domain.Domain.Service
|
||||
private readonly object _syncLock = new object();
|
||||
private List<LLamaModel> modelList = new List<LLamaModel>();
|
||||
|
||||
public LLamaFactoryService() { }
|
||||
|
||||
public delegate Task LogMessageHandler(string message);
|
||||
public event LogMessageHandler LogMessageReceived;
|
||||
protected virtual async Task OnLogMessageReceived(string message)
|
||||
@@ -56,12 +58,12 @@ namespace AntSK.Domain.Domain.Service
|
||||
};
|
||||
process.OutputDataReceived += (sender, eventArgs) =>
|
||||
{
|
||||
Console.WriteLine($"{eventArgs.Data}");
|
||||
_logger.LogInformation($"{eventArgs.Data}");
|
||||
OnLogMessageReceived(eventArgs.Data);
|
||||
};
|
||||
process.ErrorDataReceived += (sender, eventArgs) =>
|
||||
{
|
||||
Console.WriteLine($"{eventArgs.Data}");
|
||||
_logger.LogInformation($"{eventArgs.Data}");
|
||||
OnLogMessageReceived(eventArgs.Data);
|
||||
};
|
||||
process.Start();
|
||||
@@ -92,17 +94,17 @@ namespace AntSK.Domain.Domain.Service
|
||||
WorkingDirectory = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location), "llamafactory"),
|
||||
}
|
||||
};
|
||||
process.StartInfo.Environment["CUDA_VISIBLE_DEVICES"] = "0";
|
||||
process.StartInfo.Environment["CUDA_VISIBLE_DEVICES"] = Environment.GetEnvironmentVariable("CUDA_VISIBLE_DEVICES") ?? "0";
|
||||
process.StartInfo.Environment["API_PORT"] = "8000";
|
||||
process.StartInfo.EnvironmentVariables["USE_MODELSCOPE_HUB"] = "1";
|
||||
process.StartInfo.EnvironmentVariables["USE_MODELSCOPE_HUB"] = Environment.GetEnvironmentVariable("USE_MODELSCOPE_HUB") ?? "1";
|
||||
process.OutputDataReceived += (sender, eventArgs) =>
|
||||
{
|
||||
Console.WriteLine($"{eventArgs.Data}");
|
||||
_logger.LogInformation($"{eventArgs.Data}");
|
||||
OnLogMessageReceived(eventArgs.Data);
|
||||
};
|
||||
process.ErrorDataReceived += (sender, eventArgs) =>
|
||||
{
|
||||
Console.WriteLine($"{eventArgs.Data}");
|
||||
_logger.LogInformation($"{eventArgs.Data}");
|
||||
OnLogMessageReceived(eventArgs.Data);
|
||||
};
|
||||
process.Start();
|
||||
@@ -137,7 +139,7 @@ namespace AntSK.Domain.Domain.Service
|
||||
if (process1.ProcessName.ToLower() == "python")
|
||||
{
|
||||
process1.Kill();
|
||||
System.Console.WriteLine("kill python");
|
||||
_logger.LogInformation("kill python");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
13
src/AntSK.Domain/Options/FileDirOption.cs
Normal file
13
src/AntSK.Domain/Options/FileDirOption.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AntSK.Domain.Options
|
||||
{
|
||||
public class FileDirOption
|
||||
{
|
||||
public static string DirectoryPath { get; set; } = Directory.GetCurrentDirectory();
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
public class LLamaSharpOption
|
||||
{
|
||||
public static string RunType { get; set; }
|
||||
public static string FileDirectory { get; set; } = Directory.GetCurrentDirectory();
|
||||
public static uint? ContextSize { get; set; }
|
||||
public static int? GpuLayerCount { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,6 +44,9 @@ namespace AntSK.Domain.Repositories
|
||||
/// </summary>
|
||||
public string? EmbeddingModelID { get; set; }
|
||||
|
||||
public string? RerankModelID { get; set; }
|
||||
|
||||
|
||||
public string? ImageModelID { get; set; }
|
||||
/// <summary>
|
||||
/// 温度
|
||||
@@ -83,7 +86,7 @@ namespace AntSK.Domain.Repositories
|
||||
/// 相似度
|
||||
/// </summary>
|
||||
[SugarColumn(DefaultValue = "70")]
|
||||
public double Relevance { get; set; } = 70;
|
||||
public double Relevance { get; set; } = 70f;
|
||||
|
||||
/// <summary>
|
||||
/// 提问最大token数
|
||||
@@ -96,6 +99,9 @@ namespace AntSK.Domain.Repositories
|
||||
[SugarColumn(DefaultValue = "3")]
|
||||
public int MaxMatchesCount { get; set; } = 3;
|
||||
|
||||
|
||||
[SugarColumn(DefaultValue = "20")]
|
||||
public int RerankCount { get; set; } = 20;
|
||||
/// <summary>
|
||||
/// 回答最大token数
|
||||
/// </summary>
|
||||
|
||||
41
src/AntSK.Domain/Repositories/AI/Chat/Chats.cs
Normal file
41
src/AntSK.Domain/Repositories/AI/Chat/Chats.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using AntSK.Domain.Domain.Model.Enum;
|
||||
using SqlSugar;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace AntSK.Domain.Repositories
|
||||
{
|
||||
[SugarTable("Chats")]
|
||||
public partial class Chats
|
||||
{
|
||||
[SugarColumn(IsPrimaryKey = true)]
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户名
|
||||
/// </summary>
|
||||
public string UserName { get; set; }
|
||||
/// <summary>
|
||||
/// 应用ID
|
||||
/// </summary>
|
||||
public string AppId { get; set; }
|
||||
/// <summary>
|
||||
/// 消息内容
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDataType = "varchar(4000)")]
|
||||
public string Context { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// 发送是true 接收是false
|
||||
/// </summary>
|
||||
public bool IsSend { get; set; } = false;
|
||||
/// <summary>
|
||||
/// 创建事件
|
||||
/// </summary>
|
||||
public DateTime CreateTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 文件名
|
||||
/// </summary>
|
||||
public string? FileName { get; set; }
|
||||
}
|
||||
}
|
||||
11
src/AntSK.Domain/Repositories/AI/Chat/Chats_Repositories.cs
Normal file
11
src/AntSK.Domain/Repositories/AI/Chat/Chats_Repositories.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
using AntSK.Domain.Common.DependencyInjection;
|
||||
using AntSK.Domain.Repositories.Base;
|
||||
|
||||
namespace AntSK.Domain.Repositories
|
||||
{
|
||||
[ServiceDescription(typeof(IChats_Repositories), ServiceLifetime.Scoped)]
|
||||
public class Chats_Repositories : Repository<Chats>, IChats_Repositories
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using AntSK.Domain.Repositories.Base;
|
||||
|
||||
namespace AntSK.Domain.Repositories
|
||||
{
|
||||
public interface IChats_Repositories : IRepository<Chats>
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -55,6 +55,7 @@ namespace AntSK.Domain.Repositories
|
||||
[SugarColumn(DefaultValue = "49")]
|
||||
public int OverlappingTokens { get; set; } = 49;
|
||||
|
||||
|
||||
[SugarColumn(DefaultValue = "0")]
|
||||
public int IsOCR { get; set; } = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Web;
|
||||
using System.Security.Cryptography;
|
||||
using System.Web;
|
||||
|
||||
namespace AntSK.Domain.Utils
|
||||
{
|
||||
@@ -261,5 +262,11 @@ namespace AntSK.Domain.Utils
|
||||
{
|
||||
return s.Equals(value, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public static string AntSKCalculateSHA256(this BinaryData binaryData)
|
||||
{
|
||||
byte[] byteArray = SHA256.HashData(binaryData.ToMemory().Span);
|
||||
return Convert.ToHexString(byteArray).ToLowerInvariant();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using Serilog;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace AntSK.Domain.Utils
|
||||
{
|
||||
@@ -19,7 +21,7 @@ namespace AntSK.Domain.Utils
|
||||
{
|
||||
string requestBody = await request.Content.ReadAsStringAsync();
|
||||
//便于调试查看请求prompt
|
||||
Console.WriteLine(requestBody);
|
||||
Log.Information(requestBody);
|
||||
}
|
||||
if (match.Success)
|
||||
{
|
||||
|
||||
@@ -17,4 +17,5 @@ matplotlib
|
||||
fire
|
||||
modelscope
|
||||
langchain-community
|
||||
sentence_transformers
|
||||
sentence_transformers
|
||||
FlagEmbedding
|
||||
|
||||
19
src/AntSK.OCR/AntSK.OCR.csproj
Normal file
19
src/AntSK.OCR/AntSK.OCR.csproj
Normal file
@@ -0,0 +1,19 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.KernelMemory.Core" Version="$(KMVersion)" />
|
||||
<PackageReference Include="OpenCvSharp4.runtime.win" Version="4.9.0.20240103" />
|
||||
<PackageReference Include="Sdcb.OpenCvSharp4.mini.runtime.debian.12-x64" Version="4.8.0.20231125" />
|
||||
<PackageReference Include="Sdcb.OpenVINO" Version="0.6.4" />
|
||||
<PackageReference Include="Sdcb.OpenVINO.PaddleOCR.Models.Online" Version="0.6.2" />
|
||||
<PackageReference Include="Sdcb.OpenVINO.PaddleOCR" Version="0.6.3" />
|
||||
<PackageReference Include="Sdcb.OpenVINO.runtime.ubuntu.22.04-x64" Version="2024.0.0" />
|
||||
<PackageReference Include="Sdcb.OpenVINO.runtime.win-x64" Version="2024.0.0" />
|
||||
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
56
src/AntSK.OCR/AntSKOcrEngine.cs
Normal file
56
src/AntSK.OCR/AntSKOcrEngine.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using Microsoft.KernelMemory.DataFormats;
|
||||
using Sdcb.OpenVINO.PaddleOCR;
|
||||
using Sdcb.OpenVINO.PaddleOCR.Models.Online;
|
||||
using Sdcb.OpenVINO.PaddleOCR.Models;
|
||||
using OpenCvSharp;
|
||||
|
||||
namespace AntSK.OCR
|
||||
{
|
||||
/// <summary>
|
||||
/// OCR
|
||||
/// </summary>
|
||||
public class AntSKOcrEngine : IOcrEngine
|
||||
{
|
||||
FullOcrModel model;
|
||||
public Task<string> ExtractTextFromImageAsync(Stream imageContent, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
model = OnlineFullModels.ChineseV4.DownloadAsync().Result;
|
||||
}
|
||||
using (PaddleOcrAll all = new(model)
|
||||
{
|
||||
AllowRotateDetection = true,
|
||||
Enable180Classification = true,
|
||||
})
|
||||
{
|
||||
Mat src = Cv2.ImDecode(StreamToByte(imageContent), ImreadModes.Color);
|
||||
PaddleOcrResult result = all.Run(src);
|
||||
return Task.FromResult(result.Text);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message);
|
||||
return Task.FromResult("");
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] StreamToByte(Stream stream)
|
||||
{
|
||||
using (var memoryStream = new MemoryStream())
|
||||
{
|
||||
byte[] buffer = new byte[1024]; //自定义大小,例如 1024
|
||||
int bytesRead;
|
||||
while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
|
||||
{
|
||||
memoryStream.Write(buffer, 0, bytesRead);
|
||||
}
|
||||
byte[] bytes = memoryStream.ToArray();
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace AntSK.PyNet
|
||||
{
|
||||
public class Class1
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
22
src/AntSK.ServiceDefaults/AntSK.ServiceDefaults.csproj
Normal file
22
src/AntSK.ServiceDefaults/AntSK.ServiceDefaults.csproj
Normal file
@@ -0,0 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsAspireSharedProject>true</IsAspireSharedProject>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
|
||||
<PackageReference Include="Microsoft.Extensions.Http.Resilience" Version="8.3.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.ServiceDiscovery" Version="8.0.1" />
|
||||
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.8.1" />
|
||||
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.8.1" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.8.1" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.8.1" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.Runtime" Version="1.8.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
118
src/AntSK.ServiceDefaults/Extensions.cs
Normal file
118
src/AntSK.ServiceDefaults/Extensions.cs
Normal file
@@ -0,0 +1,118 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.ServiceDiscovery;
|
||||
using OpenTelemetry;
|
||||
using OpenTelemetry.Metrics;
|
||||
using OpenTelemetry.Trace;
|
||||
|
||||
namespace Microsoft.Extensions.Hosting;
|
||||
|
||||
// Adds common .NET Aspire services: service discovery, resilience, health checks, and OpenTelemetry.
|
||||
// This project should be referenced by each service project in your solution.
|
||||
// To learn more about using this project, see https://aka.ms/dotnet/aspire/service-defaults
|
||||
public static class Extensions
|
||||
{
|
||||
public static IHostApplicationBuilder AddServiceDefaults(this IHostApplicationBuilder builder)
|
||||
{
|
||||
builder.ConfigureOpenTelemetry();
|
||||
|
||||
builder.AddDefaultHealthChecks();
|
||||
|
||||
builder.Services.AddServiceDiscovery();
|
||||
|
||||
builder.Services.ConfigureHttpClientDefaults(http =>
|
||||
{
|
||||
// Turn on resilience by default
|
||||
http.AddStandardResilienceHandler();
|
||||
|
||||
// Turn on service discovery by default
|
||||
http.AddServiceDiscovery();
|
||||
});
|
||||
|
||||
// Uncomment the following to restrict the allowed schemes for service discovery.
|
||||
// builder.Services.Configure<ServiceDiscoveryOptions>(options =>
|
||||
// {
|
||||
// options.AllowedSchemes = ["https"];
|
||||
// });
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static IHostApplicationBuilder ConfigureOpenTelemetry(this IHostApplicationBuilder builder)
|
||||
{
|
||||
builder.Logging.AddOpenTelemetry(logging =>
|
||||
{
|
||||
logging.IncludeFormattedMessage = true;
|
||||
logging.IncludeScopes = true;
|
||||
});
|
||||
|
||||
builder.Services.AddOpenTelemetry()
|
||||
.WithMetrics(metrics =>
|
||||
{
|
||||
metrics.AddAspNetCoreInstrumentation()
|
||||
.AddHttpClientInstrumentation()
|
||||
.AddRuntimeInstrumentation();
|
||||
})
|
||||
.WithTracing(tracing =>
|
||||
{
|
||||
tracing.AddAspNetCoreInstrumentation()
|
||||
// Uncomment the following line to enable gRPC instrumentation (requires the OpenTelemetry.Instrumentation.GrpcNetClient package)
|
||||
//.AddGrpcClientInstrumentation()
|
||||
.AddHttpClientInstrumentation();
|
||||
});
|
||||
|
||||
builder.AddOpenTelemetryExporters();
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
private static IHostApplicationBuilder AddOpenTelemetryExporters(this IHostApplicationBuilder builder)
|
||||
{
|
||||
var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]);
|
||||
|
||||
if (useOtlpExporter)
|
||||
{
|
||||
builder.Services.AddOpenTelemetry().UseOtlpExporter();
|
||||
}
|
||||
|
||||
// Uncomment the following lines to enable the Azure Monitor exporter (requires the Azure.Monitor.OpenTelemetry.AspNetCore package)
|
||||
//if (!string.IsNullOrEmpty(builder.Configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"]))
|
||||
//{
|
||||
// builder.Services.AddOpenTelemetry()
|
||||
// .UseAzureMonitor();
|
||||
//}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static IHostApplicationBuilder AddDefaultHealthChecks(this IHostApplicationBuilder builder)
|
||||
{
|
||||
builder.Services.AddHealthChecks()
|
||||
// Add a default liveness check to ensure app is responsive
|
||||
.AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static WebApplication MapDefaultEndpoints(this WebApplication app)
|
||||
{
|
||||
// Adding health checks endpoints to applications in non-development environments has security implications.
|
||||
// See https://aka.ms/dotnet/aspire/healthchecks for details before enabling these endpoints in non-development environments.
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
// All health checks must pass for app to be considered ready to accept traffic after starting
|
||||
app.MapHealthChecks("/health");
|
||||
|
||||
// Only health checks tagged with the "live" tag must pass for app to be considered alive
|
||||
app.MapHealthChecks("/alive", new HealthCheckOptions
|
||||
{
|
||||
Predicate = r => r.Tags.Contains("live")
|
||||
});
|
||||
}
|
||||
|
||||
return app;
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Docker", "Docker", "{9F2E19
|
||||
..\docker-compose.simple.yml = ..\docker-compose.simple.yml
|
||||
..\docker-compose.yml = ..\docker-compose.yml
|
||||
..\Dockerfile = ..\Dockerfile
|
||||
..\Dockerfile-py = ..\Dockerfile-py
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MiddleWare", "MiddleWare", "{40DDB1DC-571B-4A95-9F34-47F52981C511}"
|
||||
@@ -24,6 +25,19 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AntSK.Test", "AntSK.Test\An
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AntSK.LLamaFactory", "AntSK.LLamaFactory\AntSK.LLamaFactory.csproj", "{664DFA1F-68B7-49C7-B889-FA14D1756D3D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AntSK.OCR", "AntSK.OCR\AntSK.OCR.csproj", "{6195F7AA-18C2-4372-85CA-11FC4B522686}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Aspire", "Aspire", "{8578F0F2-5DE5-45EF-AE54-C37A07B62248}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AntSKWeb", "AntSKWeb", "{F341BA6B-E329-42F7-8005-1E366C8A7B1F}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
Directory.Build.props = Directory.Build.props
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AntSK.AppHost", "AntSK.AppHost\AntSK.AppHost.csproj", "{3EEC5A22-2C4D-4D6F-9039-C4AF3FEA3418}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AntSK.ServiceDefaults", "AntSK.ServiceDefaults\AntSK.ServiceDefaults.csproj", "{21AC6184-336E-475F-8975-80A39D59B0CC}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -54,12 +68,32 @@ Global
|
||||
{664DFA1F-68B7-49C7-B889-FA14D1756D3D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{664DFA1F-68B7-49C7-B889-FA14D1756D3D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{664DFA1F-68B7-49C7-B889-FA14D1756D3D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6195F7AA-18C2-4372-85CA-11FC4B522686}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6195F7AA-18C2-4372-85CA-11FC4B522686}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6195F7AA-18C2-4372-85CA-11FC4B522686}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6195F7AA-18C2-4372-85CA-11FC4B522686}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3EEC5A22-2C4D-4D6F-9039-C4AF3FEA3418}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3EEC5A22-2C4D-4D6F-9039-C4AF3FEA3418}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3EEC5A22-2C4D-4D6F-9039-C4AF3FEA3418}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3EEC5A22-2C4D-4D6F-9039-C4AF3FEA3418}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{21AC6184-336E-475F-8975-80A39D59B0CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{21AC6184-336E-475F-8975-80A39D59B0CC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{21AC6184-336E-475F-8975-80A39D59B0CC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{21AC6184-336E-475F-8975-80A39D59B0CC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{9AA5A735-8FB1-4CC5-AB3E-D02B3A3B6682} = {F341BA6B-E329-42F7-8005-1E366C8A7B1F}
|
||||
{64F17C9A-97C2-46FA-9345-86C5289288AD} = {F341BA6B-E329-42F7-8005-1E366C8A7B1F}
|
||||
{DF87E829-99C5-44A7-9718-B3E67DC801F6} = {40DDB1DC-571B-4A95-9F34-47F52981C511}
|
||||
{19529BFA-152F-4A8C-8254-F2D4896AB739} = {F341BA6B-E329-42F7-8005-1E366C8A7B1F}
|
||||
{6AD71410-127F-4C83-95A8-F699C39B44FF} = {F341BA6B-E329-42F7-8005-1E366C8A7B1F}
|
||||
{664DFA1F-68B7-49C7-B889-FA14D1756D3D} = {F341BA6B-E329-42F7-8005-1E366C8A7B1F}
|
||||
{6195F7AA-18C2-4372-85CA-11FC4B522686} = {F341BA6B-E329-42F7-8005-1E366C8A7B1F}
|
||||
{3EEC5A22-2C4D-4D6F-9039-C4AF3FEA3418} = {8578F0F2-5DE5-45EF-AE54-C37A07B62248}
|
||||
{21AC6184-336E-475F-8975-80A39D59B0CC} = {8578F0F2-5DE5-45EF-AE54-C37A07B62248}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {2076B7C9-2E5B-4580-9712-03F0D56BC1AF}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<DocumentationFile>AntSK.xml</DocumentationFile>
|
||||
<NoWarn>CA1050,CA1707,CA2007,VSTHRD111,CS1591,RCS1110,CA5394,SKEXP0001,SKEXP0002,SKEXP0003,SKEXP0004,SKEXP0010,SKEXP0011,,SKEXP0012,SKEXP0020,SKEXP0021,SKEXP0022,SKEXP0023,SKEXP0024,SKEXP0025,SKEXP0026,SKEXP0027,SKEXP0028,SKEXP0029,SKEXP0030,SKEXP0031,SKEXP0032,SKEXP0040,SKEXP0041,SKEXP0042,SKEXP0050,SKEXP0051,SKEXP0052,SKEXP0053,SKEXP0054,SKEXP0055,SKEXP0060,SKEXP0061,SKEXP0101,SKEXP0102</NoWarn>
|
||||
<ApplicationIcon>AntSKlogo.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -14,26 +15,26 @@
|
||||
<EmbeddedResource Remove="llamafactory\**" />
|
||||
<None Remove="llamafactory\**" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="AntSKlogo.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authorization" Version="8.0.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="8.0.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="8.0.2" />
|
||||
<PackageReference Include="System.Net.Http.Json" Version="8.0.0" />
|
||||
<PackageReference Include="Downloader" Version="3.0.6" />
|
||||
<PackageReference Include="Downloader" Version="3.0.6" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\AntSK.Domain\AntSK.Domain.csproj" />
|
||||
<ProjectReference Include="..\AntSK.ServiceDefaults\AntSK.ServiceDefaults.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="plugins\KMSPlugin\Ask1\skprompt.txt">
|
||||
<None Update="plugins\**">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="plugins\KMSPlugin\Ask\skprompt.txt">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
BIN
src/AntSK/AntSKlogo.ico
Normal file
BIN
src/AntSK/AntSKlogo.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
@@ -23,7 +23,7 @@ namespace AntSK.Controllers
|
||||
}
|
||||
|
||||
// 创建文件存储的路径
|
||||
var uploadsFolderPath = Path.Combine(Path.Combine(Directory.GetCurrentDirectory(), LLamaSharpOption.FileDirectory), "files");// 给定的文件夹名称
|
||||
var uploadsFolderPath = Path.Combine(Path.Combine(Directory.GetCurrentDirectory(), FileDirOption.DirectoryPath), "files");// 给定的文件夹名称
|
||||
|
||||
// 如果路径不存在,则创建一个新的目录
|
||||
if (!Directory.Exists(uploadsFolderPath))
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
using AntSK.Domain.Repositories;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace AntSK.Controllers
|
||||
{
|
||||
[Route("api/[controller]/[action]")]
|
||||
[ApiController]
|
||||
public class InitController : ControllerBase
|
||||
{
|
||||
private readonly IApps_Repositories _repository;
|
||||
|
||||
public InitController(IApps_Repositories repository)
|
||||
{
|
||||
_repository = repository;
|
||||
}
|
||||
/// <summary>
|
||||
/// 初始化DB 和表
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public IActionResult InitTable()
|
||||
{
|
||||
_repository.GetDB().DbMaintenance.CreateDatabase();
|
||||
_repository.GetDB().CodeFirst.InitTables(typeof(Apps));
|
||||
_repository.GetDB().CodeFirst.InitTables(typeof(Kmss));
|
||||
_repository.GetDB().CodeFirst.InitTables(typeof(KmsDetails));
|
||||
_repository.GetDB().CodeFirst.InitTables(typeof(Users));
|
||||
_repository.GetDB().CodeFirst.InitTables(typeof(Apis));
|
||||
_repository.GetDB().CodeFirst.InitTables(typeof(AIModels));
|
||||
//创建vector插件如果数据库没有则需要提供支持向量的数据库
|
||||
_repository.GetDB().Ado.ExecuteCommandAsync($"CREATE EXTENSION IF NOT EXISTS vector;");
|
||||
return Ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,17 @@
|
||||
using AntSK.BackgroundTask;
|
||||
using AntDesign;
|
||||
using AntSK.BackgroundTask;
|
||||
using AntSK.Domain.Common.Map;
|
||||
using AntSK.Domain.Domain.Interface;
|
||||
using AntSK.Domain.Domain.Model;
|
||||
using AntSK.Domain.Domain.Model.Enum;
|
||||
using AntSK.Domain.Domain.Service;
|
||||
using AntSK.Domain.Repositories;
|
||||
using AntSK.Domain.Utils;
|
||||
using Microsoft.AspNetCore.Components.Forms;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace AntSK.Controllers
|
||||
{
|
||||
@@ -17,14 +24,17 @@ namespace AntSK.Controllers
|
||||
{
|
||||
private readonly IKmsDetails_Repositories _kmsDetailsRepositories;
|
||||
private readonly BackgroundTaskBroker<ImportKMSTaskReq> _taskBroker;
|
||||
private readonly IKernelService _kernelService;
|
||||
|
||||
public KMSController(
|
||||
IKmsDetails_Repositories kmsDetailsRepositories,
|
||||
BackgroundTaskBroker<ImportKMSTaskReq> taskBroker
|
||||
BackgroundTaskBroker<ImportKMSTaskReq> taskBroker,
|
||||
IKernelService kernelService
|
||||
)
|
||||
{
|
||||
_kmsDetailsRepositories = kmsDetailsRepositories;
|
||||
_taskBroker = taskBroker;
|
||||
_kernelService = kernelService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -47,8 +57,34 @@ namespace AntSK.Controllers
|
||||
|
||||
await _kmsDetailsRepositories.InsertAsync(detail);
|
||||
req.KmsDetail = detail;
|
||||
req.IsQA=model.IsQA;
|
||||
_taskBroker.QueueWorkItem(req);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> QA(QAModel model)
|
||||
{
|
||||
var kernel = _kernelService.GetKernelByAIModelID(model.ChatModelId);
|
||||
var lines = TextChunker.SplitPlainTextLines(model.Context, 299);
|
||||
var paragraphs = TextChunker.SplitPlainTextParagraphs(lines, 4000);
|
||||
KernelFunction jsonFun = kernel.Plugins.GetFunction("KMSPlugin", "QA");
|
||||
|
||||
List<string> qaList = new List<string>();
|
||||
foreach (var para in paragraphs)
|
||||
{
|
||||
var qaresult = await kernel.InvokeAsync(function: jsonFun, new KernelArguments() { ["input"] = para });
|
||||
var qaListStr = qaresult.GetValue<string>().ConvertToString();
|
||||
|
||||
string pattern = @"Q\d+:.*?A\d+:.*?(?=(Q\d+:|$))";
|
||||
RegexOptions options = RegexOptions.Singleline;
|
||||
|
||||
foreach (Match match in Regex.Matches(qaListStr, pattern, options))
|
||||
{
|
||||
qaList.Add(match.Value.Trim()); // Trim用于删除可能的首尾空格
|
||||
}
|
||||
}
|
||||
return Ok(qaList);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
@inject INotificationService _notice
|
||||
@inherits LayoutComponentBase
|
||||
|
||||
<AntDesign.ProLayout.BasicLayout Logo="@("https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg")"
|
||||
<AntDesign.ProLayout.BasicLayout Logo="@("/assets/logo.svg")"
|
||||
MenuData="_menuData">
|
||||
<RightContentRender>
|
||||
<AntSK.Components.RightContent />
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
<Button Type="@ButtonType.Link" OnClick="NavigateModelList">去创建</Button>
|
||||
</FormItem>
|
||||
<FormItem Label="提示词" LabelCol="LayoutModel._formItemLayout.LabelCol" WrapperCol="LayoutModel._formItemLayout.WrapperCol">
|
||||
<TextArea MinRows="4" Placeholder="请输入提示词,用户输入使用{{$input}} 来做占位符" @bind-Value="@context.Prompt" />
|
||||
<TextArea MinRows="4" Placeholder="请输入角色信息" @bind-Value="@context.Prompt" />
|
||||
</FormItem>
|
||||
<FormItem Label="温度系数" LabelCol="LayoutModel._formItemLayout.LabelCol" WrapperCol="LayoutModel._formItemLayout.WrapperCol">
|
||||
<span>更确定</span>
|
||||
@@ -61,6 +61,7 @@
|
||||
<span>更发散</span>
|
||||
</FormItem>
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
<FormItem Label="图片模型" LabelCol="LayoutModel._formItemLayout.LabelCol" WrapperCol="LayoutModel._formItemLayout.WrapperCol">
|
||||
@@ -124,6 +125,17 @@
|
||||
</Select>
|
||||
<Button Type="@ButtonType.Link" OnClick="NavigateKmsList">去创建</Button>
|
||||
</FormItem>
|
||||
<FormItem Label="Rerank重排模型" LabelCol="LayoutModel._formItemLayout.LabelCol" WrapperCol="LayoutModel._formItemLayout.WrapperCol">
|
||||
<Select DataSource="@_rerankList"
|
||||
@bind-Value="@context.RerankModelID"
|
||||
ValueProperty="c=>c.Id"
|
||||
LabelProperty="c=>'【'+c.AIType.ToString()+'】'+c.ModelDescription">
|
||||
</Select>
|
||||
<Button Type="@ButtonType.Link" OnClick="NavigateModelList">去创建</Button>
|
||||
</FormItem>
|
||||
<FormItem Label="Rerank数" LabelCol="LayoutModel._formItemLayout.LabelCol" WrapperCol="LayoutModel._formItemLayout.WrapperCol">
|
||||
<AntDesign.InputNumber @bind-Value="context.RerankCount" PlaceHolder="Rerank数"></AntDesign.InputNumber>
|
||||
</FormItem>
|
||||
<FormItem Label="提问最大token数" LabelCol="LayoutModel._formItemLayout.LabelCol" WrapperCol="LayoutModel._formItemLayout.WrapperCol">
|
||||
<AntDesign.InputNumber @bind-Value="context.MaxAskPromptSize" PlaceHolder="提问最大token数"></AntDesign.InputNumber>
|
||||
</FormItem>
|
||||
|
||||
@@ -47,6 +47,7 @@ namespace AntSK.Pages.AppPage
|
||||
|
||||
private List<AIModels> _chatList;
|
||||
private List<AIModels> _embedingList;
|
||||
private List<AIModels> _rerankList;
|
||||
private List<AIModels> _imageList;
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
@@ -56,6 +57,7 @@ namespace AntSK.Pages.AppPage
|
||||
var models=_aimodels_Repositories.GetList();
|
||||
_chatList = models.Where(p => p.AIModelType == AIModelType.Chat).ToList();
|
||||
_embedingList = models.Where(p => p.AIModelType == AIModelType.Embedding).ToList();
|
||||
_rerankList = models.Where(p => p.AIModelType == AIModelType.Rerank).ToList();
|
||||
_imageList = models.Where(p => p.AIModelType == AIModelType.Image).ToList();
|
||||
|
||||
_functionService.SearchMarkedMethods();
|
||||
@@ -141,7 +143,7 @@ namespace AntSK.Pages.AppPage
|
||||
|
||||
private void NavigateModelList()
|
||||
{
|
||||
NavigationManager.NavigateTo("/setting/modellist");
|
||||
NavigationManager.NavigateTo("/modelmanager/modellist");
|
||||
}
|
||||
|
||||
private void NavigateKmsList()
|
||||
|
||||
@@ -22,7 +22,13 @@
|
||||
</Button>
|
||||
</FormItem>
|
||||
<FormItem Label="使用方法" LabelCol="_formItemLayout.LabelCol" WrapperCol="_formItemLayout.WrapperCol">
|
||||
<TextArea @bind-Value="@_desc" ReadOnly="true" Rows="15" />
|
||||
<h3>为了方便其他应用对接,接口符合openai规范,省略了温度TopP等参数。</h3>
|
||||
<h3>BaseUrl:</h3>
|
||||
<p>@_openApiUrl</p>
|
||||
<h3>Headers::</h3>
|
||||
<p>Authorization : Bearer @_appModel.SecretKey</p>
|
||||
<h3>Body: </h3>
|
||||
<TextArea @bind-Value="@_desc" ReadOnly="true" Rows="10" />
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Card>
|
||||
|
||||
@@ -58,13 +58,7 @@ namespace AntSK.Pages.AppPage
|
||||
|
||||
private void GetDesc()
|
||||
{
|
||||
_desc = @$"为了方便其他应用对接,接口符合openai规范,省略了温度TopP等参数。
|
||||
BaseUrl:
|
||||
{_openApiUrl}
|
||||
headers:
|
||||
Authorization:Bearer {_appModel.SecretKey}
|
||||
Body:
|
||||
{JsonConvert.SerializeObject(new OpenAIModel() { messages = new List<OpenAIMessage>() { new OpenAIMessage() { role = "user", content = "你好,你是谁" } } }, Formatting.Indented)}";
|
||||
_desc = JsonConvert.SerializeObject(new OpenAIModel() { messages = new List<OpenAIMessage>() { new OpenAIMessage() { role = "user", content = "你好,你是谁" } } }, Formatting.Indented);
|
||||
}
|
||||
|
||||
private void GetScript()
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
@inherits AuthComponentBase
|
||||
|
||||
<GridRow Gutter="(16, 16)">
|
||||
<GridCol Span="12">
|
||||
<GridCol Span="14">
|
||||
<Card Style="height:75vh;overflow: auto;">
|
||||
<TitleTemplate>
|
||||
<Icon Type="setting" /> 选择应用
|
||||
@@ -25,12 +25,14 @@
|
||||
<Body>
|
||||
@if (!string.IsNullOrEmpty(AppId))
|
||||
{
|
||||
<ChatView AppId="@AppId" ShowTitle=false OnRelevantSources="OnRelevantSources"></ChatView>
|
||||
<Watermark Content="AntSK">
|
||||
<ChatView AppId="@AppId" ShowTitle=false OnRelevantSources="OnRelevantSources"></ChatView>
|
||||
</Watermark>
|
||||
}
|
||||
</Body>
|
||||
</Card>
|
||||
</GridCol>
|
||||
<GridCol Span="12">
|
||||
<GridCol Span="10">
|
||||
<Card Style="height: 75vh;overflow: auto;">
|
||||
<TitleTemplate>
|
||||
<Icon Type="search" /> 调试结果
|
||||
@@ -41,7 +43,14 @@
|
||||
<Body>
|
||||
<AntList Bordered DataSource="@_relevantSources" Style="padding:10px;">
|
||||
<ChildContent Context="item">
|
||||
<span> <b>@item.SourceName </b> 相似度:<Text Mark> @item.Relevance</Text></span>
|
||||
<span> <b>@item.SourceName </b> </span>
|
||||
<br />
|
||||
<span>相似度:<Text Mark> @item.Relevance</Text></span>
|
||||
@if (@item.RerankScore != 0)
|
||||
{
|
||||
<br />
|
||||
<span> Rerank相关性:<Text Mark> @item.RerankScore</Text></span>
|
||||
}
|
||||
<Body>
|
||||
@((MarkupString)(@item.Text))
|
||||
</Body>
|
||||
@@ -59,12 +68,10 @@
|
||||
flex-direction: column;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
@layout OpenLayout
|
||||
@inherits AntDomComponentBase
|
||||
|
||||
|
||||
<div id="chat">
|
||||
@if (ShowTitle)
|
||||
{
|
||||
@@ -64,7 +65,7 @@
|
||||
<Flex Justify="end">
|
||||
|
||||
<AntDesign.Input @bind-Value="@(_messageInput)" DebounceMilliseconds="@(-1)" Placeholder="输入消息回车发送" OnPressEnter="@(async () => await OnSendAsync())" Disabled="@Sendding"></AntDesign.Input>
|
||||
@if (app.EmbeddingModelID!=null)
|
||||
@if (app.EmbeddingModelID != null)
|
||||
{
|
||||
<Upload Action="@("api/File/UploadFile")"
|
||||
Name="file"
|
||||
|
||||
@@ -6,14 +6,19 @@ using AntSK.Domain.Domain.Model.Enum;
|
||||
using AntSK.Domain.Repositories;
|
||||
using AntSK.Domain.Utils;
|
||||
using AntSK.LLM.StableDiffusion;
|
||||
using AntSK.Models;
|
||||
using AntSK.Pages.KmsPage;
|
||||
using Blazored.LocalStorage;
|
||||
using DocumentFormat.OpenXml.InkML;
|
||||
using Markdig;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage;
|
||||
using Microsoft.JSInterop;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.ChatCompletion;
|
||||
using Microsoft.SemanticKernel.Connectors.OpenAI;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AntSK.Pages.ChatPage.Components
|
||||
{
|
||||
@@ -36,8 +41,12 @@ namespace AntSK.Pages.ChatPage.Components
|
||||
[Inject] IChatService _chatService { get; set; }
|
||||
[Inject] IJSRuntime _JSRuntime { get; set; }
|
||||
[Inject] ILocalStorageService _localStorage { get; set; }
|
||||
[Inject] IChats_Repositories _chats_Repositories { get; set; }
|
||||
[Inject] ProtectedSessionStorage _protectedSessionStore { get; set; }
|
||||
|
||||
protected List<MessageInfo> MessageList = [];
|
||||
[Inject] protected ILogger<ChatView> _logger { get; set; }
|
||||
|
||||
protected List<Chats> MessageList = [];
|
||||
protected string? _messageInput;
|
||||
protected string _json = "";
|
||||
protected bool Sendding = false;
|
||||
@@ -48,25 +57,87 @@ namespace AntSK.Pages.ChatPage.Components
|
||||
|
||||
private List<RelevantSource> _relevantSources = new List<RelevantSource>();
|
||||
|
||||
private string _userName { get; set; }
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
await LoadData();
|
||||
var msgs = await _localStorage.GetItemAsync<List<MessageInfo>>("msgs");
|
||||
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
await LoadData();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化加载数据
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private async Task LoadData()
|
||||
{
|
||||
app = _apps_Repositories.GetFirst(p => p.Id == AppId);
|
||||
var userSessionStorageResult = await _protectedSessionStore.GetAsync<UserSession>("UserSession");
|
||||
var userSession = userSessionStorageResult.Success ? userSessionStorageResult.Value : null;
|
||||
_userName = userSession?.UserName;
|
||||
await GetMsgList();
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取聊天记录列表
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private async Task GetMsgList()
|
||||
{
|
||||
List<Chats> msgs = new List<Chats>();
|
||||
if (string.IsNullOrEmpty(_userName))
|
||||
{
|
||||
//匿名访问使用localstore
|
||||
msgs = await _localStorage.GetItemAsync<List<Chats>>($"msgs:{AppId}");
|
||||
}
|
||||
else
|
||||
{
|
||||
msgs = await _chats_Repositories.GetListAsync(p => p.AppId == AppId && p.UserName == _userName);
|
||||
}
|
||||
if (msgs != null && msgs.Count > 0)
|
||||
{
|
||||
MessageList = msgs;
|
||||
}
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
/// <summary>
|
||||
/// 清空聊天记录列表
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private async Task ClearMsgList()
|
||||
{
|
||||
await LoadData();
|
||||
MessageList.Clear();
|
||||
if (string.IsNullOrEmpty(_userName))
|
||||
{
|
||||
await _localStorage.SetItemAsync<List<Chats>>($"msgs:{AppId}", MessageList);
|
||||
}
|
||||
else
|
||||
{
|
||||
await _chats_Repositories.DeleteAsync(p => p.AppId == AppId && p.UserName == _userName);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task LoadData()
|
||||
/// <summary>
|
||||
/// 保存聊天记录
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private async Task SaveMsg(List<Chats> MessageList)
|
||||
{
|
||||
app =await _apps_Repositories.GetFirstAsync(p => p.Id == AppId);
|
||||
if (string.IsNullOrEmpty(_userName))
|
||||
{
|
||||
await _localStorage.SetItemAsync<List<Chats>>($"msgs:{AppId}", MessageList);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (MessageList.Count() > 0)
|
||||
{
|
||||
await _chats_Repositories.InsertAsync(MessageList.LastOrDefault());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected async Task OnClearAsync()
|
||||
@@ -78,11 +149,11 @@ namespace AntSK.Pages.ChatPage.Components
|
||||
var result = await _confirmService.Show(content, title, ConfirmButtons.YesNo);
|
||||
if (result == ConfirmResult.Yes)
|
||||
{
|
||||
MessageList.Clear();
|
||||
await _localStorage.SetItemAsync<List<MessageInfo>>("msgs", MessageList);
|
||||
|
||||
await ClearMsgList();
|
||||
await InvokeAsync(StateHasChanged);
|
||||
_ = Message.Info("清理成功");
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -102,28 +173,45 @@ namespace AntSK.Pages.ChatPage.Components
|
||||
var filePath = fileList.FirstOrDefault()?.Url;
|
||||
var fileName = fileList.FirstOrDefault()?.FileName;
|
||||
|
||||
MessageList.Add(new MessageInfo()
|
||||
var chat = new Chats()
|
||||
{
|
||||
ID = Guid.NewGuid().ToString(),
|
||||
Id = Guid.NewGuid().ToString(),
|
||||
UserName = _userName,
|
||||
AppId = AppId,
|
||||
Context = _messageInput,
|
||||
CreateTime = DateTime.Now,
|
||||
IsSend = true
|
||||
});
|
||||
|
||||
};
|
||||
MessageList.Add(chat);
|
||||
if (!string.IsNullOrEmpty(_userName))
|
||||
{
|
||||
await _chats_Repositories.InsertAsync(chat);
|
||||
}
|
||||
|
||||
Sendding = true;
|
||||
await SendAsync(_messageInput,filePath);
|
||||
_messageInput = "";
|
||||
Sendding = false;
|
||||
Task.Run(async () =>
|
||||
{
|
||||
await SendAsync(_messageInput, filePath);
|
||||
}).ContinueWith(task => {
|
||||
|
||||
_messageInput = "";
|
||||
Sendding = false;
|
||||
InvokeAsync(StateHasChanged);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Sendding = false;
|
||||
Console.WriteLine("异常:" + ex.Message);
|
||||
_logger.LogError("异常:" + ex.Message);
|
||||
_ = Message.Error("异常:" + ex.Message, 2);
|
||||
}
|
||||
|
||||
}
|
||||
protected async Task OnCopyAsync(MessageInfo item)
|
||||
|
||||
|
||||
protected async Task OnCopyAsync(Chats item)
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
@@ -135,48 +223,74 @@ namespace AntSK.Pages.ChatPage.Components
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
MessageList = MessageList.Where(w => w.ID != id).ToList();
|
||||
MessageList = MessageList.Where(w => w.Id != id).ToList();
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 开始发送消息
|
||||
/// </summary>
|
||||
/// <param name="questions"></param>
|
||||
/// <param name="filePath"></param>
|
||||
/// <returns></returns>
|
||||
protected async Task<bool> SendAsync(string questions, string? filePath)
|
||||
{
|
||||
ChatHistory history = new ChatHistory();
|
||||
|
||||
//处理多轮会话
|
||||
Apps app = _apps_Repositories.GetFirst(p => p.Id == AppId);
|
||||
if (MessageList.Count > 0)
|
||||
{
|
||||
history = await _chatService.GetChatHistory(MessageList);
|
||||
}
|
||||
ChatHistory history = new ChatHistory();
|
||||
|
||||
if (app.Type == AppType.chat.ToString() && (filePath == null || app.EmbeddingModelID.IsNull()))
|
||||
{
|
||||
await SendChat(questions, history, app);
|
||||
if (!string.IsNullOrEmpty(app.Prompt))
|
||||
{
|
||||
history = new ChatHistory(app.Prompt.ConvertToString());
|
||||
}
|
||||
//聊天应用增加系统角色
|
||||
if (MessageList.Count > 0)
|
||||
{
|
||||
history = await _chatService.GetChatHistory(MessageList, history);
|
||||
}
|
||||
await SendChat(history, app);
|
||||
}
|
||||
else if (app.Type == AppType.kms.ToString() || filePath != null || app.EmbeddingModelID.IsNotNull())
|
||||
{
|
||||
if (MessageList.Count > 0)
|
||||
{
|
||||
history = await _chatService.GetChatHistory(MessageList, history);
|
||||
}
|
||||
await SendKms(questions, history, app, filePath);
|
||||
|
||||
|
||||
}
|
||||
else if (app.Type == AppType.img.ToString())
|
||||
{
|
||||
await SendImg(questions,app);
|
||||
await SendImg(questions, app);
|
||||
}
|
||||
|
||||
//缓存消息记录
|
||||
if (app.Type != AppType.img.ToString())
|
||||
{
|
||||
await _localStorage.SetItemAsync<List<MessageInfo>>("msgs", MessageList);
|
||||
await SaveMsg(MessageList);
|
||||
if (OnRelevantSources.IsNotNull())
|
||||
{
|
||||
await OnRelevantSources.InvokeAsync(_relevantSources);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return await Task.FromResult(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送图片对话
|
||||
/// </summary>
|
||||
/// <param name="questions"></param>
|
||||
/// <param name="app"></param>
|
||||
/// <returns></returns>
|
||||
private async Task SendImg(string questions,Apps app)
|
||||
{
|
||||
MessageInfo info = new MessageInfo();
|
||||
info.ID = Guid.NewGuid().ToString();
|
||||
Chats info = new Chats();
|
||||
info.Id = Guid.NewGuid().ToString();
|
||||
info.UserName=_userName;
|
||||
info.AppId=AppId;
|
||||
info.CreateTime = DateTime.Now;
|
||||
var base64= await _chatService.SendImgByAppAsync(app, questions);
|
||||
if (string.IsNullOrEmpty(base64))
|
||||
@@ -199,27 +313,23 @@ namespace AntSK.Pages.ChatPage.Components
|
||||
/// <returns></returns>
|
||||
private async Task SendKms(string questions, ChatHistory history, Apps app, string? filePath)
|
||||
{
|
||||
MessageInfo info = null;
|
||||
Chats info = new Chats()
|
||||
{
|
||||
Id = Guid.NewGuid().ToString(),
|
||||
AppId = AppId,
|
||||
UserName = _userName,
|
||||
CreateTime = DateTime.Now,
|
||||
Context=""
|
||||
};
|
||||
MessageList.Add(info);
|
||||
var chatResult = _chatService.SendKmsByAppAsync(app, questions, history, filePath, _relevantSources);
|
||||
await foreach (var content in chatResult)
|
||||
{
|
||||
if (info == null)
|
||||
{
|
||||
info = new MessageInfo();
|
||||
info.ID = Guid.NewGuid().ToString();
|
||||
info.Context = content.ConvertToString();
|
||||
info.CreateTime = DateTime.Now;
|
||||
|
||||
MessageList.Add(info);
|
||||
}
|
||||
else
|
||||
{
|
||||
info.Context += content.ConvertToString();
|
||||
await Task.Delay(50);
|
||||
}
|
||||
info.Context += content.ConvertToString();
|
||||
await Task.Delay(50);
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
await OnRelevantSources.InvokeAsync(_relevantSources);
|
||||
//全部处理完后再处理一次Markdown
|
||||
await MarkDown(info);
|
||||
}
|
||||
@@ -227,20 +337,21 @@ namespace AntSK.Pages.ChatPage.Components
|
||||
/// <summary>
|
||||
/// 发送普通对话
|
||||
/// </summary>
|
||||
/// <param name="questions"></param>
|
||||
/// <param name="history"></param>
|
||||
/// <param name="app"></param>
|
||||
/// <returns></returns>
|
||||
private async Task SendChat(string questions, ChatHistory history, Apps app)
|
||||
private async Task SendChat(ChatHistory history, Apps app)
|
||||
{
|
||||
MessageInfo info = null;
|
||||
var chatResult = _chatService.SendChatByAppAsync(app, questions, history);
|
||||
Chats info = null;
|
||||
var chatResult = _chatService.SendChatByAppAsync(app, history);
|
||||
await foreach (var content in chatResult)
|
||||
{
|
||||
if (info == null)
|
||||
{
|
||||
info = new MessageInfo();
|
||||
info.ID = Guid.NewGuid().ToString();
|
||||
info = new Chats();
|
||||
info.Id = Guid.NewGuid().ToString();
|
||||
info.UserName = _userName;
|
||||
info.AppId = AppId;
|
||||
info.Context = content.ConvertToString();
|
||||
info.CreateTime = DateTime.Now;
|
||||
|
||||
@@ -257,7 +368,12 @@ namespace AntSK.Pages.ChatPage.Components
|
||||
await MarkDown(info);
|
||||
}
|
||||
|
||||
private async Task MarkDown(MessageInfo info)
|
||||
/// <summary>
|
||||
/// 处理markdown
|
||||
/// </summary>
|
||||
/// <param name="info"></param>
|
||||
/// <returns></returns>
|
||||
private async Task MarkDown(Chats info)
|
||||
{
|
||||
if (info.IsNotNull())
|
||||
{
|
||||
@@ -270,6 +386,10 @@ namespace AntSK.Pages.ChatPage.Components
|
||||
await _JSRuntime.ScrollToBottomAsync("scrollDiv");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 上传文件事件
|
||||
/// </summary>
|
||||
/// <param name="fileInfo"></param>
|
||||
private void OnSingleCompleted(UploadInfo fileInfo)
|
||||
{
|
||||
fileList.Add(new()
|
||||
@@ -281,6 +401,11 @@ namespace AntSK.Pages.ChatPage.Components
|
||||
});
|
||||
_kMService.OnSingleCompleted(fileInfo);
|
||||
}
|
||||
/// <summary>
|
||||
/// 移除文件事件
|
||||
/// </summary>
|
||||
/// <param name="file"></param>
|
||||
/// <returns></returns>
|
||||
private async Task<bool> HandleFileRemove(UploadFileItem file)
|
||||
{
|
||||
fileList.RemoveAll(x => x.FileName == file.FileName);
|
||||
|
||||
@@ -6,14 +6,16 @@
|
||||
@page "/OpenChat/{AppId}"
|
||||
@layout OpenLayout
|
||||
|
||||
|
||||
<ChatView AppId="@AppId" ShowTitle=true>
|
||||
|
||||
</ChatView>
|
||||
|
||||
|
||||
<style>
|
||||
#chat{
|
||||
height:100% ;
|
||||
display:flex;
|
||||
#chat {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow-x: hidden;
|
||||
font-family: Arial, sans-serif;
|
||||
@@ -21,7 +23,7 @@
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
@code{
|
||||
@code {
|
||||
[Parameter]
|
||||
public string AppId { get; set; }
|
||||
}
|
||||
@@ -70,7 +70,7 @@ namespace AntSK.Pages
|
||||
|
||||
private void NavToAIModel()
|
||||
{
|
||||
NavigationManager.NavigateTo("/setting/modellist");
|
||||
NavigationManager.NavigateTo("/modelmanager/modellist");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,9 @@
|
||||
<FormItem Label="重叠部分(token)" LabelCol="LayoutModel._formItemLayout.LabelCol" WrapperCol="LayoutModel._formItemLayout.WrapperCol">
|
||||
<AntDesign.InputNumber @bind-Value="context.OverlappingTokens" PlaceHolder="重叠部分"></AntDesign.InputNumber>
|
||||
</FormItem>
|
||||
<FormItem Label="是否开启OCR" LabelCol="LayoutModel._formItemLayout.LabelCol" WrapperCol="LayoutModel._formItemLayout.WrapperCol">
|
||||
<Switch @bind-Value="@isOcr" />
|
||||
</FormItem>
|
||||
|
||||
<FormItem Label=" " Style="margin-top:32px" WrapperCol="LayoutModel._submitFormLayout.WrapperCol">
|
||||
<Button Type="primary" HtmlType="submit">
|
||||
|
||||
@@ -25,6 +25,8 @@ namespace AntSK.Pages.KmsPage
|
||||
|
||||
private List<AIModels> _chatList { get; set; }
|
||||
private List<AIModels> _embeddingList { get; set; }
|
||||
|
||||
private bool isOcr { get; set; }
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
@@ -36,6 +38,7 @@ namespace AntSK.Pages.KmsPage
|
||||
{
|
||||
//查看
|
||||
_kmsModel = await _kmss_Repositories.GetFirstAsync(p => p.Id == KmsId);
|
||||
isOcr = _kmsModel.IsOCR == 1;
|
||||
}
|
||||
}
|
||||
private void HandleSubmit()
|
||||
@@ -51,6 +54,10 @@ namespace AntSK.Pages.KmsPage
|
||||
_ = Message.Error("行切片需小于段落切片!", 2);
|
||||
return;
|
||||
}
|
||||
if (isOcr)
|
||||
{
|
||||
_kmsModel.IsOCR = 1;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(KmsId))
|
||||
{
|
||||
@@ -73,7 +80,7 @@ namespace AntSK.Pages.KmsPage
|
||||
|
||||
private void NavigateModelList()
|
||||
{
|
||||
NavigationManager.NavigateTo("/setting/modellist");
|
||||
NavigationManager.NavigateTo("/modelmanager/modellist");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,7 @@
|
||||
<ChildContent>
|
||||
<div class="standardList">
|
||||
<Card Class="listCard"
|
||||
Title="知识库文档"
|
||||
>
|
||||
Title="知识库文档">
|
||||
|
||||
<Extra>
|
||||
<Button Type="@ButtonType.Primary" Style="position: absolute; right:360px; margin-bottom: 8px;" OnClick="Refresh">刷新 </Button>
|
||||
@@ -106,7 +105,7 @@
|
||||
<TabPane Key="2">
|
||||
<TabTemplate>搜索测试</TabTemplate>
|
||||
<ChildContent>
|
||||
<KmsTest KmsId="@KmsId"></KmsTest>
|
||||
<KmsTest KmsId="@KmsId"></KmsTest>
|
||||
</ChildContent>
|
||||
</TabPane>
|
||||
</Tabs>
|
||||
@@ -125,6 +124,12 @@
|
||||
<FormItem Label="URL地址">
|
||||
<Input @bind-Value="@context.Url" />
|
||||
</FormItem>
|
||||
<FormItem Label="切分方式">
|
||||
<RadioGroup @bind-Value="@_isQa">
|
||||
<Radio Value="false">直接切分</Radio>
|
||||
<Radio Value="true">QA切分</Radio>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Modal>
|
||||
|
||||
@@ -136,10 +141,16 @@
|
||||
<Form Model="@textModel"
|
||||
LabelColSpan="8"
|
||||
WrapperColSpan="16"
|
||||
@ref="@_textForm">
|
||||
@ref="@_textForm">
|
||||
<FormItem Label="文本内容">
|
||||
<TextArea @bind-Value="@context.Text" Rows="5" />
|
||||
</FormItem>
|
||||
<FormItem Label="切分方式">
|
||||
<RadioGroup @bind-Value="@_isQa">
|
||||
<Radio Value="false">直接切分</Radio>
|
||||
<Radio Value="true">QA切分</Radio>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Modal>
|
||||
|
||||
@@ -147,7 +158,7 @@
|
||||
Visible="@_fileVisible"
|
||||
OnOk="@FileHandleOk"
|
||||
OnCancel="@FileHandleCancel"
|
||||
ConfirmLoading="@_fileConfirmLoading">
|
||||
ConfirmLoading="@_fileConfirmLoading">
|
||||
<Upload Action="@("api/File/UploadFile")"
|
||||
Name="file"
|
||||
Drag
|
||||
@@ -159,10 +170,24 @@
|
||||
<Icon Type="inbox" />
|
||||
</p>
|
||||
<p class="ant-upload-text">单击或拖动文件到此区域进行上传</p>
|
||||
<p class="ant-upload-hint">
|
||||
支持txt、word、pdf、md、excel、ppt等文件。
|
||||
</p>
|
||||
@if (km.IsOCR == 1)
|
||||
{
|
||||
<p class="ant-upload-hint">
|
||||
支持 txt、word、pdf、md、excel、ppt、jpeg、png、tiff 等文件。
|
||||
</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<p class="ant-upload-hint">
|
||||
支持 txt、word、pdf、md、excel、ppt 等文件。
|
||||
</p>
|
||||
}
|
||||
|
||||
</Upload>
|
||||
<RadioGroup @bind-Value="@_isQa" Style="margin-top:5px;">
|
||||
<Radio Value="false">直接切分</Radio>
|
||||
<Radio Value="true">QA切分</Radio>
|
||||
</RadioGroup>
|
||||
</Modal>
|
||||
|
||||
<Modal Title="Excel导入"
|
||||
|
||||
@@ -19,6 +19,33 @@ namespace AntSK.Pages.KmsPage
|
||||
[Parameter]
|
||||
public string KmsId { get; set; }
|
||||
|
||||
[Inject]
|
||||
protected IConfirmService _confirmService { get; set; }
|
||||
|
||||
[Inject]
|
||||
protected IKmsDetails_Repositories _kmsDetails_Repositories { get; set; }
|
||||
|
||||
[Inject]
|
||||
protected IKmss_Repositories _kmss_Repositories { get; set; }
|
||||
|
||||
private MemoryServerless _memory { get; set; }
|
||||
|
||||
[Inject]
|
||||
protected IKMService iKMService { get; set; }
|
||||
|
||||
[Inject]
|
||||
protected MessageService? _message { get; set; }
|
||||
|
||||
[Inject]
|
||||
protected BackgroundTaskBroker<ImportKMSTaskReq> _taskBroker { get; set; }
|
||||
|
||||
[Inject]
|
||||
protected IHttpService _httpService { get; set; }
|
||||
[Inject]
|
||||
protected ILogger<KmsDetail> _logger { get; set; }
|
||||
|
||||
private Kmss km;
|
||||
|
||||
private readonly KmsDetails _model = new KmsDetails();
|
||||
|
||||
private bool _urlVisible = false;
|
||||
@@ -51,34 +78,15 @@ namespace AntSK.Pages.KmsPage
|
||||
|
||||
private List<KmsDetails> _data = new List<KmsDetails>();
|
||||
|
||||
[Inject]
|
||||
protected IConfirmService _confirmService { get; set; }
|
||||
|
||||
[Inject]
|
||||
protected IKmsDetails_Repositories _kmsDetails_Repositories { get; set; }
|
||||
private bool _isQa { get; set; } = false;
|
||||
|
||||
[Inject]
|
||||
protected IKmss_Repositories _kmss_Repositories { get; set; }
|
||||
|
||||
private MemoryServerless _memory { get; set; }
|
||||
|
||||
[Inject]
|
||||
protected IKMService iKMService { get; set; }
|
||||
|
||||
[Inject]
|
||||
protected MessageService? _message { get; set; }
|
||||
|
||||
[Inject]
|
||||
protected BackgroundTaskBroker<ImportKMSTaskReq> _taskBroker { get; set; }
|
||||
|
||||
[Inject]
|
||||
protected IHttpService _httpService { get; set; }
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
_data = await _kmsDetails_Repositories.GetListAsync(p => p.KmsId == KmsId);
|
||||
var km = _kmss_Repositories.GetFirst(p => p.Id == KmsId);
|
||||
km = _kmss_Repositories.GetFirst(p => p.Id == KmsId);
|
||||
//使用知识库设置的参数,
|
||||
_memory = iKMService.GetMemoryByKMS(km.Id);
|
||||
}
|
||||
@@ -112,6 +120,7 @@ namespace AntSK.Pages.KmsPage
|
||||
ImportType = ImportType.Url,
|
||||
KmsId = KmsId,
|
||||
Url = urlModel.Url,
|
||||
IsQA = _isQa
|
||||
});
|
||||
_data = await _kmsDetails_Repositories.GetListAsync(p => p.KmsId == KmsId);
|
||||
_urlVisible = false;
|
||||
@@ -120,7 +129,7 @@ namespace AntSK.Pages.KmsPage
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message + " ---- " + ex.StackTrace);
|
||||
_logger.LogError(ex.Message + " ---- " + ex.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,7 +161,8 @@ namespace AntSK.Pages.KmsPage
|
||||
{
|
||||
ImportType = ImportType.Text,
|
||||
KmsId = KmsId,
|
||||
Text = textModel.Text
|
||||
Text = textModel.Text,
|
||||
IsQA = _isQa
|
||||
});
|
||||
_data = await _kmsDetails_Repositories.GetListAsync(p => p.KmsId == KmsId);
|
||||
_textVisible = false;
|
||||
@@ -161,7 +171,7 @@ namespace AntSK.Pages.KmsPage
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message + " ---- " + ex.StackTrace);
|
||||
_logger.LogError(ex.Message + " ---- " + ex.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,7 +200,8 @@ namespace AntSK.Pages.KmsPage
|
||||
ImportType = ImportType.File,
|
||||
KmsId = KmsId,
|
||||
FilePath = item.Url,
|
||||
FileName = item.FileName
|
||||
FileName = item.FileName,
|
||||
IsQA=_isQa
|
||||
});
|
||||
}
|
||||
_data = await _kmsDetails_Repositories.GetListAsync(p => p.KmsId == KmsId);
|
||||
@@ -201,7 +212,7 @@ namespace AntSK.Pages.KmsPage
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message + " ---- " + ex.StackTrace);
|
||||
_logger.LogError(ex.Message + " ---- " + ex.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,7 +240,8 @@ namespace AntSK.Pages.KmsPage
|
||||
ImportType = ImportType.Excel,
|
||||
KmsId = KmsId,
|
||||
FilePath = item.Url,
|
||||
FileName = item.FileName
|
||||
FileName = item.FileName,
|
||||
IsQA = false
|
||||
});
|
||||
}
|
||||
_data = await _kmsDetails_Repositories.GetListAsync(p => p.KmsId == KmsId);
|
||||
@@ -240,7 +252,7 @@ namespace AntSK.Pages.KmsPage
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message + " ---- " + ex.StackTrace);
|
||||
_logger.LogError(ex.Message + " ---- " + ex.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,7 +291,7 @@ namespace AntSK.Pages.KmsPage
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message + " ---- " + ex.StackTrace);
|
||||
_logger.LogError(ex.Message + " ---- " + ex.StackTrace);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
@@ -15,14 +15,8 @@
|
||||
info(()=> Info(context.Text)) ,
|
||||
})">
|
||||
<CardMeta>
|
||||
<AvatarTemplate>
|
||||
|
||||
</AvatarTemplate>
|
||||
<TitleTemplate>
|
||||
<a>@context.LastUpdate</a>
|
||||
</TitleTemplate>
|
||||
<DescriptionTemplate>
|
||||
<Paragraph class="item" Ellipsis Style=" white-space: nowrap; ">
|
||||
<Paragraph class="item" Ellipsis Style="display: -webkit-box; -webkit-line-clamp: 3;-webkit-box-orient: vertical;overflow: hidden; text-overflow: ellipsis;white-space: normal;height:65px;">
|
||||
<!--todo: Ellipsis not working-->
|
||||
@context.Text
|
||||
</Paragraph>
|
||||
|
||||
@@ -4,6 +4,7 @@ using AntSK.Domain.Domain.Model.Fun;
|
||||
using AntSK.Domain.Domain.Service;
|
||||
using AntSK.Domain.Repositories;
|
||||
using AntSK.Models;
|
||||
using AntSK.Pages.KmsPage;
|
||||
using DocumentFormat.OpenXml.Office2010.Excel;
|
||||
using HtmlAgilityPack;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
@@ -27,7 +28,7 @@ namespace AntSK.Pages.FunPage
|
||||
|
||||
[Inject]
|
||||
protected MessageService? _message { get; set; }
|
||||
|
||||
[Inject] protected ILogger<FunDto> _logger { get; set; }
|
||||
|
||||
bool _fileVisible = false;
|
||||
bool _fileConfirmLoading = false;
|
||||
@@ -102,7 +103,7 @@ namespace AntSK.Pages.FunPage
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message + " ---- " + ex.StackTrace);
|
||||
_logger.LogError(ex.Message + " ---- " + ex.StackTrace);
|
||||
}
|
||||
}
|
||||
private void FileHandleCancel(MouseEventArgs e)
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
@using AntSK.LLamaFactory.Model
|
||||
@using AntSK.LLamaFactory
|
||||
@using BlazorComponents.Terminal
|
||||
@page "/setting/model/add"
|
||||
@page "/setting/model/add/{ModelId}"
|
||||
@page "/setting/model/addbypath/{ModelPath}"
|
||||
@page "/modelmanager/model/add"
|
||||
@page "/modelmanager/model/add/{ModelId}"
|
||||
@page "/modelmanager/model/addbypath/{ModelPath}"
|
||||
@using AntSK.Services.Auth
|
||||
@inherits AuthComponentBase
|
||||
@using Microsoft.AspNetCore.Authorization
|
||||
@@ -27,21 +27,25 @@
|
||||
<EnumRadioGroup @bind-Value="context.AIType" ButtonStyle="RadioButtonStyle.Solid" OnChange="AITypeChange" TEnum="AIType"> </EnumRadioGroup>
|
||||
</FormItem>
|
||||
<FormItem Label="模型类型" LabelCol="LayoutModel._formItemLayout.LabelCol" WrapperCol="LayoutModel._formItemLayout.WrapperCol">
|
||||
<RadioGroup @bind-Value="context.AIModelType">
|
||||
<RadioGroup @bind-Value="context.AIModelType">
|
||||
@if (context.AIType == AIType.StableDiffusion)
|
||||
{
|
||||
<Radio RadioButton Value="@(AIModelType.Image)">图片模型</Radio>
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
@if (context.AIType != AIType.BgeEmbedding)
|
||||
@if (context.AIType != AIType.BgeEmbedding && context.AIType != AIType.BgeRerank)
|
||||
{
|
||||
<Radio RadioButton Value="@(AIModelType.Chat)">会话模型</Radio>
|
||||
}
|
||||
@if (context.AIType != AIType.LLamaFactory && context.AIType != AIType.Mock && context.AIType != AIType.SparkDesk)
|
||||
@if (context.AIType != AIType.LLamaFactory && context.AIType != AIType.Mock && context.AIType != AIType.SparkDesk && context.AIType != AIType.BgeRerank)
|
||||
{
|
||||
<Radio RadioButton Value="@(AIModelType.Embedding)">向量模型</Radio>
|
||||
}
|
||||
@if (context.AIType == AIType.BgeRerank)
|
||||
{
|
||||
<Radio RadioButton Value="@(AIModelType.Rerank)">Rerank重排模型</Radio>
|
||||
}
|
||||
}
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
@@ -61,7 +65,7 @@
|
||||
<Input Placeholder="请输入部署名" @bind-Value="@context.ModelName" />
|
||||
</FormItem>
|
||||
<FormItem Label="模型秘钥" LabelCol="LayoutModel._formItemLayout.LabelCol" WrapperCol="LayoutModel._formItemLayout.WrapperCol">
|
||||
<InputPassword @bind-Value="@context.ModelKey" Placeholder="请输入模型秘钥" Size="@InputSize.Large" />
|
||||
<InputPassword @bind-Value="@context.ModelKey" Placeholder="请输入模型秘钥" />
|
||||
</FormItem>
|
||||
}
|
||||
@if (context.AIType == AIType.OpenAI)
|
||||
@@ -73,7 +77,7 @@
|
||||
<Input Placeholder="请输入模型名称" @bind-Value="@context.ModelName" />
|
||||
</FormItem>
|
||||
<FormItem Label="模型秘钥" LabelCol="LayoutModel._formItemLayout.LabelCol" WrapperCol="LayoutModel._formItemLayout.WrapperCol">
|
||||
<InputPassword @bind-Value="@context.ModelKey" Placeholder="请输入模型秘钥" Size="@InputSize.Large" />
|
||||
<InputPassword @bind-Value="@context.ModelKey" Placeholder="请输入模型秘钥" />
|
||||
</FormItem>
|
||||
}
|
||||
@if (context.AIType == AIType.SparkDesk)
|
||||
@@ -81,12 +85,13 @@
|
||||
<FormItem Label="APPID" LabelCol="LayoutModel._formItemLayout.LabelCol" WrapperCol="LayoutModel._formItemLayout.WrapperCol">
|
||||
<Input Placeholder="请输入APPID" @bind-Value="@context.EndPoint" />
|
||||
</FormItem>
|
||||
<FormItem Label="APISecret" LabelCol="LayoutModel._formItemLayout.LabelCol" WrapperCol="LayoutModel._formItemLayout.WrapperCol">
|
||||
<InputPassword @bind-Value="@context.ModelKey" Placeholder="APISecret" />
|
||||
</FormItem>
|
||||
<FormItem Label="APIKey" LabelCol="LayoutModel._formItemLayout.LabelCol" WrapperCol="LayoutModel._formItemLayout.WrapperCol">
|
||||
<Input Placeholder="请输入请输入APIKey" @bind-Value="@context.ModelName" />
|
||||
</FormItem>
|
||||
<FormItem Label="APISecret" LabelCol="LayoutModel._formItemLayout.LabelCol" WrapperCol="LayoutModel._formItemLayout.WrapperCol">
|
||||
<InputPassword @bind-Value="@context.ModelKey" Placeholder="APISecret" Size="@InputSize.Large" />
|
||||
</FormItem>
|
||||
|
||||
}
|
||||
@if (context.AIType == AIType.DashScope)
|
||||
{
|
||||
@@ -140,7 +145,7 @@
|
||||
<Button OnClick="StopLFService" Disabled="@(!llamaFactoryIsStart)">停止</Button>
|
||||
}
|
||||
</InputGroup>
|
||||
</FormItem>
|
||||
</FormItem>
|
||||
}
|
||||
|
||||
@if (context.AIType == AIType.BgeEmbedding)
|
||||
@@ -152,19 +157,45 @@
|
||||
LabelProperty="c=>c">
|
||||
</Select>
|
||||
</FormItem>
|
||||
<FormItem Label="PythonDll路径" LabelCol="LayoutModel._formItemLayout.LabelCol" WrapperCol="LayoutModel._formItemLayout.WrapperCol">
|
||||
<Input Placeholder="D:\Programs\Python\Python311\python311.dll" @bind-Value="@context.EndPoint" />
|
||||
|
||||
<FormItem Label="Python路径" LabelCol="LayoutModel._formItemLayout.LabelCol" WrapperCol="LayoutModel._formItemLayout.WrapperCol">
|
||||
<Popover ContentTemplate="@_content" Title="提示" Style="width:100%">
|
||||
<Input Placeholder="D:\Programs\Python\Python311\python311.dll" @bind-Value="@context.EndPoint" />
|
||||
</Popover>
|
||||
</FormItem>
|
||||
|
||||
<FormItem Label="环境安装" LabelCol="LayoutModel._formItemLayout.LabelCol" WrapperCol="LayoutModel._formItemLayout.WrapperCol">
|
||||
<Button Type="primary" OnClick="PipInstall">环境安装</Button>
|
||||
</FormItem>
|
||||
<FormItem Label="下载并初始化" LabelCol="LayoutModel._formItemLayout.LabelCol" WrapperCol="LayoutModel._formItemLayout.WrapperCol">
|
||||
<Spin Tip="请等待..." Spinning="@(BgeEmbeddingIsStart)">
|
||||
<Button Type="primary" Disabled="@(BgeEmbeddingIsStart)" OnClick="BgeEmbedding">@BgeEmbeddingBtnText</Button>
|
||||
</Spin>
|
||||
</FormItem>
|
||||
}
|
||||
@if (context.AIType == AIType.BgeRerank)
|
||||
{
|
||||
<FormItem Label="模型名称" LabelCol="LayoutModel._formItemLayout.LabelCol" WrapperCol="LayoutModel._formItemLayout.WrapperCol">
|
||||
<Select DataSource="@bgeRerankList"
|
||||
@bind-Value="@context.ModelName"
|
||||
ValueProperty="c=>c"
|
||||
LabelProperty="c=>c">
|
||||
</Select>
|
||||
</FormItem>
|
||||
<FormItem Label="Python路径" LabelCol="LayoutModel._formItemLayout.LabelCol" WrapperCol="LayoutModel._formItemLayout.WrapperCol">
|
||||
<Popover ContentTemplate="@_content" Title="提示" Style="width:100%">
|
||||
<Input Placeholder="D:\Programs\Python\Python311\python311.dll" @bind-Value="@context.EndPoint" />
|
||||
</Popover>
|
||||
</FormItem>
|
||||
<FormItem Label="环境安装" LabelCol="LayoutModel._formItemLayout.LabelCol" WrapperCol="LayoutModel._formItemLayout.WrapperCol">
|
||||
<Button Type="primary" OnClick="PipInstall">环境安装</Button>
|
||||
</FormItem>
|
||||
<FormItem Label="下载并初始化" LabelCol="LayoutModel._formItemLayout.LabelCol" WrapperCol="LayoutModel._formItemLayout.WrapperCol">
|
||||
<Spin Tip="请等待..." Spinning="@(BgeIsStart)" >
|
||||
<Button Type="primary" Disabled="@(BgeIsStart)" OnClick="BgeDownload">@BgeBtnText</Button>
|
||||
<Spin Tip="请等待..." Spinning="@(BgeRerankIsStart)">
|
||||
<Button Type="primary" Disabled="@(BgeRerankIsStart)" OnClick="BgeRerank">@BgeRerankBtnText</Button>
|
||||
</Spin>
|
||||
</FormItem>
|
||||
}
|
||||
|
||||
@if (context.AIType == AIType.Mock)
|
||||
{
|
||||
}
|
||||
@@ -206,5 +237,8 @@
|
||||
|
||||
@code
|
||||
{
|
||||
|
||||
RenderFragment _content =
|
||||
@<div>
|
||||
<p>在windows上使用 python311.dll文件,在linux上使用 libpython3.10.so</p>
|
||||
</div>;
|
||||
}
|
||||
@@ -3,7 +3,7 @@ using AntDesign.ProLayout;
|
||||
using AntSK.Domain.Domain.Interface;
|
||||
using AntSK.Domain.Domain.Model.Constant;
|
||||
using AntSK.Domain.Domain.Model.Enum;
|
||||
using AntSK.Domain.Domain.Other;
|
||||
using AntSK.Domain.Domain.Other.Bge;
|
||||
using AntSK.Domain.Domain.Service;
|
||||
using AntSK.Domain.Options;
|
||||
using AntSK.Domain.Repositories;
|
||||
@@ -61,8 +61,13 @@ namespace AntSK.Pages.Setting.AIModel
|
||||
private bool _logModalVisible;
|
||||
|
||||
private List<string> bgeEmbeddingList = new List<string>() { "AI-ModelScope/bge-small-zh-v1.5", "AI-ModelScope/bge-base-zh-v1.5", "AI-ModelScope/bge-large-zh-v1.5" };
|
||||
private bool BgeIsStart = false;
|
||||
private string BgeBtnText = "初始化";
|
||||
private List<string> bgeRerankList = new List<string>() { "Xorbits/bge-reranker-base", "Xorbits/bge-reranker-large", "AI-ModelScope/bge-reranker-v2-m3", "AI-ModelScope/bge-reranker-v2-gemma"};
|
||||
private bool BgeEmbeddingIsStart = false;
|
||||
private string BgeEmbeddingBtnText = "初始化";
|
||||
|
||||
private bool BgeRerankIsStart = false;
|
||||
private string BgeRerankBtnText = "初始化";
|
||||
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
@@ -83,7 +88,7 @@ namespace AntSK.Pages.Setting.AIModel
|
||||
|
||||
|
||||
//目前只支持gguf的 所以筛选一下
|
||||
_modelFiles = Directory.GetFiles(Path.Combine(Directory.GetCurrentDirectory(), LLamaSharpOption.FileDirectory)).Where(p=> p.Contains(".gguf")||p.Contains(".ckpt")|| p.Contains(".safetensors")).ToArray();
|
||||
_modelFiles = Directory.GetFiles(Path.Combine(Directory.GetCurrentDirectory(), FileDirOption.DirectoryPath)).Where(p=> p.Contains(".gguf")||p.Contains(".ckpt")|| p.Contains(".safetensors")).ToArray();
|
||||
if (!string.IsNullOrEmpty(ModelPath))
|
||||
{
|
||||
string extension = Path.GetExtension(ModelPath);
|
||||
@@ -150,7 +155,7 @@ namespace AntSK.Pages.Setting.AIModel
|
||||
|
||||
private void Back()
|
||||
{
|
||||
NavigationManager.NavigateTo("/setting/modellist");
|
||||
NavigationManager.NavigateTo("/modelmanager/modellist");
|
||||
}
|
||||
|
||||
private async Task StartDownload()
|
||||
@@ -162,7 +167,7 @@ namespace AntSK.Pages.Setting.AIModel
|
||||
|
||||
_download = DownloadBuilder.New()
|
||||
.WithUrl(_downloadUrl)
|
||||
.WithDirectory(Path.Combine(Directory.GetCurrentDirectory(), LLamaSharpOption.FileDirectory))
|
||||
.WithDirectory(Path.Combine(Directory.GetCurrentDirectory(), FileDirOption.DirectoryPath))
|
||||
.WithConfiguration(new DownloadConfiguration()
|
||||
{
|
||||
ParallelCount = 5,
|
||||
@@ -190,7 +195,7 @@ namespace AntSK.Pages.Setting.AIModel
|
||||
_aiModel.ModelName = _download.Package.FileName;
|
||||
_downloadModalVisible = false;
|
||||
_downloadStarted = false;
|
||||
_modelFiles = Directory.GetFiles(Path.Combine(Directory.GetCurrentDirectory(), LLamaSharpOption.FileDirectory));
|
||||
_modelFiles = Directory.GetFiles(Path.Combine(Directory.GetCurrentDirectory(), FileDirOption.DirectoryPath));
|
||||
InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
@@ -268,7 +273,7 @@ namespace AntSK.Pages.Setting.AIModel
|
||||
}
|
||||
}
|
||||
|
||||
private async Task BgeDownload()
|
||||
private async Task BgeEmbedding()
|
||||
{
|
||||
if (string.IsNullOrEmpty(_aiModel.ModelName))
|
||||
{
|
||||
@@ -277,27 +282,60 @@ namespace AntSK.Pages.Setting.AIModel
|
||||
}
|
||||
if (string.IsNullOrEmpty(_aiModel.EndPoint))
|
||||
{
|
||||
_ = Message.Error("请输入正确的Python dll路径!", 2);
|
||||
_ = Message.Error("请输入正确的Python dll或python so路径!", 2);
|
||||
return;
|
||||
}
|
||||
|
||||
BgeIsStart = true;
|
||||
BgeBtnText = "正在初始化...";
|
||||
BgeEmbeddingIsStart = true;
|
||||
BgeEmbeddingBtnText = "正在初始化...";
|
||||
await Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
EmbeddingConfig.LoadModel(_aiModel.EndPoint, _aiModel.ModelName);
|
||||
BgeBtnText = "初始化完成";
|
||||
BgeIsStart = false;
|
||||
BgeEmbeddingConfig.LoadModel(_aiModel.EndPoint, _aiModel.ModelName);
|
||||
BgeEmbeddingBtnText = "初始化完成";
|
||||
BgeEmbeddingIsStart = false;
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
_ = Message.Error(ex.Message, 2);
|
||||
BgeIsStart = false;
|
||||
BgeEmbeddingIsStart = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async Task BgeRerank()
|
||||
{
|
||||
if (string.IsNullOrEmpty(_aiModel.ModelName))
|
||||
{
|
||||
_ = Message.Error("请输入模型名称!", 2);
|
||||
return;
|
||||
}
|
||||
if (string.IsNullOrEmpty(_aiModel.EndPoint))
|
||||
{
|
||||
_ = Message.Error("请输入正确的Python dll或python so路径!", 2);
|
||||
return;
|
||||
}
|
||||
|
||||
BgeRerankIsStart = true;
|
||||
BgeRerankBtnText = "正在初始化...";
|
||||
await Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
BegRerankConfig.LoadModel(_aiModel.EndPoint, _aiModel.ModelName);
|
||||
BgeRerankBtnText = "初始化完成";
|
||||
BgeRerankIsStart = false;
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
_ = Message.Error(ex.Message, 2);
|
||||
BgeRerankIsStart = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private async Task CmdLogHandler(string message)
|
||||
{
|
||||
await InvokeAsync(() =>
|
||||
@@ -319,7 +357,7 @@ namespace AntSK.Pages.Setting.AIModel
|
||||
switch (aiType)
|
||||
{
|
||||
case AIType.LLamaFactory:
|
||||
_aiModel.EndPoint = "http://localhost:8080/";
|
||||
_aiModel.EndPoint = "http://localhost:8000/";
|
||||
_aiModel.AIModelType=AIModelType.Chat;
|
||||
break;
|
||||
case AIType.StableDiffusion:
|
||||
@@ -331,6 +369,9 @@ namespace AntSK.Pages.Setting.AIModel
|
||||
case AIType.BgeEmbedding:
|
||||
_aiModel.AIModelType = AIModelType.Embedding;
|
||||
break;
|
||||
case AIType.BgeRerank:
|
||||
_aiModel.AIModelType = AIModelType.Rerank;
|
||||
break;
|
||||
default:
|
||||
_aiModel.AIModelType = AIModelType.Chat;
|
||||
break;
|
||||
|
||||
@@ -1,67 +1,69 @@
|
||||
@namespace AntSK.Pages.Setting.AIModel
|
||||
@page "/setting/modeldown"
|
||||
@page "/modelmanager/modeldown"
|
||||
@using AntSK.Services.Auth
|
||||
@inherits AuthComponentBase
|
||||
@using Microsoft.AspNetCore.Authorization
|
||||
@using AntSK.Domain.Domain.Model.hfmirror;
|
||||
using AntSK.Domain.Domain.Model.hfmirror
|
||||
@using AntSK.Domain.Domain.Model.hfmirror
|
||||
@attribute [Authorize(Roles = "AntSKAdmin")]
|
||||
|
||||
<div>
|
||||
<PageContainer Title="模型列表">
|
||||
<Content>
|
||||
<RadioGroup @bind-Value="@_modelType" OnChange="OnModelTypeChange" TValue="string">
|
||||
<Radio Value="@("gguf")" DefaultChecked=true>LLama本地模型(gguf)</Radio>
|
||||
<Radio Value="@("safetensors")">StableDiffusion(safetensors)</Radio>
|
||||
<Radio Value="@("ckpt")">StableDiffusion2(ckpt)</Radio>
|
||||
</RadioGroup>
|
||||
<div style="text-align: center;">
|
||||
|
||||
<PageContainer Title="模型列表">
|
||||
<Content>
|
||||
<RadioGroup @bind-Value="@_modelType" OnChange="OnModelTypeChange" TValue="string">
|
||||
<Radio Value="@("gguf")" DefaultChecked=true>LLama本地模型(gguf)</Radio>
|
||||
<Radio Value="@("safetensors")">StableDiffusion(safetensors)</Radio>
|
||||
<Radio Value="@("ckpt")">StableDiffusion2(ckpt)</Radio>
|
||||
</RadioGroup>
|
||||
<div style="text-align: center;">
|
||||
|
||||
<Search Placeholder="输入回车"
|
||||
EnterButton="@("搜索")"
|
||||
Size="large"
|
||||
Style="max-width: 522px; width: 100%;"
|
||||
OnSearch="Search" />
|
||||
|
||||
</div>
|
||||
</Content>
|
||||
<ChildContent>
|
||||
<div class="filterCardList">
|
||||
<AntList TItem="HfModels"
|
||||
Grid="LayoutModel._listGridType"
|
||||
DataSource="_modelList">
|
||||
<ListItem NoFlex>
|
||||
<Card Hoverable
|
||||
BodyStyle="padding-bottom: 20px;"
|
||||
Actions="new[] {
|
||||
down(()=> Down(context.Id))
|
||||
<Search Placeholder="输入回车"
|
||||
EnterButton="@("搜索")"
|
||||
Size="large"
|
||||
Style="max-width: 522px; width: 100%;"
|
||||
OnSearch="Search" />
|
||||
|
||||
</div>
|
||||
</Content>
|
||||
<ChildContent>
|
||||
<div class="filterCardList">
|
||||
<Spin Tip="加载中..." Spinning="@(loaddding)">
|
||||
<AntList TItem="HfModels"
|
||||
Grid="LayoutModel._listGridType"
|
||||
DataSource="_modelList">
|
||||
<ListItem NoFlex>
|
||||
<Card Hoverable
|
||||
BodyStyle="padding-bottom: 20px;"
|
||||
Actions="new[] {
|
||||
down(()=> Down(context.Id))
|
||||
}">
|
||||
<CardMeta>
|
||||
<TitleTemplate>
|
||||
@context.Id
|
||||
</TitleTemplate>
|
||||
<AvatarTemplate>
|
||||
<Avatar Size="small" Src="@context.AuthorData.AvatarUrl" />
|
||||
</AvatarTemplate>
|
||||
</CardMeta>
|
||||
<div class="cardItemContent">
|
||||
<div class="cardInfo">
|
||||
<div>
|
||||
<p>Downloads</p>
|
||||
<p>@context.Downloads.ToString("0,0")</p>
|
||||
<CardMeta>
|
||||
<TitleTemplate>
|
||||
@context.Id
|
||||
</TitleTemplate>
|
||||
<AvatarTemplate>
|
||||
<Avatar Size="small" Src="@context.AuthorData.AvatarUrl" />
|
||||
</AvatarTemplate>
|
||||
</CardMeta>
|
||||
<div class="cardItemContent">
|
||||
<div class="cardInfo">
|
||||
<div>
|
||||
<p>Downloads</p>
|
||||
<p>@context.Downloads.ToString("0,0")</p>
|
||||
</div>
|
||||
<div>
|
||||
<p>Likes</p>
|
||||
<p>@context.Likes.ToString("0,0")</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p>Likes</p>
|
||||
<p>@context.Likes.ToString("0,0")</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</ListItem>
|
||||
</AntList>
|
||||
</div>
|
||||
</ChildContent>
|
||||
</PageContainer>
|
||||
</Card>
|
||||
</ListItem>
|
||||
</AntList>
|
||||
</Spin>
|
||||
</div>
|
||||
</ChildContent>
|
||||
</PageContainer>
|
||||
</div>
|
||||
@code
|
||||
{
|
||||
RenderFragment down(Action clickAction) =>@<a key="down" @onclick="@clickAction">下载</a>;
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
using AntDesign;
|
||||
using AntSK.Domain.Domain.Model.hfmirror;
|
||||
using AntSK.Domain.Utils;
|
||||
using AntSK.Models;
|
||||
using AntSK.Services;
|
||||
using DocumentFormat.OpenXml.Office2010.Excel;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Newtonsoft.Json;
|
||||
using RestSharp;
|
||||
using AntSK.Domain.Utils;
|
||||
using AntSK.Domain.Domain.Model.hfmirror;
|
||||
|
||||
namespace AntSK.Pages.Setting.AIModel
|
||||
{
|
||||
@@ -16,27 +13,55 @@ namespace AntSK.Pages.Setting.AIModel
|
||||
private readonly IList<string> _selectCategories = new List<string>();
|
||||
|
||||
private List<HfModels> _modelList = new List<HfModels>();
|
||||
private string _modelType;
|
||||
private string _modelType="gguf";
|
||||
private bool loaddding = false;
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
InitData("");
|
||||
}
|
||||
|
||||
private void InitData(string searchKey)
|
||||
private async Task InitData(string searchKey)
|
||||
{
|
||||
var param = searchKey.ConvertToString().Split(" ");
|
||||
|
||||
string urlBase = $"https://hf-mirror.com/models-json?sort=trending&search={_modelType}";
|
||||
if (param.Count() > 0)
|
||||
loaddding = true;
|
||||
if (_modelType.Contains("safetensors"))
|
||||
{
|
||||
urlBase += "+" + string.Join("+", param);
|
||||
_modelList.Clear();
|
||||
var param = searchKey.ConvertToString().Split(" ");
|
||||
string[] lines = File.ReadAllLines(Path.Combine(AppContext.BaseDirectory, "StableDiffusionModelList.txt"));
|
||||
foreach (string line in lines)
|
||||
{
|
||||
string urlBase = $"https://hf-mirror.com/models-json?sort=trending&search={line}";
|
||||
if (param.Count() > 0)
|
||||
{
|
||||
urlBase += "+" + string.Join("+", param);
|
||||
}
|
||||
RestClient client = new RestClient();
|
||||
RestRequest request = new RestRequest(urlBase, Method.Get);
|
||||
var response =await client.ExecuteAsync(request);
|
||||
var model = JsonConvert.DeserializeObject<HfModel>(response.Content);
|
||||
_modelList.AddRange(model.models);
|
||||
}
|
||||
|
||||
}
|
||||
RestClient client = new RestClient();
|
||||
RestRequest request = new RestRequest(urlBase, Method.Get);
|
||||
var response = client.Execute(request);
|
||||
var model = JsonConvert.DeserializeObject<HfModel>(response.Content);
|
||||
_modelList = model.models;
|
||||
else
|
||||
{
|
||||
var param = searchKey.ConvertToString().Split(" ");
|
||||
|
||||
string urlBase = $"https://hf-mirror.com/models-json?sort=trending&search={_modelType}";
|
||||
if (param.Count() > 0)
|
||||
{
|
||||
urlBase += "+" + string.Join("+", param);
|
||||
}
|
||||
RestClient client = new RestClient();
|
||||
RestRequest request = new RestRequest(urlBase, Method.Get);
|
||||
var response = await client.ExecuteAsync(request);
|
||||
var model = JsonConvert.DeserializeObject<HfModel>(response.Content);
|
||||
_modelList = model.models;
|
||||
}
|
||||
|
||||
loaddding = false;
|
||||
InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
private async Task Search(string searchKey)
|
||||
@@ -46,7 +71,7 @@ namespace AntSK.Pages.Setting.AIModel
|
||||
|
||||
private void Down(string modelPath)
|
||||
{
|
||||
NavigationManager.NavigateTo($"/setting/modeldown/detail/{modelPath}");
|
||||
NavigationManager.NavigateTo($"/modelmanager/modeldown/detail/{modelPath}");
|
||||
}
|
||||
|
||||
private void OnModelTypeChange(string value)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@namespace AntSK.Pages.Setting.AIModel
|
||||
@page "/setting/modeldown/detail/{ModelName}/{ModelPath}"
|
||||
@page "/modelmanager/modeldown/detail/{ModelName}/{ModelPath}"
|
||||
@using AntSK.Services.Auth
|
||||
@inherits AuthComponentBase
|
||||
@using Microsoft.AspNetCore.Authorization
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace AntSK.Pages.Setting.AIModel
|
||||
|
||||
private void Down(string path)
|
||||
{
|
||||
NavigationManager.NavigateTo($"/setting/model/addbypath/{path.Replace("?download=true", "").Replace("/", "---")}");
|
||||
NavigationManager.NavigateTo($"/modelmanager/model/addbypath/{path.Replace("?download=true", "").Replace("/", "---")}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@namespace AntSK.Pages.Setting.AIModel
|
||||
@using AntSK.Domain.Repositories
|
||||
@using AntSK.Domain.Domain.Model.Enum
|
||||
@page "/setting/modellist"
|
||||
@page "/modelmanager/modellist"
|
||||
@inject NavigationManager NavigationManager
|
||||
@using AntSK.Services.Auth
|
||||
@inherits AuthComponentBase
|
||||
@@ -39,44 +39,48 @@
|
||||
delete(async ()=>await Delete(context.Id))
|
||||
}" Style="width:100%">
|
||||
<div class="listContent" style="width:100%">
|
||||
<div class="listContentItem" style="width:20%">
|
||||
<div class="listContentItem" style="width:15%">
|
||||
<b>模型描述</b>
|
||||
<p>@context.ModelDescription</p>
|
||||
<p title="@context.ModelDescription">@context.ModelDescription</p>
|
||||
</div>
|
||||
<div class="listContentItem" style="width:10%">
|
||||
<b>AI类型</b>
|
||||
<p>
|
||||
@if (context.AIType == AIType.OpenAI)
|
||||
{
|
||||
<Tag Color="@PresetColor.Yellow.ToString()">OpenAI</Tag>
|
||||
<Tag Color="@PresetColor.Pink.ToString()">OpenAI</Tag>
|
||||
}
|
||||
else if (context.AIType == AIType.AzureOpenAI)
|
||||
{
|
||||
<Tag Color="@PresetColor.Green.ToString()">AzureOpenAI</Tag>
|
||||
<Tag Color="@PresetColor.Red.ToString()">AzureOpenAI</Tag>
|
||||
}
|
||||
else if (context.AIType == AIType.LLamaSharp)
|
||||
{
|
||||
<Tag Color="@PresetColor.Red.ToString()">LLamaSharp</Tag>
|
||||
<Tag Color="@PresetColor.Yellow.ToString()">LLamaSharp</Tag>
|
||||
}
|
||||
else if (context.AIType == AIType.SparkDesk)
|
||||
{
|
||||
<Tag Color="@PresetColor.Orange.ToString()">SparkDesk</Tag>
|
||||
<Tag Color="@PresetColor.Cyan.ToString()">SparkDesk</Tag>
|
||||
}
|
||||
else if (context.AIType == AIType.Mock)
|
||||
{
|
||||
<Tag Color="@PresetColor.Cyan.ToString()">Mock</Tag>
|
||||
<Tag Color="@PresetColor.Green.ToString()">Mock</Tag>
|
||||
}
|
||||
else if (context.AIType == AIType.LLamaFactory)
|
||||
{
|
||||
<Tag Color="@PresetColor.Cyan.ToString()">LLamaFactory</Tag>
|
||||
<Tag Color="@PresetColor.Blue.ToString()">LLamaFactory</Tag>
|
||||
}
|
||||
else if (context.AIType == AIType.BgeEmbedding)
|
||||
{
|
||||
<Tag Color="@PresetColor.Gold.ToString()">BgeEmbedding</Tag>
|
||||
<Tag Color="@PresetColor.Purple.ToString()">BgeEmbedding</Tag>
|
||||
}
|
||||
else if (context.AIType == AIType.BgeRerank)
|
||||
{
|
||||
<Tag Color="@PresetColor.GeekBlue.ToString()">BgeRerank</Tag>
|
||||
}
|
||||
else if (context.AIType == AIType.StableDiffusion)
|
||||
{
|
||||
<Tag Color="@PresetColor.Lime.ToString()">StableDiffusion</Tag>
|
||||
<Tag Color="@PresetColor.Magenta.ToString()">StableDiffusion</Tag>
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
@@ -97,15 +101,19 @@
|
||||
{
|
||||
<Tag Color="@PresetColor.Lime.ToString()">图片模型</Tag>
|
||||
}
|
||||
else if (context.AIModelType == AIModelType.Rerank)
|
||||
{
|
||||
<Tag Color="@PresetColor.GeekBlue.ToString()">Rerank重排模型</Tag>
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
<div class="listContentItem" style="width:20%">
|
||||
<div class="listContentItem" style="width:25%">
|
||||
<b>模型地址</b>
|
||||
<p>@context.EndPoint</p>
|
||||
<p title="@context.EndPoint">@context.EndPoint</p>
|
||||
</div>
|
||||
<div class="listContentItem" style="width:10%">
|
||||
<div class="listContentItem" style="width:15%">
|
||||
<b>模型名称</b>
|
||||
<p>@context.ModelName</p>
|
||||
<p title="@context.ModelName">@context.ModelName</p>
|
||||
</div>
|
||||
</div>
|
||||
</ListItem>
|
||||
@@ -116,7 +124,31 @@
|
||||
</ChildContent>
|
||||
</PageContainer>
|
||||
</div>
|
||||
<style>
|
||||
.listContentItem {
|
||||
width: 20%;
|
||||
overflow: hidden; /* 防止内容溢出 */
|
||||
text-overflow: ellipsis; /* 超出部分显示省略号 */
|
||||
white-space: nowrap; /* 防止内容换行 */
|
||||
}
|
||||
|
||||
/* 为需要显示工具提示的元素设置title属性 */
|
||||
.listContentItem p[title] {
|
||||
cursor: pointer; /* 鼠标移动上去时显示小手势 */
|
||||
}
|
||||
|
||||
/* 悬停样式 */
|
||||
.listContentItem:hover p[title]:before {
|
||||
content: attr(title); /* 使用title属性的内容 */
|
||||
position: absolute;
|
||||
background: #333; /* 工具提示的背景颜色 */
|
||||
color: #fff; /* 工具提示的文字颜色 */
|
||||
padding: 4px 8px; /* 工具提示内部的填充 */
|
||||
border-radius: 4px; /* 工具提示的边框圆角 */
|
||||
text-align: center; /* 工具提示文字居中对齐 */
|
||||
z-index: 1000; /* 工具提示在最顶层 */
|
||||
}
|
||||
</style>
|
||||
@code
|
||||
{
|
||||
RenderFragment edit(Action clickAction) =>@<a key="edit" @onclick="@clickAction">修改</a>;
|
||||
|
||||
@@ -16,6 +16,13 @@ namespace AntSK.Pages.Setting.AIModel
|
||||
[Inject]
|
||||
protected IAIModels_Repositories _aIModels_Repositories { get; set; }
|
||||
|
||||
[Inject]
|
||||
protected IApps_Repositories _apps_Repositories{ get; set; }
|
||||
[Inject]
|
||||
protected IKmss_Repositories _kmss_Repositories { get; set; }
|
||||
|
||||
[Inject] protected MessageService? Message { get; set; }
|
||||
|
||||
[Inject]
|
||||
IConfirmService _confirmService { get; set; }
|
||||
|
||||
@@ -44,12 +51,12 @@ namespace AntSK.Pages.Setting.AIModel
|
||||
|
||||
public async Task AddModel()
|
||||
{
|
||||
NavigationManager.NavigateTo("/setting/model/add");
|
||||
NavigationManager.NavigateTo("/modelmanager/model/add");
|
||||
}
|
||||
|
||||
public void Edit(string modelid)
|
||||
{
|
||||
NavigationManager.NavigateTo("/setting/model/add/" + modelid);
|
||||
NavigationManager.NavigateTo("/modelmanager/model/add/" + modelid);
|
||||
}
|
||||
|
||||
public async Task Delete(string modelid)
|
||||
@@ -59,6 +66,16 @@ namespace AntSK.Pages.Setting.AIModel
|
||||
var result = await _confirmService.Show(content, title, ConfirmButtons.YesNo);
|
||||
if (result == ConfirmResult.Yes)
|
||||
{
|
||||
if (_apps_Repositories.IsAny(p => p.ChatModelID == modelid || p.EmbeddingModelID == modelid))
|
||||
{
|
||||
_ = Message.Error("该模型有应用在使用,请先删除应用后才允许删除该模型");
|
||||
return;
|
||||
}
|
||||
if (_kmss_Repositories.IsAny(p => p.ChatModelID == modelid || p.EmbeddingModelID == modelid))
|
||||
{
|
||||
_ = Message.Error("该模型有知识库在使用,请先删除知识库后才允许删除该模型");
|
||||
return;
|
||||
}
|
||||
await _aIModels_Repositories.DeleteAsync(modelid);
|
||||
await InitData("");
|
||||
}
|
||||
|
||||
121
src/AntSK/Pages/Setting/ChatHistory/ChatHistory.razor
Normal file
121
src/AntSK/Pages/Setting/ChatHistory/ChatHistory.razor
Normal file
@@ -0,0 +1,121 @@
|
||||
@namespace AntSK.Pages.Setting.AIModel
|
||||
@page "/setting/chathistory"
|
||||
@using AntSK.Services.Auth
|
||||
@inherits AuthComponentBase
|
||||
@using Microsoft.AspNetCore.Authorization
|
||||
@using System.ComponentModel
|
||||
@using AntDesign.TableModels
|
||||
@using AntSK.Domain.Repositories
|
||||
@using AntSK.Domain.Common.Map
|
||||
@attribute [Authorize(Roles = "AntSKAdmin")]
|
||||
|
||||
<Table @ref="table"
|
||||
TItem="ChatsDto"
|
||||
DataSource="@chatDtoList"
|
||||
Total="_total"
|
||||
@bind-PageIndex="_pageIndex"
|
||||
@bind-PageSize="_pageSize"
|
||||
OnChange="OnChange"
|
||||
Size="TableSize.Small"
|
||||
RowKey="x=>x.Id">
|
||||
<TitleTemplate>
|
||||
<GridRow>
|
||||
<GridCol Span="4">
|
||||
<Title Level="3">聊天记录</Title>
|
||||
</GridCol>
|
||||
<GridCol Span="8" Offset="12">
|
||||
<Search Placeholder="搜索" @bind-Value="searchString" OnSearch="Search" />
|
||||
</GridCol>
|
||||
</GridRow>
|
||||
</TitleTemplate>
|
||||
<ColumnDefinitions>
|
||||
<PropertyColumn Property="c=>c.Id" />
|
||||
<PropertyColumn Title="用户名" Property="c=>c.UserName" />
|
||||
<PropertyColumn Title="应用名称" Property="c=>c.AppName" />
|
||||
<PropertyColumn Title="发送/接收" Property="c=>c.SendReveice" />
|
||||
<ActionColumn Title="消息内容" Width="30%">
|
||||
<Space>
|
||||
<SpaceItem>
|
||||
@((MarkupString)(context.Context))
|
||||
</SpaceItem>
|
||||
</Space>
|
||||
</ActionColumn>
|
||||
<PropertyColumn Title="时间" Property="c=>c.CreateTime" Format="yyyy-MM-dd HH:mm:ss" />
|
||||
</ColumnDefinitions>
|
||||
</Table>
|
||||
|
||||
@using System.Text.Json;
|
||||
@code {
|
||||
[Inject] IChats_Repositories _chats_Repositories { get; set; }
|
||||
|
||||
ChatsDto[] chatDtoList;
|
||||
|
||||
ITable table;
|
||||
|
||||
int _pageIndex = 1;
|
||||
int _pageSize = 10;
|
||||
int _total = 0;
|
||||
string searchString;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await InitData();
|
||||
}
|
||||
|
||||
public async Task OnChange(QueryModel<ChatsDto> queryModel)
|
||||
{
|
||||
await InitData();
|
||||
}
|
||||
|
||||
private async Task InitData()
|
||||
{
|
||||
if (string.IsNullOrEmpty(searchString))
|
||||
{
|
||||
_total = _chats_Repositories.Count(p => true);
|
||||
var chatList = _chats_Repositories.GetDB().Queryable<Chats, Apps>((c, a) => new object[] {
|
||||
SqlSugar.JoinType.Left,c.AppId==a.Id
|
||||
}).Select((c, a) => new ChatsDto
|
||||
{
|
||||
Id = c.Id,
|
||||
UserName = c.UserName,
|
||||
AppId = c.AppId,
|
||||
IsSend = c.IsSend,
|
||||
SendReveice = c.IsSend ? "发送" : "接收",
|
||||
Context = c.Context,
|
||||
CreateTime = c.CreateTime,
|
||||
AppName = a.Name
|
||||
}).ToPageList(_pageIndex, _pageSize);
|
||||
chatDtoList = chatList.ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
_total = _chats_Repositories.Count(p => p.UserName.Contains(searchString) || p.Context.Contains(searchString));
|
||||
var chatList = _chats_Repositories.GetDB().Queryable<Chats, Apps>((c, a) => new object[] {
|
||||
SqlSugar.JoinType.Left,c.AppId==a.Id
|
||||
}).Select((c, a) => new ChatsDto
|
||||
{
|
||||
Id = c.Id,
|
||||
UserName = c.UserName,
|
||||
AppId = c.AppId,
|
||||
IsSend = c.IsSend,
|
||||
SendReveice = c.IsSend ? "发送" : "接收",
|
||||
Context = c.Context,
|
||||
CreateTime = c.CreateTime,
|
||||
AppName = a.Name
|
||||
}).Where(c => c.UserName.Contains(searchString) || c.Context.Contains(searchString)).ToPageList(_pageIndex, _pageSize);
|
||||
chatDtoList = chatList.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task Search(string searchKey)
|
||||
{
|
||||
await InitData();
|
||||
}
|
||||
|
||||
public class ChatsDto : Chats
|
||||
{
|
||||
public string AppName { get; set; }
|
||||
public string SendReveice { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
89
src/AntSK/Pages/Setting/DelKms/DelKms.razor
Normal file
89
src/AntSK/Pages/Setting/DelKms/DelKms.razor
Normal file
@@ -0,0 +1,89 @@
|
||||
@namespace AntSK.Pages.Setting.AIModel
|
||||
@page "/setting/delkms"
|
||||
@using AntSK.Services.Auth
|
||||
@using AntSK.Domain.Options
|
||||
@using AntSK.Domain.Repositories
|
||||
@inherits AuthComponentBase
|
||||
@using Microsoft.AspNetCore.Authorization
|
||||
@attribute [Authorize(Roles = "AntSKAdmin")]
|
||||
|
||||
<GridContent>
|
||||
<Card>
|
||||
<Result Status="error"
|
||||
Title="删除向量表"
|
||||
SubTitle="删除向量表将会删除您的所有知识库文件,以及知识库向量。请谨慎操作!"
|
||||
Style="margin-top: 48px; margin-bottom: 16px;">
|
||||
<Extra>
|
||||
<Button Type="primary" OnClick="DelDimensions">删除向量表</Button>
|
||||
</Extra>
|
||||
<ChildContent>
|
||||
<div class="title__b__0">
|
||||
当您切换不同维度的向量模型时,出现异常:
|
||||
</div>
|
||||
<div style="margin-bottom: 16px;">
|
||||
<Icon Type="close-circle" Theme="outline" Class="error_icon" Style="margin-right: 8px;" />
|
||||
Npgsql.PostgresException (0x80004005): 22000: expected 2048 dimensions, not 1024
|
||||
</div>
|
||||
<div>
|
||||
<Icon Type="close-circle" Theme="outline" Class="error_icon" Style="margin-right: 8px;" />
|
||||
您需要删除向量表,然后重建向量维度。
|
||||
</div>
|
||||
</ChildContent>
|
||||
</Result>
|
||||
</Card>
|
||||
</GridContent>
|
||||
|
||||
<Modal @ref="_modal" Visible="_showAdminPwdVisible" Footer="null" Closable Title="请输入管理员密码" OnCancel="OnCancel" DestroyOnClose>
|
||||
<Flex Gap="10" Vertical>
|
||||
<InputGroup>
|
||||
<InputPassword @bind-Value="@adminPwd" Placeholder="管理员密码" Size="@InputSize.Large" />
|
||||
</InputGroup>
|
||||
<InputGroup>
|
||||
<Button Type="primary" OnClick="DelSubmit">确认</Button>
|
||||
</InputGroup>
|
||||
</Flex>
|
||||
</Modal>
|
||||
@code {
|
||||
[Inject] protected MessageService? Message { get; set; }
|
||||
[Inject] protected IKmsDetails_Repositories kmsDetails_Repositories { get; set; }
|
||||
|
||||
[Inject] protected IConfirmService _confirmService { get; set; }
|
||||
|
||||
private Modal _modal;
|
||||
private bool _showAdminPwdVisible = false;
|
||||
private string adminPwd = "";
|
||||
|
||||
public async Task DelDimensions()
|
||||
{
|
||||
var content = "删除向量表将会删除您的所有知识库文件,以及知识库向量。请谨慎操作!";
|
||||
var title = "删除向量表";
|
||||
var result = await _confirmService.Show(content, title, ConfirmButtons.YesNo);
|
||||
if (result == ConfirmResult.Yes)
|
||||
{
|
||||
_showAdminPwdVisible = true;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task DelSubmit() {
|
||||
if (adminPwd != LoginOption.Password)
|
||||
{
|
||||
_ = Message.Error("管理员密码错误!");
|
||||
return;
|
||||
}
|
||||
|
||||
kmsDetails_Repositories.GetDB().Ado.ExecuteCommand("DROP TABLE IF EXISTS \"km-kms\"");
|
||||
kmsDetails_Repositories.GetDB().Ado.ExecuteCommand("DROP TABLE IF EXISTS \"km-file\"");
|
||||
var kmsDetails = await kmsDetails_Repositories.GetListAsync();
|
||||
foreach (var detail in kmsDetails)
|
||||
{
|
||||
kmsDetails_Repositories.Delete(detail);
|
||||
}
|
||||
_showAdminPwdVisible = false;
|
||||
_ = Message.Info("删除成功!");
|
||||
}
|
||||
|
||||
private void OnCancel()
|
||||
{
|
||||
_showAdminPwdVisible = false;
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,8 @@ using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using OpenTelemetry.Exporter;
|
||||
using Serilog;
|
||||
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||
using System.Reflection;
|
||||
using System.Text.Encodings.Web;
|
||||
@@ -30,6 +32,28 @@ builder.Services.AddControllers().AddJsonOptions(config =>
|
||||
config.JsonSerializerOptions.Converters.Add(new DateTimeConverter());
|
||||
config.JsonSerializerOptions.Converters.Add(new DateTimeNullableConvert());
|
||||
});
|
||||
|
||||
builder.AddServiceDefaults();
|
||||
|
||||
builder.Configuration.GetSection("DBConnection").Get<DBConnectionOption>();
|
||||
builder.Configuration.GetSection("Login").Get<LoginOption>();
|
||||
builder.Configuration.GetSection("LLamaSharp").Get<LLamaSharpOption>();
|
||||
builder.Configuration.GetSection("KernelMemory").Get<KernelMemoryOption>();
|
||||
builder.Configuration.GetSection("FileDir").Get<FileDirOption>();
|
||||
|
||||
builder.Services.Configure<OtlpExporterOptions>(
|
||||
o => o.Headers = $"x-otlp-api-key=antsk");
|
||||
|
||||
Log.Logger = new LoggerConfiguration()
|
||||
.ReadFrom.Configuration(builder.Configuration)
|
||||
.CreateLogger();
|
||||
|
||||
var loggerFactory = LoggerFactory.Create(builder => {
|
||||
builder.ClearProviders();
|
||||
builder.AddSerilog();
|
||||
});
|
||||
ILogger<Program> logger = loggerFactory.CreateLogger<Program>();
|
||||
InitExtensions.InitLog(logger);
|
||||
// Add services to the container.
|
||||
builder.Services.AddRazorPages();
|
||||
builder.Services.AddServerSideBlazor();
|
||||
@@ -56,26 +80,36 @@ builder.Services.AddMapper();
|
||||
//后台队列任务
|
||||
builder.Services.AddBackgroundTaskBroker().AddHandler<ImportKMSTaskReq, BackGroundTaskHandler>("ImportKMSTask");
|
||||
// 读取连接字符串配置
|
||||
{
|
||||
builder.Configuration.GetSection("DBConnection").Get<DBConnectionOption>();
|
||||
builder.Configuration.GetSection("Login").Get<LoginOption>();
|
||||
builder.Configuration.GetSection("LLamaSharp").Get<LLamaSharpOption>();
|
||||
builder.Configuration.GetSection("KernelMemory").Get<KernelMemoryOption>();
|
||||
|
||||
if (LLamaSharpOption.RunType.ToUpper() == "CPU")
|
||||
{
|
||||
NativeLibraryConfig
|
||||
.Instance
|
||||
.All
|
||||
.WithCuda(false)
|
||||
.WithLogs(true);
|
||||
.WithLogCallback((level, message) => {
|
||||
logger.LogInformation($"[llama {level}]: {message.TrimEnd('\n')}");
|
||||
});
|
||||
}
|
||||
else if (LLamaSharpOption.RunType.ToUpper() == "GPU")
|
||||
{
|
||||
NativeLibraryConfig
|
||||
.Instance
|
||||
.All
|
||||
.WithCuda(true)
|
||||
.WithLogs(true);
|
||||
.WithLogCallback((level, message) => {
|
||||
logger.LogInformation($"[llama {level}]: {message.TrimEnd('\n')}");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//增加API允许跨域调用
|
||||
builder.Services.AddCors(options => options.AddPolicy("Any",
|
||||
builder =>
|
||||
{
|
||||
builder.AllowAnyMethod()
|
||||
.AllowAnyHeader()
|
||||
.SetIsOriginAllowed(_ => true)
|
||||
.AllowCredentials();
|
||||
}));
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
@@ -89,6 +123,8 @@ if (!app.Environment.IsDevelopment())
|
||||
|
||||
//app.UseHttpsRedirection();
|
||||
|
||||
app.UseCors("Any");
|
||||
|
||||
app.UseStaticFiles();
|
||||
|
||||
//扩展初始化实现
|
||||
|
||||
@@ -33,24 +33,25 @@ namespace AntSK.Services.OpenApi
|
||||
Regex regex = new Regex(@"Bearer (.*)");
|
||||
Match match = regex.Match(headerValue);
|
||||
string token = match.Groups[1].Value;
|
||||
string questions;
|
||||
ChatHistory history;
|
||||
Apps app = _apps_Repositories.GetFirst(p => p.SecretKey == token);
|
||||
if (app.IsNotNull())
|
||||
{
|
||||
(string questions,ChatHistory history) = await GetHistory(model);
|
||||
|
||||
switch (app.Type)
|
||||
{
|
||||
case "chat":
|
||||
(questions, history) = await GetHistory(model,app.Prompt);
|
||||
//普通会话
|
||||
history.AddUserMessage(questions);
|
||||
if (model.stream)
|
||||
{
|
||||
OpenAIStreamResult result1 = new OpenAIStreamResult();
|
||||
result1.created = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
||||
result1.choices = new List<StreamChoicesModel>()
|
||||
{ new StreamChoicesModel() { delta = new OpenAIMessage() { role = "assistant" } } };
|
||||
await SendChatStream(HttpContext, result1, app, questions,history);
|
||||
HttpContext.Response.ContentType = "application/json";
|
||||
await HttpContext.Response.WriteAsync(JsonConvert.SerializeObject(result1));
|
||||
await HttpContext.Response.CompleteAsync();
|
||||
await SendChatStream(HttpContext, result1, app,history);
|
||||
return;
|
||||
}
|
||||
else
|
||||
@@ -59,15 +60,14 @@ namespace AntSK.Services.OpenApi
|
||||
result2.created = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
||||
result2.choices = new List<ChoicesModel>()
|
||||
{ new ChoicesModel() { message = new OpenAIMessage() { role = "assistant" } } };
|
||||
result2.choices[0].message.content = await SendChat(questions,history, app);
|
||||
result2.choices[0].message.content = await SendChat(history, app);
|
||||
HttpContext.Response.ContentType = "application/json";
|
||||
await HttpContext.Response.WriteAsync(JsonConvert.SerializeObject(result2));
|
||||
await HttpContext.Response.CompleteAsync();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "kms":
|
||||
(questions, history) = await GetHistory(model,"");
|
||||
//知识库问答
|
||||
if (model.stream)
|
||||
{
|
||||
@@ -76,9 +76,6 @@ namespace AntSK.Services.OpenApi
|
||||
result3.choices = new List<StreamChoicesModel>()
|
||||
{ new StreamChoicesModel() { delta = new OpenAIMessage() { role = "assistant" } } };
|
||||
await SendKmsStream(HttpContext, result3, app, questions,history);
|
||||
HttpContext.Response.ContentType = "application/json";
|
||||
await HttpContext.Response.WriteAsync(JsonConvert.SerializeObject(result3));
|
||||
await HttpContext.Response.CompleteAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -91,16 +88,15 @@ namespace AntSK.Services.OpenApi
|
||||
await HttpContext.Response.WriteAsync(JsonConvert.SerializeObject(result4));
|
||||
await HttpContext.Response.CompleteAsync();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SendChatStream(HttpContext HttpContext, OpenAIStreamResult result, Apps app,string questions, ChatHistory history)
|
||||
private async Task SendChatStream(HttpContext HttpContext, OpenAIStreamResult result, Apps app, ChatHistory history)
|
||||
{
|
||||
HttpContext.Response.Headers.Add("Content-Type", "text/event-stream");
|
||||
var chatResult = _chatService.SendChatByAppAsync(app, questions, history);
|
||||
var chatResult = _chatService.SendChatByAppAsync(app, history);
|
||||
await foreach (var content in chatResult)
|
||||
{
|
||||
result.choices[0].delta.content = content.ConvertToString();
|
||||
@@ -113,7 +109,6 @@ namespace AntSK.Services.OpenApi
|
||||
|
||||
await HttpContext.Response.WriteAsync("data: [DONE]");
|
||||
await HttpContext.Response.Body.FlushAsync();
|
||||
|
||||
await HttpContext.Response.CompleteAsync();
|
||||
}
|
||||
|
||||
@@ -124,49 +119,48 @@ namespace AntSK.Services.OpenApi
|
||||
/// <param name="history"></param>
|
||||
/// <param name="app"></param>
|
||||
/// <returns></returns>
|
||||
private async Task<string> SendChat(string questions, ChatHistory history, Apps app)
|
||||
private async Task<string> SendChat(ChatHistory history, Apps app)
|
||||
{
|
||||
string result = "";
|
||||
|
||||
if (string.IsNullOrEmpty(app.Prompt) || !app.Prompt.Contains("{{$input}}"))
|
||||
{
|
||||
//如果模板为空,给默认提示词
|
||||
app.Prompt = app.Prompt.ConvertToString() + "{{$input}}";
|
||||
}
|
||||
KernelArguments args = new KernelArguments();
|
||||
if (history.Count > 10)
|
||||
{
|
||||
app.Prompt = @"${{ConversationSummaryPlugin.SummarizeConversation $history}}" + app.Prompt;
|
||||
args = new() {
|
||||
{ "history", string.Join("\n", history.Select(x => x.Role + ": " + x.Content)) },
|
||||
{ "input", questions }
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
args = new()
|
||||
{
|
||||
{ "input", $"{string.Join("\n", history.Select(x => x.Role + ": " + x.Content))}{Environment.NewLine} user:{questions}" }
|
||||
};
|
||||
}
|
||||
|
||||
var _kernel = _kernelService.GetKernelByApp(app);
|
||||
var temperature = app.Temperature / 100; //存的是0~100需要缩小
|
||||
var chat = _kernel.GetRequiredService<IChatCompletionService>();
|
||||
|
||||
var temperature = app.Temperature / 100;//存的是0~100需要缩小
|
||||
OpenAIPromptExecutionSettings settings = new() { Temperature = temperature };
|
||||
List<string> completionList = new List<string>();
|
||||
if (!string.IsNullOrEmpty(app.ApiFunctionList) || !string.IsNullOrEmpty(app.NativeFunctionList))//这里还需要加上本地插件的
|
||||
{
|
||||
_kernelService.ImportFunctionsByApp(app, _kernel);
|
||||
settings.ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions;
|
||||
}
|
||||
var func = _kernel.CreateFunctionFromPrompt(app.Prompt, settings);
|
||||
var chatResult =await _kernel.InvokeAsync(function: func, arguments: args);
|
||||
if (chatResult.IsNotNull())
|
||||
{
|
||||
string answers = chatResult.GetValue<string>();
|
||||
result = answers;
|
||||
}
|
||||
settings.ToolCallBehavior = ToolCallBehavior.EnableKernelFunctions;
|
||||
while (true)
|
||||
{
|
||||
ChatMessageContent result = await chat.GetChatMessageContentAsync(history, settings, _kernel);
|
||||
if (result.Content is not null)
|
||||
{
|
||||
string chunkCompletion = result.Content.ConvertToString();
|
||||
completionList.Add(chunkCompletion);
|
||||
return chunkCompletion;
|
||||
}
|
||||
history.Add(result);
|
||||
IEnumerable<FunctionCallContent> functionCalls = FunctionCallContent.GetFunctionCalls(result);
|
||||
if (!functionCalls.Any())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
foreach (var functionCall in functionCalls)
|
||||
{
|
||||
FunctionResultContent resultContent = await functionCall.InvokeAsync(_kernel);
|
||||
|
||||
history.Add(resultContent.ToChatMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ChatMessageContent result = await chat.GetChatMessageContentAsync(history, settings, _kernel);
|
||||
return result.Content.ConvertToString();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private async Task SendKmsStream(HttpContext HttpContext, OpenAIStreamResult result, Apps app, string questions,ChatHistory history)
|
||||
@@ -232,11 +226,15 @@ namespace AntSK.Services.OpenApi
|
||||
/// <param name="app"></param>
|
||||
/// <param name="model"></param>
|
||||
/// <returns></returns>
|
||||
private async Task<(string,ChatHistory)> GetHistory(OpenAIModel model)
|
||||
private async Task<(string,ChatHistory)> GetHistory(OpenAIModel model,string systemPrompt)
|
||||
{
|
||||
ChatHistory history = new ChatHistory();
|
||||
if (!string.IsNullOrEmpty(systemPrompt))
|
||||
{
|
||||
history = new ChatHistory(systemPrompt);
|
||||
}
|
||||
string questions = model.messages[model.messages.Count - 1].content;
|
||||
for (int i = 0; i < model.messages.Count() - 1; i++)
|
||||
for (int i = 0; i < model.messages.Count()-1 ; i++)
|
||||
{
|
||||
var item = model.messages[i];
|
||||
if (item.role.ComparisonIgnoreCase("user"))
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"urls":"http://*:5000",
|
||||
"urls": "http://*:5000",
|
||||
"ProSettings": {
|
||||
"NavTheme": "light",
|
||||
"Layout": "side",
|
||||
@@ -25,17 +25,21 @@
|
||||
"HeaderHeight": 48
|
||||
},
|
||||
"DBConnection": {
|
||||
"DbType": "Sqlite",
|
||||
"DbType": "Sqlite",
|
||||
"ConnectionStrings": "Data Source=AntSK.db;"
|
||||
},
|
||||
"KernelMemory": {
|
||||
"VectorDb": "Disk",
|
||||
"VectorDb": "Disk",
|
||||
"ConnectionString": "Host=;Port=;Database=antsk;Username=;Password=",
|
||||
"TableNamePrefix": "km-"
|
||||
},
|
||||
"LLamaSharp": {
|
||||
"RunType": "GPU",
|
||||
"FileDirectory": "D:\\git\\AntBlazor\\model"
|
||||
"ContextSize": 2048,
|
||||
"GpuLayerCount": 20
|
||||
},
|
||||
"FileDir": {
|
||||
"DirectoryPath": "D:\\model"
|
||||
},
|
||||
"Login": {
|
||||
"User": "admin",
|
||||
@@ -43,7 +47,29 @@
|
||||
},
|
||||
"BackgroundTaskBroker": {
|
||||
"ImportKMSTask": {
|
||||
"WorkerCount": 1
|
||||
"WorkerCount": 1
|
||||
}
|
||||
},
|
||||
"Serilog": {
|
||||
"Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.Seq", "Serilog.Sinks.File" ],
|
||||
"MinimumLevel": "Debug",
|
||||
"WriteTo": [
|
||||
{ "Name": "Console" },
|
||||
{
|
||||
"Name": "OpenTelemetry",
|
||||
"Args": {
|
||||
"Endpoint": "http://aspire-dashboard:18889"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "File",
|
||||
"Args": {
|
||||
"path": "D:\\model\\logs\\log-.txt",
|
||||
"rollingInterval": "Day",
|
||||
"fileSizeLimitBytes": 10485760
|
||||
}
|
||||
}
|
||||
],
|
||||
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ]
|
||||
}
|
||||
}
|
||||
|
||||
12
src/AntSK/plugins/KMSPlugin/QA/config.json
Normal file
12
src/AntSK/plugins/KMSPlugin/QA/config.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"schema": 1,
|
||||
"description": "知识库问答",
|
||||
"execution_settings": {
|
||||
"default": {
|
||||
"temperature": 0.0,
|
||||
"top_p": 0.0,
|
||||
"presence_penalty": 0.0,
|
||||
"frequency_penalty": 0.0
|
||||
}
|
||||
}
|
||||
}
|
||||
13
src/AntSK/plugins/KMSPlugin/QA/skprompt.txt
Normal file
13
src/AntSK/plugins/KMSPlugin/QA/skprompt.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
我会给你一段文本,学习它们,并整理学习成果,要求为:
|
||||
1. 提出最多 25 个问题。
|
||||
2. 给出每个问题的答案。
|
||||
3. 答案要详细完整,答案可以包含普通文字、链接、代码、表格、公示、媒体链接等 markdown 元素。
|
||||
4. 按格式返回多个问题和答案:
|
||||
|
||||
Q1: 问题。
|
||||
A1: 答案。
|
||||
Q2:
|
||||
A2:
|
||||
……
|
||||
|
||||
我的文本:"""{{$input}}"""
|
||||
@@ -1 +1,30 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200" version="1.1" viewBox="0 0 200 200"><title>Group 28 Copy 5</title><desc>Created with Sketch.</desc><defs><linearGradient id="linearGradient-1" x1="62.102%" x2="108.197%" y1="0%" y2="37.864%"><stop offset="0%" stop-color="#4285EB"/><stop offset="100%" stop-color="#2EC7FF"/></linearGradient><linearGradient id="linearGradient-2" x1="69.644%" x2="54.043%" y1="0%" y2="108.457%"><stop offset="0%" stop-color="#29CDFF"/><stop offset="37.86%" stop-color="#148EFF"/><stop offset="100%" stop-color="#0A60FF"/></linearGradient><linearGradient id="linearGradient-3" x1="69.691%" x2="16.723%" y1="-12.974%" y2="117.391%"><stop offset="0%" stop-color="#FA816E"/><stop offset="41.473%" stop-color="#F74A5C"/><stop offset="100%" stop-color="#F51D2C"/></linearGradient><linearGradient id="linearGradient-4" x1="68.128%" x2="30.44%" y1="-35.691%" y2="114.943%"><stop offset="0%" stop-color="#FA8E7D"/><stop offset="51.264%" stop-color="#F74A5C"/><stop offset="100%" stop-color="#F51D2C"/></linearGradient></defs><g id="Page-1" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="logo" transform="translate(-20.000000, -20.000000)"><g id="Group-28-Copy-5" transform="translate(20.000000, 20.000000)"><g id="Group-27-Copy-3"><g id="Group-25" fill-rule="nonzero"><g id="2"><path id="Shape" fill="url(#linearGradient-1)" d="M91.5880863,4.17652823 L4.17996544,91.5127728 C-0.519240605,96.2081146 -0.519240605,103.791885 4.17996544,108.487227 L91.5880863,195.823472 C96.2872923,200.518814 103.877304,200.518814 108.57651,195.823472 L145.225487,159.204632 C149.433969,154.999611 149.433969,148.181924 145.225487,143.976903 C141.017005,139.771881 134.193707,139.771881 129.985225,143.976903 L102.20193,171.737352 C101.032305,172.906015 99.2571609,172.906015 98.0875359,171.737352 L28.285908,101.993122 C27.1162831,100.824459 27.1162831,99.050775 28.285908,97.8821118 L98.0875359,28.1378823 C99.2571609,26.9692191 101.032305,26.9692191 102.20193,28.1378823 L129.985225,55.8983314 C134.193707,60.1033528 141.017005,60.1033528 145.225487,55.8983314 C149.433969,51.69331 149.433969,44.8756232 145.225487,40.6706018 L108.58055,4.05574592 C103.862049,-0.537986846 96.2692618,-0.500797906 91.5880863,4.17652823 Z"/><path id="Shape" fill="url(#linearGradient-2)" d="M91.5880863,4.17652823 L4.17996544,91.5127728 C-0.519240605,96.2081146 -0.519240605,103.791885 4.17996544,108.487227 L91.5880863,195.823472 C96.2872923,200.518814 103.877304,200.518814 108.57651,195.823472 L145.225487,159.204632 C149.433969,154.999611 149.433969,148.181924 145.225487,143.976903 C141.017005,139.771881 134.193707,139.771881 129.985225,143.976903 L102.20193,171.737352 C101.032305,172.906015 99.2571609,172.906015 98.0875359,171.737352 L28.285908,101.993122 C27.1162831,100.824459 27.1162831,99.050775 28.285908,97.8821118 L98.0875359,28.1378823 C100.999864,25.6271836 105.751642,20.541824 112.729652,19.3524487 C117.915585,18.4685261 123.585219,20.4140239 129.738554,25.1889424 C125.624663,21.0784292 118.571995,14.0340304 108.58055,4.05574592 C103.862049,-0.537986846 96.2692618,-0.500797906 91.5880863,4.17652823 Z"/></g><path id="Shape" fill="url(#linearGradient-3)" d="M153.685633,135.854579 C157.894115,140.0596 164.717412,140.0596 168.925894,135.854579 L195.959977,108.842726 C200.659183,104.147384 200.659183,96.5636133 195.960527,91.8688194 L168.690777,64.7181159 C164.472332,60.5180858 157.646868,60.5241425 153.435895,64.7316526 C149.227413,68.936674 149.227413,75.7543607 153.435895,79.9593821 L171.854035,98.3623765 C173.02366,99.5310396 173.02366,101.304724 171.854035,102.473387 L153.685633,120.626849 C149.47715,124.83187 149.47715,131.649557 153.685633,135.854579 Z"/></g><ellipse id="Combined-Shape" cx="100.519" cy="100.437" fill="url(#linearGradient-4)" rx="23.6" ry="23.581"/></g></g></g></g></svg>
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="370.000000pt" height="370.000000pt" viewBox="0 0 370.000000 370.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
|
||||
<g transform="translate(0.000000,370.000000) scale(0.100000,-0.100000)"
|
||||
fill="#000000" stroke="none">
|
||||
<path d="M1914 3198 c-87 -152 -450 -815 -526 -960 l-46 -86 26 -7 c15 -4 116
|
||||
-3 225 1 l197 7 69 121 c38 66 83 150 101 185 l32 65 19 -25 c10 -13 44 -71
|
||||
75 -129 32 -58 73 -134 92 -168 l35 -64 213 4 c117 1 215 6 219 9 8 9 -57 139
|
||||
-203 404 -177 324 -439 785 -446 785 0 0 -38 -64 -82 -142z"/>
|
||||
<path d="M772 3019 c-198 -53 -353 -165 -459 -332 -13 -20 -41 -72 -63 -115
|
||||
-51 -102 -64 -184 -58 -372 5 -129 8 -153 33 -215 48 -118 105 -205 195 -295
|
||||
75 -75 101 -93 215 -152 l130 -66 440 -11 c242 -7 467 -16 499 -22 119 -21
|
||||
211 -93 263 -204 24 -51 28 -72 28 -145 -2 -190 -105 -314 -305 -365 l-45 -11
|
||||
-3 -212 -2 -212 22 0 c63 1 202 43 298 91 93 45 116 63 201 148 86 87 102 109
|
||||
153 211 65 131 76 182 76 345 -1 248 -46 365 -209 537 -80 85 -157 141 -277
|
||||
201 l-91 46 -494 11 -494 11 -40 26 c-76 50 -142 121 -171 186 -25 54 -29 74
|
||||
-29 152 1 76 5 99 27 147 47 101 142 175 263 205 l65 16 0 208 0 209 -47 -1
|
||||
c-27 0 -81 -9 -121 -20z"/>
|
||||
<path d="M830 1153 c-38 -7 -42 -14 -123 -156 -153 -271 -169 -304 -151 -311
|
||||
8 -3 109 -6 224 -6 l209 0 70 128 c132 242 176 330 168 339 -9 9 -356 14 -397
|
||||
6z"/>
|
||||
<path d="M2802 1152 l-42 -7 93 -170 c121 -220 154 -273 175 -279 55 -15 114
|
||||
-17 263 -11 l166 7 -119 222 c-66 121 -122 224 -126 227 -10 10 -359 18 -410
|
||||
11z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 1.6 KiB |
@@ -35,9 +35,27 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/modelmanager",
|
||||
"name": "模型管理",
|
||||
"key": "modelmanager",
|
||||
"icon": "shop",
|
||||
"children": [
|
||||
{
|
||||
"path": "/modelmanager/modellist",
|
||||
"name": "模型管理",
|
||||
"key": "modelmanager.modellist"
|
||||
},
|
||||
{
|
||||
"path": "/modelmanager/modeldown",
|
||||
"name": "模型下载",
|
||||
"key": "modelmanager.modeldown"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/setting",
|
||||
"name": "设置",
|
||||
"name": "系统设置",
|
||||
"key": "setting",
|
||||
"icon": "setting",
|
||||
"children": [
|
||||
@@ -47,21 +65,27 @@
|
||||
"key": "setting.user"
|
||||
},
|
||||
{
|
||||
"path": "/setting/modellist",
|
||||
"name": "模型管理",
|
||||
"key": "setting.modellist"
|
||||
"path": "/setting/chathistory",
|
||||
"name": "聊天记录",
|
||||
"key": "setting.chathistory"
|
||||
},
|
||||
{
|
||||
"path": "/setting/modeldown",
|
||||
"name": "模型下载",
|
||||
"key": "setting.modeldown"
|
||||
"path": "/setting/delkms",
|
||||
"name": "删除向量表",
|
||||
"key": "setting.delkms"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "http://antsk.cn/",
|
||||
"name": "文档",
|
||||
"name": "使用文档",
|
||||
"key": "antskdoc",
|
||||
"icon": "question-circle"
|
||||
},
|
||||
{
|
||||
"path": "https://www.bilibili.com/video/BV1vK421b7NF",
|
||||
"name": "教程视频",
|
||||
"key": "antskvideo",
|
||||
"icon": "video-camera"
|
||||
}
|
||||
]
|
||||
@@ -11,14 +11,38 @@
|
||||
<PackageReference Include="RestSharp" Version="110.2.0" />
|
||||
<PackageReference Include="Cnblogs.KernelMemory.AI.DashScope" Version="0.1.0" />
|
||||
<PackageReference Include="Cnblogs.SemanticKernel.Connectors.DashScope" Version="0.3.2" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel" Version="1.6.3" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel" Version="1.13.0" />
|
||||
<PackageReference Include="Sdcb.SparkDesk" Version="3.0.0" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="stable-diffusion.dll">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<None Update="StableDiffusion\Backend\CPU\stable-diffusion.dll">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="StableDiffusion\Backend\CPU\stable-diffusion.so">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="StableDiffusion\Backend\Cuda11\stable-diffusion.dll">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="StableDiffusion\Backend\Cuda11\stable-diffusion.so">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="StableDiffusion\Backend\Cuda12\stable-diffusion.dll">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="StableDiffusion\Backend\Cuda12\stable-diffusion.so">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="StableDiffusion\Backend\ROCm\stable-diffusion.dll">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="StableDiffusion\Backend\ROCm\stable-diffusion.so">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="StableDiffusionModelList.txt">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
55
src/AntSk.LLM/Mock/MockChatCompletion.cs
Normal file
55
src/AntSk.LLM/Mock/MockChatCompletion.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using AntSK.LLM.SparkDesk;
|
||||
using Microsoft.SemanticKernel.ChatCompletion;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Sdcb.SparkDesk;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.Json;
|
||||
using System.Text.Unicode;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AntSK.LLM.Mock
|
||||
{
|
||||
public class MockChatCompletion : IChatCompletionService
|
||||
{
|
||||
private readonly Dictionary<string, object?> _attributes = new();
|
||||
private readonly SparkDeskClient _client;
|
||||
private string _chatId;
|
||||
private readonly SparkDeskOptions _options;
|
||||
|
||||
private static readonly JsonSerializerOptions _jsonSerializerOptions = new()
|
||||
{
|
||||
NumberHandling = JsonNumberHandling.AllowReadingFromString,
|
||||
Encoder = JavaScriptEncoder.Create(UnicodeRanges.All)
|
||||
};
|
||||
|
||||
public IReadOnlyDictionary<string, object?> Attributes => _attributes;
|
||||
|
||||
public MockChatCompletion()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyList<ChatMessageContent>> GetChatMessageContentsAsync(ChatHistory chatHistory, PromptExecutionSettings? executionSettings = null, Kernel? kernel = null, [EnumeratorCancellation] CancellationToken cancellationToken = default)
|
||||
{
|
||||
StringBuilder sb = new();
|
||||
string result = $"这是一条Mock数据,便于聊天测试,你的消息是:{chatHistory.LastOrDefault().ToString()}";
|
||||
return [new(AuthorRole.Assistant, result.ToString())];
|
||||
}
|
||||
|
||||
public async IAsyncEnumerable<StreamingChatMessageContent> GetStreamingChatMessageContentsAsync(ChatHistory chatHistory, PromptExecutionSettings? executionSettings = null, Kernel? kernel = null, [EnumeratorCancellation] CancellationToken cancellationToken = default)
|
||||
{
|
||||
StringBuilder sb = new();
|
||||
string result = $"这是一条Mock数据,便于聊天测试,你的消息是:{chatHistory.LastOrDefault().ToString()}";
|
||||
foreach (var c in result)
|
||||
{
|
||||
yield return new StreamingChatMessageContent(AuthorRole.Assistant, c.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
231
src/AntSk.LLM/SparkDesk/SparkDeskChatCompletion.cs
Normal file
231
src/AntSk.LLM/SparkDesk/SparkDeskChatCompletion.cs
Normal file
@@ -0,0 +1,231 @@
|
||||
using Microsoft.SemanticKernel.ChatCompletion;
|
||||
using Microsoft.SemanticKernel.Connectors.OpenAI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Sdcb.SparkDesk;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.Json;
|
||||
using System.Text.Unicode;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AntSK.LLM.SparkDesk
|
||||
{
|
||||
public class SparkDeskChatCompletion : IChatCompletionService
|
||||
{
|
||||
private readonly Dictionary<string, object?> _attributes = new();
|
||||
private readonly SparkDeskClient _client;
|
||||
private string _chatId;
|
||||
private readonly SparkDeskOptions _options;
|
||||
|
||||
private static readonly JsonSerializerOptions _jsonSerializerOptions = new()
|
||||
{
|
||||
NumberHandling = JsonNumberHandling.AllowReadingFromString,
|
||||
Encoder = JavaScriptEncoder.Create(UnicodeRanges.All)
|
||||
};
|
||||
|
||||
public IReadOnlyDictionary<string, object?> Attributes => _attributes;
|
||||
|
||||
public SparkDeskChatCompletion(SparkDeskOptions options, string chatId)
|
||||
{
|
||||
_options = options;
|
||||
_chatId = chatId;
|
||||
_client = new(options.AppId, options.ApiKey, options.ApiSecret);
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyList<ChatMessageContent>> GetChatMessageContentsAsync(ChatHistory chatHistory, PromptExecutionSettings? executionSettings = null, Kernel? kernel = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
StringBuilder sb = new();
|
||||
var parameters = new ChatRequestParameters
|
||||
{
|
||||
ChatId = _chatId,
|
||||
};
|
||||
|
||||
OpenAIPromptExecutionSettings chatExecutionSettings = OpenAIPromptExecutionSettings.FromExecutionSettings(executionSettings);
|
||||
|
||||
parameters.Temperature = (float)chatExecutionSettings.Temperature;
|
||||
parameters.MaxTokens = chatExecutionSettings.MaxTokens ?? parameters.MaxTokens;
|
||||
|
||||
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", p.Description, p.IsRequired)).ToList())).ToList();
|
||||
|
||||
List<ChatMessage> messages = GetSparkMessage(chatHistory);
|
||||
|
||||
var result = await _client.ChatAsync(_options.ModelVersion, messages.ToArray(), parameters, functionDefs.Count > 0 ? [.. functionDefs] : null, cancellationToken: cancellationToken);
|
||||
|
||||
if (result.FunctionCall != null)
|
||||
{
|
||||
var func = functions.Where(x => x.Name == result.FunctionCall.Name).FirstOrDefault();
|
||||
|
||||
if (func == null)
|
||||
{
|
||||
return new List<ChatMessageContent> { new(AuthorRole.Assistant, $"插件{result.FunctionCall.Name}未注册") }.AsReadOnly();
|
||||
}
|
||||
|
||||
if (kernel.Plugins.TryGetFunction(func.PluginName, func.Name, out var function))
|
||||
{
|
||||
var arguments = new KernelArguments();
|
||||
|
||||
var JsonElement = JsonDocument.Parse(result.FunctionCall.Arguments).RootElement;
|
||||
foreach (var parameter in func.Parameters)
|
||||
{
|
||||
var error = "";
|
||||
try
|
||||
{
|
||||
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))
|
||||
{
|
||||
return new List<ChatMessageContent> { new(AuthorRole.Assistant, error) }.AsReadOnly();
|
||||
|
||||
}
|
||||
}
|
||||
var functionResult = await function.InvokeAsync(kernel, arguments, cancellationToken);
|
||||
messages = [ ChatMessage.FromUser(messages.LastOrDefault().Content),
|
||||
ChatMessage.FromSystem($@"
|
||||
执行函数调用成功
|
||||
函数描述:{func.Description}
|
||||
函数执行结果:{functionResult}
|
||||
"),
|
||||
ChatMessage.FromUser("请根据函数调用结果回答我的问题,不要超出函数调用结果的返回,以及不要有多余描述:")];
|
||||
|
||||
|
||||
var callResult = await _client.ChatAsync(_options.ModelVersion, messages.ToArray(), parameters, null);
|
||||
ChatMessageContent chatMessageContent = new(AuthorRole.Assistant, callResult.Text.ToString(), modelId: "SparkDesk");
|
||||
|
||||
return new List<ChatMessageContent> { chatMessageContent }.AsReadOnly();
|
||||
|
||||
}
|
||||
return new List<ChatMessageContent> { new(AuthorRole.Assistant, "未找到插件") }.AsReadOnly();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
ChatMessageContent chatMessageContent = new(AuthorRole.Assistant, result.Text.ToString(), modelId: "SparkDesk");
|
||||
|
||||
return new List<ChatMessageContent> { chatMessageContent }.AsReadOnly();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public async IAsyncEnumerable<StreamingChatMessageContent> GetStreamingChatMessageContentsAsync(ChatHistory chatHistory, PromptExecutionSettings? executionSettings = null, Kernel? kernel = null, [EnumeratorCancellation] CancellationToken cancellationToken = default)
|
||||
{
|
||||
var parameters = new ChatRequestParameters
|
||||
{
|
||||
ChatId = _chatId,
|
||||
};
|
||||
OpenAIPromptExecutionSettings chatExecutionSettings = OpenAIPromptExecutionSettings.FromExecutionSettings(executionSettings);
|
||||
|
||||
parameters.Temperature = (float)chatExecutionSettings.Temperature;
|
||||
parameters.MaxTokens = chatExecutionSettings.MaxTokens ?? parameters.MaxTokens;
|
||||
|
||||
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", p.Description, p.IsRequired)).ToList())).ToList();
|
||||
List<ChatMessage> messages = GetSparkMessage(chatHistory);
|
||||
await foreach (StreamedChatResponse msg in _client.ChatAsStreamAsync(_options.ModelVersion, messages.ToArray(), parameters, functionDefs.Count > 0 ? [.. functionDefs] : null, cancellationToken: cancellationToken))
|
||||
{
|
||||
|
||||
yield return new StreamingChatMessageContent(AuthorRole.Assistant, msg);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
private static List<ChatMessage> GetSparkMessage(ChatHistory chatHistory)
|
||||
{
|
||||
List<ChatMessage> messages = new List<ChatMessage>();
|
||||
foreach (var msg in chatHistory.ToList())
|
||||
{
|
||||
string role = "";
|
||||
if (msg.Role == AuthorRole.User)
|
||||
{
|
||||
role = "user";
|
||||
}
|
||||
else if (msg.Role == AuthorRole.System)
|
||||
{
|
||||
role = "system";
|
||||
}
|
||||
else
|
||||
{
|
||||
role = "assistant";
|
||||
}
|
||||
messages.Add(new ChatMessage(role, msg.ToString()));
|
||||
}
|
||||
|
||||
return messages;
|
||||
}
|
||||
|
||||
|
||||
private static string? ProcessFunctionResult(object functionResult, ToolCallBehavior? toolCallBehavior)
|
||||
{
|
||||
if (functionResult is string stringResult)
|
||||
{
|
||||
return stringResult;
|
||||
}
|
||||
|
||||
if (functionResult is ChatMessageContent chatMessageContent)
|
||||
{
|
||||
return chatMessageContent.ToString();
|
||||
}
|
||||
|
||||
return JsonSerializer.Serialize(functionResult, _jsonSerializerOptions);
|
||||
}
|
||||
|
||||
public static Dictionary<string, object> ParseJsonElement(JsonElement element, string propertyName)
|
||||
{
|
||||
Dictionary<string, object> dict = new();
|
||||
|
||||
switch (element.ValueKind)
|
||||
{
|
||||
case JsonValueKind.Object:
|
||||
foreach (JsonProperty property in element.EnumerateObject())
|
||||
{
|
||||
dict.Add(property.Name, ParseJsonElement(property.Value, property.Name));
|
||||
}
|
||||
break;
|
||||
|
||||
case JsonValueKind.Array:
|
||||
List<object> list = new List<object>();
|
||||
foreach (JsonElement arrayElement in element.EnumerateArray())
|
||||
{
|
||||
list.Add(ParseJsonElement(arrayElement, ""));
|
||||
}
|
||||
dict.Add(propertyName, list);
|
||||
break;
|
||||
|
||||
case JsonValueKind.String:
|
||||
dict.Add(propertyName, element.GetString());
|
||||
break;
|
||||
|
||||
case JsonValueKind.Number:
|
||||
dict.Add(propertyName, element.GetInt32());
|
||||
break;
|
||||
|
||||
case JsonValueKind.True:
|
||||
case JsonValueKind.False:
|
||||
dict.Add(propertyName, element.GetBoolean());
|
||||
break;
|
||||
|
||||
default:
|
||||
dict.Add(propertyName, "Unsupported value type");
|
||||
break;
|
||||
}
|
||||
|
||||
return dict;
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user