ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

生产级知识库与Agent网关优化实践:稳定、可控、可观测

生产级知识库与Agent网关优化实践:稳定、可控、可观测 1. 先聊聊“生产级”这三个字的分量不知道你有没有这种经历本地写一个知识库 Demo文档全部切好、索引建好、问什么答什么效果棒得想立刻上线。结果真到了线上几十个用户一进来延迟飙到十几秒回答一会儿对一会儿错知识库更新完之后检索出来的还是旧内容更别提 Agent 一接进来整个链路变成一团乱麻。最近我正好在优化一套生产级知识库和 Agent 网关整个过程走下来最深的感触是生产级拼的不是单个模型的聪明程度而是一整套工程化的取舍逻辑。先说清楚一件事知识库在生产环境里到底承担什么角色。它不是给人用的“搜索框”而是给 Agent 和上层业务系统提供“事实依据”的数据基础设施。知识库的产出是一个个带元数据、可溯源、可更新的文本块通过向量化之后被召回再拼进 Prompt 里最后交给大模型生成答案。这个链路里任何一环不稳定用户看到的就是“答非所问”或者“胡说八道”。所以生产级知识库的第一标准不是“模型多聪明”而是结果可复现、数据可更新、召回可评估、错误可追踪。Agent 网关则是另一层东西它夹在应用和大模型/知识库之间负责路由、鉴权、限流、缓存、可观测、模型切换。很多人把 Agent 网关当成单纯的“API 转发”但真正生产级场景里它要管的复杂得多同一个知识库要服务多个业务 Agent有的 Agent 需要走快模型有的需要走强模型有的要带工具调用有的要严格限定只读知识库访问高峰期还得保证核心业务不被打爆。没有网关这层治理知识库做得再好也撑不住多 Agent 同时接入。这篇文章不打算写成教科书式的“技术原理详解”而是把我这轮优化里的真实判断、踩过的坑、留下来的配置方案都摊开来讲。适合正在做 RAG 应用、接了 Agent 但总觉得效果和稳定性不够的团队参考。内容会分四条线展开知识库侧的数据处理和检索策略、Agent 网关的治理能力、两者如何串成一套完整流水线、以及我在生产环境里实际踩过的坑。2. 知识库侧让 RAG 管线真正“可被生产使用”2.1 数据接入与文档解析最容易翻车的环节知识库优化的第一步往往不是向量模型而是“文档进来之后变成了什么”。我见过太多团队花大力气调 embedding 和 rerank最后发现效果差的根源是源文档解析完就是一团乱码。生产级知识库必须接受现实业务侧给到你的文档不是整齐的 Markdown而是 PDF、Word、Excel、扫描件、网页导出的 HTML甚至还有图片表格混排。文档解析这块有几个核心点需要注意PDF文本型 PDF 用 PyMuPDF 或 pdfplumber 提取速度和准确率都不错。扫描型 PDF 必须走 OCR我目前用的是 PaddleOCR中文识别效果比 Tesseract 好一截但要注意它对表格的识别仍然不够完美复杂表格建议配合表格结构解析工具一起用。Word/ExcelWord 直接按段落提取没问题Excel 是个隐藏深坑。直接把整张表塞进知识库检索时模型很难理解“这一行和上一行的关系”。我目前的处理方式是将 Excel 转成 Markdown 表格或者按行拆成“字段-值”的语义描述比如“产品型号 X200起售价 4999发布于 2025 年 3 月”这样召回和生成都会准很多。HTML/网页要先把标签剥掉、按正文结构提取不然导航栏、广告、版权信息全会被当成知识内容灌进去。解析完成之后再清洗一遍这一步不能省去掉重复段落、修正乱码字符、统一日期格式、识别文档中的章节层级。清洗后的文本才进入分块环节。2.2 分块策略与向量化直接决定召回质量分块是整个 RAG 过程里最影响结果的环节之一。如果块太大embedding 的语义会被稀释检索出来的内容不够聚焦如果块太小上下文不完整大模型生成答案时容易拼错逻辑。而且不同文档类型、不同业务场景最优分块参数完全不一样没有“万能参数”。我常用的分块方式是结构感知 递归分割的组合而不是单纯按固定字符数硬切。具体来说先用文档自带的结构信息切分按 Markdown 标题、HTML 的 h1/h2、PDF 的章节编号把文档切成“语义块”对仍然过长的语义块再用递归字符分割器按字符数切块大小设置在 500~700 个 token 之间重叠设 50~80 个 token每个切好的块打上元数据文档名、章节路径、页码、最后更新时间、来源 URL。这一步非常关键因为后面做过滤和引用溯源都要靠元数据。分块不是一劳永逸的事。我前阵子做技术文档知识库发现代码片段和描述文字经常被切散代码块中间被截断导致检索结果中代码不完整。后来把代码片段单独识别出来、整块保留效果才明显改善。所以分块策略务必基于你的真实文档结构来调整并且每一次调整都要用测试集去验证不要凭感觉。向量化方面我目前生产环境用的是 bge-m3 这类中文效果稳定的 embedding 模型输出 1024 维向量支持中英混合检索。如果团队预算紧张、对效果要求也没那么苛刻也可以考虑线上 API 的向量模型但要注意维度不一致会带来后续迁移成本。这里给一个小建议不要频繁切换 embedding 模型一旦切换向量索引必须全量重建否则新旧向量语义空间不一致召回质量会迅速劣化。2.3 向量库选型稳定比炫技重要向量库这一轮我对比过 Qdrant、Milvus、pgvector 和 Chroma。结论是如果做生产级系统强烈建议在 Qdrant 和 Milvus 之间选。Chroma 适合本地验证和原型开发但生产环境部署高可用、数据持久化、性能调优的生态还不够成熟数据量大之后问题会更明显。pgvector 的优势是复用现有 PostgreSQL 基础设施适合数据量在几百万以内的场景但高并发查询和向量索引调优的灵活性有限。Milvus 功能完整支持分布式但部署运维成本偏高团队没有专门的人维护会有点吃力。Qdrant 在这几个里平衡性最好Rust 写的单机性能好支持 payload 过滤部署也不复杂我目前的主力向量库就是它。向量索引类型和参数我也给一套起步配置用余弦距离的话选 HNSWm 设为 16ef_construct 设为 100查询时 ef 设为 128 左右。数据量越大ef 越大召回越好但延迟也会涨这需要实测平衡。重要的是给向量增加 metadata 过滤条件比如按文档类型、业务线、日期范围过滤后再做相似度检索这样既提升准确性也减少无关结果。2.4 提高“匹配度”的关键混合检索与重排序“怎么提高匹配度”这个问题几乎每个做知识库的人都会问。我的回答是不要只依赖向量相似度。很多人部署完之后问“答案不对”第一反应是换 embedding 模型、调分块大小但其实最常见的提升手段是混合检索。向量检索擅长语义相似但它在“精确匹配”上很弱。比如产品型号“X200”这种字符串语义向量很容易把它和“200 元产品”扯上关系但如果用 BM25 关键词检索“X200”就能精确命中。所以我在生产环境里用的是向量检索 关键词检索并行再用 RRFReciprocal Rank Fusion做结果融合。RRF 不依赖分数绝对值只看排名天然避免了两个检索引擎分数尺度不同的问题实测下来效果非常稳定。召回之后再加一道重排序。向量检索先给你 Top 50 候选重排序模型比如 bge-reranker-v2-m3再对这 50 条精排取 Top 5 拼进 Prompt。这一步增加的时间消耗很小但答案相关性会有肉眼可见的提升。我自己实测对比过不加 rerank 的时候答案准确率大概 65%加上 rerank 之后能到 85% 左右尤其在长文档、候选内容杂的场景下提升更明显。至于“阈值怎么设置”我不建议单看相似度分数设一个全局阈值因为不同模型的分数分布完全不同。更好的做法是固定召回数量比如 Top 50 候选 Top 5 最终结果再配合重排序后的分数做相对过滤。这样系统对分布变化更鲁棒。3. Agent 网关治理层是我这一轮优化的重心3.1 Agent 网关到底在解决什么问题知识库本身只是被动的数据服务真正让它“活”起来的是 Agent 系统。但每个 Agent 都直接连模型、直接查知识库会造成三个问题第一鉴权和限流策略散落在各个 Agent 里安全性和一致性没法保证第二Agent 之间没有统一的路由入口新接入一个 Agent 就得重复对接一遍模型 API第三知识库的调用方式和 Prompt 模板散落业务代码里想统一升级一次就得改一堆地方。Agent 网关就是把这些横切能力收口。它不是“代理服务器”四个字能概括的而是一个轻量级的 Agent 调度和治理层。网关至少要负责五件事路由分发根据请求的业务标识、Agent 类型把请求转发到对应的模型服务或知识库流水线鉴权与权限隔离验证调用方身份并控制该身份能访问哪些知识库、能调用哪些工具统一上下文策略规定 Prompt 里知识库结果的位置、token 预算、引用格式缓存与限流对重复问题做语义缓存对突发流量做速率限制可观测性把一次 Agent 会话的完整轨迹记录下来包括模型输出、知识库召回结果、工具调用结果。我这一轮优化其实核心就是补上网关这一层。知识库做得再好如果 Agent 接入没有章法最后的数据流仍然是混乱的。3.2 网关与知识库的协作方式网关和知识库不是简单的“网关转发请求给知识库 API”关系而是要定义一套协作协议。我把我的实现概括成三步第一步Agent 收到用户问题后网关先把请求送到“请求意图识别”模块判断这个问题需不需要查询知识库。如果只是想闲聊或者只需要模型常识就能回答就直接走模型生成不浪费知识库的检索资源。第二步如果判断需要查知识库网关调用知识库的检索接口把检索到的候选文本块、元数据、相关性分数一起带回来。这里我特别强调不要把知识库处理成一个黑盒网关要能看到召回结果的内容和来源才能决定怎么拼 Prompt、怎么过滤。第三步网关把知识块拼进 Prompt并通过系统提示词规定“只依据给定知识回答知识库中没有的内容不要编造”。资源充足的情况下还会让网关验证“最终答案是否引用了指定知识块”这一步对降低幻觉很有效。举一个实际例子我有一个业务 Agent 专门处理产品售前咨询经过网关的知识库模块判断后产品参数类的问题走产品手册知识库价格政策类的问题走价格策略知识库如果用户问题同时涉及两者网关会把两个知识库的结果合并起来再统一排序。这种多知识库的融合调度如果没有网关在业务代码里实现会非常臃肿。3.3 缓存、限流与成本控制生产级系统绕不开成本和稳定性。我在这轮优化里给网关做了两层缓存结果缓存和语义缓存。结果缓存比较好理解完全相同的问题哈希命中后直接返回之前的结果。适合问答对固定、业务答案不经常变化的场景。语义缓存更考验功底。它把用户问题先向量化和缓存池里已有的问题做相似度匹配如果相似度超过阈值直接复用之前的答案。对知识库场景特别有用客服问答里大量用户问的是“怎么退货”“退款多久到账”这类相似问法语义缓存命中的话可以省掉整条检索和模型生成链路成本直降响应速度也快不少。限流方面我按“用户维度 Agent 维度 模型维度”做三级限制。用户维度限制单用户 QPS防止有人刷流量Agent 维度限制某个业务 Agent 的总吞吐防止一个异常业务拖垮整个网关模型维度限制模型服务本身的 TPM每分钟 token 消耗因为模型 API 的配额是硬约束。超限的请求统一排队或降级而不是直接抛错。成本控制还有一个容易被忽视的点长上下文。知识库召回加上工具调用结果很容易把 Prompt 撑到几万 token。网关要给单次请求设置 token 预算超出预算时做优先级截断把最不相关的知识块裁掉。别小看这一步它能让每千次调用的 token 消耗下降 30% 以上。3.4 可观测性与灰度发布生产级系统如果看不清内部发生了什么出了问题就只能瞎猜。我这次把可观测性分成了三层日志层记录每次请求的完整轨迹用户问题、路由到的模型、召回了哪些知识块、各知识块的分、模型生成的最终答案、耗时。指标层用 Prometheus 统计 QPS、延迟分位数、错误率、缓存命中率、知识库召回率。追踪层基于 OpenTelemetry 做全链路追踪从用户请求进入网关到知识库检索、模型调用一步步都能在链路视图里看到耗时分布。有了这三层灰度发布才有底气。模型切换、知识库更新、Prompt 模板调整都先走流量灰度先放 10% 的流量测一段对比新旧链路的答案和延迟确认没有回归再逐步放量。这个流程听起来麻烦但能救你很多次。实际上我这次优化就因为先灰度避免了一次 embedding 模型切换后召回质量大幅劣化的小事故。4. 从知识库到网关的整体流水线一个可复用的参考实现4.1 整体链路与模块划分我把整个系统拆成六个模块每个模块都在单独的服务或容器里跑通过 API 通信数据接入层负责文档上传、解析、清洗输出标准化文本块索引构建层对文本块做分块、embedding、写入向量库同时构建关键词索引知识检索服务对外提供检索接口内部实现混合检索、rerank、metadata 过滤Agent 网关负责路由、鉴权、缓存、限流、语义缓存模型服务层封装各家大模型 API提供统一的 OpenAI 兼容接口可观测平台日志、指标、追踪三合一。模块之间通过 API 解耦好处是可以独立扩容。比如接入高峰期模型服务压力大只需要单独扩展模型服务知识库更新频繁时也只影响索引构建层不打断检索服务。4.2 关键配置参数与路由规则示例我给一份目前生产环境的参数快照方便你做对照参考。分块这块我用结构感知切分Markdown 文档按标题层级切普通文本用递归分割块大小 600 token、重叠 60 tokenEmbedding 模型 bge-m3输出 1024 维向量库 QdrantHNSW 配置 m16、ef_construct100查询 ef128检索时先取 Top 50rerank 后取 Top 5。网关的路由规则我简化成一段伪配置方便理解routes: - name: product_consult match: intent: product_query knowledge_bases: - product_manual - price_policy model: provider: internal_llm model_name: deepseek-chat context_budget: 4000 cache: semantic: true threshold: 0.92 - name: after_sales match: intent: after_sales_query knowledge_bases: - return_policy - shipping_policy model: provider: internal_llm model_name: fast_llm context_budget: 3000 cache: result: true这段配置的意思是售前咨询路由到产品手册加价格策略知识库用 4000 token 的上下文预算启用语义缓存售后问题路由到退货和物流知识库切换到快模型启用结果缓存。规则统一收口在网关这里调整路由不需要改任何业务代码。4.3 生产部署的几个要点部署层面有几个容易被忽略但又非常关键的点我按优先级列一下模型服务必须支持流式输出。网关转发模型请求时如果只支持一次性返回用户体验会很差长文本生成尤其明显。网关侧要支持 SSE 流式转发并且把流式关闭、停止等信号在前端和模型之间正确传递。向量库需要持久化和备份。Qdrant 快照备份、异地备份至少要有一套可恢复的机制。知识库索引本身是长期积累的数据资产丢一次重建的成本会让你很痛苦。网关要做优雅降级。比如知识库检索服务抖动时可以让网关切换到“仅模型”模式先保证用户聊天的流畅性而不是整个系统直接不可用。所有配置代码化留痕。路由规则、Prompt 模板、缓存策略全部放在版本控制里每次修改都有 diff能回滚。这个习惯能省掉大量排查时间。5. 生产环境里我踩过的四个坑5.1 坑一向量库混入了新旧两版 embedding 向量有一次我更新了 embedding 模型但没有做全量重建只增量导入了新文档。结果发现检索质量全面劣化部分老文档怎么查都查不出相关内容。查询向量空间和旧向量的语义空间不同导致匹配分数一片混乱。这个问题的根源是我没有设置“版本控制”概念。现在我在向量库里给每个文档都打上embedding_version标签检索时强制过滤版本号一旦切换模型必须全量重建索引。5.2 坑二相似度阈值带来的假安全感早期我给知识库设了“相似度低于 0.75 就返回无结果”的阈值结果大批正常问题因为分数不到阈值被拦掉了。不同 embedding 模型的分数分布差异很大有的模型 0.75 很低有的模型 0.75 已经是高门槛。后来我放弃了绝对阈值思路改用“Top N 召回 rerank 排序 最低分兜底”策略问题彻底解决。我的建议是不要相信“调大阈值就能提升准确率”这种直觉阈值只会让你“宁缺毋滥”不会让你“精准命中”。5.3 坑三Agent 网关变成同步阻塞瓶颈网关初期实现比较粗暴对模型请求用同步方式等待结果结果高并发下网关线程被占满明明模型服务能力充足整个系统却卡在网关这里。后来改成异步流式转发把长请求的等待转移到异步任务并发能力立刻上来了。再往后期我加上了响应超时熔断单次模型请求如果超过 60 秒网关直接返回部分结果或重试不让请求无限挂起。5.4 坑四可观测数据只采集不分析我一度把所有日志、指标都接进了监控平台仪表盘看起来非常豪华但实际作用很有限。原因是没有把观测数据和业务指标关联起来。后来我给每条请求都加上一个conversation_id从用户提问、知识库召回、模型生成一路带下去再配合人工抽检和自动评估才真正做到“出了问题能定位到具体是哪一步”。观测不是为了“有图可看”而是为了能回答“这个回答是哪个知识块支撑的、为什么选它”。6. 一些真实体会不是总结这轮优化最后沉淀下来的东西其实不是某一两个参数而是一整套工作习惯知识库侧把数据解析、分块、向量化、检索当成一条需要持续迭代的流水线每一环都能独立评估Agent 网关把路由、缓存、限流、可观测这些横切能力标准化确保所有 Agent 接入都有同一套治理骨架。如果你现在也在做类似的东西建议先别急着换模型。从我的经验看绝大多数“效果不好”的问题根源出在数据解析、分块、检索融合这些基础环节上而不是模型不够强。最后再分享一个小技巧我每次调完一个环节都会用一套固定的测试问题集跑一遍记录每个问题的“检索 Top5 内容”和“最终答案”人工看一遍差异。这套回归测试只要坚持做效果不会跑偏。知识库和 Agent 网关的优化永远没有终点但只要链路可观察、可评估每一次调整都是累积性的而不是靠运气。
返回列表