RAG 每日一技(四):让AI读懂你的话,初探RAG的“灵魂”——Embedding

前情回顾

经过前三天的努力,我们已经成功掌握了如何将各种类型的文档(纯文本、代码、Markdown)"优雅地"切分成高质量的文本块(Chunks)。可以说,我们为RAG系统准备好了最优质的"原材料"。

但是,新的问题紧接着就来了:

当用户提出一个问题(比如:"RAG的核心组件是什么?")时,我们如何在成千上万,甚至数百万个Chunks中,快速、准确地找到与这个问题最相关的那几个呢?

你可能会想到传统的关键词搜索。但关键词搜索有巨大的局限性。比如用户问"苹果公司的创始人",包含"乔布斯"的文本块可能就匹配不到;用户问"AI的未来",包含"人工智能的前景"的文本块也可能被错过。

我们需要一种能理解语义相似度 ,而不仅仅是字面匹配的方法。而实现这一切的核心技术,就是我们今天要探索的RAG系统的"灵魂"------Embedding

什么是Embedding?

简单来说,Embedding(嵌入)就是一种将文本(或其他任何东西,如图片、声音)转换成一串数字(即"向量")的技术。

这串数字(向量)并不是随机的,它会尽可能地捕捉原始文本的语义信息

我们可以打一个比方:

想象一张世界地图。我们可以用经纬度(一个二维向量)来表示任何一个城市的位置。在地图上,"巴黎"、"罗马"、"马德里"这些欧洲城市会聚集在一起,而"北京"、"东京"则在另一个区域,它们之间的距离反映了地理上的关系。

Embedding做的事情类似,但它是在一个更高维度的"语义空间"里,为每个词、每个句子、每个文本块分配一个"语义坐标"(一个高维向量)。在这个空间里:

  • "国王"和"女王"的"坐标"会非常接近。
  • "我喜欢夏天"和"炎热的天气真棒"的"坐标"也会很接近。
  • 而"科技新闻"和"美食菜谱"的"坐标"则会相距甚远。

通过这种方式,"文本相似度"这个模糊的概念,就被转化成了可以精确计算的"向量空间距离"。计算机不擅长理解语言,但极其擅长数学运算。这就是Embedding的魔力所在。

上手实践:将文本转化为向量

理论说完了,我们马上动手实践。我们将使用一个非常流行的开源Embedding模型库 sentence-transformers 和一个在中文领域表现优异的开源模型 m3e-base

首先,确保你已经安装了必要的库:

bash 复制代码
pip install sentence-transformers

然后,我们用代码来感受一下文本是如何变成向量的。

python 复制代码
from sentence_transformers import SentenceTransformer

# 加载一个预训练好的中文Embedding模型
# 第一次运行时,它会自动从HuggingFace下载模型文件
model = SentenceTransformer('m3e-base')

# 准备几个待转换的句子
sentences = [
    "我喜欢吃苹果",
    "我喜欢吃香蕉",
    "今天天气真好",
    "我讨厌上班"
]

# 使用模型将句子编码为向量
embeddings = model.encode(sentences)

# 我们来看看结果
for sentence, embedding in zip(sentences, embeddings):
    print("句子:", sentence)
    # 打印向量的前5个维度和向量的总维度
    print(f"向量 (前5维): {embedding[:5]}")
    print(f"向量维度: {len(embedding)}")
    print("-" * 20)

输出结果(你运行的结果中,向量的具体数值可能略有不同,但维度是固定的):

markdown 复制代码
句子: 我喜欢吃苹果
向量 (前5维): [ 0.01391807 -0.01953284  0.01596547 -0.01229419 -0.00160986]
向量维度: 768
--------------------
句子: 我喜欢吃香蕉
向量 (前5维): [ 0.01850123 -0.01908993  0.00392336 -0.01168233 -0.00832363]
向量维度: 768
--------------------
句子: 今天天气真好
向量 (前5维): [ 0.00445524 -0.03813957  0.01150338 -0.0321528  -0.03158003]
向量维度: 768
--------------------
句子: 我讨厌上班
向量 (前5维): [-0.00890695 -0.03367128  0.03842103  0.0210134  -0.01174621]
向量维度: 768
--------------------

