git pull dev
This commit is contained in:
commit
80f44ba24e
52
README.md
52
README.md
|
|
@ -41,7 +41,7 @@
|
||||||
|
|
||||||
🚩 本项目未涉及微调、训练过程,但可利用微调或训练对本项目效果进行优化。
|
🚩 本项目未涉及微调、训练过程,但可利用微调或训练对本项目效果进行优化。
|
||||||
|
|
||||||
🌐 [AutoDL 镜像](https://www.codewithgpu.com/i/imClumsyPanda/langchain-ChatGLM/langchain-ChatGLM) 中 v4 版本所使用代码已更新至本项目 `0.2.0` 版本。
|
🌐 [AutoDL 镜像](https://www.codewithgpu.com/i/imClumsyPanda/langchain-ChatGLM/langchain-ChatGLM) 中 `v5` 版本所使用代码已更新至本项目 `0.2.0` 版本。
|
||||||
|
|
||||||
🐳 [Docker 镜像](registry.cn-beijing.aliyuncs.com/chatchat/chatchat:0.2.0)
|
🐳 [Docker 镜像](registry.cn-beijing.aliyuncs.com/chatchat/chatchat:0.2.0)
|
||||||
|
|
||||||
|
|
@ -57,7 +57,7 @@ docker run -d --gpus all -p 80:8501 registry.cn-beijing.aliyuncs.com/chatchat/ch
|
||||||
|
|
||||||
参见 [版本更新日志](https://github.com/imClumsyPanda/langchain-ChatGLM/releases)。
|
参见 [版本更新日志](https://github.com/imClumsyPanda/langchain-ChatGLM/releases)。
|
||||||
|
|
||||||
从 `0.1.x`升级过来的用户请注意,在完成[“开发部署 3 设置配置项”](docs/INSTALL.md)之后,需要将现有知识库迁移到新格式,具体见[知识库初始化与迁移](docs/INSTALL.md#知识库初始化与迁移)。
|
从 `0.1.x` 升级过来的用户请注意,需要按照[开发部署](README.md#3.-开发部署)过程操作,将现有知识库迁移到新格式,具体见[知识库初始化与迁移](docs/INSTALL.md#知识库初始化与迁移)。
|
||||||
|
|
||||||
### `0.2.0` 版本与 `0.1.x` 版本区别
|
### `0.2.0` 版本与 `0.1.x` 版本区别
|
||||||
|
|
||||||
|
|
@ -144,7 +144,7 @@ docker run -d --gpus all -p 80:8501 registry.cn-beijing.aliyuncs.com/chatchat/ch
|
||||||
```
|
```
|
||||||
|
|
||||||
- 该版本镜像大小 `33.9GB`,使用 `v0.2.0`,以 `nvidia/cuda:12.1.1-cudnn8-devel-ubuntu22.04` 为基础镜像
|
- 该版本镜像大小 `33.9GB`,使用 `v0.2.0`,以 `nvidia/cuda:12.1.1-cudnn8-devel-ubuntu22.04` 为基础镜像
|
||||||
- 该版本内置一个 `embedding` 模型:`m3e-large`,内置 `fastchat+chatglm2-6b-32k`
|
- 该版本内置一个 `embedding` 模型:`m3e-large`,内置 `chatglm2-6b-32k`
|
||||||
- 该版本目标为方便一键部署使用,请确保您已经在Linux发行版上安装了NVIDIA驱动程序
|
- 该版本目标为方便一键部署使用,请确保您已经在Linux发行版上安装了NVIDIA驱动程序
|
||||||
- 请注意,您不需要在主机系统上安装CUDA工具包,但需要安装 `NVIDIA Driver` 以及 `NVIDIA Container Toolkit`,请参考[安装指南](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html)
|
- 请注意,您不需要在主机系统上安装CUDA工具包,但需要安装 `NVIDIA Driver` 以及 `NVIDIA Container Toolkit`,请参考[安装指南](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html)
|
||||||
- 首次拉取和启动均需要一定时间,首次启动时请参照下图使用 `docker logs -f <container id>` 查看日志
|
- 首次拉取和启动均需要一定时间,首次启动时请参照下图使用 `docker logs -f <container id>` 查看日志
|
||||||
|
|
@ -162,7 +162,7 @@ docker run -d --gpus all -p 80:8501 registry.cn-beijing.aliyuncs.com/chatchat/ch
|
||||||
|
|
||||||
参见 [开发环境准备](docs/INSTALL.md)。
|
参见 [开发环境准备](docs/INSTALL.md)。
|
||||||
|
|
||||||
**请注意:** `0.2.0`及更新版本的依赖包与 `0.1.x`版本依赖包可能发生冲突,强烈建议新建环境后重新安装依赖包。
|
**请注意:** `0.2.0` 及更新版本的依赖包与 `0.1.x` 版本依赖包可能发生冲突,强烈建议新建环境后重新安装依赖包。
|
||||||
|
|
||||||
### 2. 下载模型至本地
|
### 2. 下载模型至本地
|
||||||
|
|
||||||
|
|
@ -190,7 +190,7 @@ $ git clone https://huggingface.co/moka-ai/m3e-base
|
||||||
llm_model_dict={
|
llm_model_dict={
|
||||||
"chatglm2-6b": {
|
"chatglm2-6b": {
|
||||||
"local_model_path": "/Users/xxx/Downloads/chatglm2-6b",
|
"local_model_path": "/Users/xxx/Downloads/chatglm2-6b",
|
||||||
"api_base_url": "http://localhost:8888/v1", # "name"修改为fastchat服务中的"api_base_url"
|
"api_base_url": "http://localhost:8888/v1", # "name"修改为 FastChat 服务中的"api_base_url"
|
||||||
"api_key": "EMPTY"
|
"api_key": "EMPTY"
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -213,6 +213,7 @@ embedding_model_dict = {
|
||||||
```shell
|
```shell
|
||||||
$ python init_database.py
|
$ python init_database.py
|
||||||
```
|
```
|
||||||
|
|
||||||
- 如果您是第一次运行本项目,知识库尚未建立,或者配置文件中的知识库类型、嵌入模型发生变化,需要以下命令初始化或重建知识库:
|
- 如果您是第一次运行本项目,知识库尚未建立,或者配置文件中的知识库类型、嵌入模型发生变化,需要以下命令初始化或重建知识库:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
|
|
@ -223,11 +224,17 @@ embedding_model_dict = {
|
||||||
|
|
||||||
#### 5.1 启动 LLM 服务
|
#### 5.1 启动 LLM 服务
|
||||||
|
|
||||||
**!!!注意1**:5.1.1-5.1.3三种方式只需选择一个即可。
|
如需使用开源模型进行本地部署,需首先启动 LLM 服务,启动方式分为三种:
|
||||||
|
|
||||||
**!!!注意2**:如果启动在线的API服务(如OPENAI的api接口),则无需启动LLM服务,即5.1小节的任何命令均无需启动。
|
- [基于多进程脚本 llm_api.py 启动 LLM 服务](README.md#5.1.1-基于多进程脚本-llm_api.py-启动-LLM-服务)
|
||||||
|
- [基于命令行脚本 llm_api_launch.py 启动 LLM 服务](README.md#5.1.2-基于命令行脚本-llm_api_launch.py-启动-LLM-服务)
|
||||||
|
- [LoRA 加载](README.md#5.1.3-LoRA-加载)
|
||||||
|
|
||||||
##### 5.1.1 基于多进程脚本llm_api.py启动LLM服务
|
三种方式只需选择一个即可,具体操作方式详见 5.1.1 - 5.1.3。
|
||||||
|
|
||||||
|
如果启动在线的API服务(如 OPENAI 的 API 接口),则无需启动 LLM 服务,即 5.1 小节的任何命令均无需启动。
|
||||||
|
|
||||||
|
##### 5.1.1 基于多进程脚本 llm_api.py 启动 LLM 服务
|
||||||
|
|
||||||
在项目根目录下,执行 [server/llm_api.py](server/llm_api.py) 脚本启动 **LLM 模型**服务:
|
在项目根目录下,执行 [server/llm_api.py](server/llm_api.py) 脚本启动 **LLM 模型**服务:
|
||||||
|
|
||||||
|
|
@ -235,9 +242,19 @@ embedding_model_dict = {
|
||||||
$ python server/llm_api.py
|
$ python server/llm_api.py
|
||||||
```
|
```
|
||||||
|
|
||||||
项目支持多卡加载,需在llm_api.py中修改create_model_worker_app函数中,修改gpus=None,num_gpus=1,max_gpu_memory="20GiB",三个参数,其中gpus控制使用的卡的ID,如果“0,1";num_gpus控制使用的卡数;max_gpu_memory控制每个卡使用的显存容量。
|
项目支持多卡加载,需在 llm_api.py 中修改 create_model_worker_app 函数中,修改如下三个参数:
|
||||||
|
```python
|
||||||
|
gpus=None,
|
||||||
|
num_gpus=1,
|
||||||
|
max_gpu_memory="20GiB"
|
||||||
|
```
|
||||||
|
其中,`gpus` 控制使用的显卡的ID,如果 "0,1";
|
||||||
|
|
||||||
##### 5.1.2 基于命令行脚本llm_api_launch.py启动LLM服务
|
`num_gpus` 控制使用的卡数;
|
||||||
|
|
||||||
|
`max_gpu_memory` 控制每个卡使用的显存容量。
|
||||||
|
|
||||||
|
##### 5.1.2 基于命令行脚本 llm_api_launch.py 启动 LLM 服务
|
||||||
|
|
||||||
在项目根目录下,执行 [server/llm_api_launch.py](server/llm_api.py) 脚本启动 **LLM 模型**服务:
|
在项目根目录下,执行 [server/llm_api_launch.py](server/llm_api.py) 脚本启动 **LLM 模型**服务:
|
||||||
|
|
||||||
|
|
@ -263,11 +280,11 @@ $ python server/llm_api_launch.py --gpus 0,1 --num-gpus 2 --max-gpu-memory 10GiB
|
||||||
$ python server/llm_api_shutdown.py --serve all
|
$ python server/llm_api_shutdown.py --serve all
|
||||||
```
|
```
|
||||||
|
|
||||||
亦可单独停止一个 fastchat 服务模块,可选 [`all`, `controller`, `model_worker`, `openai_api_server`]
|
亦可单独停止一个 FastChat 服务模块,可选 [`all`, `controller`, `model_worker`, `openai_api_server`]
|
||||||
|
|
||||||
##### 5.1.3 lora加载
|
##### 5.1.3 LoRA 加载
|
||||||
|
|
||||||
本项目基于fastchat加载LLM服务,故需以fastchat加载lora路径,即保证路径名称里必须有peft这个词,配置文件的名字为adapter_config.json,peft路径下包含model.bin格式的lora权重。
|
本项目基于 FastChat 加载 LLM 服务,故需以 FastChat 加载 LoRA 路径,即保证路径名称里必须有 peft 这个词,配置文件的名字为 adapter_config.json,peft 路径下包含 model.bin 格式的 LoRA 权重。
|
||||||
|
|
||||||
示例代码如下:
|
示例代码如下:
|
||||||
|
|
||||||
|
|
@ -282,11 +299,11 @@ PEFT_SHARE_BASE_WEIGHTS=true python3 -m fastchat.serve.multi_model_worker \
|
||||||
--num-gpus 2
|
--num-gpus 2
|
||||||
```
|
```
|
||||||
|
|
||||||
详见 https://github.com/lm-sys/FastChat/pull/1905#issuecomment-1627801216
|
详见 [FastChat 相关 PR](https://github.com/lm-sys/fastchat/pull/1905#issuecomment-1627801216)
|
||||||
|
|
||||||
#### 5.2 启动 API 服务
|
#### 5.2 启动 API 服务
|
||||||
|
|
||||||
本地部署情况下,!!!**启动LLM 服务后!!!**,再执行 [server/api.py](server/api.py) 脚本启动 **API** 服务;
|
本地部署情况下,按照 [5.1 节](README.md#5.1-启动-LLM-服务)**启动 LLM 服务后**,再执行 [server/api.py](server/api.py) 脚本启动 **API** 服务;
|
||||||
|
|
||||||
在线调用API服务的情况下,直接执执行 [server/api.py](server/api.py) 脚本启动 **API** 服务;
|
在线调用API服务的情况下,直接执执行 [server/api.py](server/api.py) 脚本启动 **API** 服务;
|
||||||
|
|
||||||
|
|
@ -304,7 +321,7 @@ $ python server/api.py
|
||||||
|
|
||||||
#### 5.3 启动 Web UI 服务
|
#### 5.3 启动 Web UI 服务
|
||||||
|
|
||||||
**!!!启动API服务后!!!**,执行 [webui.py](webui.py) 启动 **Web UI** 服务(默认使用端口 `8501`)
|
按照 [5.2 节](README.md#5.2-启动-API-服务)**启动 API 服务后**,执行 [webui.py](webui.py) 启动 **Web UI** 服务(默认使用端口 `8501`)
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ streamlit run webui.py
|
$ streamlit run webui.py
|
||||||
|
|
@ -325,6 +342,7 @@ $ streamlit run webui.py --server.port 666
|
||||||
- Web UI 对话界面:
|
- Web UI 对话界面:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
- Web UI 知识库管理页面:
|
- Web UI 知识库管理页面:
|
||||||
|
|
||||||

|

|
||||||
|
|
@ -409,7 +427,7 @@ python webui_alline.py --model-path-address model@host@port --num-gpus 2 --gpus
|
||||||
- [X] DuckDuckGo 搜索
|
- [X] DuckDuckGo 搜索
|
||||||
- [ ] Agent 实现
|
- [ ] Agent 实现
|
||||||
- [X] LLM 模型接入
|
- [X] LLM 模型接入
|
||||||
- [X] 支持通过调用 [fastchat](https://github.com/lm-sys/FastChat) api 调用 llm
|
- [X] 支持通过调用 [FastChat](https://github.com/lm-sys/fastchat) api 调用 llm
|
||||||
- [ ] 支持 ChatGLM API 等 LLM API 的接入
|
- [ ] 支持 ChatGLM API 等 LLM API 的接入
|
||||||
- [X] Embedding 模型接入
|
- [X] Embedding 模型接入
|
||||||
- [X] 支持调用 HuggingFace 中各开源 Emebdding 模型
|
- [X] 支持调用 HuggingFace 中各开源 Emebdding 模型
|
||||||
|
|
|
||||||
|
|
@ -78,9 +78,9 @@ llm_model_dict = {
|
||||||
# urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPSConnection object at 0x000001FE4BDB85E0>:
|
# urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPSConnection object at 0x000001FE4BDB85E0>:
|
||||||
# Failed to establish a new connection: [WinError 10060]
|
# Failed to establish a new connection: [WinError 10060]
|
||||||
# 则是因为内地和香港的IP都被OPENAI封了,需要切换为日本、新加坡等地
|
# 则是因为内地和香港的IP都被OPENAI封了,需要切换为日本、新加坡等地
|
||||||
"openai-chatgpt-3.5": {
|
"gpt-3.5-turbo": {
|
||||||
"local_model_path": "gpt-3.5-turbo",
|
"local_model_path": "gpt-3.5-turbo",
|
||||||
"api_base_url": "https://api.openapi.com/v1",
|
"api_base_url": "https://api.openai.com/v1",
|
||||||
"api_key": os.environ.get("OPENAI_API_KEY")
|
"api_key": os.environ.get("OPENAI_API_KEY")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,18 @@ def delete_file_from_db(session, kb_file: KnowledgeFile):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@with_session
|
||||||
|
def delete_files_from_db(session, knowledge_base_name: str):
|
||||||
|
session.query(KnowledgeFileModel).filter_by(kb_name=knowledge_base_name).delete()
|
||||||
|
|
||||||
|
kb = session.query(KnowledgeBaseModel).filter_by(kb_name=knowledge_base_name).first()
|
||||||
|
if kb:
|
||||||
|
kb.file_count = 0
|
||||||
|
|
||||||
|
session.commit()
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
@with_session
|
@with_session
|
||||||
def doc_exists(session, kb_file: KnowledgeFile):
|
def doc_exists(session, kb_file: KnowledgeFile):
|
||||||
existing_file = session.query(KnowledgeFileModel).filter_by(file_name=kb_file.filename,
|
existing_file = session.query(KnowledgeFileModel).filter_by(file_name=kb_file.filename,
|
||||||
|
|
|
||||||
|
|
@ -44,8 +44,12 @@ async def delete_kb(
|
||||||
if kb is None:
|
if kb is None:
|
||||||
return BaseResponse(code=404, msg=f"未找到知识库 {knowledge_base_name}")
|
return BaseResponse(code=404, msg=f"未找到知识库 {knowledge_base_name}")
|
||||||
|
|
||||||
status = kb.drop_kb()
|
try:
|
||||||
if status:
|
status = kb.clear_vs()
|
||||||
return BaseResponse(code=200, msg=f"成功删除知识库 {knowledge_base_name}")
|
status = kb.drop_kb()
|
||||||
else:
|
if status:
|
||||||
return BaseResponse(code=500, msg=f"删除知识库失败 {knowledge_base_name}")
|
return BaseResponse(code=200, msg=f"成功删除知识库 {knowledge_base_name}")
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
|
||||||
|
return BaseResponse(code=500, msg=f"删除知识库失败 {knowledge_base_name}")
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@ from server.db.repository.knowledge_base_repository import (
|
||||||
load_kb_from_db, get_kb_detail,
|
load_kb_from_db, get_kb_detail,
|
||||||
)
|
)
|
||||||
from server.db.repository.knowledge_file_repository import (
|
from server.db.repository.knowledge_file_repository import (
|
||||||
add_doc_to_db, delete_file_from_db, doc_exists,
|
add_doc_to_db, delete_file_from_db, delete_files_from_db, doc_exists,
|
||||||
list_docs_from_db, get_file_detail
|
list_docs_from_db, get_file_detail, delete_file_from_db
|
||||||
)
|
)
|
||||||
|
|
||||||
from configs.model_config import (kbs_config, VECTOR_SEARCH_TOP_K,
|
from configs.model_config import (kbs_config, VECTOR_SEARCH_TOP_K,
|
||||||
|
|
@ -56,9 +56,12 @@ class KBService(ABC):
|
||||||
|
|
||||||
def clear_vs(self):
|
def clear_vs(self):
|
||||||
"""
|
"""
|
||||||
用知识库中已上传文件重建向量库
|
删除向量库中所有内容
|
||||||
"""
|
"""
|
||||||
self.do_clear_vs()
|
self.do_clear_vs()
|
||||||
|
status = delete_files_from_db(self.kb_name)
|
||||||
|
return status
|
||||||
|
|
||||||
|
|
||||||
def drop_kb(self):
|
def drop_kb(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
url = 'http://localhost:7861/chat/chat'
|
||||||
|
headers = {
|
||||||
|
'accept': 'application/json',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
}
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"query": "请用100字左右的文字介绍自己",
|
||||||
|
"history": [
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": "你好"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "assistant",
|
||||||
|
"content": "你好,我是 ChatGLM"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stream": True
|
||||||
|
}
|
||||||
|
|
||||||
|
response = requests.post(url, headers=headers, data=json.dumps(data), stream=True)
|
||||||
|
if response.status_code == 200:
|
||||||
|
for line in response.iter_content(decode_unicode=True):
|
||||||
|
print(line, flush=True)
|
||||||
|
else:
|
||||||
|
print("Error:", response.status_code)
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
import sqlite3
|
|
||||||
|
|
||||||
import streamlit as st
|
import streamlit as st
|
||||||
from webui_pages.utils import *
|
from webui_pages.utils import *
|
||||||
from st_aggrid import AgGrid, JsCode
|
from st_aggrid import AgGrid, JsCode
|
||||||
|
|
@ -9,6 +7,9 @@ from server.knowledge_base.utils import get_file_path, LOADER_DICT
|
||||||
from server.knowledge_base.kb_service.base import get_kb_details, get_kb_doc_details
|
from server.knowledge_base.kb_service.base import get_kb_details, get_kb_doc_details
|
||||||
from typing import Literal, Dict, Tuple
|
from typing import Literal, Dict, Tuple
|
||||||
from configs.model_config import embedding_model_dict, kbs_config, EMBEDDING_MODEL, DEFAULT_VS_TYPE
|
from configs.model_config import embedding_model_dict, kbs_config, EMBEDDING_MODEL, DEFAULT_VS_TYPE
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
# SENTENCE_SIZE = 100
|
# SENTENCE_SIZE = 100
|
||||||
|
|
||||||
|
|
@ -33,6 +34,19 @@ def config_aggrid(
|
||||||
return gb
|
return gb
|
||||||
|
|
||||||
|
|
||||||
|
def file_exists(kb: str, selected_rows: List) -> Tuple[str, str]:
|
||||||
|
'''
|
||||||
|
check whether a doc file exists in local knowledge base folder.
|
||||||
|
return the file's name and path if it exists.
|
||||||
|
'''
|
||||||
|
if selected_rows:
|
||||||
|
file_name = selected_rows[0]["file_name"]
|
||||||
|
file_path = get_file_path(kb, file_name)
|
||||||
|
if os.path.isfile(file_path):
|
||||||
|
return file_name, file_path
|
||||||
|
return "", ""
|
||||||
|
|
||||||
|
|
||||||
def knowledge_base_page(api: ApiRequest):
|
def knowledge_base_page(api: ApiRequest):
|
||||||
try:
|
try:
|
||||||
kb_list = get_kb_details()
|
kb_list = get_kb_details()
|
||||||
|
|
@ -174,9 +188,8 @@ def knowledge_base_page(api: ApiRequest):
|
||||||
selected_rows = doc_grid.get("selected_rows", [])
|
selected_rows = doc_grid.get("selected_rows", [])
|
||||||
|
|
||||||
cols = st.columns(4)
|
cols = st.columns(4)
|
||||||
if selected_rows:
|
file_name, file_path = file_exists(kb, selected_rows)
|
||||||
file_name = selected_rows[0]["file_name"]
|
if file_path:
|
||||||
file_path = get_file_path(kb, file_name)
|
|
||||||
with open(file_path, "rb") as fp:
|
with open(file_path, "rb") as fp:
|
||||||
cols[0].download_button(
|
cols[0].download_button(
|
||||||
"下载选中文档",
|
"下载选中文档",
|
||||||
|
|
@ -194,7 +207,7 @@ def knowledge_base_page(api: ApiRequest):
|
||||||
# 将文件分词并加载到向量库中
|
# 将文件分词并加载到向量库中
|
||||||
if cols[1].button(
|
if cols[1].button(
|
||||||
"重新添加至向量库" if selected_rows and (pd.DataFrame(selected_rows)["in_db"]).any() else "添加至向量库",
|
"重新添加至向量库" if selected_rows and (pd.DataFrame(selected_rows)["in_db"]).any() else "添加至向量库",
|
||||||
disabled=len(selected_rows) == 0,
|
disabled=not file_exists(kb, selected_rows)[0],
|
||||||
use_container_width=True,
|
use_container_width=True,
|
||||||
):
|
):
|
||||||
for row in selected_rows:
|
for row in selected_rows:
|
||||||
|
|
@ -204,7 +217,7 @@ def knowledge_base_page(api: ApiRequest):
|
||||||
# 将文件从向量库中删除,但不删除文件本身。
|
# 将文件从向量库中删除,但不删除文件本身。
|
||||||
if cols[2].button(
|
if cols[2].button(
|
||||||
"从向量库删除",
|
"从向量库删除",
|
||||||
disabled=len(selected_rows) == 0,
|
disabled=not (selected_rows and selected_rows[0]["in_db"]),
|
||||||
use_container_width=True,
|
use_container_width=True,
|
||||||
):
|
):
|
||||||
for row in selected_rows:
|
for row in selected_rows:
|
||||||
|
|
@ -245,5 +258,6 @@ def knowledge_base_page(api: ApiRequest):
|
||||||
use_container_width=True,
|
use_container_width=True,
|
||||||
):
|
):
|
||||||
ret = api.delete_knowledge_base(kb)
|
ret = api.delete_knowledge_base(kb)
|
||||||
st.experimental_rerun()
|
|
||||||
st.toast(ret["msg"])
|
st.toast(ret["msg"])
|
||||||
|
time.sleep(1)
|
||||||
|
st.experimental_rerun()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue