掘金 人工智能 20小时前
RAG轻松通-P2:向量化
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文深入探讨了RAG流程中的向量化环节,详细介绍了如何使用Embedding模型将文本转化为机器可理解的向量。文章解释了向量化的核心原理,即语义相近的文本在向量空间中的距离更近。通过代码示例,演示了使用sentence-transformers库进行向量化的过程,包括模型加载、向量生成以及相似度计算。此外,文章还对比了余弦相似度、点积和欧氏距离在向量比较中的应用,强调了余弦相似度在RAG系统中的优势,并提供了归一化处理的细节。

💡RAG流程的核心在于将人类语言转化为机器可理解的向量,这一过程被称为向量化,它依赖于Embedding模型,将文本映射到多维向量空间。

✨语义相似的文本在向量空间中距离更近,这是向量化的基本原则。通过计算向量之间的距离或相似度,可以衡量文本之间的语义相关性,例如,点积越大,通常表示两个向量在方向上越接近,也就是越“相似”。

🚀使用sentence-transformers库进行向量化,需要加载合适的Embedding模型,例如适用于中文的bge-small-zh-v1.5。通过model.encode()方法,可以将文本转化为向量,并观察向量的形状(样本数, 维度),其中维度由Embedding模型决定,代表了模型的复杂度和表达能力。

💯在RAG和语义搜索场景中,余弦相似度是首选的相似度计算方法。它只关注向量的方向,不关心大小,对文本长度和用词强度不敏感。余弦相似度的值被归一化到[-1, 1]的区间内,结果直观易于比较。对于归一化向量,余弦相似度等于点积。

欢迎来到啾啾的博客🐱。
记录学习点滴。分享工作思考和实用技巧,偶尔也分享一些杂谈💬。
有很多很多不足的地方,欢迎评论交流,感谢您的阅读和评论😄。

1 引言

在上一篇中,我们了解到RAG的第一阶段,资料分块。了解到了分块的原因,大小的权衡与常用库。

本篇继续了解RAG的下一个步骤,向量化。

2 向量化:让机器看懂语言

RAG流程中,我们需要使用Embedding模型来充当“翻译”,将人类的语言(文本)精准地翻译成机器能够理解和计算的语言(向量)。

2.1 转换文本为坐标

文本经Embedding模型转换后成为一串数字坐标,比如:

[0.1, 0.9, 0.2, ...]

关键原则:在语义上相似的文本,它们转换后的向量,在数学空间中的距离也更近。

假设我们有三段文本需要转换:

假设转换后的向量(Numpy数组)为:

import numpy as np# 文本A: "今天天气真好" 的向量vector_a = np.array([0.9, 0.8, 0.1, 0.2])# 文本B: "今天阳光明媚" 的向量vector_b = np.array([0.8, 0.9, 0.1, 0.3])# 文本C: "我喜欢吃披萨" 的向量vector_c = np.array([0.1, 0.2, 0.9, 0.8])

点积的值越大,通常表示两个向量在方向上越接近,也就是越“相似”。

我们继续使用Numpy计算”点积“:

a_b = vector_a @ vector_bprint(a_b) # 1.5100000000000002a_c = vector_a @ vector_cprint(a_c) # 0.5000000000000001b_c = np.dot(vector_b, vector_c)print(b_c) # 0.5900000000000001

很容易看出来文本A与文本B相似度更高。

当一个用户提问时,简单的RAG系统可以这样做:

    把用户的问题(比如“今天天气怎么样?”)也转换成一个向量。然后用这个“问题向量”去和数据库里成千上万个“文本块向量”逐一计算点积(或者更高效的相似度算法)。最后,选出点积得分最高的那几个文本块,作为“开卷考试”的参考资料,喂给LLM。

实际场景中一般使用嵌入模型。

3 使用sentence-transformers在本地生成向量

使用适合中文处理的Embedding模型:bge-small-zh-v1.5。