看,每一个句子都被成功转换成了一个包含768个数字的向量!这就是它们的"语义坐标"。

魔法时刻:计算语义相似度

有了向量坐标,我们就可以计算它们之间的相似度了。最常用的方法是余弦相似度 (Cosine Similarity),它测量两个向量在方向上的接近程度。结果范围在-1到1之间,1表示完全相同,0表示完全无关,-1表示完全相反。

sentence-transformers 库也为我们提供了便捷的工具。

python 复制代码
from sentence_transformers import util

# 计算"我喜欢吃苹果"和其它所有句子之间的余弦相似度
query_embedding = embeddings[0]
other_embeddings = embeddings[1:]

# util.cos_sim会返回一个张量(tensor),包含查询向量和其它所有向量的相似度
cosine_scores = util.cos_sim(query_embedding, other_embeddings)

print(f"查询句子: '{sentences[0]}'")
for i in range(len(other_embeddings)):
    print(f"与 '{sentences[i+1]}' 的相似度: {cosine_scores[0][i]:.4f}")

输出结果:

arduino 复制代码
查询句子: '我喜欢吃苹果'
与 '我喜欢吃香蕉' 的相似度: 0.9038
与 '今天天气真好' 的相似度: 0.5847
与 '我讨厌上班' 的相似度: 0.6120

结果一目了然!

  • "我喜欢吃苹果"和"我喜欢吃香蕉"的语义极其相似(都关于喜欢吃某种水果),所以相似度高达 0.90
  • 而与"天气"和"上班"的句子相比,虽然都包含"我",但主题完全不同,所以相似度就低了很多。

这就是Embedding和语义搜索的威力!

总结与预告

今日小结:

  • Embedding 是将文本转换为数字向量(语义坐标)的过程,是RAG系统实现语义检索的基石。
  • 通过计算向量间的余弦相似度,我们可以准确地判断文本间的语义关联程度。
  • 我们可以使用 sentence-transformers 这样的开源库和 m3e-base 这样的模型,轻松地实现文本的Embedding。

现在,我们已经能将所有的文本块(Chunks)都转换成向量了。但一个新的、非常工程化的问题又摆在了面前:

当我们的知识库有数百万个Chunks,也就意味着有数百万个向量。当用户提出一个问题时,难道我们要把用户问题的向量,和这数百万个向量逐一计算余弦相似度,然后排序找分最高的吗?

这太慢了!在实际应用中是绝对无法接受的。我们需要一种能从海量向量中进行高效相似度搜索的专门技术。

明天预告:RAG 每日一技(五):大海捞针第一步,亲手构建你的向量索引!

明天,我们将正式踏入向量数据库 的世界,并亲手用一个流行的库(如FAISS)来构建我们的第一个向量索引,体验什么叫"瞬间"从百万向量中找到你的目标!

相关推荐
Real_man21 分钟前
新物种与新法则:AI重塑开发与产品未来
前端·后端·面试
小马爱打代码1 小时前
Spring Boot:将应用部署到Kubernetes的完整指南
spring boot·后端·kubernetes
卜锦元1 小时前
Go中使用wire进行统一依赖注入管理
开发语言·后端·golang
SoniaChen333 小时前
Rust基础-part3-函数
开发语言·后端·rust
全干engineer3 小时前
Flask 入门教程:用 Python 快速搭建你的第一个 Web 应用
后端·python·flask·web
William一直在路上3 小时前
SpringBoot 拦截器和过滤器的区别
hive·spring boot·后端
小马爱打代码4 小时前
Spring Boot 3.4 :@Fallback 注解 - 让微服务容错更简单
spring boot·后端·微服务
曾曜4 小时前
PostgreSQL逻辑复制的原理和实践
后端
豌豆花下猫4 小时前
Python 潮流周刊#110:JIT 编译器两年回顾,AI 智能体工具大爆发(摘要)
后端·python·ai
轻语呢喃5 小时前
JavaScript :事件循环机制的深度解析
javascript·后端