资讯详情

资讯详情

AI智能体生产级高可靠设计:分片与分散检索实践

做AI智能体时间长了你会发现一个规律demo好做生产难。单体Agent跑通一个复盘类、问答类的任务很简单但一旦进入真实业务——成千上万条知识库条目、十几个业务源头、动辄上万行的仓库分析——上下文窗口、单点检索、串行执行这些瓶颈马上就暴露出来。这篇文章想分享的是我在多轮生产实践里反复验证过的一套设计思路分片与分散检索。核心就两句话别让Agent一次吞下整个世界而是把数据分片、把检索分散再用聚合层兜住整体的高可靠性。适合正在从原型走向生产、被上下文超限和检索不准反复折磨的开发者参考。1. 先弄清楚单体Agent到底怎么崩的1.1 三类最典型的故障模式说到高可靠设计得先明确我们到底在防什么问题。单体Agent最常见的故障模式我归纳成三类。第一类上下文超限。这是接触面最大的问题。我见过有人把一个30万字的知识库直接往上下文里塞结果还没开始干活调用直接返回超过最大长度。即便没超token成本也高得吓人一次请求烧掉几美元都是常事。更隐蔽的是上下文越长注意力越稀释模型在5000行代码里找一个函数的行为逻辑效果远不如给它50行精准片段来得清楚。这个问题不是加大窗口能解决的窗口变大只是把崩溃点后移成本和精度会一起恶化。第二类单点依赖崩溃。Agent依赖一个检索服务、一套向量库或一个第三方工具时这个环节一挂整个任务就跟着失败。我之前某个项目里用单一向量库做全部召回结果那套服务一抖动一批任务全部重跑损失不小。做单点依赖还有个麻烦排查困难。不知道是模型问题、工具问题还是数据源问题只能一层层看日志。第三类串行执行导致的低可靠。任务步骤一步接一步任何一步失败后面全部白做。任务是长链条时成功概率是各步成功率的乘积。假设每步成功率为90%十步下来成功率只剩35%这可靠性根本扛不住生产。1.2 高可靠不是绝对不挂而是三件事在实际工程里高可靠不是玄学也不是绝对不挂而是可度量的三件事可用性、一致性、可恢复性。可用性指任务在合理时间内能完成。一个检索任务如果两秒内能给结果就算可用拖到三十秒用户早走了。一致性指同一查询在不同时间、不同负载下输出偏差可控。不是要求每次一模一样而是核心结论不能忽对忽错。可恢复性指失败之后能降级或重试而不是直接报废。比如检索源挂了能不能退回老索引这一路超时了能不能用另一路的结果顶上分片解决的主要是可用性和一致性问题——把大任务变小减少单次执行的波动范围分散检索解决的是可用性和可恢复性问题——多路召回一路挂了还有其他路。这两个模式不是割裂的它们共同服务于同一个目标让Agent在高负载、多故障的真实环境中依然给出稳定可用的输出。2. 分片策略别让Agent一次吞下整个世界2.1 分片到底分什么不是切文件那么简单分片的核心不是把文件切成几段而是根据任务语义选择正确的分片维度。维度选错了切出来的片既不自洽也没法独立处理。我实践下来主要分四种。数据分片按内容结构切。知识库按条目切数据库按记录或分区键切日志按区间切。这种分片最直观也最好落地。任务分片把一个复杂任务拆成多个子任务。比如代码评审拆成静态分析、依赖检查、测试覆盖评估三路并行再比如写一份行业报告拆成市场现状、竞品分析、趋势判断三路分别调研最后汇总。任务分片的重点在边界清晰子任务之间不能有纠缠不清的依赖。时间窗口分片处理流式数据、历史数据时按时间切。比如分析某个业务过去一年的趋势按月份切成十二个窗口分别处理每个窗口内部有完整的时间上下文不会被跨月数据搅乱。语义分片按主题、实体或意图聚类。同话题的对话记录归为一组同一实体的材料放一个片里。这种分片对检索类Agent尤其有用因为查询往往绑定某个实体或主题。选择维度的标准很简单分完之后的每个片要自包含、可独立处理且片与片之间尽量减少依赖。做不到自包含的切法只是把原来的问题切碎了重组成更多问题。2.2 分片大小的经验值以及背后的计算逻辑分片大小没有统一公式但我摸索出一个经验区间单片内容控制在3000到6000 token之间这是多数模型既有足够上下文理解局部语义、又不至于因过长而漂移的舒适区。算笔账你就明白为什么要这么设计。一个知识库有20万字按中文字符大约1.5到2 token每个算总token量在30万到40万之间。如果单片按5000 token算需要切60到80片。这么多片全由Agent挨个串行处理响应时效没法看成本也会翻好几倍。所以分片往往不是单独出现的它后面必然跟着并行处理——这也是下一章分散检索的底层逻辑之一把串行变并行把单点变多点。分片还有一个经常被忽略的细节重叠。切片如果完全不重叠跨片上下文就断了。比如一个概念在A片段开头定义、在B片段末尾解释切成两片后各自都只有半截信息。我通常把重叠区域控制在10%到20%让相邻片段保留一段公共上下文。这样检索时不会漏掉跨边界的语义代价是稍微增加一点token开销完全值得。2.3 分片之后的合并逻辑比分片本身更重要分片只是手段最终还得把各片的结果合回来。这里有个关键经验合并时优先收集各片的结构化输出再做统一决策。举个例子。分析一个仓库的代码质量让每个子任务返回问题列表加置信度评分最后汇总排序。这样每个片的结果是结构化的、可比较的、可去重的还可以做一致性校验——比如两个片都报了同一个文件有性能问题那这个问题就值得提级处理。反过来如果让Agent逐片写长文再拼接你会得到一堆又长又啰嗦、互相重复甚至互相矛盾的段落整理成本比重新跑一遍还高。结构化中间结果比自然语言中间结果可靠得多这一点在分片模式下怎么强调都不过分。合并阶段的另一个要点是冲突处理。不同片对同一个问题可能有不同结论这时候不要简单投票。我习惯的做法是给每个片配置一个权威度权重来源更可靠、证据链更完整的片话语权更大。权重可以来自数据源的可信等级也可以来自模型输出时附带的置信度分数。3. 分散检索多路召回才是可靠性的护城河3.1 单一检索源为什么撑不住单一检索源的问题一句话总结你的可靠性等于你最短的那块木板。向量库挂了检索全挂向量库里没收录相关数据结果再准也没用即便一切正常单一路径的召回覆盖率天然有限——它只会给你它认为最像的而真正有用的可能藏在它不擅长的匹配方式里。分散检索的思路就是把查一个库变成查多路源再合并排序。它的价值不只是容灾更在于召回覆盖率的提升。不同检索方式看到的相关性完全不同多路组合能互相补齐盲区。3.2 多路检索的组合设计我常用的四路配置我实际项目里常用的检索路有这么几种组合。向量检索负责语义召回。适合用户说不清准确名词、只描述意图的场景比如那个关于支付超时退款的流程文档。它的短板是精确匹配能力弱专有名词、编号、代码符号经常跑偏。关键词检索BM25负责精确匹配。适合含型号、编号、人名、报错码的查询。比如ERR-2043语义检索大概率会模糊化处理BM25直接命中。它的短板是不理解同义语义换个说法就召回不到。结构化查询负责元数据过滤。按时间范围、文档类型、作者、业务线过滤把候选集缩小再喂给后续排序。它不做相似度判断只管精确条件筛选。工具或外部API检索负责实时数据。比如查库存、查价格、查实时状态。这些信息不在静态知识库里必须走外部接口。各路检索各有优势和死角组合起来才能覆盖真实场景里五花八门的查询。3.3 合并、去重与重排决定最终质量的三板斧多路结果合并前做分数归一化是第一步。向量相似度0.8和BM25得分8.0数值上看着差十倍实际可能代表差不多的相关程度直接把原始分数相加是拿苹果加橙子。我用过的最小可行方案是min-max归一化把各路分数压到0到1区间再线性加权。更精细的做法是让每路检索返回时附带一个校准后的置信度但那个调起来费劲初期用min-max够了。归一化之后必须做语义去重。同一条信息可能被向量库、BM25、结构化查询同时命中重复内容进了重排会虚高相关度。轻量做法是算文本的embedding相似度阈值设在0.85以上视为重复保留分数最高的一条。数据量大时可以上MinHash做近似去重速度更快。然后是重排。多路召回的结果合并后我一般用一个轻量级的cross-encoder模型做终排因为它能同时看到查询和文档能捕捉到向量检索和BM25单独看不出来的关联。没有cross-encoder资源时用规则融合——各路归一化分数加权加一个新鲜度或来源权威度的惩罚项——也能凑合效果差一些但稳定。4. 一个可以直接抄作业的落地配置4.1 整体架构与模块划分我最近在做一个企业内部的跨业务文档问答Agent就叫它某企业内部文档智能问答Agent架构分四层每一层职责单一互相独立。接入层负责接收查询做意图解析和参数清洗判断查询是找文档还是问数据。分片层负责按文档结构把长文档切出候选片段建好索引标注每片的元数据包括所属业务线、时间、类型。检索层并行调用四路检索向量库召回、BM25召回、结构化过滤、外部API查询。聚合层负责分数归一化、去重、重排最后把Top结果连同引用片段一起交给模型生成答案。四层互相独立任何一层挂了其他层还能降级工作。这个架构的核心价值在于故障被限制在单层内部不会像单体Agent那样一个接口超时就把整条链路拖垮。4.2 关键参数配置我踩过坑后的推荐值分片大小正文部分已经说过3000到6000 token重叠10%到20%。并发度并行检索的并发数设为3到5路。不是越多越快检索服务本身有吞吐上限并发太高反而引发雪崩。实测3路检索和5路检索的延迟差距不大但3路的资源消耗少很多。超时控制单路检索超时设500到800毫秒总检索超时2秒。单路时间太长会拖住整体所以要给每一路单独的超时上限。最长的一路决定整体延迟所以还要配快速路径优先返回。重试次数幂等操作可以重试两次非幂等操作比如外部数据写入不重试直接走降级。多数检索是幂等只读的重试安全性高但要加指数退避第一次等100毫秒第二次等200毫秒避免服务恢复过程中被重试请求压垮。TopK取值每路检索取top 20合并去重重排后取top 5进入最终生成。取太多徒增生成阶段的上下文负担取太少又容易漏掉正确答案。20和5是我试过多个值之后比较稳的组合。4.3 降级能力可靠性设计的最后防线降级顺序我定为向量库挂了就只用BM25BM25也挂了就退到元数据精确匹配所有检索源全挂就返回静态FAQ兜底。这里有个原则宁肯返回不完整的准确结果也不要返回完整的错误结果。降级不是做得差一点而是保证底线可用。用户问一个问题给三条相关文档的摘要远好过给一大篇编造出来的自信满满的回答。降级的触发要自动化。我在聚合层放了一个健康检查模块每路检索返回时带上状态标记聚合层根据各路健康状态动态调整权重。健康的路权重上调不健康的路自动摘除。这个机制上线后我再也不用半夜爬起来手动切开关了。5. 常见问题与排查技巧实录5.1 分片不均导致的结果偏差这是分片最容易踩的坑。如果切片器只按固定字符数切不看实际内容就会出现有些片大得超限、有些片小得没信息。我排查过一次某个大文档里有一段特别长的表格切片器把整个表格完整保留成了一个超大片段模型处理时直接截断表格后半部分全部丢失后续检索怎么都查不到那几条记录。解决办法是改用长度感知切片器。切之前先估算token数超出上限的片段递归下钻找到段落边界再切。表格类内容要单独处理按行列维度二次拆分不能整块硬塞。5.2 多路检索结果重复与结论冲突多路检索对同一信息命中多次很常见。症状是最终答案里同一句话反复出现或者重排结果里前三名都是同一篇文章的不同片段。处理方案前面说过embedding相似度去重阈值0.85保留分最高的。更麻烦的是结论冲突。向量检索认为方案A好BM25把支持方案B的文档权重排得很高。这种情况不能靠去重解决要靠证据链。我给每个片段标注来源层级和时效性冲突时优先采信权威度更高的来源同时在生成提示词里明确要求模型把冲突点暴露出来而不是强行融合成一个含糊结论。5.3 延迟抖动与慢路径拖累并行检索不是万能的最慢的一路决定整体延迟。我遇到过向量库响应突然从200毫秒涨到1.8秒的情况整个查询跟着变慢。处理技巧是差异化超时加动态等待。主要检索源给足时间次要检索源严格限制。快速路先出结果就先渲染给用户慢速路结果到了再补充刷新。这种方式在交互场景里体验改善非常明显——用户第一眼看到的是近实时的高质量结果而不是干等一个缓慢的完美答案。另外给每路检索加一个滑动窗口的延迟统计超过历史均值两倍就主动降级。这个机制帮我挡了好几次检索源抖动引起的雪崩。5.4 排查这类系统我有一个固定套路日志要打全链路的trace ID从接入层到聚合层一个查询一个ID。所有中间结果落盘合并前的各路召回结果、归一化分数、去重命中记录都要能追溯。我踩过最深的坑是线上答案错了但只查最终输出日志完全看不出是哪一路检索带偏的。后来加了中间结果上报问题定位从小时级缩短到分钟级。排查分布式检索系统的核心原则就一句话——必须能回答这个答案凭什么这么生成。我个人在实际操作中还有一个体会这套架构不是一步到位的。最早做单体Agent时我也以为把上下文塞满就能让模型看得全结果又贵又慢还容易偏。后来一步一步加上分片、分散检索和聚合层才真正把它跑稳了生产任务。如果你正卡在长文档处理和检索不准这个坎上建议从小规模试验开始。先把检索源从一路加到三路再引入分片最后慢慢调合并和重排策略——顺序别反了。分片和分散检索不是银弹但它们是目前把Agent从能跑推向可靠的最实用路径之一。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →