文章

RAG Agent 的正确打开方式:让检索成为推理的一部分

RAG 接进 Agent 后,检索会变成一个反复补证据的过程。切块、过滤、引用和拒答都要落到具体规则上。

“文档切块,放进向量库,召回几段文字,再交给模型回答。”这是最常见的 RAG 入门做法,回答一条制度写在哪儿,往往够用。

问题稍微复杂一点就不够了。比如用户问:“今年华东地区哪些客户的续约风险最高,依据是什么?”系统要处理时间、地域、客户和风险口径,证据还可能散在合同、跟进记录和评分规则里。一次相似度搜索很难把这些东西凑齐。

检索要跑几轮

RAG Agent 会先列出要找的证据,再决定查询词和过滤条件。结果不够,就改一次查询;遇到表格或业务数据,换结构化工具查。流程可能长这样:

识别问题类型
  -> 拆出时间、主体、指标等约束
  -> 生成一个或多个检索计划
  -> 混合召回并重排
  -> 检查证据覆盖和冲突
  -> 必要时补充检索
  -> 带引用生成答案

模型仍然负责理解问题,但每轮检索都留下查询、过滤器和命中文档。这样至少能查出错误发生在哪一轮。

入库时别只盯着 chunk 大小

切块不能只按 500 字、800 字硬截。制度标题、章节、表格行和适用范围最好跟内容一起保留。每个块还要带文档 ID、版本、生效时间、组织或地域、章节路径和访问权限。少了这些字段,后面很难回答“今年”“华东”“企业客户”这类带限制的问题。

向量检索找语义相近的段落,关键词检索找产品名、编号和专有名词,元数据负责卡住时间与权限。三种方式可以混合召回,再做一次重排。只用向量库,常见结果是“意思很像,版本不对”。

我还会保留块和章节的父子关系。先用小块命中答案,再带回它前后的一小段章节上下文。整份 PDF 塞进模型很痛快,成本和噪声也一起进去了。

先问“缺哪份证据”

续约风险这个问题至少缺三份材料:客户合同与续约状态、风险评分规则、评分依赖的行为数据。只搜“续约风险”,很可能得到一堆解释文章,具体客户却一个都没有。

每轮检索后做一次很朴素的检查:

  • 问题中的实体和时间范围覆盖了吗?
  • 证据来自哪个版本,生效区间能对上吗?
  • 两个来源有没有互相冲突?
  • 结果只是语义相近,还是确实带有所需字段?

没覆盖就继续查,或者向用户问清楚。两份制度互相冲突时,把版本和来源都摆出来。这里不需要模型挑一份“看起来更合理”的替用户做决定。

引用必须能回到原文

“来源:内部知识库”没法复核。关键结论应该带文档 ID、章节、页码,或者能打开的原文片段。生成答案前,可以先让模型交一份很短的中间结果:

{
  "claim": "退款申请需在签收后 7 日内提交",
  "evidence": ["policy-2026-03#refund-window"]
}

程序检查 evidence 是否存在、当前用户能否访问,再把它渲染成引用。文档更新后,也能顺着这个编号找到哪些答案需要重跑。

找不到就写“没找到”

拒答要有规则。关键结论至少对应一个仍在生效的权威来源;金额、日期和资格条件必须同时命中实体与时间过滤。没达到门槛,就返回已经找到的部分和缺少的字段。

回答里最好把“文档明确写了”“根据资料推断”“资料中没找到”分开。三种说法混在一起,引用再多也救不了。

最后怎么测

上线前准备六类题:单跳、多跳、旧版本、权限隔离、来源冲突、确实无答案。每道题都标出标准证据的位置,并保存实际查询和召回结果。

如果答案错了,先查正确文档有没有进候选集。没有,修切块和召回;进了候选集却没被采用,再看重排和生成。把所有错误都归成“模型幻觉”,后面基本无从下手。