资讯详情

生产级RAG知识库与Agent网关优化实践:从能用到稳定用

📅 2026/9/28 8:59:30 | 华诺云谱 👁 阅读
生产级RAG知识库与Agent网关优化实践:从能用到稳定用
1. 这次优化要解决的问题到底长什么样最近一两周我几乎把所有精力都压在“生产级知识库和 Agent 网关”这两个系统上。先说背景团队的知识库已经跑了大半年早期只是把一堆文档传上去、接了个向量检索能回答就算完事。但业务量一上来问题就藏不住了——同样的问法上午能答对下午换了措辞就答偏文档更新后回答里永远带着旧信息并发一高Agent 调用动不动就超时错误信息堆得到处都是。这其实是很多团队做 RAG 知识库都会撞见的拐点能用不等于能稳定用。从“能用”到“生产级”之间差距往往不在模型能力而在知识处理链路和网关调度层。我这次优化的核心就两件事让知识库从“搜得着”变成“搜得准、用得上”让 Agent 网关从“转发请求”变成“可控、可观测、可降级”。下面把这一个多星期的实测过程、踩坑记录和最终方案完整拆出来给同样在做 Agent 开发和知识库搭建的朋友一个可参考的底稿。先说清楚一个容易被低估的事实知识库和 Agent 网关是强耦合的。知识库检索质量再高如果网关侧没有合理的超时控制和重试策略用户感受到的依然是“卡死”和“报错”。反过来网关调度做得再花哨检索结果本身是垃圾Agent 生成得再流畅也是垃圾输出。所以这次优化我把两者放在同一条链路上一起改而不是分开各自调优。文字链接: ## 1. 这次优化要解决的问题到底长什么样最近一两周我几乎把所有精力都压在“生产级知识库和 Agent 网关”这两个系统上。先说背景团队的知识库已经跑了大半年早期只是把一堆文档传上去、接了个向量检索能回答就算完事。但业务量一上来问题就藏不住了——同样的问法上午能答对下午换了措辞就答偏文档更新后回答里永远带着旧信息并发一高Agent 调用动不动就超时错误信息堆得到处都是。这其实是很多团队做 RAG 知识库都会撞见的拐点能用不等于能稳定用。从“能用”到“生产级”之间差距往往不在模型能力而在知识处理链路和网关调度层。我这次优化的核心就两件事让知识库从“搜得着”变成“搜得准、用得上”让 Agent 网关从“转发请求”变成“可控、可观测、可降级”。下面把这一个多星期的实测过程、踩坑记录和最终方案完整拆出来给同样在做 Agent 开发和知识库搭建的朋友一个可参考的底稿。先说清楚一个容易被低估的事实知识库和 Agent 网关是强耦合的。知识库检索质量再高如果网关侧没有合理的超时控制和重试策略用户感受到的依然是“卡死”和“报错”。反过来网关调度做得再花哨检索结果本身是垃圾Agent 生成得再流畅也是垃圾输出。所以这次优化我把两者放在同一条链路上一起改而不是分开各自调优。2. 知识库优化从“能搜到”到“搜得准、用得上”2.1 数据治理是捡回准确率性价比最高的一步很多人一上来就调 embedding 模型参数但实测下来知识库准确率的最大敌人永远是脏数据和烂切片。我接手后第一批优化的文档来自三个渠道业务同事手写的操作手册、导出的一批 Markdown 格式的内部 wiki、还有散落在各处的 Excel 表格。这三个渠道的问题各不相同。操作手册是 Word 转 PDF 再上传的结果是标题层级全丢段落被截断成一个个孤立句子。Markdown wiki 好一点但代码块和表格经常粘连在一起导致一条切片里同时混着“接口调用示例”和“数据库连接配置”检索召回时语义严重不聚焦。Excel 最头疼直接把整张表塞进知识库切片在行与行之间乱切模型经常把表头和下一行数据组合成一条无意义的内容。我做的第一个改动是全部转成统一格式再入库。具体操作是写了一个文档清洗脚本把 PDF 先过一遍 OCR 识别再把 Word 和 Markdown 统一转换成 HTML 再转纯文本期间自动剥离页眉页脚、目录、脚注这些干扰信息。Excel 则按“表头 数据行”逐行拆条单独成片。清洗完以后同样的 Question 在评测集上的 Recall 直接涨了 9 个百分点一点花哨技巧没用纯粹是靠去掉脏数据换来的。这里插一个很多知识库搭建教程不会提的细节清洗脚本一定要保留文档结构标记。比如 Markdown 里的##二级标题、表格的table边界这些结构信息在后面做切片策略时是分块依据提前丢掉的后悔莫及。我的做法是清洗后保留一层轻量级的 JSON 结构里面带着 title、heading_level、text 三组字段后续切片直接从这层结构上做而不是从扁平文本里硬切。2.2 切片策略实测固定长度不靠谱语义边界才是关键切片这件事我试过四种方案可以直接给结论方案做法实测效果固定字符数每 500 字一刀切最差上下文频繁被切断固定字符数 重叠500 字切50 字重叠比纯固定好一点但语义边界问题没解决段落级切片按 Markdown 标题和空行分块较好适合结构化文档语义级切片利用 embedding 相似度切分最好但代价是最高的计算量我最终在线上采用的是“标题层级 段落边界 上限兜底”混合策略。具体逻辑是优先按二级标题分块比如一篇文档有“接口说明”“常见问题”两个大节就切成两大块如果某一大节内容过长超过 1200 字再按段落边界空行、列表等继续拆单块上限设定在 1500 字符左右避免超长块拖低检索精度。这样切出来的块每一块内部主题基本聚焦检索命中时上下文干扰小。这里必须多说一句重叠窗口不是越多越好。我刚开始做固定切片时设了 100 字的 overlap结果发现模型经常从重叠区重复引用同一段内容回答变得冗余。后来把重叠砍到 30 字以内只在上一块结尾和下一块开头各保留一个句子的余量用于承接语义效果反而更好。原因是 embedding 模型编码时本身会对短文本做 padding 归一化重叠区过长反而稀释了块内的主题浓度。另外表格数据一定要单独处理不能和普通文本混在一起切。我见过很多知识库把“库存量”和“安全库存预警值”这种数值型字段切割到两个切片里检索时漏掉关键值。我的做法是把一行数据和一个表头的键值对拼接成一个句子比如“商品A 的库存量为 1200安全库存预警值为 300”保证单块内信息自足。2.3 向量检索 关键词兜底混合检索的落地方法只用向量检索是生产级知识库最容易翻车的地方。原因很简单query 里的专有名词和缩写经常不在一个语义空间里。比如我们的知识库里有一份文档专门讲“调拨单”业务但用户提问时说的是“转仓单”向量检索能关联上可如果用户直接问“TD-2024-01 调拨单状态”这串编号是精确值语义检索反而帮不上忙必须靠关键词精确匹配。我这次搭的是“向量召回 关键词召回 融合排序”的结构。向量召回部分用 embedding 模型算 query 和切片之间的余弦相似度取 Top 50 候选关键词部分用 BM25 做文本匹配取 Top 20 候选两路结果按加权分数合并。加权系数我调了半天最后定为 0.6 的向量分加 0.4 的关键词分——这不是一次性拍脑袋定的而是用一小组有代表性的 query 在评测集上跑了几轮之后取的均衡点。如果你们的知识库以中文搜索为主建议关键词权重再高一点中文分词与拼音模糊匹配在向量检索里覆盖不到的边界情况比英文场景多。混合检索的收益直接体现在一个高频问题上。以前用户问“退单原因怎么录”知识库里明明有答案但因为“录”这个口语化动词和正式文档里的“填写”语义距离较大向量检索偶尔漏召回加了 BM25 后“退单”“原因”“录”这些字面关键词能把对应文档强行拉回来基本不再出现这种低级漏召回。2.4 重排序不贵但能大幅提升精排质量召回做得再准Top 5 里也难免混着一两条“看起来像但实际不对”的内容。我这次加了一个轻量的 rerank 步骤从召回候选里取 Top 40用一个 cross-encoder 模型逐条计算 query 与候选块的相关性再按相关性得分重新排序截断到 Top 5 送入 Agent 上下文。Cross-encoder 和双塔向量模型不一样它是把 query 和文档拼在一起过一遍模型精度明显更高代价是单次推理耗时更大。但只对几十个候选做重排整个链路增加的时间只有 200 到 400 毫秒换来的是 Top 5 的质量提升这笔开销我觉得非常值。接入重排序后我观察到一个明显变化Agent 的引用准确率上来了回答里编造来源的情况减少了。因为送给模型的事实上下文更集中hallucination 的空间被压缩了。注意重排序模型和 embedding 模型最好保持同一个语言域。中文场景下如果 embedding 用中文模型、rerank 用英文通用模型效果会打折扣。实测用同系列的跨语言 rerank 模型各项指标都更稳定。2.5 知识更新别全量重建要分层刷新知识库最怕的不是知识不够而是知识更新后向量索引没有跟上。我们的业务文档平均每周要更新 30% 左右如果每次全量重新 embedding 并重建索引计算量大、成本高而且全量重建期间查询会出现真空期用户体验很差。我这次是把更新机制拆成了三层增量更新新增文档或修改章节只对变更的切片重新向量化并 upsert 到索引默认走这条路。过期标记业务方明确标注“已下线”的文档不直接删除向量而是先把状态置为 inactive检索时过滤掉。这么设计是为了保留变更历史万一业务反悔要回滚不用重新解析上传。全量重建只在索引结构升级或历史脏数据过多时才执行频率大约一季度一次。另外发现一个坑向量数据库里的 upsert 操作如果主键设计不合理更新时会产生大量冗余向量。我刚开始时用文档 ID 作为主键后来发现同一文档多次更新后旧版本向量并没有被正确覆盖索引膨胀了将近一倍检索速度也往下掉。改成“文档 ID 切片序号”联合主键之后每次更新能精确覆盖对应切片索引体积恢复到了正常范围。3. Agent 网关从转发工具到流量中枢3.1 为什么需要一个独立的网关层一开始很多团队会想我们都用编排框架了直接调用模型不就完事儿了吗网关是不是多余的一层这个想法我很理解但经过生产环境毒打之后我可以负责任地说编排框架解决的是“单个 Agent 内部怎么思考”而网关解决的是“多个 Agent 之间怎么调度、怎么保护后端”两者解决的是完全不同的问题。对我们的场景来说网关层存在的理由至少有四个统一入口Web 端、移动端、内部系统都要调用 Agent 服务各自直连会导致鉴权、限流、审计各写一套维护成本爆炸。多模型路由我们接入了不止一个模型服务有开源部署的底座模型也有商业 API 模型网关要把不同请求按照业务场景路由到合适的目标。稳定性和降级模型服务商偶尔抖动或者自建推理服务排队网关层要做超时、熔断、重试、降级这逻辑放在 Agent 服务内部会污染业务代码。所以网关的本质是一个带 AI 语义能力的 API 网关它不仅做普通网关的 HTTP 转发、鉴权、限流还得理解请求里的模型名、参数、会话上下文并做出路由决策。我们最终选了开源网关做底座再包了一层自定义的模型路由策略下面具体拆解。3.2 网关落地的技术选型对比这里直接给大家一个对比表按我们团队的处境给一个参考结论方案核心能力适用场景我的评价基于 OpenAPI 的通用 API 网关HTTP 路由、限流、鉴权普通后端服务治理不够完全不懂 AI 语义自研网关完全可控大厂、超深定制场景成本高我们果断放弃开源 LLM 网关模型路由、成本追踪、多密钥管理大多数中小团队我们最终采用的路线我们最后选的是一个开源 LLM 网关做核心底座上面挂了自己写的两层扩展路由策略层和语义缓存层。选开源方案而不是自研核心原因是我们不想重复维护“鉴权限流多租户”这些通用能力把有限的开发资源集中在路由算法和缓存策略上这两块才是 AI 网关差异化价值所在。如果你们团队没有专职的网关开发人力不建议一上来就自研。先用开源方案跑通业务等流量规模和服务数量上来了再逐步把差异化的那部分逻辑抽出来改造成自研插件是性价比最高的路径。3.3 路由策略多模型共存的流量调度细节我们接了三个模型渠道实际使用中各有用武之地。网关的模型路由功能正好承担了流量调度任务业务 A消费级问答高并发、对延迟敏感路由到速度更快的底座模型业务 B复杂推理需要强推理能力路由到更大参数量模型业务 C内部测试流量走独立测试通道不占用生产资源同时方便对比模型之间的效果差异。网关层用 Tag 和优先级来做路由选择。例如一个质检场景的请求会被打上quality:high标签网关优先路由到强推理模型如果强推理模型服务异常则按照配置好的 failover 顺序降到次级模型同时记录一条降级日志。早期没做这个降级策略时强推理模型一抖动整个业务线跟着一起不可用后来加了权重降级和预案分流状况好了很多。另一个容易被忽略的参数是provider 超时时间。不同模型服务响应速度差异很大开源底座模型首字延迟明显高于商业 API。如果所有 provider 共用一个超时配置要么太短导致强推理模型频繁误判超时要么太长导致消费级问答请求迟迟不失败、拖慢用户体验。我按模型类型分别设置了超时开源模型给 30 秒商业 API 给 15 秒并在网关层区分“首字超时”和“总响应超时”。首字超时卡 10 到 15 秒总响应超时卡 60 到 120 秒能避免对话类请求长时间占着连接不释放。3.4 语义缓存用缓存兜住 60% 的高频重复请求调用模型是要花真金白银的而且生成耗时远比普通 API 长。我们线上观察到一个现象知识库问答场景中用户问的问题高度集中“如何创建调拨单”“退货流程是什么”这类高频问题占了总流量的 60% 以上。同一个问题反复调模型、反复检索知识库是巨大的浪费。所以我在网关层加了一个语义缓存模块。核心逻辑是对进来的 query 先算一个 embedding然后在缓存池里找相似度超过 0.92 的历史 query如果命中直接把当时缓存的回答结果返回不再进入检索和模型调用链路。为了保证不答旧话缓存 key 绑定了知识库版本号和模型版本号知识库更新或模型切换后缓存自动失效。这个缓存上线后实测效果非常直观缓存命中率稳定在 35%50%取决于当天问题集中度平均响应时间下降约 40%因为大量重复请求直接在网关层就被挡掉了模型调用成本下降约 30%省下来的预算非常可观但这里有个非常关键的坑缓存不能盲目复用流式输出。如果 App 端展示的是打字机效果的流式内容网关把一次性结果返回会导致前端兼容性错乱。我们的处理方式是网关内部缓存完整结果但对外提供两种协议支持流式请求的按流式格式重放缓存内容普通请求直接返回完整 JSON。这样前端无需改造也能吃到缓存的收益。4. 实操现场一条 Agent 请求从进网关到回包的全过程4.1 请求进来后发生了什么很多朋友可能对 Agent 网关全链路的内部流转没有实感我在这里完整走一遍线上真实请求的处理过程第一步用户输入“如何申请退货”后请求先到达网关网关做统一认证和权限校验。与此同时网关把请求方的租户 ID、模型偏好参数和超时策略附加到内部上下文。第二步网关对 query 提取 embedding然后到语义缓存层查找相似度大于 0.92 的历史缓存。如果命中直接进入回包阶段如果没有命中继续往下走。第三步请求被转发到知识库服务。知识库侧做混合检索向量 关键词把召回结果送到 rerank 模型重排截取 Top 5 相关切片连同用户 query 一起组装成 prompt再返回给网关。第四步网关根据路由规则确定使用哪个模型服务签名鉴权后发送 prompt并开启计时器。这里注意模型调用采用流式返回首字到达后网关立刻向客户端转流后续内容逐字转发。第五步响应全部接收完毕后网关把完整回答写入语义缓存同时记录一条日志包含模型名、延迟、token 数、耗时分布供后续分析和成本分摊。这个链路从用户视角看可能就只有一秒多的时间但内部实际上走了两层服务、经过了三次网络调用。任何一个环节出问题都会表现为用户体验上的卡顿或错误这也就是必须做网关层治理的原因——你总得有个地方统一兜底。4.2 稳定流式转发的两个关键参数流式转发最容易踩坑的点是背压控制。模型端如果生成速度较快而客户端消费速度较慢网关在中间需要做好缓冲否则两端的传输速度不匹配轻则延迟堆积重则内存被冲垮。这里我设置了两层保险内部缓冲池大小控制为 256 个 token 以内超过就触发读取暂停等客户端消费掉一部分再继续拉流。维护一条 heartbeat 机制每 15 秒向客户端发送一个空事件用于探测客户端是否还活着。如果连续两次 heartbeat 没有 ACK网关主动断掉该请求避免僵尸连接长期占着资源。这两个参数早期的数值分别是 1024 和 60 秒实测发现问题不少。缓冲池 1024 在业务高峰期会让网关内存明显上涨降到 256 后占用平稳且没有影响用户体验。heartbeat 60 秒太慢客户端断网后网关要等很久才能感知降到 15 秒后连接回收速度明显加快。4.3 灰度发布与分流配置示例网关层支持按用户维度分流。我们这周上线新模型底座时就是先让 5% 的流量走新模型观察了三个核心指标——回答准确率人工评测、响应延迟、错误率——才逐步放量到 30%、50%、100%。配置格式大致是route_rules: - rule_name: new-model-rollout match: user_id_suffix: 0-4 # 5% 用户灰度组 route_to: new-model-service fallback: stable-model-service - rule_name: default match: user_id_suffix: * route_to: stable-model-service做到一半时我发现一个容易遗漏的点灰度灰度的不只是模型还有 prompt 模板和参数配置。prompt 模板出现语法错误或格式问题模型输出质量会全面下降而且这种下降很难靠自动化指标发现。所以我的建议是任何灰度发布都要配一个独立的人工评测集至少 30 个有代表性的问题先人工离线打分再将流量放量。5. 常见问题与排查技巧实录5.1 知识更新后回答总是旧内容的排查链路先检查网关缓存是否命中。我们在知识库更新时有事件通知机制一旦文档变更触发知识库内部版本号递增网关的缓存 key 会跟着失效。但如果这个事件通知链路因为某个环节没打通就会出现“知识库更新了但网关还在返回旧回答”的故障。排查顺序记一下先确认向量库里的数据是不是新的用文档 ID 查一下索引里的内容再确认检索召回的是不是新切片可以临时打开 trace 日志看召回的片段内容最后检查缓存 key 是否带了新的版本号这个字段容易在联调时被遗漏。我们线上就出过一次事故运维手动重新导入了知识库数据但导入工具没有触发版本号递增事件导致网关缓存 key 没变。用户问“最新退换货规则”缓存直接命中旧结果连续三天都是错误答案。后来我把“知识库库表更新时间”作为缓存 key 的一部分让缓存自动跟随知识库数据变更而失效问题才彻底解决。5.2 响应超时的根因往往不在模型而在检索层很多人以为 Agent 响应慢就是模型推理慢实际上我这次优化里发现响应超时的大头在知识库检索层。具体排查案例一个复杂 query 包含了大量专有名词混合检索的向量召回阶段还能应付但 rerank 阶段要对 40 个候选块逐一做 cross-encoder 计算单次推理就要 3 到 5 秒。如果并发一高rerank 服务排队整个请求直接超时。我的处理是给 rerank 加了一个降级策略当 rerank 服务的队列深度超过某个阈值时跳过 rerank 步骤直接按向量相似度排序取 Top 5。虽然问答精度略有下降但至少保证响应不超时、用户不用看着加载圈转半天。生产环境下优先保证可用性、再谈精度这是我做系统设计以来最深刻的教训之一。5.3 Agent 复读和错误格式的排查思路知识库问答最常见的用户反馈之一就是“回答太机械了像在复读文档原文”。这种情况往往是 prompt 里对模型的语言风格约束不够。我们在 prompt 里加了一条指令基于给定资料回答采用口语化表达、面向一线业务人员使用不超过 200 字的短句作答。调整后反馈明显改善。另一个高频问题是格式错误。我们要求模型输出的退货单号必须严格带前缀TD-但模型经常漏掉前缀或改格式。这类问题的根因通常不是模型不聪明而是检索切片里给到的示例格式不一致。后来统一了知识库内退货单号的写法规范并补充了正反示例各两条模型输出格式的准确率从 78% 提到了 96%。经验总结AI Agent 的问题大部分不是模型问题而是围绕模型的“上下文工程”没有做细。输入侧的质量和格式直接决定输出侧的下限。别一味换个更大的模型先把知识库切好、Prompt 定好、网关兜好底效果提升往往更明显。5.4 成本与性能不可兼得用分级方案替代统一策略最后聊一个比较务实的点知识库不是所有内容都需要最高质量的检索链路。我们这次把知识库服务分成了两级效果很好核心业务知识比如退换货、财务流程、安全规范全链路保留——混合检索 rerank 强推理模型回答准确性放在第一位。普通辅助知识比如团队介绍、系统帮助、百科类内容直接走普通向量检索 高性价比底座模型响应速度优先成本优先。分级方案上线后整体成本比之前“一刀切”策略下降了 20%但因为核心业务知识全部保住了精度用户满意度并没有下降。这个思路其实很适合大多数生产级知识库场景因为实际上你不可能也不需要对每条知识都一视同仁地投入重算力。结尾这段优化做完之后我最大的一个感触是知识库和 Agent 网关看起来是两个系统其实是一条链路上的两个瓶颈。知识库不干净模型吃得再好也吐不出好料网关不控流模型服务再快也会在超时和成本里被拖垮。两者必须放在一起做整体设计单点优化很难带来质变。如果你也在做类似的 Agent 项目建议按这个顺序来推进先把知识库的数据清洗和切片做扎实再搭混合检索和 rerank最后才轮得到网关的缓存、路由和限流。不要一上来就追新框架、新模型先把地基踩实后面的上层建筑才稳。我现在还在持续观察灰度流量和缓存命中率的变化后续如果发现新的坑再来更新。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