这道题其实问的是,当[[RAG]]和[[Agent]]组合起来之后,为什么延迟和正确率的问题会变得更棘手,以及怎么去解决。核心在于Agent的多步决策会把RAG的缺陷放大,比如检索慢一点或者错一点,后面每一步都会跟着慢或错,像滚雪球一样。
具体说一下延迟。延迟主要来自三个环节:检索、Agent决策、还有服务间的编排。先说检索,最常见的问题是[[向量库]]冷启动,比如新知识刚加进去,还没建好索引,第一次查就很慢。还有就是跨地域查询,比如库在北京,服务在上海,网络开销就上去了。我的做法是,预加载热数据到内存,比如高频的客服退款政策,提前放到内存里。另外,本地缓存高频Query的[[Embedding]],避免重复计算。索引上我会用[[HNSW]]加量化,这样能在召回率和速度之间平衡。
再一个,Agent决策层。[[ReAct]]模式里,Agent每步都要思考、调用工具,如果迭代次数太多,延迟就上去了。我一般设一个最大迭代阈值,比如5次,超出就强制返回。另外,如果多个工具调用是独立的,就并行化。这里有个技巧,用小模型做意图路由,大模型只做最终生成,比如用个轻量模型判断用户是想查订单还是查退款,然后直接路由到对应的工具,这样能省掉大模型推理的时间。
正确率的问题更隐蔽。核心矛盾是Agent的“动态性”和RAG的“静态性”。比如Agent在对话中任务会漂移,一开始问退款政策,中间可能转到物流问题,但知识库里的知识是固定的,检索出来的结果可能不匹配。我的做法是引入Query改写模块,比如HyDE,根据Agent的历史上下文做共指消解,把“它”指代的东西补全。
另一个常见问题是上下文碎片化。多轮检索的结果拼在一起,逻辑可能不连贯。举个例子,客服场景里,用户说“我买了满减商品,但订单显示原价”,Agent先搜满减政策,再搜订单信息,把两段拼起来,但模型可能没理解满减和订单的关系。我会在检索后加一个[[重排序]],用[[Cross-Encoder]]打分,只保留和当前子目标最相关的片段。
最严重的是决策漂移,早期检索错误导致后面全错。比如第一次搜错了商品价格,后面所有计算都基于错误价格。我的做法是设一个检索置信度阈值,分太低就触发“反思”模式,让Agent重新规划。比如用[[Self-RAG]],让模型自己判断检索结果是否可靠,不可靠就重来。
从架构层面看,我会把RAG封装成Agent的一个工具,而不是底层依赖。这样Agent可以自由选择是否调用RAG,而不是每次都要查库。比如用户问“今天天气怎么样”,Agent可以直接调天气API,不用走RAG。这样架构更灵活。
还有一个点值得深入,就是检索的置信度怎么量化。我通常用检索结果的得分分布和LLM自身的困惑度做联合判断,但实际落地时,阈值很难定,调得太高容易漏召回,太低又容易引入噪声。这块我觉得还有优化空间。
总结一下,RAG加Agent的优化,前提是区分场景。比如客服场景,高频问题走缓存,低频问题走检索;订单查询场景,优先走结构化数据,RAG只做补充。如果知识库更新频繁,还要考虑增量索引。上线我会特别关注延迟的P99和正确率的坏案例,用ARMS做全链路追踪。所以我的倾向是,不要追求一个方案解决所有问题,而是把RAG、缓存、结构化查询结合起来,根据场景做取舍。