2024年12月15日

基础检索增强

基础 RAG(Naive RAG)是最简单的检索增强生成管线,由**索引构建**和**查询生成**两个阶段组成,是所有高级 RAG 方案的基线和起点。

知识库大模型检索增强ragbasics

基础检索增强

先说结论

基础 RAG(Naive RAG)是最简单的检索增强生成管线,由索引构建查询生成两个阶段组成,是所有高级 RAG 方案的基线和起点。

QUESTION 面试高频:请描述基础 RAG 的完整流程 分为两个阶段:离线索引——文档经过加载、文本分割(Chunking)、向量化(Embedding)后存入向量数据库;在线查询——用户查询被向量化后,通过相似度检索(如余弦相似度)从向量库中召回 Top-K 文档片段,拼接为上下文送入 LLM 生成回答。

离线索引阶段

文档加载

数据源类型 常用工具 注意事项
PDF PyMuPDF, pdfplumber 表格和图片需特殊处理
网页 BeautifulSoup, Trafilatura 去噪(导航栏、广告等)
数据库 SQL Connector 需设计查询模板
Office 文档 python-docx, openpyxl 保留格式层级
代码 AST Parser 按函数/类分割

文本分割(Chunking)

QUESTION 面试高频:文本分块有哪些策略?各自的优缺点?

策略 原理 优势 劣势 适用场景
固定大小分割 按字符/Token 数切分 简单可控 可能截断语义 通用基线
递归字符分割 按分隔符层级递归切分 平衡性好 仍可能不尊重语义 最常用的默认选择
语义分割 基于嵌入相似度变化切分 语义完整性好 计算成本高 高精度需求
文档结构分割 按 Markdown/HTML/代码结构切分 尊重文档原生结构 需要格式感知 结构化文档
AST 感知分割 按代码语法树切分 函数/类完整 仅适用于代码 代码库 RAG
LLM 驱动分割 用 LLM 决定切分边界 质量最高 成本极高 高价值场景
版面分析分割 用视觉模型分析文档版面 处理复杂排版 依赖版面模型 PDF/扫描件

版面分析与分块

QUESTION 面试高频:什么是版面分析?为什么对 RAG 分块很重要?

版面分析(Layout Analysis)是指用视觉模型(如 LayoutLM、DocTR)识别文档的视觉结构(标题、段落、表格、图片、页眉页脚等),然后按语义区域进行分块。

传统分块的问题

  • 跨页段落被截断
  • 表格被拆散,行列关系丢失
  • 图表与说明文字分离
  • 页眉页脚混入正文

版面分析分块的流程

文档页面 → 版面检测模型 → 识别区域类型(标题/段落/表格/图片)
                                        ↓
                              按语义区域聚合 → 生成 Chunk
                                        ↓
                              保留区域元数据(位置、类型、层级)

Chunk 大小选择

检索精确度1Chunk 大小,上下文完整度Chunk 大小\text{检索精确度} \propto \frac{1}{\text{Chunk 大小}}, \quad \text{上下文完整度} \propto \text{Chunk 大小}

经验法则:

  • 起始值:512 Token + 100 Token 重叠
  • 精确检索场景(如 FAQ):128-256 Token
  • 综合性问答场景:512-1024 Token
  • 需配合重排序使用以过滤噪声

嵌入模型选择

模型 维度 特点 适用场景
OpenAI text-embedding-3-large 3072 效果好,API 调用 通用场景
BGE-large-zh 1024 中文效果好,开源 中文场景
Cohere embed-v3 1024 多语言,支持不同任务类型 多语言场景
GTE-Qwen2 1536 中文优秀,开源 中文企业场景
Jina-embeddings-v3 2048 长文本支持好 长文档场景

在线查询阶段

查询处理

用户原始查询 → 查询预处理 → 查询嵌入 → 向量检索 → 结果后处理

查询预处理技巧

  • 查询改写(Query Rewriting):用 LLM 将模糊查询改写为更具体的查询
  • 查询扩展(Query Expansion):生成多个相关查询并行检索
  • HyDE:先让 LLM 生成假设性回答,用回答的嵌入去检索

向量检索

方法 距离度量 特点
余弦相似度 cos(q,d)=qdqd\cos(\mathbf{q}, \mathbf{d}) = \frac{\mathbf{q} \cdot \mathbf{d}}{\|\mathbf{q}\| \|\mathbf{d}\|} 最常用,归一化后等价于内积
欧氏距离(L2) qd2\|\mathbf{q} - \mathbf{d}\|_2 对向量尺度敏感
内积(IP) qd\mathbf{q} \cdot \mathbf{d} 归一化向量上等价于余弦

上下文拼接

# 典型的 Prompt 模板
prompt = f"""基于以下检索到的上下文信息回答用户问题。
如果上下文中没有相关信息,请说明无法回答。

上下文:
{context}

用户问题:{query}

回答:"""

容易踩的坑

  • 检索不相关:查询与文档在语义空间中的距离远,检索结果南辕北辙
  • Chunk 上下文丢失:切分后 Chunk 失去了原文的上下文语境
  • 信息过载:塞入过多检索结果,模型无法有效利用反而降低质量
  • 重复/冗余检索:多个 Chunk 包含相似内容,浪费上下文窗口
  • 时效性失效:向量数据库未及时更新,返回过时信息
  • 多跳推理困难:回答需要综合多个不相关的文档片段时容易失败
  • 表格和图片处理差:纯文本分割无法有效处理非纯文本内容

工程落地时我会怎么做

  1. 从简单开始:先用 Recursive Character Splitting + Dense Retrieval 搭建基线
  2. Chunk 附加元数据:为每个 Chunk 附加来源、标题、层级信息
  3. 定期更新索引:建立文档变更检测和增量索引更新机制
  4. 退化优雅:当检索结果质量不足时,应有明确的降级策略
  5. 评估驱动迭代:用 RAGAS 或 TruLens 量化评估,不要凭感觉调优

如果要对外讲,可以怎么概括

"基础 RAG 的核心流程是'索引-检索-生成'三步。索引阶段最关键的是文本分块策略,我的经验是先从 Recursive Character Splitting + 512 Token + 100 Token 重叠开始作为基线,然后根据评估结果针对性优化。对于结构化文档(如 PDF),版面分析可以显著提升分块质量,避免跨页截断和表格拆散的问题。检索阶段,余弦相似度是最常用的距离度量。在工程实践中,我会先搭基线、量化评估、再逐步引入 Hybrid Search、Reranking 等高级优化。"

最后记几条

  1. 512 Token + 100 Token 重叠是通用的 Chunk 起始参数
  2. 版面分析是处理 PDF/复杂排版文档的关键预处理步骤
  3. Chunk 元数据(来源、标题、层级)对检索和生成都至关重要
  4. 基础 RAG 是基线——任何高级优化都必须证明相对基线的提升
  5. 检索-生成要联合评估:检索好不代表生成好,反之亦然

参考资料

延伸阅读