上周从 语雀迁移到了 Obsidian 的过程中拿到了个人的所有文档,发现也写了不少东西,但很多笔记实际上都没什么印象了,没有利用起来,想起前段时间非常火的基于 LLM + 外挂知识库的知识库问答系统,于是想尝试搭建一个个人知识库,通过 LLM 的推理和归纳能力,将这些吃灰的笔记回收利用 。
外挂知识库是什么
在介绍外挂知识库前,我们先来看看 ChatGPT 的特点:
- 可以生成高质量的文本,并且语义连贯、流畅度高。
- 可以根据输入的上下文信息,推理和归纳,针对问题生成更相关的回答。
我们希望 ChatGPT 的回答能根据自己本地的文档,或者其他的一些数据源来回答,但 ChatGPT 回答的数据来自于训练时的数据(比如现在是截止到 2022 的数据),不能使用其他的数据。那我们可以将数据和问题一起输入,比如给出这样的 prompt
【这里是某些数据源...】
请根据上面的信息,回答我的问题,如果上面的信息得不出答案,请回答:”没有足够的信息“,那么我的问题是:xxxxx
这样的方案是可行的,但前提是数据源的数据不能太多,ChatGPT 携带的上下文有限,假设我们希望将一本书的内容作为上下文,然后让其根据书中的内容来回答是不行,ChatGPT 一次能支持输入的长度有限。而且每次提问将一大段内容贴进去,也不现实。
那么是否可以只将和问题相关的内容提取出来作为上下文输入呢?这样既可以减少数据源,还能让 ChatGPT 根据这些内容取分析总结出想要的回答。
那么问题就变成了如何根据想要问的问题,从书中检索出相关的内容,这其实就是搜索引擎做的事情。具体的做法就是将这本书的内容通过某些格式保存到数据库中,然后每次提问的时候,先取数据库检索相关的内容,然后将内容和问题按照类似上面的 prompt 提交给 ChatGPT,经过 ChatGPT 来生成高质量的回答。而这个保存了书内容的数据库就是外挂知识库。
其中保存到数据库的过程是对原文本进行 Tokenizer(分词) + Embedding(向量化),数据库则称为 Vector Store (向量数据库)
整个过程如下:
名词解释:
-
分词(Tokenizer): 将文本拆分成单个单词或词语,结构化为计算机可以处理的结构化形式,,比如 我每天六点下班 可以拆分为 “我”,“每天”,“六点下班”,常见的分词器有 markdown 分词器 MarkdownTextSplitter
-
向量化(Embedding):将文本数据转换为向量的过程。计算机无法直接处理文本,因此需要将文本转换为数学向量形式,以便算法能够理解和处理。文本和数学向量之间互相映射,但数学向量更便于计算机运算。对中文比较友好的向量模型库有 shibing624/text2vec-base-chinese
-
向量数据库(Vector Store): 存储和管理向量化后的文本数据的数据库,能快速检索相似文本或进行文本相似性比较。 比如 FAISS 这个库
方案选择
目前已经有许多开源的方案,也有许多商业化的方案,基本上可以分为:
- ChatGPT + Fine-tune: 微调出一个自己的模型,从一些大佬的反馈来看,这种方式成本高,需要花费很多精力去训练,效果不一定能够很好。可以看看 如何使用OpenAI fine-tuning(微调)训练属于自己的专有模型? – 知乎 和 大模型外挂(向量)知识库 – 知乎
- ChatGPT + 外挂知识库: 这个有两个方案,第一个就是官方提供的插件 chatgpt-retrieval-plugin 来处理文档向量,视频 效果演示,缺点就是只能在 ChatGPT 源站点使用,并且要有插件开发者权限。另一个是利用 LangChain 处理生成向量库,然后调用 ChatGPT openapi , 带上检索出来的相关数据和问题去使用。
- 开源 LLM + 微调: 就是利用开源的 LLM 微调训练目标的知识库,比如 ChatGLM3,当然训练成本也是在的,但可以做到数据不泄露,前面 2 种始终需要通过 ChatGPT,难免出现一些数据泄露。
- LangChain + 开源 LLM: 如果不想自己训练,又想保证数据安全,那么结合 2,3 点的方案则是安全可靠的,用 LangChain 对文档进行向量化,然后检索内容,在调用 LLM 对得到的内容进行总结输出。
上面几种方案,2,4 都是比较简单的方案,区别就是模型的问题和数据是否私有化,这里我选择方案 4,不依赖 Openai,可以少处理点坑。最终选择的方案就是 Langchain-Chatchat + chatglm3-6b
LangChain-chatchat 是什么
一种利用 LangChain 思想实现的基于本地知识库的问答应用,而 LangChain 则是一个 AI 开发框架,方便调用各类 AI 工具。
LangChain-chatchat 的处理过程与上面介绍的类似,包括 加载文件 -> 读取文本 -> 文本分割 -> 文本向量化 -> 问句向量化 -> 在文本向量中匹配出与问句向量最相似的
top k 个 -> 匹配出的文本作为上下文和问题一起添加到
prompt 中 -> 提交给
LLM 生成回答
。
不过其提供了完整的解决方案,可以做到开箱即用,私有化部署,极大的简化了本地知识库的搭建。
ChatGLM3 是什么
ChatGLM3 是智谱 AI 和清华大学 KEG 实验室联合发布的新一代对话预训练模型,和 ChatGPT 类似的大预言模型,对中文的支持更好,同时对硬件的支持更小(16G 的消费级显卡就可以),部署门槛比较低。当然训练的数据相对 ChatGPT 来说也小很多,能力上也会有所不足。这里在我部署了 ChatGLM3 针对其和 ChatGPT 做了一些测试,还是 ChatGPT 的回答更出色些。
ChatGLM3 的回答
ChatGPT 的回答
实战
环境准备
这里建议找一些环境可以的云服务,不然对于不熟悉的同学安装各种环境依赖都可能搞很久。参考 免费部署一个开源大模型 MOSS 白嫖一个阿里 GPU 服务器。注意,镜像的选择要选最新的镜像,比如下面这个,这个刚刚好可以满足所有的环境需求:
安装相关模型
chatglm3-6b
先下载 ChatGLM3 的 LLM 模型,由于 huggingface 上一直下载不下来,所以我们选择到 modelscope 下载
# /mnt/workspace/
git clone https://www.modelscope.cn/ZhipuAI/chatglm3-6b.git
text2vec-bge-large-chinese
我们选择这个向量模型,当然也还有其他的模型,可以参考 几种中文常用向量模型比较总结 – 知乎
# /mnt/workspace/
git clone https://www.modelscope.cn/Jerry0/text2vec-bge-large-chinese.git
Langchain-Chatchat
# /mnt/workspace/
git clone https://github.com/chatchat-space/Langchain-Chatchat.git
cd Langchain-Chatchat
# 需要将分支切换到 v0.2.2 版本,最新的 master 分支需要 python 3.10 以上,且不太容易运行起来
git checkout origin v0.2.2
# 初始化依赖,在着之前需要锁定2个依赖版本,不然运行起来会报错
# streamlit-chatbox==1.1.7,分别修改 requirements.txt、requirements_webui.txt
# openai==0.28.1,分别修改 requirements.txt、requirements_api.txt
pip install -r requirements.txt
pip install -r requirements_api.txt
pip install -r requirements_webui.txt
# 初始化配置文件
cp configs/model_config.py.example configs/model_config.py
cp configs/server_config.py.example configs/server_config.py
接着,需要修改 model_config.py 中的配置
embedding_model_dict = {
# ...
# 替换成刚刚下载向量库路径
"text2vec-base": "/mnt/workspace/text2vec-bge-large-chinese",
# ...
}
llm_model_dict = {
# ...
# 增加如下配置
"chatglm3-6b": {
"local_model_path": "/mnt/workspace/chatglm3-6b", # 刚刚下载的模型库路径
"api_base_url": "", # 与其他的保持一起
"api_key": "" # 与其他的保持一起
},
# ...
}
# 默认向量模型改成 text2vec-base
EMBEDDING_MODEL = "text2vec-base"
# 默认 LLM 模型改成 chatglm3-6
LLM_MODEL = "chatglm3-6b"
接着运行: python startup.py -a
,当看到下面的提示时,则运行起来了,打开链接就可以使用了。
效果
首先可以直接使用其对话能力,也就是不带知识库的模式。
知识库模式
首先可以导入文档,创建相关的知识库,然后 选择知识库问答 模式
以之前写的文章 前端 RBAC 权限方案 – 掘金 做一下测试,确实能基于我的文档做一些检索,但还是有一些问题,也和模型有关。
也能结合已有的资料和本地知识库做整合,下面的回答不完全来源于我的文章。
整体验证下来,用于检索本地文档并且做总结归纳这方面还是挺不错的。但需要做一些推理生成一些代码之类的,就不一定能够准确,所以还是适合于针对已有文档的检索整合问答。
总结
这次简单的尝试了本地部署 LLM + 外挂知识库的方式来搭建一个私有化的知识库,整体来看还有一些提升空间,比如模型的选择上,ChatGLM3 适合于小型的系统,如果有更多的资源,则可以考虑其他更大的模型 , 如 ChatGLM-130B。
知识库也是目前 LLM 的一个实践方向,特别是这种私有化的部署方式,每个企业内部都有大量资料、文档,过去内部可能依靠人工词典,但资料的使用率其实不高,随笔人员变动出现了很多重复的资料,而这种基于 LLM 的私有化知识库,则提供了一种很好的解决方案,可以检索过去的资料,给出资料来源,如果资料有问题就可以到源地址去修改,更好的提高资料的使用率。