作为一个小白,之前接触Langchain-chatGLM的本地部署时,踩了一些坑,特此记录,也帮助大家能够快速顺利地进行本地部署。
I. 介绍
源码链接🔗
LangChain-Chatchat 是一种利用 langchain 思想实现的基于本地知识库 的问答应用,目标期望建立一套对中文场景与开源模型支持友好、可离线运行的知识库问答解决方案。
一开始对着这个描述迷迷糊糊的,看到最后看懂了代码之后才知道这是专门为实现知识库对话而创建的。
本地构建知识库的原理是什么?
之前如果想要提供某个特定领域的知识问答,需要在特定领域上的数据进行微调,消耗大量的计算资源和时间。 利用 ChatGLM-6B + langchain 来构建个人专属知识库,就可以快速实现不同领域之间的特定问答。
实现流程:
用户先上传知识文档,经过一系列处理,生成embedding(本示例用的embedding是m3e-base),然后存入VectorStore作为向量库。用户的提问也会生成embedding,跟向量库里的向量进行相似度计算,找到最匹配的向量作为上下文,跟提问一起作为prompt输入到LLM中。

II. 环境配置
A. Python 环境设置 & 安装依赖库
readme.md里有docker部署的镜像,但要注意查看自己显卡支持的cuda是否跟镜像匹配。我就是花大半天将镜像下载下来,发现不能用😫,网速慢的同学还是尝试自己配环境吧。

手动下载
python 版本为3.8.10, cuda版本为11.7,其它的环境直接使用pip install ~即可
pip install -r requirements.txt
pip install -r requirements_api.txt
pip install -r requirements_webui.txt
B. 模型下载和准备
要先安装Git LFS:
Git Large File Storage(LFS)是一个开源的Git扩展工具,它可以优化Git对大型二进制文件的处理,例如音频、视频、数据集等。Git LFS将大文件存储在专门的服务器上,而不是直接存储在Git仓库中,这可以有效地减小Git仓库的大小,同时也帮助我们更好地管理和处理大型文件。
再用git clone
下载llm模型
shell
$ git clone https://huggingface.co/THUDM/chatglm2-6b
下载知识库的embedding模型
shell
$ git clone https://huggingface.co/moka-ai/m3e-base
将环境和模型搞定已经成功一大半了
C. config配置
config配置基本上跟readme上的步骤一样,选取自己想加载的模型,在对应位置修改模型路径就好。
复制模型相关参数配置模板文件 configs/model_config.py.example 存储至项目路径下 ./configs
路径下,并重命名为 model_config.py
。
复制服务相关参数配置模板文件 configs/server_config.py.example 存储至项目路径下 ./configs
路径下,并重命名为 server_config.py
。
示例如下:
json
llm_model_dict={
"chatglm2-6b": {
"local_model_path": "/Users/xxx/Downloads/chatglm2-6b",
"api_base_url": "http://localhost:8888/v1", # "name"修改为 FastChat 服务中的"api_base_url"
"api_key": "EMPTY"
},
}
makefile
embedding_model_dict = {
"m3e-base": "/Users/xxx/Downloads/m3e-base",
}
III. 运行代码
A.初始化知识库
第一次运行项目的时候,
$ python init_database.py --recreate-vs
不是第一次运行项目,
$ python init_database.py
如下图,samples为默认知识库

B.大模型服务 (llm_api.py) 的配置和运行
⚠要注意端口冲撞的问题,这里将8888端口改成了8880,改完之后记得将model.config的也改了

验证llm_api是否跑通:
ini
# 服务启动后接口调用示例:
import openai
openai.api_key = "EMPTY" # Not support yet
openai.api_base = "http://localhost:8880/v1"
model = "chatglm2-6b"
completion = openai.ChatCompletion.create(
model=model,
messages=[{"role": "user", "content": "Hello! What is your name?"}]
)
print(completion.choices[0].message.content)
C. API 服务 (api.py)的配置和运行
python api.py
访问 http://localhost:7861/docs 会出来接口文档,可以在上面查看并进行调试。
成功的话,调用接口会返回值,而不是页面,之前调用接口直接返回html,其实就是错误响应页面。

IV 接口调用示例
A. 直接与部署的llm对话
vbnet
curl -X 'POST' \
'http://localhost:7861/chat/fastchat' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"model": "chatglm2-6b",
"messages": [
{
"role": "user",
"content": "hello"
}
],
"temperature": 0.7,
"n": 1,
"max_tokens": 1024,
"stop": [],
"stream": false,
"presence_penalty": 0,
"frequency_penalty": 0
}'
输出:

流式输出逻辑:
获取到response之后,用yield将输出以生成器形式返回,最后用StreamingResponse封装输出。

通过控制请求中stream为True / False,可以控制是否使用流式输出,若使用流式输出,curl调用接口的时候要加上--raw,示例如下:
css
curl --raw -X 'POST' 'http://localhost:7861/chat/fastchat' -H 'Content-Type: application/json' -d '{
"model": "chatglm2-6b",
"messages": [
{
"role": "user",
"content": "hello"
}
],
"temperature": 0.7,
"n": 1,
"max_tokens": 1024,
"stop": [],
"stream": true,
"presence_penalty": 0,
"frequency_penalty": 0
}
注:如果调用之后流式输出效果不明显,可以在代码中加入time.sleep()延时
B. 与知识库对话

vbnet
curl -X 'POST' \
'http://localhost:7861/chat/knowledge_base_chat' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"query": "你好",
"knowledge_base_name": "samples",
"top_k": 5,
"score_threshold": 1,
"history": [
{
"role": "user",
"content": "我们来玩成语接龙,我先来,生龙活虎"
},
{
"role": "assistant",
"content": "虎头虎脑"
}
],
"stream": false,
"local_doc_url": false
}'
新建知识库
vbnet
curl -X 'POST' \
'http://localhost:7861/knowledge_base/create_knowledge_base' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"knowledge_base_name": "test",
"vector_store_type": "faiss",
"embed_model": "m3e-base"
}'
响应返回
{ "code": 200, "msg": "已新增知识库 test" }
上传知识库文档
rust
curl -X 'POST' \
'http://localhost:7861/knowledge_base/upload_doc' \
-H 'accept: application/json' \
-H 'Content-Type: multipart/form-data' \
-F 'file=@文件名;type=text/plain' \
-F 'knowledge_base_name=test' \
-F 'override=false' \
-F 'not_refresh_vs_cache=false'
响应返回
ini
page_content='xxx你的文档内容' metadata={'source': '文档路径'}
C. 与知识库对话
rust
curl -X 'POST' \
'http://localhost:7861/chat/knowledge_base_chat' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"query": "今天天气怎么样",
"knowledge_base_name": "test",
"top_k": 5,
"score_threshold": 1,
"history": [
],
"stream": false,
"local_doc_url": false
}
响应返回
json
{"answer": "今天为晴天"]}