基础检索增强
先说结论
基础 RAG(Naive RAG)是最简单的检索增强生成管线,由索引构建和查询生成两个阶段组成,是所有高级 RAG 方案的基线和起点。
QUESTION 面试高频:请描述基础 RAG 的完整流程 分为两个阶段:离线索引——文档经过加载、文本分割(Chunking)、向量化(Embedding)后存入向量数据库;在线查询——用户查询被向量化后,通过相似度检索(如余弦相似度)从向量库中召回 Top-K 文档片段,拼接为上下文送入 LLM 生成回答。
离线索引阶段
文档加载
| 数据源类型 | 常用工具 | 注意事项 |
|---|---|---|
| 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 大小选择
经验法则:
- 起始值: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 生成假设性回答,用回答的嵌入去检索
向量检索
| 方法 | 距离度量 | 特点 |
|---|---|---|
| 余弦相似度 | 最常用,归一化后等价于内积 | |
| 欧氏距离(L2) | 对向量尺度敏感 | |
| 内积(IP) | 归一化向量上等价于余弦 |
上下文拼接
# 典型的 Prompt 模板
prompt = f"""基于以下检索到的上下文信息回答用户问题。
如果上下文中没有相关信息,请说明无法回答。
上下文:
{context}
用户问题:{query}
回答:"""
容易踩的坑
- 检索不相关:查询与文档在语义空间中的距离远,检索结果南辕北辙
- Chunk 上下文丢失:切分后 Chunk 失去了原文的上下文语境
- 信息过载:塞入过多检索结果,模型无法有效利用反而降低质量
- 重复/冗余检索:多个 Chunk 包含相似内容,浪费上下文窗口
- 时效性失效:向量数据库未及时更新,返回过时信息
- 多跳推理困难:回答需要综合多个不相关的文档片段时容易失败
- 表格和图片处理差:纯文本分割无法有效处理非纯文本内容
工程落地时我会怎么做
- 从简单开始:先用 Recursive Character Splitting + Dense Retrieval 搭建基线
- Chunk 附加元数据:为每个 Chunk 附加来源、标题、层级信息
- 定期更新索引:建立文档变更检测和增量索引更新机制
- 退化优雅:当检索结果质量不足时,应有明确的降级策略
- 评估驱动迭代:用 RAGAS 或 TruLens 量化评估,不要凭感觉调优
如果要对外讲,可以怎么概括
"基础 RAG 的核心流程是'索引-检索-生成'三步。索引阶段最关键的是文本分块策略,我的经验是先从 Recursive Character Splitting + 512 Token + 100 Token 重叠开始作为基线,然后根据评估结果针对性优化。对于结构化文档(如 PDF),版面分析可以显著提升分块质量,避免跨页截断和表格拆散的问题。检索阶段,余弦相似度是最常用的距离度量。在工程实践中,我会先搭基线、量化评估、再逐步引入 Hybrid Search、Reranking 等高级优化。"
最后记几条
- 512 Token + 100 Token 重叠是通用的 Chunk 起始参数
- 版面分析是处理 PDF/复杂排版文档的关键预处理步骤
- Chunk 元数据(来源、标题、层级)对检索和生成都至关重要
- 基础 RAG 是基线——任何高级优化都必须证明相对基线的提升
- 检索-生成要联合评估:检索好不代表生成好,反之亦然
参考资料
- Lewis, P. et al. "Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks" (NeurIPS 2020)
- LangChain Text Splitters 文档: https://python.langchain.com/docs/modules/data_connection/document_transformers/
- LayoutLM: "Pre-training of Text and Layout for Document Understanding" (Microsoft)