Appearance
5.18 微调·Embedding 与 Reranker
5.13–5.16 讲的都是微调生成模型(让它按你的风格、格式答话)。但 RAG 系统里,决定成败的往往不是生成,而是检索——召回不准,后面生成得再好也是基于错料瞎编。这一节讲怎么微调检索侧的两个模型:Embedding 和 Reranker。
💡 类比:通用 Embedding 模型像一个博览群书但不懂你行业的实习生——日常对话它分得清远近,但你公司内部的黑话、专业缩写、产品代号,它觉得"看起来都差不多",于是相关的文档反而排不到前面。微调,就是带它在你的领域里"补课",让它对你这行的语义距离重新校准。
什么时候才需要微调检索模型
⚠️ 先说结论:大多数情况你不需要。遇到召回不准,按这个顺序补救,能不微调就不微调:
- 先优化分块和查询(5.1)——很多"召回差"其实是块切坏了
- 加一个通用 Reranker——这是性价比最高的一步,常常立竿见影(见下)
- 以上都试过还不行,且你的领域术语很特殊(医疗、法律、内部系统),才考虑微调
什么场景值得微调:通用模型把你领域里语义相关但字面不同的内容判成不相关("心梗" vs "心肌梗死"、内部产品代号 vs 全称)。
两件不同的事:Embedding 微调 vs Reranker 微调
RAG 检索通常是"两段式":先用 Embedding 从海量文档里粗筛出几十条(快),再用 Reranker 对这几十条精排出最相关的几条(准)。两个模型都能微调,但角色不同:
| Embedding 模型 | Reranker(重排模型) | |
|---|---|---|
| 干什么 | 把文本变向量,粗筛召回 | 给"查询-文档"对打相关性分,精排 |
| 速度 | 快(可预先算好建索引) | 慢(每个候选都要现算) |
| 微调收益 | 提升召回率(别漏) | 提升精度(排得准) |
| 优先级 | 改动大(要重算全库向量) | 改动小,建议先做 |
⚠️ 微调 Embedding 有个大坑:模型一换,整个知识库的历史向量全部作废,必须用新模型重新 embed 一遍再重建索引。库越大,这个重算成本越高。Reranker 没这问题——它不改变索引,只在召回后重排,所以"先上 Reranker"几乎总是更划算。
数据怎么来:三元组
微调检索模型的数据核心是三元组:(查询, 正样本=相关文档, 负样本=不相关文档)。让模型学会"把正样本拉近、负样本推远"。
数据来源:
- 用户行为日志:用户搜了 query、点了哪条结果 → 点的是正样本,没点的是负样本(最真实,量大)
- 人工标注:少量高质量标注,适合冷启动
- LLM 合成:给一段文档,让强模型"反推"出几个用户可能会问的问题,构成 (问题, 该文档) 正样本对(5.13 数据准备 那套合成思路)
⚠️ 难负样本(hard negatives)最关键:负样本不能随便挑无关的(那太好区分,学不到东西),要挑"看起来相关、其实不对"的。比如查"苹果手机保修",难负样本是"苹果手机以旧换新"——字面像,意思不同。难负样本的质量基本决定微调效果。
怎么训:sentence-transformers
检索模型微调是 Python 生态的活,sentence-transformers 是事实标准,几十行就能跑:
python
# pip install sentence-transformers
from sentence_transformers import SentenceTransformer, InputExample, losses
from torch.utils.data import DataLoader
# 1. 拿一个通用中文 embedding 模型做底座(如 BAAI/bge-small-zh)
model = SentenceTransformer("BAAI/bge-small-zh-v1.5")
# 2. 准备三元组数据:(查询, 正样本, 难负样本)
train_examples = [
InputExample(texts=["苹果手机怎么保修", "iPhone 保修政策与送修流程", "iPhone 以旧换新折抵"]),
InputExample(texts=["心梗的早期症状", "心肌梗死的前驱表现", "心脏搭桥手术费用"]),
# …用你领域的数据补到几百~几千条,难负样本质量是关键
]
loader = DataLoader(train_examples, shuffle=True, batch_size=16)
# 3. 用对比损失训练(把正样本拉近、负样本推远)
loss = losses.TripletLoss(model)
model.fit(train_objectives=[(loader, loss)], epochs=3, warmup_steps=100)
# 4. 保存,之后用它给【整个知识库】重新 embed 并重建索引
model.save("./bge-finetuned")国产平台:阿里百炼等也提供 Embedding/Reranker 的训练或行业定制能力,不想自己管 GPU 可以走云端(思路同 5.14 云端微调)。
🛠️ 实战练习:先量化收益,再决定要不要微调
别一上来就训。先建一个小评估集,量出"通用模型 vs 加 Reranker vs 微调"各自的召回效果,用数字说话。
具体步骤:
- 从你的领域挑 20~30 个真实查询,每个人工标注出"正确答案应该来自哪几篇文档"
- 基线:用通用 Embedding(如 bge-small-zh)检索,算 Top-5 命中率(正确文档有没有进前 5)
- 加 Reranker:召回 Top-20 后用通用 Reranker(如 bge-reranker)精排,再算 Top-5 命中率
- 对比两组数字,看加 Reranker 提升了多少
期望结果:通常你会看到"加 Reranker"就带来明显提升,且零训练成本——这一步往往就够了。
进阶挑战:用 LLM 给这 20 个查询合成训练三元组(含难负样本),用 sentence-transformers 微调 embedding,重算评估集向量,看命中率还能不能再涨——以及涨幅值不值回重算全库的成本。
📌 关键结论
- RAG 成败常在检索而非生成;召回不准时,先优化分块、再加通用 Reranker,最后才考虑微调
- Embedding 微调提召回率但换模型要重算全库向量;Reranker 微调提精度且不动索引——优先上 Reranker
- 训练数据是三元组 (查询, 正样本, 难负样本),可从点击日志、人工标注、LLM 合成获得
- 难负样本(看着相关其实不对)的质量基本决定微调效果,别用随便的无关负样本
- 工具用
sentence-transformers(Python 事实标准)或国产云平台;动手前先用评估集量化收益,别为想象中的问题买单
🎉 第 5 章完成,四大主题(RAG / MCP / Skill / 微调)连同进阶范式全部收尾。下一步:第 6 章 · 提示词工程精通,或去 🎯 复习巩固 · 词汇速查 · 跟上 AI 前沿