这是”AI Agent落地业务系统智能化改造”系列的第七篇。第六篇讲了RAG全景——是什么、怎么演进、每个环节的作用。这篇讲我实际搭RAG系统时的设计决策为什么这样选、哪些work、哪些还没验证。不是”正确答案”而是”决策过程”。目录引言架构不是画出来的是踩出来的一、整体架构从需求倒推二、五个关键设计决策分块策略 / 检索通道 / 融合策略 / 上下文组织 / 生成控制三、踩坑清单四、待优化的问题五、上手的建议总结引言架构不是画出来的是踩出来的第六篇讲了RAG的7层管线、四类索引、混合检索、Rerank。那些是”业界共识”教科书上能查到。这篇讲教科书上查不到的东西面对具体业务每一层怎么选、为什么选、选错了怎么办。我搭的RAG系统服务的是乡村产业监测类的应用800政策文档、15900分块、用户是政府管理人员。他们问的问题五花八门——”山东省2024年产业园申报情况”精确词项、”哪些产业发展比较好”语义模糊、”帮我做个对比分析”多步推理。没有一种检索策略能覆盖所有场景。架构设计的本质是在有限资源下为你的业务场景做最优组合。这篇文章讲五件事整体架构怎么从需求倒推、五个关键设计决策怎么做取舍、六个真实踩坑、四个还没解决的问题、给读者的五条建议。每个决策讲三件事选项有哪些、我选了什么、为什么。一、整体架构从需求倒推业务需求分析在画架构之前先搞清楚用户怎么用这个系统用户行为示例对RAG的要求精确查询“2024年山东省产业园名单”关键词匹配必须准语义查询“哪些产业发展势头好”需要语义理解表格查询“各省产业园数量对比”需要结构化数据检索多步分析“对比山东和浙江的产业差异”需要多次检索综合报告生成“帮我写一份分析报告”需要大量上下文防幻觉五种行为对检索的要求完全不同。单一检索通道不可能覆盖。架构选择已验证最终的架构是”5通道检索 3级策略 防幻觉体系”用户提问 │ ▼ 查询分析意图识别 查询改写 │ ├──→ FTS全文检索BM25精确词项 ├──→ 向量检索Embedding语义匹配 ├──→ 表格检索结构化数据查询 ├──→ 事实表检索预构建的事实对 └──→ 文档目录检索按文档结构定位 │ ▼ RRF融合排序 │ ▼ Rerank精排 │ ▼ 上下文组织裁剪 去重 分层 │ ▼ 生成控制引用溯源 语料收缩 answer_guard │ ▼ 输出有把握5通道的设计逻辑是对的——不同类型的查询需要不同的检索方式。待验证当文档量增长到2000时5通道的检索延迟是否还能保持在可接受范围内目前800文档时延迟约200-500ms。二、五个关键设计决策决策1分块策略——固定 vs 语义 vs 结构选项策略做法优势劣势固定长度按500字符切分简单、可控容易在句子中间截断语义切片按语义相似度断开语义完整计算量大阈值敏感按文档结构以标题、章节为边界保留文档逻辑单节过长时需二次切分Parent-Child小块检索大块生成兼顾精度和上下文需要维护两级索引我选了什么按文档结构切分 固定长度二次切分。为什么我的文档主要是政策文件和案例报告特点是章节结构清晰、段落逻辑完整。按标题切分能保留”一个块≈一个主题”的语义完整性。但有些章节太长比如一个案例报告可能有3000字所以超长的章节用固定长度二次切分chunk_size500overlap50。没选语义切片的原因计算成本太高。800文档、15900块逐句向量化再比较相似度离线索引时间会从分钟级变成小时级。对于政策文档这种结构化程度高的文本结构切分的效果已经够用。没选Parent-Child的原因增加了系统复杂度两级索引、检索时需要回查Parent而我的场景中500字的块已经能提供足够的上下文。如果后续发现上下文不够再升级到Parent-Child。踩过的坑最初用固定长度500字符切分不看文档结构。结果一个政策文件的”第三条”被切成了两半前半段在块A后半段在块B。用户问”第三条是什么”检索命中了块A但答案不完整。改成结构切分后解决了。确定性结构切分二次切分的组合在800文档的场景下效果验证过。但不同文档类型比如纯表格、纯文本可能需要不同策略还没做对比实验。决策2检索通道——为什么需要5通道背景大多数RAG教程只讲两种检索——BM25和向量。但我发现两种不够。用户查询的真实分布查询类型占比只用BM25只用向量混合检索精确词项地名、年份、政策名~30%✅ 能命中❌ 容易漏✅语义模糊”发展好的”~25%❌ 命中不了✅ 能命中✅表格数据”各省数量”~20%⚠️ 看分词❌ 向量不懂表格⚠️事实查询”谁负责”~15%⚠️⚠️⚠️结构导航”第三章”~10%❌❌❌后三类查询BM25向量的混合检索覆盖不了。所以加了三个专用通道表格检索专门处理结构化数据查询。表格在入库时就提取成结构化格式检索时支持按列名、数值范围查询。事实表检索预构建”实体-属性-值”三元组。比如”山东省产业园数量→12个”直接查事实表比从文档里检索快得多、准得多。文档目录检索按文档结构树定位。用户问”第三章讲了什么”不需要语义匹配直接按章节索引找。已验证5通道比2通道BM25向量在120个评测查询上的Recall5从72%提升到89%。待验证事实表的维护成本。每新增一批文档需要重新构建事实表。目前是手动半自动还没做到全自动化。决策3融合策略——RRF vs加权选项策略做法优势劣势RRF按排名位置融合score Σ 1/(krank)不需要调权重对不同分数尺度天然兼容丢失绝对分数信息加权融合对各通道分数归一化后加权求和保留分数信息可调权重需要归一化BM25和向量分数的归一化本身引入误差我选了什么RRFk60。为什么RRF不需要调权重。5个通道的分数尺度完全不同——BM25的分数是一个体系向量相似度是另一个体系表格检索可能返回精确匹配的布尔值。归一化这些异构分数本身就是个难题。RRF的工程实现简单几行代码就够。k60是业界通用经验值在我的场景下没有调过效果已经够用。代价RRF只有相对排序没有绝对置信度。也就是说我知道”这个结果排第一”但不知道”这个结果有多好”。如果需要设”置信度低于0.3就不返回”的阈值RRF做不到。待验证k60是否是最优值。理论上应该在评测集上做网格搜索k10,20,30,…,100但还没做。决策4上下文组织——TopK直接塞 vs 压缩 vs 分层问题检索返回了10个块每个500字总共5000字。全部塞给模型还是压缩后再塞选项策略做法优势劣势TopK直接塞取前K个块直接拼接简单token消耗大噪声多上下文压缩用LLM提取每个块中和查询相关的部分减少噪声多一次LLM调用增加延迟分层披露先给摘要需要时再给详情省token实现复杂我选了什么TopK直接塞 简单去重。为什么在当前800文档的规模下简单方案已经够用。上下文压缩需要额外的LLM调用延迟翻倍分层披露需要设计摘要策略工程量大。如果后续文档量增长到万级再考虑升级。效果在800文档的规模下Top52500字已经能覆盖大多数查询的上下文需求。token消耗在可接受范围内。代价有时候5个块里有2个是重复信息同一个政策被不同分块包含浪费了token。简单去重按文本相似度0.9过滤能解决一部分但不彻底。待验证上下文压缩是否能显著提升生成质量。理论上应该做A/B测试——同样的查询一组用TopK直接塞一组用压缩后的上下文比较答案质量。还没做。决策5生成控制——防幻觉的三层机制RAG最大的风险不是检索不到而是检索到了但模型不用反而自己编。三层防幻觉机制第一层Prompt约束你是一个乡村产业数据分析助手。请严格基于以下检索结果回答问题。 如果检索结果中没有相关信息请明确说暂无相关数据。 回答时请标注信息来源。已验证Prompt约束能减少60%以上的幻觉。但不是100%——有些情况下模型还是会”创造性地”解读检索结果。第二层引用溯源每个检索结果带元数据文档名、页码、章节生成答案时要求模型引用来源。用户可以点进去验证。已验证引用溯源本身不减少幻觉但让幻觉变得可检测——如果引用的来源和答案对不上用户能发现。第三层answer_guard在答案返回前用另一个LLM调用做一轮检查def answer_guard(question, answer, contexts):检查答案是否基于检索结果简化示例生产中用异步调用 promptf请判断以下回答是否完全基于提供的检索结果。 如果有任何信息不在检索结果中请标记为存在幻觉。 问题{question}回答{answer}检索结果{contexts}只返回基于检索 / 存在幻觉 / 部分基于检索returnllm.invoke(prompt).content有把握这个机制能捕获大部分幻觉。但有两个问题1多一次LLM调用延迟增加2guard模型本身也可能误判。待验证guard的准确率。理论上应该用标注数据集测precision/recall但还没做。三、踩坑清单这些是我实际踩过的坑按严重程度排序。坑1分块大小选错了检索精度直接废了现象用户问”2024年产业园申报条件”返回的5个块里只有1个真正相关其他4个是噪声。原因chunk_size1000太大。一个1000字的块里可能包含3个不同主题的内容向量检索命中了其中1个主题但其他2个主题是噪声。解决chunk_size从1000改到500overlap从100改到50。块小了语义更纯检索精度提升。效果Recall5从65%提升到78%。教训不要网上抄一个”最佳chunk_size”就用。拿你自己的数据准备50个真实查询跑评测。chunk_size的选择和文档类型强相关——政策文档500字合适FAQ可能200字更好。坑2向量检索对精确词项不稳定现象用户问”山东省2024年产业集群名单”向量检索返回的结果里没有”山东”而是”河北”——因为”山东”和”河北”在向量空间里很近都是省份。原因Embedding模型对专有名词地名、年份、编号的区分度不如关键词检索。”2024”和”2023”在向量空间里的距离可能很近但在业务上完全不同。解决加了BM25全文检索通道。精确词项走BM25语义查询走向量两路并行。效果精确词项查询的准确率从60%提升到92%。教训向量检索不是万能的。它擅长”意思相近”不擅长”字面精确”。大多数生产场景推荐混合检索。坑3Rerank延迟太高用户体验差现象加了Rerank模型后检索延迟从200ms变成了800ms。用户感觉”卡了一下”。原因Rerank是Cross-Encoder模型需要把查询和每个候选结果一起输入模型计算相关性分数。10个候选就是10次推理。解决两个优化——1Rerank的输入从Top10减少到Top5先粗排再精排2Rerank模型从大模型换成小模型bge-reranker-base精度损失约3%延迟减少60%。效果总延迟从800ms降到350ms。教训Rerank是”精度vs延迟”的trade-off。不是候选越多越好也不是模型越大越好。找到你的业务能接受的平衡点。坑4多轮对话的指代消解现象用户山东省产业园有哪些 系统[返回12个产业园列表]用户第三个的详细情况呢 系统[返回了一堆不相关的内容]原因”第三个”指代的是上一轮返回的列表中的第三个但检索模块收到的查询是”第三个的详细情况呢”没有上下文。解决在检索前用LLM把指代消解成完整问题。把对话历史和当前问题一起传给LLM让它改写成独立可检索的问题。def resolve_reference(history, current_query): promptf对话历史{history}当前问题{current_query}请将当前问题改写为一个独立的、不含指代的问题。只返回改写后的问题。returnllm.invoke(prompt).content# 第三个的详细情况呢 → 山东省兰陵县国家现代农业产业园的详细情况有把握这个方案能解决大部分指代问题。但增加了每次查询的LLM调用次数。待验证指代消解的准确率。有些复杂的指代比如”那个去年说的政策”可能消解不了。坑5评测集没覆盖边界场景现象系统在常规查询上效果不错但遇到边界情况就翻车——比如空查询用户只发了一个””、超长查询用户粘贴了一整段话、多语言查询中英混杂。原因最初的评测集只有50个”正常”查询没有覆盖边界场景。解决扩充评测集到120个查询增加了30个边界场景空查询/极短查询5个超长查询5个多语言混杂5个歧义查询5个否定查询”不包含山东的”5个多意图查询”对比A和B”5个教训评测集的质量决定了你能发现多少问题。50个”正常”查询的评测集给你一种”效果很好”的错觉。真正的考验在边界场景。补充一点评测集本身的代表性也很重要。如果120个查询都是你自己想出来的可能和真实用户的查询分布有偏差。更好的做法是从线上日志中采样真实查询按场景分类后构建评测集。每月校准一次确保评测集覆盖了新出现的查询模式。坑6表格数据检索是个大坑现象用户问”各省产业园数量排名”系统返回了一堆文字描述没有返回表格数据。原因表格在文档里是以图片或PDF表格形式存在的切片后变成了纯文本丢失了行列结构。向量检索把表格当普通文本处理自然检索不到结构化信息。解决表格单独处理——在文档解析阶段提取表格为结构化格式DataFrame单独建索引检索时支持按列名、数值范围查询。有把握这个方向是对的。但表格解析的准确率依赖文档质量——有些PDF的表格解析出来行列错位。待验证自动化的表格提取管线。目前部分表格还是手动处理的。四、还没解决的问题诚实地说RAG在业务系统还有几个问题需要优化跟着业务走很多时候需要优先满足核心需求问题1跨文档推理用户问”对比山东和浙江的产业发展差异”需要从多个文档中分别提取两个省的数据再综合对比。当前系统能分别检索到山东和浙江的信息但没有”对比”的能力——它会把两个省的信息混在一起返回而不是结构化对比。可能的解法Agent编排——先拆分为两个子查询”山东产业情况”和”浙江产业情况”分别检索再用LLM综合对比。但还没实现。问题2实时数据接入当前RAG的知识库是静态的——文档更新后需要重新索引。如果要接入实时数据比如最新的产业统计数据需要一个增量索引管线。可能的解法监听文档目录变化触发增量索引。但需要处理文档版本冲突和索引一致性问题。问题3评测体系不完整有评测集120个查询但没有自动化评测管线。每次改了Prompt或检索策略都是手动跑几个查询看效果没有系统化的指标对比。可能的解法用RAGAS框架搭建自动化评测核心指标Faithfulness、Answer Relevancy、Context Precision、Context Recall。但还没落地。问题4多模态检索文档里有图片地图、流程图、数据图表当前系统只检索文本图片被忽略了。用户问”产业园分布图”系统找不到。可能的解法图片单独建索引用CLIP或其他多模态Embedding检索时文本和图片并行召回。但增加了系统复杂度。五、上手的建议看完这些如果你正准备搭RAG系统几条建议1. 不要照搬架构理解取舍逻辑我的5通道架构是在”800政策文档、多种查询类型”这个场景下的选择。你的场景可能只需要2通道BM25向量就够了也可能需要更多比如加GraphRAG处理关系推理。关键是先分析你的用户怎么用系统再决定需要几条检索通道。2. 先跑通最简单的再逐步加通道第一步纯向量检索跑通Demo。 第二步加BM25混合检索。 第三步加Rerank。 第四步按业务需求加专用通道表格、事实表等。每加一个通道都要有评测数据证明”加了之后效果变好”。不要为了”架构好看”而加。3. 评测集比架构更重要一个2通道RAG 100个高质量评测集比5通道RAG 10个随便写的测试问题强100倍。评测集要覆盖正常查询、精确词项、语义模糊、边界场景、多轮对话。每种至少10个。4. 分块策略要拿自己的数据测不要抄网上的”最佳chunk_size”。拿你自己的文档准备50个真实查询对比不同chunk_size的Recall5。你会发现最佳值和你的文档类型、查询模式强相关。5. 防幻觉比检索优化更重要用户能容忍”没检索到”系统说”暂无数据”但不能容忍”检索到了但答案是编的”。Prompt约束 引用溯源 answer_guard三层机制缺一不可。6. 场景→方案速查不确定自己需要几个通道对号入座你的场景推荐方案原因纯FAQ/知识问答纯向量检索查询模式单一语义匹配够用政策/法规文档BM25向量混合检索精确词项多政策名、年份、编号推荐加BM25有大量表格数据混合检索表格专用通道表格的行列结构向量检索处理不了多轮对话混合检索指代消解“那个”“第三个”这类指代需要消解关系推理”对比A和B”混合检索Agent编排需要拆分子查询分别检索再综合小库100个文档长上下文就够了文档少直接塞进模型窗口不需要检索总结架构设计的本质是取舍。没有”正确的RAG架构”只有”适合你业务场景的RAG架构”。每个决策都有代价——5通道比2通道更准但更复杂RRF比加权融合更简单但丢失绝对分数TopK直接塞比上下文压缩更快但噪声更多。踩坑是正常的。分块大小选错、向量检索精确词项漏召回、Rerank延迟太高、多轮对话指代消解——这些问题不是你的架构有问题是RAG系统天然会遇到的挑战。关键是建立”发现问题→定位原因→验证修复”的闭环。诚实面对不确定性。我的系统还有跨文档推理、实时数据接入、评测体系、多模态检索四个问题没解决。这不是失败是工程的常态。知道”什么还没解决”比假装”什么都解决了”更有价值。评测集是最被低估的武器。花在评测集上的时间回报率比花在架构优化上高得多。没有评测集你改了任何东西都不知道是变好还是变差。欢迎评论区交流~相关关键词RAG架构、RAG实战、混合检索、BM25、向量检索、RRF、Rerank、分块策略、防幻觉、RAG评测、生产级RAG