第 16 章:RAG 效果优化:召回、重排、引用来源
本章目标
这一章解决 RAG 项目最真实的问题:能跑不等于好用。我们要优化检索质量、答案可信度和引用展示。
RAG 常见失败原因
RAG 失败通常不是单点问题:
- 文档切分太粗或太碎
- Embedding 模型效果一般
- 检索 topK 太少或太多
- 没有关键词过滤
- 上下文包含无关片段
- Prompt 没要求基于资料回答
- 引用来源缺失
- 用户问题太模糊
优化时要先定位是哪一环出问题。
调整 chunk
切分参数会直接影响检索。
const chunkSize = 800;
const overlap = 120;
可以准备一组测试问题,比较不同参数下召回的片段是否正确。
TopK 策略
topK 太小可能漏资料,太大可能污染上下文。
const topK = Number(process.env.RAG_TOP_K ?? 5);
建议在日志中记录每次检索结果:
console.log({
question,
topK,
results: results.map((item) => ({
source: item.record.metadata.source,
score: item.score
}))
});
阈值过滤
const filteredResults = results.filter((item) => item.score >= 0.25);
如果过滤后没有结果,就拒答或引导用户换个问法。
混合检索
向量检索擅长语义相似,关键词检索擅长精确匹配。业务文档里经常有:
- 编号
- 人名
- 产品名
- 制度名称
- API 字段名
这些内容可以先用关键词过滤,再做向量排序。
function keywordBoost(content: string, question: string) {
const keywords = question.split(/\s+/).filter(Boolean);
return keywords.some((keyword) => content.includes(keyword)) ? 0.05 : 0;
}
引用来源设计
引用来源至少包含:
- 文档标题
- chunk 序号
- 片段摘要
- 相似度分数
- 原文预览
{
title: "报销制度.md",
chunkIndex: 3,
score: 0.8123,
preview: "报销必须提供真实有效发票..."
}
前端可以展示:
引用来源
1. 报销制度.md · 片段 3
2. 差旅制度.md · 片段 1
让模型只基于引用回答
Prompt 中强调:
如果知识库片段没有明确支持,不要给出确定结论。
每个关键结论都应该能从片段中找到依据。
这不能完全消除幻觉,但能明显改善回答边界。
实战任务
完成:
- RAG_TOP_K 配置
- 相似度阈值过滤
- 检索日志
- 引用来源增强
- 5 个固定测试问题
常见坑
不要只凭一次测试判断 RAG 效果。至少准备 20 个问题覆盖不同类型。
不要把 score 展示得像准确率。可以展示给开发者,普通用户只看来源即可。
不要忽略“检索不到”的体验。拒答也是产品能力。
本章小结
RAG 优化的核心是让模型拿到正确、精简、可引用的上下文。下一章补齐多轮对话和会话记忆。