跳到主要内容

RAG 分块、召回、重排与引用

📚 RAG(检索增强生成)让 LLM 基于外部知识回答,核心挑战是:如何把相关内容检索出来并准确引用。

RAG 完整链路

文档 → 分块 → Embedding → 向量库

用户问题 → Embedding → 向量检索 → 重排 → 注入 PromptLLM → 带引用的回答

分块策略

固定大小分块

按 token 数切分(如每块 512 tokens,重叠 64 tokens):

  • 优点:简单,均匀
  • 缺点:可能切断语义单元

语义分块

按段落、标题、句子边界切分:

  • 优点:语义完整
  • 缺点:块大小不均

递归字符分块(LangChain 默认)

\n\n → \n → 句号 → 空格 优先级递归切分,保留语义结构。

分块设计要点

参数建议说明
chunk_size256-512 tokens太大检索精度低,太小语义不完整
chunk_overlap10-15%避免答案跨块丢失
metadata必须保留来源、页码、标题用于引用

召回策略

向量检索(稠密检索)

用 Embedding 相似度召回:擅长语义理解,弱于关键词精确匹配。

BM25(稀疏检索)

基于词频的关键词匹配:擅长专有名词、代码、版本号等精确匹配。

结合两者,用 RRF(Reciprocal Rank Fusion)融合排名:

# RRF 融合
rrf_score = sum(1 / (k + rank_i) for rank_i in ranks)
# k=60 是经验值

重排(Reranking)

向量检索召回 Top-K(如 20 个),用 Cross-Encoder 对每对 (query, doc) 精确打分,取 Top-N(如 5 个):

模型特点
Cohere RerankAPI,效果好,有延迟
BGE-Reranker开源,中文友好
Cross-Encoder通用框架,需自部署

权衡:重排提升精度,但增加 50-200ms 延迟。


引用与溯源

Chunk 元数据设计

{
"content": "...",
"metadata": {
"source": "document.pdf",
"page": 3,
"section": "第二章",
"chunk_id": "doc-p3-001"
}
}

引用生成策略

  1. 直接引用:在 Prompt 中告知模型引用 chunk_id
  2. 后处理匹配:模型生成答案后,将句子与 chunk 做相似度匹配
  3. Structured Output:模型返回 JSON,包含 answer + cited_chunk_ids

效果评估指标

指标测量内容
Recall@KTop-K 结果中包含正确答案的比例
MRR第一个正确结果的排名倒数均值
Faithfulness答案是否仅基于检索内容
Answer Relevance答案与问题的相关性
Context Precision召回内容中真正有用的比例

常见问题排查

问题可能原因解决
召回率低分块太细或 Embedding 模型弱增大 chunk,换更好的 Embedding
答案不准召回了噪音内容加重排,提升 Context Precision
引用错误元数据不完整分块时保留完整 metadata
延迟高重排或 Embedding 慢缓存热门 query,批量 Embedding