向量与 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 模型怎么选 →