RAG 检索增强
RAG 质量取决于分块粒度、检索策略与引用绑定三个环节。本页给出三种分块策略对比、BM25+向量混合检索的实现代码、引用格式规范,以及「检索到了但没用到」的常见失败模式分析。
RAG 管线「分块 → 嵌入 → 检索 → 重排 → 拼装 → 生成」每一步都有独立的失败模式。调试时先验证「召回是否包含正确答案块」,再查「重排是否把它顶进 top-k」,最后才调生成提示词。
RAG 流水线(示意)
下列 ASCII 描述概念顺序;实现上可把「查询改写」「权限过滤」插在检索前后不同位置,但元数据与引用 id 应自洽贯通。
[ 原始文档 / API / 爬虫 ]
│
▼
[ 清洗:去重 / 版本 / 许可标记 ]
│
▼
[ 分块 + 元数据:标题路径 / URI / 段落锚点 ]
│
▼
[ 嵌入写入向量索引 ] ◄──── [ 稀疏索引:BM25 等 ]
│
▼
┌─────────────────────────────────────┐
│ 查询侧:改写(可选)→ 混合检索 top-N │
│ → 交叉编码器重排 top-k │
│ → 上下文预算内拼装 + 引用表 │
└─────────────────────────────────────┘
│
▼
[ LLM:仅依据片段作答 / 拒答 / 输出引用 ]
- 表格、代码块、列表建议单独分块策略,避免与叙述混切导致语义断裂。
- 嵌入模型语种与业务语料一致;跨语种场景显式标注或分索引。
分块策略对比 — 何时用哪种
三种主流分块策略各有适用场景,参数选择直接影响检索命中率:
┌──────────────┬────────────────┬──────────────────────────┬────────────────────────────┐
│ 策略 │ chunk_size │ 适合场景 │ 主要风险 │
├──────────────┼────────────────┼──────────────────────────┼────────────────────────────┤
│ 固定大小 │ 512–1024 token │ 纯文本、日志、无结构文档 │ 截断句子/段落,语义断裂 │
│ │ overlap: 10% │ │ │
├──────────────┼────────────────┼──────────────────────────┼────────────────────────────┤
│ 语义分块 │ 自适应 │ 文章/论文/有段落结构的文档 │ 块大小不均,大块占用 token 多 │
│ (NLTK/spaCy) │ avg 300–600 tok│ │ │
├──────────────┼────────────────┼──────────────────────────┼────────────────────────────┤
│ 递归分块 │ 先按 \n\n, │ Markdown/HTML/代码库 │ 需维护分隔符优先级列表 │
│ (LangChain │ 再 \n,再空格 │ 有标题结构的文档 │ │
│ RecursiveTC)│ max 1024 token │ │ │
└──────────────┴────────────────┴──────────────────────────┴────────────────────────────┘
# 推荐参数(Python / LangChain):
from langchain.text_splitter import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
chunk_size=800, # 字符数,中文文档约 500–800,英文约 800–1200
chunk_overlap=80, # overlap = chunk_size × 10%,降低边界截断
separators=["\n\n", "\n", "。", ".", " ", ""], # 优先级从高到低
length_function=len, # 改为 tiktoken 计数可得到精确 token 数
)
# metadata 必须写入:
{
"source": "docs/install-guide.md", # 文档路径
"section": "§3.2 环境变量配置", # 标题路径(H1 > H2 > H3)
"chunk_index": 7, # 块在文档中的顺序
"updated_at": "2024-03-01", # 文档更新时间,用于过期过滤
"doc_version": "v2.4.1" # 文档版本号
}
- overlap 计算:chunk_size=800 时,overlap=80(10%)是经验下限;中文叙述文档可提高到 15%(120 字),因为中文每句信息密度更高。
- 表格/代码块:整体作为一个块,不做内部切分;超过 max 时截断前加注释
# (truncated, full at {uri})。
检索与重排
纯向量检索易漏精确词与专有名词;关键词稀疏检索易噪声大。常见做法:两路各取候选,融合分数后再用小型交叉编码器对 top-N 重排,仅把 top-k 送入生成。
- 查询改写:多查询扩展或 HyDE 视场景启用,并在 SKILL 中写明副作用(延迟、成本、漂移)。
- 融合:RRF、加权线性或学习排序;记录各路的命中贡献便于调参。
- 重排:交叉编码器 batch 与截断长度固定,避免线上与离线评测不一致。
- 空结果:定义降级路径(扩召回、换索引、提示用户收窄问题),并监控「检索为空率」。
引用与生成约束
提示中要求模型仅依据检索片段作答;每条论断绑定引用 id(与向量库 metadata 一致)。无足够依据时输出结构化拒答,而非编造。
- 引用格式:例如
[doc_id § 小节]或[^chunk_uuid],与 UI 可点击锚点一致。 - 冲突片段:若检索结果互相矛盾,要求模型列出矛盾点并降低结论确定性。
- SKILL 清单项:索引更新频率、权限过滤、PII 脱敏规则、许可证是否允许摘要外传。
分块字符估算器
下方为纯前端示意:用常见经验比值把「目标 token/块」换算成大致字符上限,并用固定字符窗口对样本文本做 naive 分块计数(不调用真实 tokenizer,仅供配置初值)。
块数:—(请先输入文本)
Token→字符按英文约 1∶3.5–4、中日文约 1∶1.2–1.8 的区间展示;真实以所用 tokenizer 为准。
评测与运维
离线:命中率、MRR、nDCG、人工相关性抽检;线上:检索为空率、拒答率、引用点击率、用户纠错回流。防止索引静默退化(嵌入模型更换未全量重嵌入等)。
- 查询改写:记录改写前后召回差异,避免「改写放大漂移」。
- 版本:索引 schema、嵌入模型版本、重排模型版本写入发布说明与回滚预案。
---
name: rag-retrieval-pipeline
description: 设计或审查 RAG 检索与引用流程
---
# 步骤
1. 分块与元数据、索引更新
2. 检索:向量/关键词/重排
3. 生成:引用格式、拒答与评测