这道题其实问的是[[RAG]]在真实业务中,怎么平衡响应速度和结果质量。我理解它本质上是检索和生成两条线的协同问题,但落地时每条线都有自己的瓶颈,而且还会互相放大。
先说检索层。延迟主要来自两个地方:一是向量检索的 [[HNSW]] 索引构建,尤其是数据频繁更新时;二是 [[重排]],[[Cross-Encoder]] 虽然精度高,但延迟太高,不能每个请求都用。精度方面,常见问题是 [[Embedding]] 的语义漂移,比如用户说“退款”,客服系统里可能对应多个政策,向量相似度高的不一定就是对的。所以实际落地我倾向用 [[Hybrid Search]],把 [[BM25]] 的关键词匹配和向量检索结合起来,但这里有个坑:融合权重很难调。比如电商客服场景,用户问“满减政策”,关键词“满减”能精准命中,但向量检索可能把“优惠券”也召回来,如果权重偏向向量,就会引入噪声。我的做法是先做粗排,用快速向量召回 top-100,然后用轻量模型精排到 top-10,最后只在关键查询上启用重排,这样能平衡延迟和精度。
再来看上下文层。主要矛盾是模型窗口有限和[[Agent]]多轮对话的历史膨胀。比如代码助手场景,一个项目文件可能几十万token,直接塞进去不现实。常见的做法是截断,但截断会导致关键信息丢失。另一个问题是检索回来的top-k文档里,低相关文档会污染生成,这就是所谓的“中间丢失”现象,模型容易忽略中间位置的文档。我的优化思路是动态压缩:根据相关性分数剪枝,只保留高相关段落,然后用摘要模型生成“记忆卡片”来压缩历史。另外,我会把检索结果结构化,比如转成表格或JSON,这样模型解析起来更省力。
Agent特有的瓶颈是决策链的累积错误。比如 [[ReAct]] 循环里,检索、推理、工具调用,每一步都可能出错,而且错误会级联放大。举个例子,一个数据分析Agent要查库存,它先检索到错误的schema,然后基于这个schema生成错误SQL,最后工具返回错误结果,整个流程就崩了。所以我会把检索决策前置,让LLM先判断是否需要检索,避免无效调用。同时做结果缓存分层:Embedding 缓存设小时级,生成结果缓存设会话级,减少重复计算。另外,必须有失败降级链,比如检索超时就回退到参数知识回答,但标记待核实。
这里其实有个延伸点:当知识库频繁更新时,增量索引的实时性和一致性很难同时保证。比如新增文档后,索引还没更新,旧文档被删除了但索引还在,都会影响召回质量。我倾向用双缓冲影子索引,base加delta,查询时合并再按版本过滤,构建完用固定query回放校验,通过才原子切换。
所以整体上,我不会追求单一方案最优,而是根据场景做取舍。比如客服场景,我会更看重延迟,把简单查询走缓存,复杂查询走RAG;而风控合同场景,我会更看重精度,哪怕多花点时间。最后,我始终认为RAG不是一个孤立的组件,它和 Prompt 设计、模型选择、甚至微调策略都要协同考虑。