# 1. 从库中导入 SentenceTransformer 类from sentence_transformers import SentenceTransformerimport numpy as np# --- 向量化部分 ---# 2. 加载本地模型。#    第一次运行时,它会自动从Hugging Face下载模型文件到您的本地缓存中。#    这可能需要一些时间,取决于您的网络。model_name = 'BAAI/bge-small-zh-v1.5'print(f"正在加载本地模型: {model_name}...")model = SentenceTransformer(model_name)print("模型加载完成。")# 3. 准备一些待转换的文本块text_chunks = [    "RAG的核心思想是开卷考试。",    "RAG是一种结合了检索与生成的先进技术。", # 与上一句意思相近    "今天天气真好,万里无云。" # 与前两句意思完全不同]# 4. 使用 model.encode() 方法进行向量化。#    它会返回一个Numpy数组的列表。vectors = model.encode(text_chunks)# --- 观察与计算部分 ---# 5. 观察向量的形状 (shape)print("\n--- 向量信息 ---")# (句子数量, 每个向量的维度)print(f"生成向量的形状: {vectors.shape}") # 6. 计算相似度:我们来计算第一个句子和另外两个句子的相似度#    我们将使用余弦相似度,这是衡量向量方向一致性的标准方法。#    公式: (A·B) / (||A|| * ||B||)def cosine_similarity(v1, v2):    dot_product = np.dot(v1, v2)    norm_v1 = np.linalg.norm(v1) # linalg.norm 计算向量的模长    norm_v2 = np.linalg.norm(v2)    return dot_product / (norm_v1 * norm_v2)similarity_1_vs_2 = cosine_similarity(vectors[0], vectors[1])similarity_1_vs_3 = cosine_similarity(vectors[0], vectors[2])print("\n--- 相似度计算结果 ---")print(f"句子1 vs 句子2 (语义相近) 的相似度: {similarity_1_vs_2:.4f}")print(f"句子1 vs 句子3 (语义无关) 的相似度: {similarity_1_vs_3:.4f}")

3.1 向量形状

print(f"生成向量的形状: {vectors.shape}") 生成向量的形状: (3, 512)# (样本数,维度)

向量的形状 (样本数, 维度) 是对我们向量化后数据集的一个宏观描述。维度 是由你选择的 Embedding模型本身决定 的,它代表了模型的复杂度和表达能力。

当我们打印出 vectors.shape 并看到 (3, 512) 时,这个元组 (3, 512) 告诉我们两件至关重要的事:

    第一个数字 (3): 代表我们处理了多少个独立的文本项。在这里,它对应我们输入的列表 text_chunks 中有3个句子。如果我们将1000个文本块输入 model.encode(),这个数字就会是1000。它代表了我们数据集的 样本数量第二个数字 (512): 这是更关键的那个,它代表了 每个向量的维度 (Dimension)。这意味着我们选择的 bge-small-zh-v1.5 模型,会将任何输入的文本,都映射到一个固定的、512维的超空间中的一个点。

512维空间在数学上有巨大的容量,可以编码非常丰富和细微的语义信息。一个文本的最终向量,就是它在所有这些维度上“得分”的组合。这使得模型能够区分出“苹果公司发布了新手机”和“我喜欢吃苹果”这样非常细微的语义差别。

3.2 “余弦相似度”为什么是比较相似度的首选?

# 6. 计算相似度:我们来计算第一个句子和另外两个句子的相似度#    我们将使用余弦相似度,这是衡量向量方向一致性的标准方法。#    公式: (A·B) / (||A|| * ||B||)def cosine_similarity(v1, v2):    dot_product = np.dot(v1, v2)    norm_v1 = np.linalg.norm(v1) # linalg.norm 计算向量的模长    norm_v2 = np.linalg.norm(v2)    return dot_product / (norm_v1 * norm_v2)

