一、从文本到向量:Embedding 的核心思想

我们日常使用的自然语言,对于计算机来说只是一串离散的、没有内在数学意义的符号。要让机器真正“理解”语言,就需要一种方法将这些符号转化为计算机擅长处理的、连续的数值形式。Embedding(嵌入)正是实现这一目标的核心技术。它的本质是将一个离散对象(如单词、句子、文档,甚至是用户或商品)映射到一个高维连续向量空间中的一个点。

这个过程并非随意的数字编码。一个好的 Embedding 模型会确保,在这个高维空间中,语义相似的对象,它们的向量表示在空间距离上也更接近。例如,“国王”和“女王”的向量距离,会比“国王”和“苹果”的向量距离近得多。这种映射关系使得抽象的“语义”有了具体的、可计算的数学形式,成为了现代搜索、推荐、聚类等众多AI应用的基石。

二、语义检索:超越关键词的“读懂”你

传统的搜索引擎或检索系统(如 LIKE 查询)主要依赖关键词匹配。它的缺点显而易见:用户搜索“笔记本维修”时,可能错过标题包含“笔记本电脑故障排除”的完美结果。因为系统无法理解“维修”和“故障排除”在语义上的高度相关性。

语义检索正是为了解决这个问题。它的核心思想是:将用户的查询(Query)和文档库中的每一份文档(Document)都通过同一个 Embedding 模型转换成向量。然后,计算查询向量与所有文档向量之间的相似度(通常使用余弦相似度),最后返回相似度最高的文档作为结果。这个过程完全基于“意思”而非“字面”,因此能够实现更加智能和灵活的匹配。

提示:语义检索并非要完全取代关键词检索。在实际生产中,常将二者结合(混合检索),用关键词保证精确性(如搜索特定编号),用语义保证召回率(如搜索概念),从而达到最佳效果。

三、模型生成:如何获得文本的“灵魂”

如何将文本变成高质量的向量?这依赖于预训练的深度学习模型。现代主流的 Embedding 模型大多基于 Transformer 架构(如 BERT、RoBERTa 及其变种)。模型通过在海量文本语料上进行“掩码语言建模”等自监督任务预训练,学习到了丰富的语言知识。

针对语义检索任务,通常还会用对比学习(Contrastive Learning)的思路对模型进行微调。简单来说,就是让模型学习:将意思相近的句子对(如 <查询, 相关文档>)的向量拉得更近,将意思无关的句子对的向量推得更远。这样训练出的模型,其输出的向量天然具有优秀的语义区分度。

四、关键组件:相似度计算与向量索引

有了向量,检索的过程就变成了在数百万甚至数十亿向量中,快速找到与查询向量最相似的几个。这涉及两个关键点:

  1. 相似度度量:最常用的是余弦相似度,它计算两个向量夹角的余弦值,衡量它们的方向一致性,对向量长度不敏感,非常适合文本语义。
  2. 近似最近邻搜索:对于海量向量,精确计算每对向量的相似度是不可行的(时间复杂度 O(N))。因此需要使用 ANN(Approximate Nearest Neighbor)算法。常见库如 FAISS、Annoy 和 ScaNN,它们通过构建特定的索引结构(如树、图、哈希)来实现快速、近似的相似向量检索,将复杂度降至接近 O(log N)。

五、实践入门:用 Sentence Transformers 尝试语义检索

下面是一个简单的 Python 代码示例,使用流行的 sentence-transformers 库来演示从句子生成向量并进行相似度计算的全过程。

from sentence_transformers import SentenceTransformer, util
import torch

# 1. 加载一个预训练的语义相似度模型
model = SentenceTransformer('all-MiniLM-L6-v2') # 一个轻量级、效果不错的模型

# 2. 准备一些句子
sentences = [
    "如何给猫咪洗澡?",
    "洗猫的正确步骤是什么?",
    "今天股票市场大涨。",
    "猫咪清洁护理指南"
]

# 3. 将所有句子编码为向量(嵌入)
embeddings = model.encode(sentences, convert_to_tensor=True)

# 4. 定义查询句
query = "怎么给猫洗澡"
query_embedding = model.encode(query, convert_to_tensor=True)

# 5. 计算查询句与所有句子的余弦相似度
cosine_scores = util.cos_sim(query_embedding, embeddings)

# 6. 输出最相似的结果
print(f"查询:'{query}'")
print("语义相似度排名:")
for i, (sentence, score) in enumerate(zip(sentences, cosine_scores[0])):
    print(f"{i+1}. '{sentence}' (相似度: {score:.4f})")

运行上述代码,你会看到“如何给猫咪洗澡?”和“洗猫的正确步骤是什么?”这两个句子与查询的相似度得分非常高,而与股票相关的句子得分则很低,这完美体现了语义理解的能力。

六、应用场景与价值

Embedding 和语义检索技术的价值在于它能理解“意图”,因此应用场景极其广泛:

七、从原理到实践的关键提示

在将 Embedding 和语义检索技术落地时,有几个要点需要牢记:

提示:处理中文语义检索时,务必选择在中文语料上预训练或微调过的模型(如 shibing624/text2vec-base-chinese),直接用英文模型处理中文效果会大打折扣。