概述

在 RAG(检索增强生成)系统中,一个挥之不去的痛点始终困扰着我们:检索结果的质量是不可预知的。即便配置了最先进的检索引擎、最精密的匹配算法,依然无法保证每一次检索都能命中用户真正需要的内容。用户的提问千变万化——同样的操作需求可能被表述为十几种不同的问法,而知识库的覆盖范围永远追不上业务的演进速度。

传统的 RAG 系统采取的是"检完即答"的单向流水线模式:检索 → 生成 → 返回,全程没有任何质量反馈回路。这就好比一个厨师只管把菜端上桌,却从不关心菜好不好吃、客人满不满意。

为了解决这个问题,我们在智能问答系统中设计了一套 Agentic RAG 质量自检与自适应重试机制。它不是一个新的检索算法,而是一个架设在现有检索管线之上的元控制层——它监控每一次检索的质量,并在质量不达标时自动采取纠错措施,直到找到满意的答案或耗尽所有尝试路径。

本文将从系统架构出发,完整拆解这一机制的设计原理与实现细节。


一、系统架构概览

Agentic RAG 机制的核心思想是:将检索从"一次性操作"升级为"多轮自适应过程"。当 AGENTIC_MODE=true 时,系统激活这条带质量反馈回路的增强型检索管线:

用户问题
    │
    ▼
┌───────────────────────────────────────┐
│  Phase 1: 初始检索 + 质量评估          │
│    ├── 执行标准检索流程                 │
│    ├── 调用 LLM 质量评估(1-10分)      │
│    ├── >= 阈值 → 直接返回 ✓             │
│    └── < 阈值 → 进入下一阶段            │
├───────────────────────────────────────┤
│  Phase 1.5: 多意图检测与拆分(可选)    │
│    ├── 检测问题是否包含多个独立子问题    │
│    ├── 拆分后分别检索 → 合成答案         │
│    └── 合成后再次评估                   │
├───────────────────────────────────────┤
│  Phase 1.7: 递归分解(可选)            │
│    ├── 评估答案完整性、正确性            │
│    ├── 不完整 → 生成追问 → 继续检索      │
│    └── 迭代至完整或达到最大深度          │
├───────────────────────────────────────┤
│  Phase 2: 自适应重试循环               │
│    ├── 切换检索模式(navigate→index→direct)│
│    ├── 切换匹配模式(ensemble→hybrid→bm25)│
│    ├── 改写查询(从不同角度重写)         │
│    └── 质量评估 → 保留最佳结果           │
├───────────────────────────────────────┤
│  Phase 3: 网络搜索兜底(可选)          │
│    ├── Tavily / Bocha 双提供商支持      │
│    └── LLM 综合搜索结果                 │
├───────────────────────────────────────┤
│  输出最佳结果                           │
└───────────────────────────────────────┘

整个管线的核心状态由 AgenticState 类统一管理:

@dataclass
class AgenticState:
    original_question: str          # 用户原始问题
    attempt: int = 0                # 当前重试轮次
    max_retries: int = 3            # 最大重试次数
    quality_threshold: float = 7.0  # 质量合格阈值
    strategies_tried: list = None   # 已尝试策略列表
    quality_scores: list = None     # 历史质量评分
    best_result: str = None         # 最佳结果
    best_score: float = 0.0         # 最佳评分
    used_web_search: bool = False   # 是否使用了网络搜索

二、Phase 1: 初始检索与质量评估

这是 Agentic RAG 流程的起点。当用户问题到达时,系统首先执行一次标准检索——使用当前配置的检索模式(navigate/index/direct)和匹配模式(ensemble/hybrid/bm25/vector/gram)进行常规检索。

但与传统 RAG 不同的是,检索结果不会立即送入生成环节,而是先进入质量评估关卡

2.1 质量评估机制(assess_quality)

质量评估是整个 Agentic RAG 系统的核心决策节点。它的设计哲学是:宁可多花一轮 Token,也不把低质量答案交给用户

评估逻辑分为两条路径:

路径一:空结果快速判定
如果检索结果为空(没有找到任何相关内容),系统直接返回评分 1.0(满分 10 分制下的最低分),并注明原因是"未找到相关内容"。这是一个重要的短路优化——结果为空意味着再努力也是徒劳,直接触发后续的重试或网络搜索兜底更为高效。

路径二:LLM 深度评估
当检索结果非空时,系统调用 LLM 对结果进行深度质量评估。评估遵循一套精心设计的提示词模板,从以下维度打分:

评估维度 说明 权重建议
相关性 结果是否与用户问题密切相关
完整性 结果是否完整覆盖了问题的各个层面
准确性 结果中的信息是否准确无误
时效性 结果是否是最新的、非过时的
可操作性 如果是操作步骤,是否清晰可执行

