实战30 分钟
RAG 深水区:从能用到好用
chunking 策略、混合检索、rerank、评测体系——JD 里最重的 RAG 落地经验,面试深水区。
能跑通 RAG 只需 30 分钟,让 RAG 达到生产水平需要处理五个深水问题。
五个深水问题
① 分段策略
没有万能的 chunkSize。按内容类型选:
| 内容类型 | 推荐分段 | 原因 |
|---|---|---|
| FAQ / 商品说明 | 按条目分(一个 FAQ = 一段) | 天然独立,一段一个答案 |
| 技术文档 | 按 H2/H3 标题分 | 保持语义完整性 |
| 长文 / 论文 | 500-1000 字 + 15% overlap | 平衡召回率和精度 |
| 对话记录 | 按轮次分 | 一轮对话一个上下文 |
| 代码 | 按函数/类分 | 保持逻辑完整 |
import { MarkdownTextSplitter } from "@langchain/textsplitters";
// Markdown 文档按标题分段
const mdSplitter = new MarkdownTextSplitter({
chunkSize: 800,
chunkOverlap: 100,
});
② 混合检索
纯向量检索的盲区:关键词匹配。用户搜「ERR_CONN_RESET」这种错误码,向量检索可能找不到(因为 embedding 把它当成普通文字),但 BM25 关键词检索能精准命中。
// 混合:向量 + BM25 各取 Top-K,合并去重
const vectorResults = await vectorStore.similaritySearch(query, 5);
const keywordResults = await bm25Retriever.getRelevantDocuments(query, 5);
const merged = dedup([...vectorResults, ...keywordResults]).slice(0, 8);
③ 重排序
向量检索的排序依据是「余弦相似度」,这不等于「语义相关性」。Reranker 模型(如 Cohere Rerank、bge-reranker)能更准确地判断「这段文字是否真的回答了这个问题」。
检索(粗筛): 从 10000 段中取 Top-20 → 快但粗糙
重排(精排): 从 Top-20 中精选 Top-3 → 慢但精准
④ 评测:不测不知道好不好
三个核心指标:
| 指标 | 测什么 | 怎么算 |
|---|---|---|
| 召回率(Recall@K) | 正确答案是否被检索到 | 命中数 / 应命中总数 |
| 准确率(Precision@K) | 检索结果中有多少是相关的 | 相关数 / 返回总数 |
| 忠实度(Faithfulness) | 回答是否基于检索结果 | 人工或 LLM 判断 |
搭一个简单评测集:准备 20-50 个「问题 + 正确答案所在文档段」的配对,每次改动后跑一遍,看召回率变化。
⑤ 幻觉防护
检索不到时,模型不会说「不知道」,它会编一个格式完美的答案。
// 在 Prompt 里明确说
const prompt = `基于以下参考资料回答问题。
如果参考资料中没有足够信息,直接说「根据现有资料无法回答」。
参考资料:
{context}
问题:{question}`;
这是第一道防线。更严格的做法是在代码层检查:如果检索结果的相似度都低于阈值,直接返回固定话术,不调 LLM。
本章要点
- 分段没有万能值——按内容类型选策略
- 混合检索 = 向量(语义)+ BM25(关键词),互补盲区
- Reranker 是「粗筛后精排」,显著提升最终质量
- 评测不是可选项——没有指标的优化是盲目的
- 幻觉防护:Prompt 约束 + 代码层阈值兜底
→ 下一章:部署、可观测与面试