什么是 Embedding
Embedding(词嵌入) 是把文字转换成一组数字(向量)的技术,让计算机能"算"出文字的语义。
打个比方:
- 文字 = 书,你只能"看",没法"算"
- Embedding = 给每本书一个 GPS 坐标,相似的书坐标接近
"猫坐在垫子上" → [0.12, -0.34, 0.56, ..., 0.78] // 1536 维
"猫咪趴在毯子上" → [0.11, -0.33, 0.55, ..., 0.77] // 坐标接近
"今天股市大涨" → [-0.45, 0.21, -0.67, ..., 0.03] // 坐标远离
向量之间的距离 = 语义相似度。这就是为什么搜索引擎能找到"意思相近"而非"字面相同"的内容。
为什么需要 Embedding
传统搜索的痛点:
用户搜:"怎么退货"
传统关键词搜索:
匹配含"退货"的文档 → 找到 3 篇
漏掉含"退款流程""7 天无理由"的文档(意思相同但字面不同)
Embedding 搜索:
"怎么退货" → 向量 A
"退款流程" → 向量 B(与 A 距离近)
"7 天无理由" → 向量 C(与 A 距离近)
→ 召回 A+B+C,更全
Embedding 解决了"字面不同但语义相同"的匹配问题,这是 RAG 和语义搜索的基础。
Embedding 怎么表示语义
直觉:词的"语义坐标"
想象把所有词放在一个空间里:
动物
↑
猫 ●
|
狗 ● ← 猫狗都是动物,距离近
|
--------→ 哺乳
|
汽车 ● ← 汽车不在此区域,距离远
真实 Embedding 是 768/1536/3072 维(人无法可视化),但原理相同:意思相近的词,向量距离近。
训练原理:上下文相似 → 语义相似
Embedding 模型通过海量文本学习,核心假设:
出现在相似上下文里的词,意思相近。
"我家养了一只 __ ,每天喂它吃鱼" → 上下文相似
可能是:猫 / 狗 / 仓鼠(都是宠物)
"我开 __ 去上班,加油很贵" → 上下文不同
可能是:车 / 汽油
模型见过数亿句话后,学会把"猫"和"狗"放在相近位置(上下文相似),把"猫"和"汽车"放远(上下文不同)。
句子级 Embedding
词的 Embedding 升级到句子:
"猫坐在垫子上" → 整句一个向量
"猫咪趴在毯子上" → 整句一个向量(与上句接近)
原理:把句子所有词的向量 + 位置信息,
通过 [Transformer](/glossary/2026-08-13-transformer) 编码器,
输出一个"句意向量"。
相似度怎么算
两个向量的相似度,常用余弦相似度:
cos(A, B) = (A · B) / (|A| × |B|)
值域 [-1, 1]:
1 = 方向完全一致(语义相同)
0 = 正交(无关)
-1 = 方向相反(语义相反,实际少见)
import numpy as np
def cosine_sim(a, b):
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
cat_vec = embed("猫坐在垫子上")
dog_vec = embed("猫咪趴在毯子上")
car_vec = embed("今天股市大涨")
print(cosine_sim(cat_vec, dog_vec)) # 0.89(很相似)
print(cosine_sim(cat_vec, car_vec)) # 0.12(不相关)
主流 Embedding 模型
| 模型 | 维度 | 特点 | 适用 |
|---|---|---|---|
| OpenAI text-embedding-3-small | 1536 | 性价比高 | 通用首选 |
| OpenAI text-embedding-3-large | 3072 | 精度高 | 高质量检索 |
| BGE-large-zh | 1024 | 中文开源 SOTA | 中文场景 |
| BGE-m3 | 1024 | 多语言 | 跨语言 |
| Cohere embed-v3 | 1024 | 多语言强 | 国际化 |
| Jina embeddings v2 | 768 | 长文本(8K) | 长文档 |
| Voyage voyage-2 | 1024 | 代码与文档 | 技术文档 |
维度越多越好吗
1536 维 vs 3072 维:
- 3072 精度更高(边界 case 更准)
- 1536 性价比更高(存储/检索快一倍)
- 大多数场景 1536 已足够
选型建议
| 场景 | 推荐 |
|---|---|
| 通用英文 | text-embedding-3-small |
| 通用中文 | BGE-large-zh |
| 高精度 | text-embedding-3-large |
| 多语言 | BGE-m3 / Cohere v3 |
| 长文档(>2K 字/段) | Jina v2 |
| 代码/技术 | Voyage-2 |
| 预算敏感 | BGE(开源免费) |
在 RAG 中的角色
Embedding 是 RAG 的"检索引擎":
RAG 流程:
离线:文档 → 切块 → Embedding → 向量库
在线:问题 → Embedding → 检索 → 拼 Prompt → LLM 回答
↑
这一步就是 Embedding 的核心作用
检索质量直接决定 RAG 质量。Embedding 模型选错,检索召不准,后面 LLM 再强也白搭。
完整代码示例
from openai import OpenAI
import chromadb
client = OpenAI()
db = chromadb.PersistentClient(path="./vector_db")
# ===== 离线:把文档 Embedding 后存库 =====
def embed_text(text):
resp = client.embeddings.create(
input=text,
model="text-embedding-3-small"
)
return resp.data[0].embedding
collection = db.get_or_create_collection("docs")
docs = [
{"id": "1", "text": "7 天无理由退货,需保留吊牌"},
{"id": "2", "text": "退款流程:登录→我的订单→申请退款"},
{"id": "3", "text": "配送时效:3-5 个工作日"},
]
for doc in docs:
vec = embed_text(doc["text"])
collection.add(
ids=[doc["id"]],
embeddings=[vec],
documents=[doc["text"]]
)
# ===== 在线:问题 → 检索 → 返回相似文档 =====
query = "怎么退款?"
query_vec = embed_text(query)
results = collection.query(query_embeddings=[query_vec], n_results=2)
for doc, dist in zip(results["documents"][0], results["distances"][0]):
print(f"相似度: {1-dist:.2f} | {doc}")
# 输出:
# 相似度: 0.91 | 退款流程:登录→我的订单→申请退款
# 相似度: 0.78 | 7 天无理由退货,需保留吊牌
常见坑点
坑 1:切块不当破坏语义
✗ 每 500 字硬切 → "退款"被切到两半,向量失真
✓ 按段落/标题切 → 完整保留"退款流程"语义
坑 2:用错相似度算法
✗ 欧氏距离 → 受向量模长影响,不准
✓ 余弦相似度 → 只看方向,标准做法
坑 3:跨语言混用模型
✗ 用英文 Embedding 模型处理中文 → 召回差
✓ 中文用 BGE-large-zh,多语言用 BGE-m3
坑 4:未做向量归一化
✗ 直接存原始向量 → 某些库需归一化后才能准确算余弦
✓ Embedding 后做 L2 归一化(多数模型已内置)
坑 5:模型升级不重建库
✗ 从 1536 维模型换到 3072 维 → 旧向量无法用
✓ 换模型 = 全库重新 Embedding
Embedding 的局限
1. 不擅长精确匹配
"找产品 SKU: ABC-123"
Embedding:可能召回 ABC-124(语义近)
解决:精确字段用关键词/数据库过滤,Embedding 只管语义
2. 不懂数字大小
"找价格 < 100 的商品"
Embedding:无法理解"100"是数值阈值
解决:用 metadata 过滤 + Embedding 语义检索组合
3. 对抗性问句处理弱
"怎么才能不退货?" ← 否定句
Embedding:可能召回退货流程(忽略了"不")
解决:查询改写 + 关键词过滤
与其他概念的关系
- Transformer:Embedding 模型的底层架构
- LLM:LLM 内部也有 Embedding 层(输入端)
- RAG:Embedding 是 RAG 的检索引擎
- 上下文窗口:Embedding 不受窗口限制(离线处理)
小结
Embedding 是让文字"可计算"的关键技术——把语义压缩成向量,让相似度变成距离。
掌握它,你就掌握了 RAG、语义搜索、推荐系统的地基。下次想做"找相似内容"的功能,别再想着关键词匹配,第一反应应该是 Embedding。