LLM 评估的 Prompt 包含两个部分:

  • AGENTIC_QUALITY_SYSTEM:系统级指令,定义评估角色、评分标准和输出格式
  • AGENTIC_QUALITY_PROMPT:任务级指令,包含用户问题、检索结果和评分要求

评估完成后,LLM 返回一个结构化的结果,包含:

  • overall:综合评分(1-10 的浮点数)
  • reason:详细的评分理由

2.2 质量关卡决策

评估结果
    │
    ├── score >= quality_threshold(默认 7.0)
    │   └── ✓ 质量合格 → 直接返回结果
    │
    └── score < quality_threshold
        ├── attempt < max_retries
        │   └── → 进入 Phase 2 重试循环
        └── attempt >= max_retries
            └── → 返回当前最佳结果或进入 Phase 3

每一次质量评估的结果都会被记录到 state.quality_scores 列表中,形成一条完整的历史评分曲线。这条曲线对于后续的调试和监控非常有价值——你可以清楚地看到每次重试是否真正改善了结果质量。


三、Phase 1.5: 多意图检测与拆分

在实际的客服场景中,用户常常在一个问题中混杂多个意图。例如:“如何创建工单订单?以及如何修改供应商信息?”——这是两个完全独立的操作步骤,如果作为一个整体去检索,很可能两个都答不好。

decomposer.detect_multi_intent 模块负责在这一阶段对问题进行检测和拆分:

"如何创建工单订单?修改供应商信息呢?"
    │
    ▼
┌──────────────────────────┐
│  多意图检测               │
│  ─────────────────────    │
│  检测到 2 个独立子问题     │
└──────────────────────────┘
    │
    ├── 子问题 1: "如何创建工单订单?"
    │   └── 独立检索 → 结果 A
    │
    ├── 子问题 2: "如何修改供应商信息?"
    │   └── 独立检索 → 结果 B
    │
    ▼
答案合成 → 将 A 和 B 组合为统一回答 → 再次质量评估

拆分后再合成的答案,由于每个子问题都得到了针对性检索,整体质量通常远高于"一把抓"的方式。

3.1 递归分解(Phase 1.7)

除了横向的多意图拆分,系统还支持纵向的递归分解。当 LLM 评估发现答案不完整时(比如只回答了"如何操作"但缺少"前置条件"),系统会:

  1. 由 LLM 判断答案的完整性缺口
  2. 自动生成一个补充性追问(例如:“用户需要先开通什么权限?”)
  3. 以追问为查询进行二次检索
  4. 将新结果与原结果合成
  5. 再次评估,迭代至满意或达到最大递归深度

这个机制特别适合"连锁型"知识场景——比如回答"如何退货"时,用户可能还需要知道"退款时效"和"运费承担"等关联信息。


四、Phase 2: 自适应重试循环(核心机制)

当 Phase 1 的质量评估不达标时,系统进入自适应重试循环。这是整个 Agentic RAG 最具工程特色的一环。

4.1 策略选择器(_pick_strategy)

重试的核心问题在于:当一种检索方式失败时,应该尝试什么样的新方式? 系统采用了一种轮询调度的策略选择机制:

def _pick_strategy(state, config):
    """根据当前重试轮次选择下一个策略"""
    attempt = state.attempt
    
    # 轮询三种策略类型
    strategies = [
        # Phase 1: 切换检索模式
        lambda: switch_mode(state, config.AGENTIC_FALLBACK_MODES),
        # Phase 2: 切换匹配算法
        lambda: switch_matcher(state, config.AGENTIC_FALLBACK_MATCHERS),
        # Phase 3: 改写查询
        lambda: rewrite_query_agentic(state, config),
    ]
    
    strategy = strategies[attempt % len(strategies)]
    return strategy()

具体策略的切换序列如下:

重试轮次 策略类型 具体动作
第 1 轮 切换检索模式 navigate → index → direct(按配置顺序轮换)
第 2 轮 切换匹配模式 ensemble → hybrid → bm25 → vector → gram
第 3 轮 改写查询 根据已尝试策略生成新角度查询
第 4+ 轮 循环以上三类 每三轮一个完整周期

这种设计的精妙之处在于:它不是一个盲目的随机重试,而是一个有方向、有层次的系统性尝试——从改变检索策略(广度),到改变匹配算法(精度),再到改变问题表述(角度),层层递进。

4.2 检索模式切换

AGENTIC_FALLBACK_MODES 配置项定义了在重试时依次尝试的检索模式列表。默认顺序是:

direct → navigate → index

不同的检索模式在 Token 消耗和召回广度上各有取舍:

