国产embedding
最开始使用LangChain结合通义千问API实现了基础的RAG(Retrieval-Augmented Generation)过程,当时认为embedding模型似乎是LangChain的一部分,然后又通过学习OpenAI的API发现,其实使用embedding模型不需要一定捆绑在LangChain上,可以作为一个独立的API来使用,因此在尝试实现了OpenAI的embedding模型之后,将当初结合LangChain使用的国产的有道的embedding模型来进行一下向单独的知识向量库的生成。
文章目录
- 国产embedding
- 1.环境安装
- 2.模型下载
- 3.生成词向量
- 4.保存知识向量库
- 5.相似文本搜索
- 6.与text-embedding-3-small的对比
- 结束
如果你对embedding还不太了解可以先看一下下面的前置文章,里面会有embedding概念的基础讲解。
前置文章: 使用 OpenAI 的 Embedding模型 构建知识向量库并进行相似搜索
1.环境安装
首先给出有道的BCEmbedding模型的GitHub官网
有道embedding:https://github.com/netease-youdao/BCEmbedding
接下来按照官方的操作先安装一下环境
首先创建一个Anaconda虚拟环境叫bce
然后启动这个环境,如果是新手不了解Anaconda和虚拟环境安装和使用的话的可以看下面的文章
|Anaconda安装| Anaconda、pycharm安装及配置Python环境详细教程(学弟提供)
conda create --name bce python=3.10 -y
conda activate bce
然后安装BCEmbedding库
执行这个命令的时候会自动安装一个CPU版本的pytorch,如果想用GPU,需要重新安装一个GPU版本的pytorch将原来的版本覆盖掉,GPU版本的使用会后续在这篇文章下进行更新。
pip install BCEmbedding==0.1.3
2.模型下载
下载的话需要有Huggingface的账号,然后同意相关使用协议才能下载,网址如下。
网址:https://huggingface.co/maidalun1020
下载完成之后的文件夹内容如下。
3.生成词向量
官网代码如下,这里对比OpenAi的embedding模型,它可以批量输入文本,然后返回一个embedding向量的数组,而OpenAI的embedding模型的官方例子中,是让我使用列表生成式,一个文本生成一次.
代码中输入embedding模型的路径的部分,最好先写绝对路径,有时候写相对路径之后读取不到,会默认进入下载模型,然后进入下载模式之后他又会提示你没有下载权限,因为我们的模型是在网页上经过授权之后下载的,在代码里怎么申请授权不知道,这可能是个小坑
from BCEmbedding import EmbeddingModel
import numpy as np
# 读取txt文档,句子列表
f = open("test.txt", 'r', encoding='utf-8')
doc = f.read().splitlines()
# 初始化embedding模型
from BCEmbedding import EmbeddingModel
import numpy as np
# list of sentences
sentences = ['sentence_0', 'sentence_1']
# init embedding model
model = EmbeddingModel(model_name_or_path=r"bce-embedding-vase_v1", device='cpu')
embeddings = model.encode(sentences)
打印查看一些信息。
# 查看一下当前设备
print(model.device)
# 查看一下embedding模型向量的维度
print(embeddings.shape)
'''
03/21/2024 13:30:38 - [INFO] -BCEmbedding.models.EmbeddingModel->>> Loading from `bce-embedding-vase_v1`.
03/21/2024 13:30:38 - [INFO] -BCEmbedding.models.EmbeddingModel->>> Execute device: cpu; gpu num: 0; use fp16: False; embedding pooling type: cls; trust remote code: False
Extract embeddings: 100%|██████████| 1/1 [00:00<00:00, 1.14it/s]
cpu
(2, 768)
'''
4.保存知识向量库
保存知识向量库的流程也很简单,读取文档,然后把一个带有句子列表输进model.encodezh中就可以了
,代码如下:
from BCEmbedding import EmbeddingModel
import numpy as np
# 读取txt文档,句子列表
f = open("test.txt", 'r', encoding='utf-8')
doc = f.read().splitlines()
# 初始化embedding模型
model = EmbeddingModel(model_name_or_path=r"bce-embedding-vase_v1", device='cpu')
# 提取词向量
embeddings = model.encode(doc)
# 保存生成的向量
np.save("embeddings.npy", embeddings)
打印查看一些信息
# 打印句子列表
print(doc)
# 打印向量维度
print(embeddings.shape)
# 打印向量数据类型
print(type(embeddings))
'''
03/21/2024 13:35:52 - [INFO] -BCEmbedding.models.EmbeddingModel->>> Loading from `bce-embedding-vase_v1`.
03/21/2024 13:35:52 - [INFO] -BCEmbedding.models.EmbeddingModel->>> Execute device: cpu; gpu num: 0; use fp16: False; embedding pooling type: cls; trust remote code: False
Extract embeddings: 100%|██████████| 1/1 [00:01<00:00, 1.28s/it]
['糖尿病', '高血压', '抑郁症', '阿尔茨海默症', '慢性阻塞性肺疾病(COPD)', '骨折', '哮喘', '乳腺癌', '心肌梗塞', '脑卒中', '化疗', '放射疗法', '心脏搭桥手术', '经皮冠状动脉介入治疗(PCI)', '腹腔镜手术', '物理疗法', '认知行为疗法', '血液透析', '绝育手术', '骨髓移植', 'MRI扫描仪', 'CT扫描仪', '心电图机', '超声波设备', '血糖仪', '血压计', '吸氧机', '呼吸机', '脉搏血氧仪', '自动体外除颤器(AED)', '青霉素', '阿司匹林', '他汀类药物', '阿片类镇痛药', '抗生素', '抗抑郁药', '胰岛素', '利尿剂', '抗凝血药', '抗病毒药', '免疫疗法', '基因编辑', '微创手术', '患者健康记录(PHR)', '电子医疗记录(EMR)', '临床试验', '医疗保健大数据', '精准医疗', '遥感监测', '医疗伦理']
(50, 768)
<class 'numpy.ndarray'>
'''
测试使用的文本文件内容如下,保存为test.txt,默认编码UTF-8,一行一个词
糖尿病
高血压
抑郁症
阿尔茨海默症
慢性阻塞性肺疾病(COPD)
骨折
哮喘
乳腺癌
心肌梗塞
脑卒中
化疗
放射疗法
心脏搭桥手术
经皮冠状动脉介入治疗(PCI)
腹腔镜手术
物理疗法
认知行为疗法
血液透析
绝育手术
骨髓移植
MRI扫描仪
CT扫描仪
心电图机
超声波设备
血糖仪
血压计
吸氧机
呼吸机
脉搏血氧仪
自动体外除颤器(AED)
青霉素
阿司匹林
他汀类药物
阿片类镇痛药
抗生素
抗抑郁药
胰岛素
利尿剂
抗凝血药
抗病毒药
免疫疗法
基因编辑
微创手术
患者健康记录(PHR)
电子医疗记录(EMR)
临床试验
医疗保健大数据
精准医疗
遥感监测
医疗伦理
5.相似文本搜索
我们使用计算两个文本向量的余弦相似度的方法来计算两个文本含义的相似程度其计算公式如下:
cosine similarity ( A , B ) = A ⋅ B ∥ A ∥ ∥ B ∥ = ∑ i = 1 n A i B i ∑ i = 1 n A i 2 ∑ i = 1 n B i 2 \text{cosine similarity}(\mathbf{A}, \mathbf{B}) = \frac{\mathbf{A} \cdot \mathbf{B}}{\|\mathbf{A}\| \|\mathbf{B}\|} = \frac{\sum_{i=1}^{n}A_iB_i}{\sqrt{\sum_{i=1}^{n}A_i^2} \sqrt{\sum_{i=1}^{n}B_i^2}} cosine similarity(A,B)=∥A∥∥B∥A⋅B=∑i=1nAi2∑i=1nBi2∑i=1nAiBi
自己使用numpy广播机制写的一对多余弦相似度计算代码如下,如果是新手的话,只需要知道输入输出是什么就好。
import numpy as np
def cos_similarity(target, embedding):
numerator = np.sum(target * embedding, axis=1)
denominator = np.sqrt(np.sum(np.square(target)) * np.sum(np.square(embedding),axis=1))
return numerator / denominator
if __name__ == '__main__':
x = np.array([1, 2])
y = np.array([[1, 2], [1, 1]])
print(cos_similarity(x, y))
# [1. 0.9486833]
搜索代码如下:
from BCEmbedding import EmbeddingModel
import numpy as np
# 读取txt文档,句子列表
f = open("test.txt", 'r', encoding='utf-8')
name = f.read().splitlines()
# 初始化embedding模型
model = EmbeddingModel(model_name_or_path=r"bce-embedding-vase_v1", device='cpu')
# 计算余弦相似度函数
def cos_similarity(target, embedding):
numerator = np.sum(target * embedding, axis=1)
denominator = np.sqrt(np.sum(np.square(target)) * np.sum(np.square(embedding), axis=1))
return numerator / denominator
# 加载知识向量库
embeddings = np.load("embeddings.npy")
# 获取用户输入
search_text = input("User:")
# 将用户的输入使用embedding模型转换为词向量
search_embedding = model.encode(search_text)
# 计算余弦相似度
embedding_similarity = cos_similarity(search_embedding, embeddings)
# 由上到下输出相似度
for i in np.argsort(embedding_similarity)[::-1]:
print(name[i], embedding_similarity[i])
输入结果如下:这里就不粘全了太多了把前面的结果粘贴出来。
03/21/2024 15:46:08 - [INFO] -BCEmbedding.models.EmbeddingModel->>> Loading from `bce-embedding-vase_v1`.
03/21/2024 15:46:08 - [INFO] -BCEmbedding.models.EmbeddingModel->>> Execute device: cpu; gpu num: 0; use fp16: False; embedding pooling type: cls; trust remote code: False
User:心脏
Extract embeddings: 100%|██████████| 1/1 [00:00<00:00, 1.22it/s]
心肌梗塞 0.7346949
心脏搭桥手术 0.6819945
呼吸机 0.6626346
心电图机 0.66097486
哮喘 0.59669954
高血压 0.58787584
抑郁症 0.5580719
骨折 0.5393874
脉搏血氧仪 0.5336546
血压计 0.52758914
血液透析 0.5266952
6.与text-embedding-3-small的对比
在进行了使用相似度搜索之后我发现OpenAI和和有道的embedding模型的结果还是有不少不同,对比之后的结果,结果见仁见智,我只把结果图放出来,不做评价。
我们拟定三个搜索词:呼吸,心脏,医疗,然后每个词分别给出两张图,一张是按招bce-embedding-vase-v1的结果排序,一个是按照text-embeddubg-3-small的结果排序,计算相似度的方式使用的都是余弦相似度。
- 搜索与呼吸相似的词汇
- 搜索与心脏相似的词汇
- 搜索与医疗相似的词汇
结束
之后会尝试考虑实验一下有道的RerankerModel模型,看看能不能输出一些结果,还有就是尝试一下在GPU上使用。