在绝大多数RAG和语义搜索场景中,余弦相似度是“事实上的标准”,但它不是唯一的选择。余弦相似度公式:Cosine Similarity=cosθ=v1v2v1v2\text{Cosine Similarity} = \cos\theta = \frac{\mathbf{v1} \cdot \mathbf{v2}}{\|\mathbf{v1}\| \|\mathbf{v2}\|}

为什么余弦相似度是首选?

3.2.1 归一化

在使用SentenceTransformer时,model.encode() 方法生成嵌入向量时,可以通过参数 normalize_embeddings 控制是否归一化。

vectors = model.encode(text_chunks, normalize_embeddings=True)

bge-small-zh-v1.5 模型在 model.encode() 中默认将 normalize_embeddings=True,即生成的嵌入向量已经是单位向量(模长为 1)。如果向量已归一化,余弦相似度公式简化为:cosθ=v1v2\cos\theta = \mathbf{v1} \cdot \mathbf{v2}

即,余弦等于点积。归一化后,使用点积计算快于余弦相似度计算。上述代码是为了演示,其实可以替换为:

# 引入封装好的工具类similarities = util.cos_sim(vectors, vectors)print(f"句子1 vs 句子2: {similarities[0][1]:.4f}")print(f"句子1 vs 句子3: {similarities[0][2]:.4f}")

util.cos_sim 支持批量计算所有向量对的相似度,避免逐个计算,提高效率。

3.3 向量比较方法

其他方法还有第二章演示向量比较的点积,另外还有欧式距离。

3.3.1 点积与余弦相似度

余弦相似度是点积的归一化形式:cosθ=abab\cos\theta = \frac{\mathbf{a} \cdot \mathbf{b}}{\|\mathbf{a}\| \|\mathbf{b}\|}

若向量已归一化(a=b=1\|\mathbf{a}\| = \|\mathbf{b}\| = 1),则点积等于余弦相似度

3.3.2 点积与欧氏距离

对于两个向量,欧氏距离与点积有以下关系(假设向量已归一化或未归一化):ab2=a2+b22ab\|\mathbf{a} - \mathbf{b}\|^2 = \|\mathbf{a}\|^2 + \|\mathbf{b}\|^2 - 2 \mathbf{a} \cdot \mathbf{b}

若向量归一化(a=b=1\|\mathbf{a}\| = \|\mathbf{b}\| = 1),则:ab2=22cosθ\|\mathbf{a} - \mathbf{b}\|^2 = 2 - 2 \cos\theta因此,欧氏距离与余弦相似度呈反比:余弦相似度越大,欧氏距离越小。

3.3.3 余弦相似度与欧氏距离

对于归一化向量,余弦相似度为 1 时,欧氏距离为 0;余弦相似度为 0 时,欧氏距离为 2\sqrt{2}。欧氏距离综合考虑长度和方向差异,而余弦相似度只关注方向。

from sentence_transformers import SentenceTransformer, utilimport torchimport numpy as np# 加载模型model = SentenceTransformer('BAAI/bge-small-zh-v1.5')# 输入句子sentences = ["今天天气很好。", "天气晴朗适合户外活动。"]# 生成嵌入(默认归一化)embeddings = model.encode(sentences, normalize_embeddings=True)# 计算点积dot_product = torch.dot(torch.tensor(embeddings[0]), torch.tensor(embeddings[1]))# 计算余弦相似度cosine_similarity = util.cos_sim(embeddings, embeddings)[0][1]# 计算欧氏距离euclidean_distance = np.linalg.norm(embeddings[0] - embeddings[1])print(f"点积: {dot_product:.4f}")print(f"余弦相似度: {cosine_similarity:.4f}")print(f"欧氏距离: {euclidean_distance:.4f}")

输出为:

点积: 0.6524余弦相似度: 0.6524欧氏距离: 0.8337

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

RAG 向量化 Embedding 余弦相似度
相关文章