模式 Token 消耗 召回覆盖 适用场景
navigate 省 ~60% 中等 默认推荐,性价比最高
index 中等 最广(BM25+向量+Ensemble) 大量文档需要粗筛
direct 最大(~50K/次) 最高精度 文档 < 200KB,追求极致精度

当 navigate 模式因导航不准确导致漏召回时,切换到 index 模式可以利用多算法粗筛扩大召回;当 index 模式因粗筛噪声过大导致误召回时,切换到 direct 模式可以拿到最精确的原文。

4.3 匹配模式切换

AGENTIC_FALLBACK_MATCHERS 配置项定义了在重试时依次尝试的匹配算法列表。默认顺序是:

ensemble → hybrid → bm25 → vector → gram

每种匹配算法有不同的"视野":

  • ensemble:三路全开(gram + bm25 + vector),最大召回
  • hybrid:BM25 + 向量加权,兼顾精确和语义
  • bm25:关键词精准匹配,适合有明确术语的查询
  • vector:语义相似度匹配,适合表述不同但含义相同的查询
  • gram:2-gram 滑动窗口,最轻量的精确匹配

4.4 改写查询(rewrite_query_agentic)

当切换模式和算法都无法提升质量时,问题可能出在查询表述本身——用户的提问方式与知识库的文档表述存在语义鸿沟。

rewrite_query_agentic 函数负责根据已尝试过的策略和历史评分,生成一个全新的查询角度。它通过 LLM 实现以下逻辑:

输入: 用户原始问题 + 已尝试的策略 + 检索结果质量评分
    │
    ▼
LLM 分析:
    "- 之前用的查询是 A,但没有找到相关内容"
    "- 可能的原因是:使用了错误的行业术语"
    "- 建议尝试:用更通用的描述重新表达"
    │
    ▼
输出: "如何在我的账户中添加一个新的供应商条目?"
        ↑ 原来问的是 "供应商新增怎么操作"

改写查询的核心优势在于:它不是一个固定的改写模板,而是基于失败经验的动态改写。每一次失败都为下一次尝试提供了信息增量。


五、Phase 3: 网络搜索兜底

当知识库检索的三种尝试路径(切换模式、切换匹配、改写查询)全部耗尽,或者初始质量评分极低(空结果等极端情况)时,系统进入最后的兜底方案——网络搜索

5.1 双提供商架构

网络搜索功能由 web_search.py 模块实现,支持两个搜索提供商:

提供商 特点 适用场景
Tavily 专为 AI Agent 优化的搜索 API 默认推荐,结构化结果好
Bocha(博查) 中文搜索引擎 API 中文查询效果更佳

双提供商通过一个统一接口封装,通过配置项 AGENTIC_WEB_SEARCH_PROVIDER 切换:

if provider == 'tavily':
    results = tavily_search(query)
elif provider == 'bocha':
    results = bocha_search(query)

5.2 开关控制

网络搜索兜底并非默认开启,它由 AGENTIC_WEB_SEARCH_ENABLED 开关控制。之所以设计为可配置,是因为:

  • 企业内部场景:很多操作知识是私有的、未公开的,网络搜索无法找到相关内容,只会浪费 Token
  • 安全合规:某些场景下不允许将内部问题发送到外部 API
  • 成本控制:外部搜索服务会产生额外费用

5.3 结果综合

网络搜索的结果不会直接返回给用户。系统会:

  1. 将网络搜索结果作为上下文,喂给 LLM
  2. LLM 综合分析搜索结果的可靠性和相关性
  3. 生成包含来源标注的答案
  4. 在结果中标记 used_web_search=true,方便后续追踪

六、结果终态与日志

6.1 终态判断(_finalize)

当以下任一条件满足时,系统进入终态返回流程:

  1. 质量达标:当前轮次的评分 >= quality_threshold
  2. 重试耗尽attempt >= max_retries,所有策略都已尝试
  3. 网络搜索完成:Phase 3 执行完毕

_finalize 函数中,系统会做两件重要的事情:

清除消歧追问字段:如果质量达标,意味着问题已经得到了充分解答,之前可能存在的模糊追问(宽泛问题提示等)应该被清除,不让它们出现在最终输出中。

汇总日志:将本次 Agentic RAG 的完整流程记录到日志中,包括:

  • 初始检索结果评分
  • 多意图拆分记录(如有)
  • 每一次重试的策略和评分
  • 最终结果和最佳评分
  • 是否启用了网络搜索
  • 总耗时和 Token 消耗

6.2 失败时的最优解

当所有重试耗尽且质量始终不达标时,系统不会返回空结果。它会从 state.quality_scores 中找出最高评分对应的 state.best_result,作为当前条件下的最优解返回。这体现了"有总比没有好"的设计哲学——即便答案不够完美,也要给用户一个可参考的方向。


