Learn
RAG/05-embeddings

向量与 Embedding 基础

RAG 的「检索」本质是向量搜索。要让计算机比较两段文字是否相关,得先把文字变成一串数字——也就是向量(embedding)。本章讲清楚向量空间与相似度,不依赖具体模型。

1. 什么是 Embedding

Embedding 是把离散对象(词、句子、文档)映射到一个高维连续向量空间的技术。语义相近的文本,在这个空间里距离更近。

"猫喜欢吃鱼"   ──► [0.21, -0.83, 0.45, ..., 0.07]   (1536 维)
"猫咪爱吃鱼肉" ──► [0.19, -0.80, 0.48, ..., 0.09]   (距离很近)
"今天股票跌了" ──► [-0.62, 0.31, -0.11, ..., 0.55]  (距离很远)

注意:单看某一维的数字没有人类可解释的含义,意义只存在于向量之间的相对位置。

2. 向量空间直觉

可以把高维空间想象成一张「语义地图」:

  • 每个点是一个文本片段
  • 「意思接近」的文本聚成簇(如所有关于「退款政策」的片段离得近)
  • 检索 = 把问题也投到这张地图,找离它最近的几个点
ℹ️Embedding 是「意义的坐标」

模型在训练时学到:同义、上下位、同主题的文本应靠近。这种几何结构让「算距离」等价于「算语义相似度」。

3. 相似度度量

检索时用一个分数衡量「多像」:

度量公式直觉取值适用
余弦相似度两向量夹角余弦[-1, 1],越大越像最常用,只看方向
点积同方向且越长越大任意向量已归一化时等价余弦
欧氏距离空间直线距离[0, ∞),越小越像少数场景

余弦相似度是 RAG 默认选择,因为它对向量「长度(文本长短)」不敏感,只关心方向。

import numpy as np
 
def cosine(a, b):
    return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
 
q = np.array([0.21, -0.83, 0.45])
d = np.array([0.19, -0.80, 0.48])
print(cosine(q, d))   # 接近 1 → 高度相关

4. 维度(dimension)的意义

Embedding 维度常见 384 / 768 / 1024 / 1536:

  • 维度越高,能编码的语义越细腻,但存储与计算成本上升
  • 同一模型家族内,维度固定不可随意改
  • 维度必须检索端与文档端一致,否则无法比较
⚠️归一化让检索更快

实际系统通常把向量归一化为单位长度,这样余弦相似度就等于点积,可用高效的近似最近邻(ANN)索引加速,详见第 7、8 章。

5. 一个向量搜索的最小演示

# 假设已有问题向量 q_vec 和文档向量列表 doc_vecs
scores = [cosine(q_vec, dv) for dv in doc_vecs]
top_k = sorted(range(len(scores)), key=lambda i: scores[i], reverse=True)[:5]
💡区分训练时与推理时

Embedding 模型是「冻结」的:它不参与 LLM 的微调,只在你需要时把文本转成向量。选好一个模型后,离线入库和在线查询都调用它即可。

🎯练习

取三组句子(同义、反义、无关各一对),用任意 Embedding API 得到向量,亲手算余弦相似度,验证「同义 > 无关」。

小结

  • Embedding = 把文本映射为高维向量,语义相近则距离近
  • 检索即「在向量空间找最近邻」
  • 余弦相似度最常用,只看方向不看长度
  • 维度需检索/文档两端一致,归一化可加速
  • 下一章盘点主流 Embedding 模型怎么选 →