RAG 系统踩坑全景从文档切分到检索排序基础设施不需要漂亮话。RAGRetrieval-Augmented Generation看起来简单把文档切分、向量化、检索、喂给大模型。上线三个月后你会发现每个环节都有坑。我们团队做了两个 RAG 项目第一个上线后检索准确率只有 42%第二个花了两个月重构才做到 78%。这篇文章把从文档切分到检索排序的踩坑经验全部列出来每个坑都附带了原因分析和修复方案。一、背景RAG 系统为什么容易踩坑RAG 的核心链路是文档摄入 → 切分 → Embedding → 索引构建 → 检索 → 排序 → Prompt 组装 → LLM 生成。这条链路看起来线性清晰但每个节点都有隐藏的失败模式。切分策略决定了检索粒度Embedding 模型决定了语义空间质量检索和排序决定了最终回答的素材质量。一个环节出问题后面的环节再怎么优化也补不回来。二、文档切分四个最常见的坑坑1固定长度切分丢失语义边界最直觉的做法是按 512 token 或 1000 字符切分。问题在于一个完整的段落可能被切断后半段缺少上下文变成无法理解的信息碎片。我们实测发现固定长度切分的检索命中率比语义边界切分低 23%。修复方案优先按段落和章节切分然后对超长段落做二次切分保留 overlap 区域通常 10%~20%。overlap 不是万能的——它增加存储成本和检索噪声需要根据文档类型调整比例。# 按语义边界切分超长段落二次切分带overlap def semantic_chunk(doc, max_tokens512, overlap_ratio0.15): paragraphs doc.split(\n\n) chunks [] for para in paragraphs: if token_count(para) max_tokens: chunks.append(para) else: # 二次切分按句子边界带overlap sentences para.split(。) sub_chunks sliding_window(sentences, max_tokens, overlap_ratio) chunks.extend(sub_chunks) return chunks坑2表格和代码被切碎表格的每一行单独切分后失去结构信息代码块被切断后变量引用丢失。这两个场景在技术文档中极其常见。修复方案对表格和代码块做特殊标记切分时将其作为不可分割单元整体保留。如果表格过长超过限制按行组切分但保留表头作为每个子块的元信息。坑3切分粒度一刀切不同类型的文档需要不同粒度FAQ 适合按问答对切分技术手册适合按章节切分日志类文档适合按事件切分。用同一套切分策略处理所有文档类型效果必然打折。修复方案按文档类型配置不同的切分策略切分策略的参数长度、overlap、边界规则要做 A/B 测试对比检索命中率。坑4元信息没有随切分保留文档的来源、版本、时间戳、章节层级这些元信息在切分后经常丢失。检索时拿到了内容却不知道它来自哪个版本的文档甚至不知道它的上下文是什么。修复方案每个 chunk 必须携带元信息字典至少包含 source、version、section_title、chunk_index。这些信息在排序和 Prompt 组装时都要用到。三、Embedding 和索引三个关键坑坁5中文 Embedding 模型选错很多人直接用多语言 Embedding 模型如 multilingual-e5-large处理中文文档认为多语言就够用。实测发现在中文场景下专用中文模型如 bge-large-zh的检索准确率比多语言模型高 15%~20%。修复方案中文为主的应用优先选中文专用模型混合语言场景用多语言模型但检索时需要加语言过滤逻辑。模型选型要在真实数据集上评测不要只看排行榜。坁6混合语言文档向量漂移一篇文档同时包含中文和英文比如技术文档Embedding 向量会在两种语言的语义空间之间漂移。检索时用中文 query可能召回英文 chunk用英文 query可能召回中文 chunk。修复方案对混合语言文档做语言检测不同语言段落用对应模型生成向量检索时匹配语言标签。或者统一用一个多语言模型但在检索结果中加语言一致性权重。坁7增量索引没有重建新文档加入后直接追加向量不重建索引。这会导致索引结构退化——HNSW 图的连通性变差检索路径变长延迟上升。我们观察到索引追加 30% 数据后检索延迟增加 40%。修复方案设定重建阈值——当新增向量超过总量的 15%~20% 时触发全量重建。重建期间用双索引策略旧索引继续服务新索引构建完成后一次性切换。四、检索和排序四个最致命的坑坁8纯向量检索忽略关键词匹配向量检索擅长语义相似但处理精确匹配产品型号、错误码、版本号的能力很差。用户问 K8s 1.28 的 CVE-2023-xxxx 怎么处理纯向量检索可能召回一堆 K8s 安全相关的通用文档而不是精确命中那个 CVE。修复方案采用混合检索——向量检索负责语义匹配关键词检索BM25负责精确匹配两路结果融合排序。融合权重需要根据 query 类型动态调整精确查询关键词权重高语义查询向量权重高。坁9Top-K 固定不动态调整不管 query 是简单还是复杂一律取 Top-5 或 Top-10。简单问题公司电话是多少Top-3 就够了多取的只会引入噪声复杂问题部署流程和回滚方案是什么可能需要 Top-20 才能覆盖完整信息。修复方案根据 query 复杂度动态调整 Top-K。简单判断标准query 长度和包含的实体数量。或者用两阶段检索先取 Top-50再用重排序模型筛选 Top-K。坁10没有重排序环节向量检索的相似度分数和 BM25 的分数不在同一个尺度直接融合效果不稳定。更关键的是向量检索的排名顺序和最终回答需要的质量排序经常不一致——语义最相似的文档不一定是最有用的文档。修复方案加重排序模型如 bge-reranker-v2-m3 或 Cohere Rerank。重排序模型用交叉编码器对 query-document 对做精细评分比双塔模型的向量点积准确率高 10%~15%。代价是延迟增加每对 query-document 需要单独推理需要控制候选数量。坁11相似度阈值一刀切设一个固定阈值如 cosine similarity 0.7过滤检索结果。问题是不同领域、不同 query 类型的合理阈值差别很大技术文档的阈值可能偏高术语精确匹配政策文档的阈值可能偏低表述模糊但语义相关。修复方案不要设全局阈值。改用百分位阈值——取当前 query 的检索结果中相似度分布的 Top 百分位或者用重排序分数的自然断点做过滤。五、避坑全景图和总结坑编号坑描述影响程度修复优先级8纯向量检索忽略关键词高P010没有重排序环节高P01固定长度切分丢失语义高P05中文Embedding选错中P19Top-K固定不调整中P111阈值一刀切中P13切分粒度一刀切中P27增量索引不重建中P22表格代码被切碎低P24元信息未保留低P26混合语言向量漂移低P3RAG 系统踩坑的核心规律链路越长每个环节的小问题会在下游被放大。切分阶段丢掉的语义信息检索阶段不可能补回来检索阶段召回的噪声排序阶段只能部分过滤。优化顺序应该是先修切分数据质量是根基再修检索策略召回率是前提最后修排序精准度是锦上添花。不要在切分还是固定长度的时候就急着调 Embedding 模型——那是在错误的地基上建高楼。
RAG 系统踩坑全景:从文档切分到检索排序
RAG 系统踩坑全景从文档切分到检索排序基础设施不需要漂亮话。RAGRetrieval-Augmented Generation看起来简单把文档切分、向量化、检索、喂给大模型。上线三个月后你会发现每个环节都有坑。我们团队做了两个 RAG 项目第一个上线后检索准确率只有 42%第二个花了两个月重构才做到 78%。这篇文章把从文档切分到检索排序的踩坑经验全部列出来每个坑都附带了原因分析和修复方案。一、背景RAG 系统为什么容易踩坑RAG 的核心链路是文档摄入 → 切分 → Embedding → 索引构建 → 检索 → 排序 → Prompt 组装 → LLM 生成。这条链路看起来线性清晰但每个节点都有隐藏的失败模式。切分策略决定了检索粒度Embedding 模型决定了语义空间质量检索和排序决定了最终回答的素材质量。一个环节出问题后面的环节再怎么优化也补不回来。二、文档切分四个最常见的坑坑1固定长度切分丢失语义边界最直觉的做法是按 512 token 或 1000 字符切分。问题在于一个完整的段落可能被切断后半段缺少上下文变成无法理解的信息碎片。我们实测发现固定长度切分的检索命中率比语义边界切分低 23%。修复方案优先按段落和章节切分然后对超长段落做二次切分保留 overlap 区域通常 10%~20%。overlap 不是万能的——它增加存储成本和检索噪声需要根据文档类型调整比例。# 按语义边界切分超长段落二次切分带overlap def semantic_chunk(doc, max_tokens512, overlap_ratio0.15): paragraphs doc.split(\n\n) chunks [] for para in paragraphs: if token_count(para) max_tokens: chunks.append(para) else: # 二次切分按句子边界带overlap sentences para.split(。) sub_chunks sliding_window(sentences, max_tokens, overlap_ratio) chunks.extend(sub_chunks) return chunks坑2表格和代码被切碎表格的每一行单独切分后失去结构信息代码块被切断后变量引用丢失。这两个场景在技术文档中极其常见。修复方案对表格和代码块做特殊标记切分时将其作为不可分割单元整体保留。如果表格过长超过限制按行组切分但保留表头作为每个子块的元信息。坑3切分粒度一刀切不同类型的文档需要不同粒度FAQ 适合按问答对切分技术手册适合按章节切分日志类文档适合按事件切分。用同一套切分策略处理所有文档类型效果必然打折。修复方案按文档类型配置不同的切分策略切分策略的参数长度、overlap、边界规则要做 A/B 测试对比检索命中率。坑4元信息没有随切分保留文档的来源、版本、时间戳、章节层级这些元信息在切分后经常丢失。检索时拿到了内容却不知道它来自哪个版本的文档甚至不知道它的上下文是什么。修复方案每个 chunk 必须携带元信息字典至少包含 source、version、section_title、chunk_index。这些信息在排序和 Prompt 组装时都要用到。三、Embedding 和索引三个关键坑坁5中文 Embedding 模型选错很多人直接用多语言 Embedding 模型如 multilingual-e5-large处理中文文档认为多语言就够用。实测发现在中文场景下专用中文模型如 bge-large-zh的检索准确率比多语言模型高 15%~20%。修复方案中文为主的应用优先选中文专用模型混合语言场景用多语言模型但检索时需要加语言过滤逻辑。模型选型要在真实数据集上评测不要只看排行榜。坁6混合语言文档向量漂移一篇文档同时包含中文和英文比如技术文档Embedding 向量会在两种语言的语义空间之间漂移。检索时用中文 query可能召回英文 chunk用英文 query可能召回中文 chunk。修复方案对混合语言文档做语言检测不同语言段落用对应模型生成向量检索时匹配语言标签。或者统一用一个多语言模型但在检索结果中加语言一致性权重。坁7增量索引没有重建新文档加入后直接追加向量不重建索引。这会导致索引结构退化——HNSW 图的连通性变差检索路径变长延迟上升。我们观察到索引追加 30% 数据后检索延迟增加 40%。修复方案设定重建阈值——当新增向量超过总量的 15%~20% 时触发全量重建。重建期间用双索引策略旧索引继续服务新索引构建完成后一次性切换。四、检索和排序四个最致命的坑坁8纯向量检索忽略关键词匹配向量检索擅长语义相似但处理精确匹配产品型号、错误码、版本号的能力很差。用户问 K8s 1.28 的 CVE-2023-xxxx 怎么处理纯向量检索可能召回一堆 K8s 安全相关的通用文档而不是精确命中那个 CVE。修复方案采用混合检索——向量检索负责语义匹配关键词检索BM25负责精确匹配两路结果融合排序。融合权重需要根据 query 类型动态调整精确查询关键词权重高语义查询向量权重高。坁9Top-K 固定不动态调整不管 query 是简单还是复杂一律取 Top-5 或 Top-10。简单问题公司电话是多少Top-3 就够了多取的只会引入噪声复杂问题部署流程和回滚方案是什么可能需要 Top-20 才能覆盖完整信息。修复方案根据 query 复杂度动态调整 Top-K。简单判断标准query 长度和包含的实体数量。或者用两阶段检索先取 Top-50再用重排序模型筛选 Top-K。坁10没有重排序环节向量检索的相似度分数和 BM25 的分数不在同一个尺度直接融合效果不稳定。更关键的是向量检索的排名顺序和最终回答需要的质量排序经常不一致——语义最相似的文档不一定是最有用的文档。修复方案加重排序模型如 bge-reranker-v2-m3 或 Cohere Rerank。重排序模型用交叉编码器对 query-document 对做精细评分比双塔模型的向量点积准确率高 10%~15%。代价是延迟增加每对 query-document 需要单独推理需要控制候选数量。坁11相似度阈值一刀切设一个固定阈值如 cosine similarity 0.7过滤检索结果。问题是不同领域、不同 query 类型的合理阈值差别很大技术文档的阈值可能偏高术语精确匹配政策文档的阈值可能偏低表述模糊但语义相关。修复方案不要设全局阈值。改用百分位阈值——取当前 query 的检索结果中相似度分布的 Top 百分位或者用重排序分数的自然断点做过滤。五、避坑全景图和总结坑编号坑描述影响程度修复优先级8纯向量检索忽略关键词高P010没有重排序环节高P01固定长度切分丢失语义高P05中文Embedding选错中P19Top-K固定不调整中P111阈值一刀切中P13切分粒度一刀切中P27增量索引不重建中P22表格代码被切碎低P24元信息未保留低P26混合语言向量漂移低P3RAG 系统踩坑的核心规律链路越长每个环节的小问题会在下游被放大。切分阶段丢掉的语义信息检索阶段不可能补回来检索阶段召回的噪声排序阶段只能部分过滤。优化顺序应该是先修切分数据质量是根基再修检索策略召回率是前提最后修排序精准度是锦上添花。不要在切分还是固定长度的时候就急着调 Embedding 模型——那是在错误的地基上建高楼。