七、配置体系

Agentic RAG 的所有行为均可通过配置项进行精细控制,以下是完整的配置体系:

7.1 核心开关

配置项 类型 默认值 说明
AGENTIC_MODE bool false 全局开关,关闭时使用标准检索
AGENTIC_MAX_RETRIES int 3 最大重试次数
AGENTIC_QUALITY_THRESHOLD float 7.0 质量合格阈值(1-10)

7.2 策略配置

配置项 类型 默认值 说明
AGENTIC_FALLBACK_MODES list [‘direct’, ‘navigate’, ‘index’] 重试时轮询的检索模式列表
AGENTIC_FALLBACK_MATCHERS list [‘ensemble’, ‘hybrid’, ‘bm25’, ‘vector’, ‘gram’] 重试时轮询的匹配算法列表

7.3 网络搜索配置

配置项 类型 默认值 说明
AGENTIC_WEB_SEARCH_ENABLED bool false 是否启用网络搜索兜底
AGENTIC_WEB_SEARCH_PROVIDER str ‘tavily’ 搜索提供商:tavily / bocha

7.4 配置调优建议

根据实际运行经验,我们总结了几组典型的配置组合:

场景一:精度优先(客服场景推荐)

AGENTIC_MODE=true
AGENTIC_MAX_RETRIES=3
AGENTIC_QUALITY_THRESHOLD=8.0
AGENTIC_FALLBACK_MODES=navigate,index,direct
AGENTIC_FALLBACK_MATCHERS=ensemble,hybrid,bm25,vector,gram
AGENTIC_WEB_SEARCH_ENABLED=false

特点:严格的质量把控,充分的重试策略,但不依赖外部搜索。适合企业内部知识库问答,所有答案都必须来源于内部文档。

场景二:速度优先(高频低延迟场景)

AGENTIC_MODE=true
AGENTIC_MAX_RETRIES=1
AGENTIC_QUALITY_THRESHOLD=6.0
AGENTIC_FALLBACK_MODES=direct
AGENTIC_WEB_SEARCH_ENABLED=false

特点:仅做一次重试兜底,质量阈值放宽到 6.0。适合对响应速度要求极高的场景。

场景三:全覆盖(公开知识问答)

AGENTIC_MODE=true
AGENTIC_MAX_RETRIES=4
AGENTIC_QUALITY_THRESHOLD=7.0
AGENTIC_FALLBACK_MODES=navigate,index,direct
AGENTIC_FALLBACK_MATCHERS=ensemble,hybrid,bm25,vector,gram
AGENTIC_WEB_SEARCH_ENABLED=true
AGENTIC_WEB_SEARCH_PROVIDER=bocha

特点:启用网络搜索兜底,使用中文优化提供商 Bocha。适合需要最大覆盖面的公开领域问答。


八、总结

Agentic RAG 质量自检与自适应重试机制,是对传统 RAG "检完即答"模式的一次系统性升级。它的核心思想可以概括为三个层次:

  1. 可测量:每次检索结果都要经过 LLM 质量评估,量化回答质量
  2. 可调节:当质量不达标时,不是简单重试一次,而是从检索模式、匹配算法、查询表述三个维度进行系统性切换
  3. 可兜底:当内部知识库无法满足需求时,通过网络搜索提供最后的保障

这套机制在某个智能问答系统的实际运行中表现出了显著的成效:

  • 首次查询满意度提升了约 35%(质量评估把关)
  • 多意图问题覆盖率提升了约 50%(拆分机制)
  • 最终回答有答案率从 82% 提升到 97%(重试+网络搜索兜底)

当然,Agentic RAG 并非没有代价。每一次重试都意味着额外的 Token 消耗和响应延迟。我们的经验法则是:将阈值设定在"大多数正常查询可以通过,少数边缘情况触发重试"的水平——既避免了大多数场景的额外开销,又保证了边缘情况下的兜底能力。

在下一篇文章中,我们将探讨智能问答系统的另一大核心能力——渐进式追问机制,看系统如何在信息不足时主动引导用户提供更多上下文,从而在不依赖复杂重试的情况下从根本上提升检索质量。


本文所属系列:智能客服问答系统(FrequentlyAskedQuestions)架构深度解析

系列文章:

  • 01: Agent 记忆分层设计实践
  • 02: 多策略路由的智能客服系统设计
  • 03: 五种检索引擎与混合匹配架构
  • 04: Agentic RAG 质量自检与自适应重试(本文)
  • 05: 渐进式追问与模糊消歧(预告)
  • 06: 结构化日志与全链路可观测性(预告)
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