一、从“关键词”到“向量”:为什么要用 Embedding?
在传统的信息检索中,我们主要依赖关键词匹配。例如,用搜索引擎搜“苹果”,系统会找出所有包含“苹果”这两个字的文档。这种方法的局限性显而易见:
- 无法理解同义词:搜“手机”,可能找不到包含“智能手机”或“移动电话”的文档。
- 无法理解语境:“苹果很甜”和“苹果发布新系统”中的“苹果”含义完全不同,但关键词匹配无法区分。
- 无法进行语义推理:搜“如何提升幸福感”,很难匹配到讨论“缓解压力”、“培养爱好”的优质内容。
Embedding(嵌入)技术应运而生。它的核心目标是将文本(字、词、句子甚至段落)转换成一个固定长度的数字向量(比如一个由768或1536个浮点数组成的列表)。这个向量就像是文本在“语义空间”中的一个坐标。核心思想是:意思相近的文本,其向量在空间中的距离也相近。这样,我们就能通过计算向量间的距离来衡量语义的相似度,从而实现真正的语义检索。
二、Embedding 是如何生成的:模型背后的直觉
我们并不需要手动为每个单词分配一个向量。现代 Embedding 模型(如 Sentence-BERT, OpenAI text-embedding-ada-002)通常是基于 Transformer 架构的深度神经网络。你可以把它想象成一个经过海量文本数据(如整个互联网)训练出来的、极其复杂的“语义编码器”。
这个模型的训练目标通常是“预测上下文”或“判断句子对相似性”。例如,在“我养了一只[遮住],它很可爱”这个句子中,模型需要根据上下文“养了”、“可爱”预测出被遮住的词是“猫”或“狗”而非“桌子”。通过数亿次这样的训练,模型学会了将语义信息压缩到一个高维向量中。
- 词义:“猫”和“狗”的向量会比较接近,因为它们都是宠物。
- 句义:“今天天气真好”和“阳光明媚”的向量会非常接近,而与“股市暴跌”的向量则相距甚远。
这个过程是端到端的,我们只需将文本输入模型,就能得到对应的 Embedding 向量。模型自动完成了从离散符号到连续向量空间的映射。
三、如何衡量“远近”:相似度计算
有了向量,我们就可以用数学公式来计算它们之间的相似度。最常用的方法是余弦相似度。
余弦相似度 计算的是两个向量在方向上的差异,取值范围是 [-1, 1]。值越接近1,表示两个向量的方向越一致,语义也就越相似。
提示:为什么常用余弦相似度而不是欧氏距离?因为余弦相似度关注向量的方向(即语义模式),而对向量的长度不敏感。两个文本即使长度差异很大(例如“猫”和“一只非常可爱的白色小猫咪”),只要核心意思一致,它们的向量方向可能非常接近,余弦相似度就会很高。
除了余弦相似度,还有点积、曼哈顿距离等度量方式,但在语义检索领域,余弦相似度因其直观和良好的效果而被广泛使用。
四、语义检索的核心流程与 RAG 应用
理解了以上概念,语义检索的原理就水到渠成了。它通常包含两个阶段:
- 离线索引阶段:
- 将你的知识库(例如,公司所有产品文档、历史博客文章)中的每一段文本,使用 Embedding 模型转换为向量。
- 将这些向量存入专门的向量数据库(如
Milvus,Pinecone,FAISS)或支持向量索引的数据库中,并记录每个向量对应的原始文本。 - 为这些向量建立高效的索引(如
HNSW, IVF),以支持快速的近似最近邻搜索。
- 在线查询阶段:
- 当用户输入一个查询(如“如何修复漏水的水龙头”),同样使用同一个 Embedding 模型将其转换为查询向量。
- 在向量数据库中,搜索与查询向量余弦相似度最高的前 K 个结果向量(Top-K)。
- 返回这些向量对应的原始文本片段,作为与查询最相关的答案。
这项技术是 RAG 的基石。RAG 让大模型在回答问题时,能够先从外部知识库中“检索”相关文档,再基于这些文档生成答案,极大地提升了回答的准确性和时效性,并提供了来源可追溯性。
五、实践入门:用代码感受 Embedding 的力量
理论说再多,不如亲手试一试。下面我们使用流行的 sentence-transformers 库来生成文本的 Embedding 并计算相似度。
首先,安装必要的库:
pip install sentence-transformers
然后,编写 Python 代码:
from sentence_transformers import SentenceTransformer, util
# 1. 加载一个预训练的句子Embedding模型
# `all-MiniLM-L6-v2` 是一个效果不错且轻量的模型
model = SentenceTransformer('all-MiniLM-L6-v2')
# 2. 准备一些文本句子
sentences = [
"今天阳光明媚,适合外出郊游。",
"天气晴朗,我们去爬山吧!",
"明天的股票市场走势预测。"
]
# 3. 生成Embedding向量
# 输出是一个2D数组,每行是一个句子的向量
embeddings = model.encode(sentences)
print(f"句子数量: {len(embeddings)}")
print(f"每个向量的维度: {embeddings[0].shape}") # 这个模型的输出维度是384
# 4. 计算第一个句子与其它句子的余弦相似度
# `util.cos_sim` 返回一个相似度矩阵
cos_sim = util.cos_sim(embeddings[0], embeddings)
print(f"\n'{sentences[0]}' 与其它句子的相似度:")
for i, sim in enumerate(cos_sim[0]):
print(f" {sentences[i]}: {sim.item():.4f}")
运行这段代码,你会清晰地看到,“今天阳光明媚”和“天气晴朗”的相似度会非常高(例如>0.7),而与“股票市场”的相似度则很低(例如<0.1)。这就是向量在衡量语义距离的直观体现。
六、总结与进阶思考
Embedding 和语义检索是一项革命性的技术,它将信息检索从“字面匹配”带入了“理解含义”的新时代。对于开发者而言,掌握它的核心思想至关重要。
- 是什么:Embedding 是将文本映射到高维向量的技术,是文本语义的数学表示。
- 为什么:它解决了传统关键词检索无法处理同义词、一词多义和深层语义的问题。
- 怎么用:通过调用预训练模型生成向量,存入向量数据库,并利用余弦相似度进行检索。它是构建 RAG 等现代 AI 应用的基础设施。
在实际应用中,你需要考虑:
- 模型选择:是使用开源模型(如
BGE,E5,GTE)还是商业API(如OpenAI)。需要在效果、成本和延迟间权衡。 - 分块策略:如何将长文档切分成大小合适的片段(Chunk)进行 Embedding,这直接影响检索效果。
- 检索优化:如何结合关键词检索(Hybrid Search)和语义检索,利用重排序(Reranking)模型对初步结果进行二次排序,以获得最佳结果。
关键提示:Embedding 模型的训练数据和目标任务直接影响其在特定领域的表现。对于专业领域(如法律、医疗),可能需要使用领域数据进行微调(Fine-tuning)才能获得最佳效果。