Unverified 提交 a53eb670 作者: imClumsyPanda 提交者: GitHub

Merge pull request #56 from liangtongt/master

新增 Web UI
...@@ -10,6 +10,20 @@ ...@@ -10,6 +10,20 @@
✅ 本项目中 Embedding 选用的是 [GanymedeNil/text2vec-large-chinese](https://huggingface.co/GanymedeNil/text2vec-large-chinese/tree/main),LLM 选用的是 [ChatGLM-6B](https://github.com/THUDM/ChatGLM-6B)。依托上述模型,本项目可实现全部使用**开源**模型**离线私有部署** ✅ 本项目中 Embedding 选用的是 [GanymedeNil/text2vec-large-chinese](https://huggingface.co/GanymedeNil/text2vec-large-chinese/tree/main),LLM 选用的是 [ChatGLM-6B](https://github.com/THUDM/ChatGLM-6B)。依托上述模型,本项目可实现全部使用**开源**模型**离线私有部署**
## webui
![webui](./img/ui1.png)
根据上图依次点击step1~3,即可完成模型加载,加载文件,以及对话历史记录的查看
![webui](./img/ui2.png)
点击底部Use via API可查看API接口,现有应用可通过post请求进行对接调用
### TODO
- [ ] 添加模型加载进度条
- [ ] 添加输出内容及错误提示
- [ ] 国际化语言切换
- [ ] 引用标注
- [ ] 添加插件系统(可基础lora训练等)
## 更新信息 ## 更新信息
**[2023/04/07]** **[2023/04/07]**
...@@ -23,6 +37,9 @@ ...@@ -23,6 +37,9 @@
3. 增加 GPU 显存需求更小的`chatglm-6b-int4``chatglm-6b-int4-qe`作为 LLM 模型备选项; 3. 增加 GPU 显存需求更小的`chatglm-6b-int4``chatglm-6b-int4-qe`作为 LLM 模型备选项;
4. 更正`README.md`中的代码错误(感谢 [@calcitem](https://github.com/calcitem))。 4. 更正`README.md`中的代码错误(感谢 [@calcitem](https://github.com/calcitem))。
**[2023/04/11]**
1. 加入 Web UI V0.1 版本。
## 使用方式 ## 使用方式
...@@ -46,10 +63,27 @@ pip install -r requirements.txt ...@@ -46,10 +63,27 @@ pip install -r requirements.txt
``` ```
注:使用 langchain.document_loaders.UnstructuredFileLoader 进行非结构化文件接入时,可能需要依据文档进行其他依赖包的安装,请参考 [langchain 文档](https://python.langchain.com/en/latest/modules/indexes/document_loaders/examples/unstructured_file.html) 注:使用 langchain.document_loaders.UnstructuredFileLoader 进行非结构化文件接入时,可能需要依据文档进行其他依赖包的安装,请参考 [langchain 文档](https://python.langchain.com/en/latest/modules/indexes/document_loaders/examples/unstructured_file.html)
### 2. 执行 [knowledge_based_chatglm.py](knowledge_based_chatglm.py) 脚本 ### 2. 执行脚本体验 Web UI 或命令行交互
执行 [webui.py](webui.py) 脚本体验 **Web 交互**
```commandline
python webui.py
```
执行后效果如下图所示:
![webui](./img/ui1.png)
Web UI 中提供的 API 接口如下图所示:
![webui](./img/ui2.png)
Web UI 可以实现如下功能:
1. 自动读取`knowledge_based_chatglm.py``LLM``embedding`模型枚举,选择后点击`setting`进行模型加载,可随时切换模型进行测试
2. 可手动调节保留对话历史长度,可根据显存大小自行调节
3. 添加上传文件功能,通过下拉框选择已上传的文件,点击`loading`加载文件,过程中可随时更换加载的文件
4. 底部添加`use via API`可对接到自己系统
或执行 [knowledge_based_chatglm.py](knowledge_based_chatglm.py) 脚本体验**命令行交互**
```commandline ```commandline
python knowledge_based_chatglm.py python knowledge_based_chatglm.py
``` ```
### 已知问题 ### 已知问题
- 目前已测试支持 txt、docx、md 格式文件,更多文件格式请参考 [langchain 文档](https://python.langchain.com/en/latest/modules/indexes/document_loaders/examples/unstructured_file.html),目前已知文档中若含有特殊字符,可能存在文件无法加载的问题; - 目前已测试支持 txt、docx、md 格式文件,更多文件格式请参考 [langchain 文档](https://python.langchain.com/en/latest/modules/indexes/document_loaders/examples/unstructured_file.html),目前已知文档中若含有特殊字符,可能存在文件无法加载的问题;
- 使用 macOS 运行本项目时,可能因为 macOS 版本为 13.3 及以上版本导致与 pytorch 不兼容,无法正常运行的情况。 - 使用 macOS 运行本项目时,可能因为 macOS 版本为 13.3 及以上版本导致与 pytorch 不兼容,无法正常运行的情况。
...@@ -94,9 +128,6 @@ A: 将 https://github.com/nltk/nltk_data/blob/gh-pages/packages/taggers/averaged ...@@ -94,9 +128,6 @@ A: 将 https://github.com/nltk/nltk_data/blob/gh-pages/packages/taggers/averaged
>4. 引入更多的评估指标:可以引入更多的评估指标来评估模型的表现,从而发现 ChatGLM-6B 存在的不足和局限性。 >4. 引入更多的评估指标:可以引入更多的评估指标来评估模型的表现,从而发现 ChatGLM-6B 存在的不足和局限性。
>5. 改进模型架构:可以改进 ChatGLM-6B 的模型架构,提高模型的性能和表现。例如,可以使用更大的神经网络或者改进的卷积神经网络结构。 >5. 改进模型架构:可以改进 ChatGLM-6B 的模型架构,提高模型的性能和表现。例如,可以使用更大的神经网络或者改进的卷积神经网络结构。
## 路线图 ## 路线图
- [x] 实现 langchain + ChatGLM-6B 本地知识应用 - [x] 实现 langchain + ChatGLM-6B 本地知识应用
- [x] 基于 langchain 实现非结构化文件接入 - [x] 基于 langchain 实现非结构化文件接入
......
...@@ -10,7 +10,29 @@ ...@@ -10,7 +10,29 @@
✅ In this project, [GanymedeNil/text2vec-large-chinese](https://huggingface.co/GanymedeNil/text2vec-large-chinese/tree/main) is used as Embedding Model,and [ChatGLM-6B](https://github.com/THUDM/ChatGLM-6B) used as LLM。Based on those models,this project can be deployed **offline** with all **open source** models。 ✅ In this project, [GanymedeNil/text2vec-large-chinese](https://huggingface.co/GanymedeNil/text2vec-large-chinese/tree/main) is used as Embedding Model,and [ChatGLM-6B](https://github.com/THUDM/ChatGLM-6B) used as LLM。Based on those models,this project can be deployed **offline** with all **open source** models。
## Webui
![webui](./img/ui1.png)
Click on steps 1-3 according to the above figure to complete the model loading, file loading, and viewing of dialogue history
![webui](./img/ui2.png)
Click on the Use via API at the bottom to view the API interface. Existing applications can be docked and called through post requests
### TODO
-[] Add Model Load progress bar
-[] Add output content and error prompts
-[] International language switching
-[] Reference annotation
-[] Add plugin system (can be used for basic LORA training, etc.)
## Update ## Update
**[2023/04/11]**
1. Add Webui V0.1 version and synchronize the updated content before the current day;
2. Automatically read knowledge_ based_ Enumerate LLM and embedding models in chatglm.py, select and click 'setting' to load the model. You can switch models for testing at any time
3. The length of the conversation history can be manually adjusted and can be adjusted according to the size of the video memory
4. Add the upload file function, select the uploaded file from the dropdown box, click loading to load the file, and the loaded file can be changed at any time during the process
5. Add use via API at the bottom to connect to your own system
**[2023/04/07]** **[2023/04/07]**
1. Fix bug which costs twice gpu memory (Thanks to [@suc16](https://github.com/suc16) and [@myml](https://github.com/myml)). 1. Fix bug which costs twice gpu memory (Thanks to [@suc16](https://github.com/suc16) and [@myml](https://github.com/myml)).
2. Add gpu memory clear function after each call of ChatGLM. 2. Add gpu memory clear function after each call of ChatGLM.
......
...@@ -18,7 +18,6 @@ LLM_HISTORY_LEN = 3 ...@@ -18,7 +18,6 @@ LLM_HISTORY_LEN = 3
# Show reply with source text from input document # Show reply with source text from input document
REPLY_WITH_SOURCE = True REPLY_WITH_SOURCE = True
embedding_model_dict = { embedding_model_dict = {
"ernie-tiny": "nghuyong/ernie-3.0-nano-zh", "ernie-tiny": "nghuyong/ernie-3.0-nano-zh",
"ernie-base": "nghuyong/ernie-3.0-base-zh", "ernie-base": "nghuyong/ernie-3.0-base-zh",
...@@ -26,25 +25,32 @@ embedding_model_dict = { ...@@ -26,25 +25,32 @@ embedding_model_dict = {
} }
llm_model_dict = { llm_model_dict = {
"chatglm-6b": "THUDM/chatglm-6b",
"chatglm-6b-int4": "THUDM/chatglm-6b-int4",
"chatglm-6b-int4-qe": "THUDM/chatglm-6b-int4-qe", "chatglm-6b-int4-qe": "THUDM/chatglm-6b-int4-qe",
"chatglm-6b-int4": "THUDM/chatglm-6b-int4",
"chatglm-6b": "THUDM/chatglm-6b",
} }
chatglm = ChatGLM()
chatglm.load_model(model_name_or_path=llm_model_dict[LLM_MODEL])
chatglm.history_len = LLM_HISTORY_LEN
def init_knowledge_vector_store(filepath): def init_cfg(LLM_MODEL, EMBEDDING_MODEL, LLM_HISTORY_LEN, V_SEARCH_TOP_K=6):
global chatglm, embeddings, VECTOR_SEARCH_TOP_K
VECTOR_SEARCH_TOP_K = V_SEARCH_TOP_K
chatglm = ChatGLM()
chatglm.load_model(model_name_or_path=llm_model_dict[LLM_MODEL])
chatglm.history_len = LLM_HISTORY_LEN
embeddings = HuggingFaceEmbeddings(model_name=embedding_model_dict[EMBEDDING_MODEL], ) embeddings = HuggingFaceEmbeddings(model_name=embedding_model_dict[EMBEDDING_MODEL], )
def init_knowledge_vector_store(filepath):
loader = UnstructuredFileLoader(filepath, mode="elements") loader = UnstructuredFileLoader(filepath, mode="elements")
docs = loader.load() docs = loader.load()
vector_store = FAISS.from_documents(docs, embeddings) vector_store = FAISS.from_documents(docs, embeddings)
return vector_store return vector_store
def get_knowledge_based_answer(query, vector_store, chat_history=[]): def get_knowledge_based_answer(query, vector_store, chat_history=[]):
global chatglm, embeddings
system_template = """基于以下内容,简洁和专业的来回答用户的问题。 system_template = """基于以下内容,简洁和专业的来回答用户的问题。
如果无法从中得到答案,请说 "不知道" 或 "没有足够的相关信息",不要试图编造答案。答案请使用中文。 如果无法从中得到答案,请说 "不知道" 或 "没有足够的相关信息",不要试图编造答案。答案请使用中文。
---------------- ----------------
...@@ -72,6 +78,7 @@ def get_knowledge_based_answer(query, vector_store, chat_history=[]): ...@@ -72,6 +78,7 @@ def get_knowledge_based_answer(query, vector_store, chat_history=[]):
if __name__ == "__main__": if __name__ == "__main__":
init_cfg(LLM_MODEL, EMBEDDING_MODEL, LLM_HISTORY_LEN)
filepath = input("Input your local knowledge file path 请输入本地知识文件路径:") filepath = input("Input your local knowledge file path 请输入本地知识文件路径:")
vector_store = init_knowledge_vector_store(filepath) vector_store = init_knowledge_vector_store(filepath)
history = [] history = []
......
...@@ -8,3 +8,4 @@ beautifulsoup4 ...@@ -8,3 +8,4 @@ beautifulsoup4
icetk icetk
cpm_kernels cpm_kernels
faiss-cpu faiss-cpu
gradio
import gradio as gr
import os
import shutil
import knowledge_based_chatglm as kb
def get_file_list():
if not os.path.exists("content"):
return []
return [f for f in os.listdir("content")]
file_list = get_file_list()
embedding_model_dict_list = list(kb.embedding_model_dict.keys())
llm_model_dict_list = list(kb.llm_model_dict.keys())
def upload_file(file):
if not os.path.exists("content"):
os.mkdir("content")
filename = os.path.basename(file.name)
shutil.move(file.name, "content/" + filename)
# file_list首位插入新上传的文件
file_list.insert(0, filename)
return gr.Dropdown.update(choices=file_list, value=filename)
def get_answer(query, vector_store, history):
resp, history = kb.get_knowledge_based_answer(
query=query, vector_store=vector_store, chat_history=history)
return history, history
def get_model_status(history):
return history + [[None, "模型已完成加载,请选择要加载的文档"]]
def get_file_status(history):
return history + [[None, "文档已完成加载,请开始提问"]]
with gr.Blocks(css="""
.importantButton {
background: linear-gradient(45deg, #7e0570,#5d1c99, #6e00ff) !important;
border: none !important;
}
.importantButton:hover {
background: linear-gradient(45deg, #ff00e0,#8500ff, #6e00ff) !important;
border: none !important;
}
""") as demo:
gr.Markdown(
f"""
# 🎉langchain-ChatGLM WebUI🎉
👍 [https://github.com/imClumsyPanda/langchain-ChatGLM](https://github.com/imClumsyPanda/langchain-ChatGLM)
""")
with gr.Row():
with gr.Column(scale=2):
chatbot = gr.Chatbot([[None, """欢迎使用 langchain-ChatGLM Web UI,开始提问前,请依次如下 3 个步骤:
1. 选择语言模型、Embedding 模型及相关参数后点击"step.1: setting",并等待加载完成提示
2. 上传或选择已有文件作为本地知识文档输入后点击"step.2 loading",并等待加载完成提示
3. 输入要提交的问题后点击"step.3 asking" """]],
elem_id="chat-box",
show_label=False).style(height=600)
with gr.Column(scale=1):
with gr.Column():
llm_model = gr.Radio(
llm_model_dict_list, label="llm model",
value="chatglm-6b", interactive=True)
LLM_HISTORY_LEN = gr.Slider(
1, 10, value=3, step=1, label="LLM history len", interactive=True)
embedding_model = gr.Radio(
embedding_model_dict_list, label="embedding model",
value="text2vec", interactive=True)
VECTOR_SEARCH_TOP_K = gr.Slider(
1, 20, value=6, step=1, label="vector search top k", interactive=True)
load_model_button = gr.Button("step.1:setting")
load_model_button.click(lambda *args:
kb.init_cfg(args[0], args[1], args[2], args[3]),
show_progress=True,
api_name="init_cfg",
inputs=[llm_model, embedding_model, VECTOR_SEARCH_TOP_K, LLM_HISTORY_LEN]
).then(
get_model_status, chatbot, chatbot
)
with gr.Column():
with gr.Tab("select"):
selectFile = gr.Dropdown(
file_list, label="content file", interactive=True,
value=file_list[0] if len(file_list) > 0 else None)
with gr.Tab("upload"):
file = gr.File(label="content file", file_types=[
'.txt', '.md', '.docx']).style(height=100)
# 将上传的文件保存到content文件夹下,并更新下拉框
file.upload(upload_file, inputs=file, outputs=selectFile)
history = gr.State([])
vector_store = gr.State()
load_button = gr.Button("step.2:loading")
load_button.click(lambda fileName:
kb.init_knowledge_vector_store(
"content/" + fileName),
show_progress=True,
api_name="init_knowledge_vector_store",
inputs=selectFile, outputs=vector_store).then(
get_file_status, chatbot, chatbot, show_progress=True,
)
with gr.Row():
with gr.Column(scale=2):
query = gr.Textbox(show_label=False, placeholder="Prompts", lines=1, value="用200字总结一下").style(
container=False)
with gr.Column(scale=1):
generate_button = gr.Button(
"step.3:asking", elem_classes="importantButton")
generate_button.click(get_answer, [query, vector_store, chatbot],
[chatbot, history], api_name="get_knowledge_based_answer")
demo.queue(concurrency_count=3).launch(
server_name='0.0.0.0', share=False, inbrowser=False)
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论