远程服务器使用chatglm结合langchain关于faiss的实战应用

知识库,用来增强大模型信息检索的能力,称之为检索增强生成(RAG),这是目前非常流行的一种做法,知识库模式相比于微调有 2 个好处。

  1. 知识准确:先把知识进行向量化,存储到向量数据库里,使用的时候通过向量检索从向量库把知识检索出来,这样可以确保知识的准确性。
  2. 更新频率快:当你发现知识库里的知识不全的时候,可以随时补充,不需要像微调一样,重新跑微调任务、验证结果、重新部署等。

除了大模型 6B 外,你还需要了解 LangChain、向量化、向量库等组件及概念。ChatGLM3 官方提供了一个和 LangChain 结合的 demo:Langchain-Chatchat,还带有 UI 界面,我们可以直接拿过来使用。如果你理解了这个演示项目,那么智能体的原理也就学得差不多了,剩下的就是工程化的事情了。

Langchain-Chatchat 架构

Langchain-Chatchat 主要包含几个模块:大语言模型、Embedding 模型(参考:https://huggingface.co/BAAI/bge-large-zh)、分词器、向量数据库、Agent Tools、API、WebUI。
在这里插入图片描述

知识库大概流程图包含分词、向量化、存储、查询等过程,图中不包括其他 Tools。

在这里插入图片描述

1~7 是文档完成向量化存储的过程,8~15 是知识库检索的过程。下面我们完整地跑一下这个 demo。

系统部署

1.安装依赖

首先,从 GitHub 上克隆代码 https://github.com/chatchat-space/Langchain-Chatchat.git。然后安装依赖,如果之前已经安装过的,可以排除掉,通过 pip3 list 查看已经安装过的包和版本,当然如果网速允许,建议直接安装,否则可能会有依赖库冲突的问题。 三个依赖全部安装:requirements.txt、requirements_api.txt、requirements_webui.txt。

避坑
目前最新的git里会发现没有requirements_api.txt、requirements_webui.txt。甚至和后面的版本也不一样,因为本教程讲的版本和目前最新的不一样(目前很多百度出来的教程也都和最新的不一样了)
只需要找对版本拉取就可以了,这里我们使用版本v0.2.10
在这里插入图片描述

# 获取git信息
git clone https://github.com/chatchat-space/Langchain-Chatchat.git
# 切换git版本
git checkout v0.2.10


# 创建虚拟环境
conda create -n langchain python=3.10

# 虚拟环境列表
conda env list

# 切换环境
conda acitivate langchain

# 指定国内源速度更快(选用)
# pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple

# 安装依赖
pip install -r requirements.txt
pip install -r requirements_api.txt
pip install -r requirements_webui.txt
2.下载模型

之前我们已经安装过 ChatGLM3-6B 了,本次无需再次安装,只要下载 Embedding 模型即可,我们选择 bge-large-zh-v1.5 进行下载,可以从 HuggingFace 下载,也可以从 ModelScope 下载,后者速度更快。

# 国内使用加速器
git clone https://www.modelscope.cn/AI-ModelScope/bge-large-zh-v1.5.git
git lfs pull

git lfs 是专门用来拉取 git 上存储的大文件的,通过 git lfs pull 将模型权重拉取到本地。

3. 参数配置

执行以下命令,将配置文件复制一份到 config 目录,方便修改。

python copy_config_example.py

主要有以下几个配置文件:
在这里插入图片描述

大部分不需要修改,我们只需要改一下 model_config.py 指定大模型和 Embedding 模型的路径即可。找到 MODEL_PATH 配置,分别修改 embed_model 里 bge-large-zh-v1.5 模型的本地目录,以及 llm_model 里 chatglm3-6b 的本地目录即可。

4.初始化向量库数据

这一步主要是确认向量数据库和 Embedding 模型有没有部署好,实际生产环境中,我们可以自己创建业务向量数据库,这里通过初始化放一些示例数据进去。执行命令:

python init_database.py --recreate-vs

如果看到不断地加载示例数据,直到进度 100% 完成,就说明成功了,接下来就是一键启动。

python startup.py -a

当命令行出现如下提示,说明启动成功了。
在这里插入图片描述
进入页面
在这里插入图片描述
到这里基本上就算安装成功了,下面我们看一下如何管理知识库,以及自定义工具来增强大模型的检索能力。

知识管理

在这里插入图片描述
在这里插入图片描述
通过上面的操作可以将文档存入所选择的向量库内,供对话时检索。我们也可以通过 API 进行知识库管理、对话及查看服务器信息等操作。
在这里插入图片描述
下面我们看一下知识库的效果,先对大模型进行提问。
在这里插入图片描述
既获取了大模型的输出,也获取到了知识库的输出,实际应用过程中,我们可以把从知识库中检索到的信息传入大模型,大模型会进行上下文理解,经过整理后输出。 这些都是这个 demo 提供的一些基本功能,实际生产中,我们可以在企业内部搭建知识管理系统,由专业的团队进行知识维护。应用过程中需要考虑的事项比较多,比如企业内部统一登录、操作权限、操作日志等,都需要按照企业需求进行详细设计。除了知识库外,在一个智能体应用中,我们可以开发各种各样的 Tool,下面我们再研究一下这个 demo 自带的天气查询工具。

1.Tools 使用

打开 kb_config.py 配置文件,里面有天气查询、搜索引擎查询等工具开发配置,我们去心知天气官网申请一个 API 密钥,赋值给 SENIVERSE_API_KEY 变量,页面上就可以直接用了。
打开 kb_config.py 配置文件,里面有天气查询、搜索引擎查询等工具开发配置,我们去心知天气官网申请一个 API 密钥,赋值给 SENIVERSE_API_KEY 变量,页面上就可以直接用了。
在这里插入图片描述
这是一个典型的检索增强生成(RAG)案例,通过 API 调用第三方服务,扩大信息检索范围。实际应用过程中,我们可以把企业内部的数据或者产品数据通过 API 喂给大模型,为产品增加 AI 能力,进而提升产品竞争力。 我们知道知识库模式,底层实际上是一个向量库,这个 demo 我们用的是 Meta 开源的向量数据库 Faiss,当然也可以替换成国产向量数据库 Milvus,接下来我们简单讲讲向量数据库是什么样的数据库,能解决什么问题。

2.向量数据库

在聊向量数据库之前,让我们先简单了解一下“向量”这个概念。在计算机科学和数学中,向量是由一系列数字组成的数组,这些数字可以表示任何东西,从物理空间的方向和大小到商品的特性和用户偏好等

3.相似度计算

比如,在评价一部电影时,你给它的评分包括剧情 8 分、特效 7 分、演技 9 分、音乐 6 分。这四个评分点就可以构成一个向量 [8, 7, 9, 6]。在这个向量中,每一个维度都代表了电影的一个属性。现在,假设你是一位开发工程师,你正在构建一个推荐系统。你的目标是根据用户的喜好向他们推荐电影。用户的喜好也可以用一个向量来表示,比如一个用户可能喜欢剧情和演技重于特效和音乐,他们的喜好向量可能是 [10, 5, 10, 4]。 现在,如果你想找出哪部电影最符合这类用户的口味,你可以计算用户喜好向量和每部电影向量之间的相似度。在向量空间中,这通常通过计算向量之间的距离来完成,如欧氏距离或余弦相似度。距离越小或相似度越高,表示电影越符合用户的口味。

import numpy as np
# 定义计算余弦相似度的函数
def calculate_similarity(vector1, vector2):
    # 使用numpy库来计算余弦相似度
    dot_product = np.dot(vector1, vector2)
    norm_vector1 = np.linalg.norm(vector1)
    norm_vector2 = np.linalg.norm(vector2)
    similarity = dot_product / (norm_vector1 * norm_vector2)
    return similarity
# 假设我们有一个向量代表用户偏好
user_preference = np.array([10, 5, 10, 4])
# 我们有一系列电影向量
movie_vectors = np.array([
    [8, 7, 9, 6],   # 电影A
    [9, 6, 8, 7],   # 电影B
    [10, 5, 7, 8]   # 电影C
])
# 计算并打印每部电影与用户偏好之间的相似度
for i, movie_vector in enumerate(movie_vectors):
    similarity = calculate_similarity(user_preference, movie_vector)
    print(f"电影{chr(65+i)}与用户偏好的相似度为: {similarity:.2f}")

我们这个示例里使用余弦相似度算法,执行这个代码块得出如下结果:

电影A与用户偏好的相似度为: 0.97
电影B与用户偏好的相似度为: 0.97
电影C与用户偏好的相似度为: 0.95

4.文本向量

在自然语言处理(NLP)中,一个词的向量值是通过在大量文本上训练得到的。一个词的向量值取决于它是如何被训练的,以及训练数据的性质。例如在不同的 Word2Vec 模型中,即使是相同的词,向量值也可能完全不同,因为它们可能基于不同的文本集或使用不同的参数训练。 常见的 Word2Vec 模型会生成几百维的向量。我们举一个例子来说明不同的词之间向量是怎么表示的,以及相似度是如何计算的。下面的例子是基于 GoogleNews-vectors-negative300.bin 模型计算的,计算男人和男孩的向量表示以及相似度。

import numpy as np
from gensim.models import KeyedVectors
model = KeyedVectors.load_word2vec_format('GoogleNews-vectors-negative300.bin', binary=True)
def cosine_similarity(vec_a, vec_b):
    # 计算两个向量的点积
    dot_product = np.dot(vec_a, vec_b)
    # 计算每个向量的欧几里得长度
    norm_a = np.linalg.norm(vec_a)
    norm_b = np.linalg.norm(vec_b)
    # 计算余弦相似度
    return dot_product / (norm_a * norm_b)
# 获取man和boy两个词的向量
man_vector = model['man']
boy_vector = model['boy']
# 打印出这两个向量的前10个元素
print(man_vector[:10])
print(boy_vector[:10])
similarity_man_boy = cosine_similarity(man_vector, boy_vector)
print(f"男人和男孩的相似度: {similarity_man_boy}")

程序输出如下:

[ 0.32617188  0.13085938  0.03466797 -0.08300781  0.08984375 -0.04125977
 -0.19824219  0.00689697  0.14355469  0.0019455 ]
[ 0.23535156  0.16503906  0.09326172 -0.12890625  0.01599121  0.03613281
 -0.11669922 -0.07324219  0.13867188  0.01153564]
男人和男孩的相似度: 0.6824870705604553

这只是一个例子,不同的模型、不同的训练数据集,甚至是不同的训练参数都会产生不同的词向量。同样的道理,女人和女孩、男人和青少年等等,相似度也很高。这种特性使我们进行信息检索的时候,不需要像传统数据库那样通过 like 去找相似的内容,而是通过向量相似度去检索相似的内容。这样做的好处是可以通过多个维度(属性)去比较,比如男人和男孩相似度很高,是因为男人和男孩在性别、社会角色、关系、活动和兴趣、情感和行为等方面都比较相似。

5.向量存储

存储向量数据有专门的向量数据库,比如 Faiss、Milvus。向量数据库专门被设计用于存储和检索向量数据,非常适合处理词向量、图像特征向量或任何其他形式的高维数据。我们以刚刚生成的词向量为例来解释如何通过向量数据库存储这些数据。

import numpy as np
import faiss

# 假设我们有一些词向量,每个向量的维度为100
dimension = 100  # 向量维度
word_vectors = np.array([
    [0.1, 0.2, ...],  # 'man'的向量
    [0.01, 0.2, ...],  # 'boy'的向量
    ...  # 更多向量
]).astype('float32')  # Faiss要求使用float32

# 创建一个用于存储向量的索引
# 这里使用的是L2距离(欧氏距离),如果你需要使用余弦相似度,需要先规范化向量
index = faiss.IndexFlatL2(dimension)

# 添加向量到索引
index.add(word_vectors)

# 假设我们想找到与'new_man'(新向量)最相似的5个向量
new_man = np.array([[0.1, 0.21, ...]]).astype('float32')  # 新的查询向量
k = 5  # 返回最相似的5个向量
D, I = index.search(new_man, k)  # D是距离的数组,I是索引的数组

# 打印出最相似的向量的索引
print(I)

记得先安装一下 Faiss 依赖。

pip install faiss-cpu  # 对于没有GPU的系统
# 或者
pip install faiss-gpu  # 对于有GPU的系统

使用起来也比较简单,和我们一般的数据存储一样,通过客户端进行数据插入和查询。和其他存储中间件一样,当数据量非常大的时候,同样会遇到性能、稳定性等问题,当大规模使用的时候需要考虑各种各样的问题,只不过对于向量数据库,挑战在于多维度的存储,比如随着数据维度的增加(一个词被表示为一个 300 维的向量),数据点(向量)之间的距离开始变得难以区分。这不仅让寻找“最近的邻居”变得更加困难和耗时,而且还会增加存储和搜索时所需的资源。 你可以本地自己搭建一个向量数据库体验一下,和传统的关系 / 非关系型数据存储有什么区别,当然,如果感兴趣也可以看看底层的存储原理。

应用场景

知识库模式可以用在相对固定的场景做推理,比如企业内部使用的员工小助手,包含考勤制度、薪酬制度、报销制度、法律帮助,以及产品操作手册、使用帮助等等,这类场景不需要太多的逻辑推理,使用知识库模式检索精确度高,并且可以随时更新。企业实际应用过程中,除了使用大语言模型本身的基础能力外,其他的也就是在不同场景下,把各种各样的 Agent 进行堆叠,产生智能化的效果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值