跳到主要内容

RAG 基础与文档分块

RAG 要解决什么问题?​

  • 全称: 检索增强生成(Retrieval-Augmented Generation, RAG);
  • 核心思想: 把大型语言模型的思考与生成能力,和外部知识库的广度与时效性结合起来;
  • 动因: 模型本身的训练数据有截止日期,而知识库可以随时更新;
  • 定位: 构建共享知识库的核心技术,也用于增强用户记忆的检索能力;

RAG 系统由哪两部分构成、核心流程是什么?​

  • 检索器: 负责从知识库里找出相关片段;
  • 生成器: 通常是 LLM,拿到这些片段作为上下文来生成答案;
  • 核心流程: 检索相关片段 → 注入上下文 → LLM 基于上下文生成答案;
  • 例子: 查询“退款流程”取回 top_k=2 的“退款政策”“退款操作步骤”两段,再由客服助手 System Prompt 约束下的 LLM 生成带步骤的回答;
query = "退款流程"
results = retriever.search(query, top_k=2)
answer = llm.generate(system="你是客服助手。", context=results, question=query)

为什么必须先做文档分块?​

  • 原因一: 嵌入模型对输入长度有限制,且一整篇文档只压缩成一个向量时多个主题混在一起,向量无法精确表达任何一个;
  • 同源问题: 这与 Enhanced Notes 遇到的困境一致——段落越长,嵌入越难抓住重点,见 用户记忆的四种存储格式;
  • 原因二: 检索的目标是只把相关的那部分注入上下文,片段太大会连带引入大量无关内容,浪费窗口、稀释注意力;

三种分块策略各自的取舍是什么?​

策略做法优势代价
固定大小切分按固定 token 数(如 512)切分,相邻块保留重叠(如 50-100 token)实现简单、结果可预测无视文档结构,段落、代码、表格可能被拦腰截断
递归/结构感知切分按章节标题、段落、句子等自然边界递归切分,仍超长时降级到更小边界尊重文档层次,Markdown、HTML 尤其适合依赖文档有显式结构;是生产系统最常用的默认选择
语义切分计算相邻句子的嵌入相似度,在语义“断崖”处下刀每块内部主题尽量单一,切分质量更高需要额外的嵌入计算

块大小与重叠如何取舍?​

  • 块太小: 单块信息不完整,脱离上下文后语义模糊——“该公司收入增长了 3%”,哪家公司?哪个季度?;
  • 块太大: 一个块混杂多个主题,嵌入向量被稀释、检索精度下降,命中后还会带入更多无关内容;
  • 常见起点: 每块 256-1024 token、相邻块重叠 10%-20%,再根据检索质量实测调优;

分块的固有缺陷是什么?​

  • 缺陷: 无论采用哪种策略,分块都会切断片段与其原始上下文的联系——“该公司”指代谁、这段话出自哪份报告,信息留在了块外;
  • 后果: 上下文在嵌入阶段就造成语义损失,直接拉低检索准确率;
  • 对策: 由 上下文感知检索 在索引阶段补回上下文;