跳到主要内容

执行器注册表与模式分发机制

在之前的文档中用了很多篇幅把 BusinessChatService#prepareExecutionPlan 给讲解完毕了,接下来依旧还是在 BusinessChatService#buildConversationExecution 中,再回顾下此方法的流程

buildConversationExecution

/**
* 构建完整的会话执行流。
* 执行顺序大致为:发送思考提示 -> 准备执行计划 -> 选择执行器 -> 消费执行器输出 -> 成功/失败收尾。
*
* @param taskInfo 当前任务
* @return 真正驱动模型输出的执行流
*/
private Flux<String> buildConversationExecution(TaskInfo taskInfo) {
return Flux.defer(() -> {

// 在真正出字前先给前端一个可见状态,减少用户等待时的空白感。
safeEmit(taskInfo.sink(), streamEventWriter.thinking("正在分析问题上下文。", taskInfo.eventMetadata()));

// 执行计划的准备可能包含检索、摘要、编排等阻塞操作,因此切到弹性线程池执行。
return Mono.fromCallable(() -> prepareExecutionPlan(taskInfo))
.subscribeOn(Schedulers.boundedElastic())
.flatMapMany(plan -> {

// 根据执行模式选择对应执行器,例如澄清、开放问答、文档问答等不同路径。
ConversationExecutor executor = conversationExecutorRegistry.get(plan.getMode());
return executor.execute(taskInfo);
});
})
.publishOn(Schedulers.boundedElastic())

// 每收到一段模型输出,就实时累计答案并向前端推送,形成流式体验。
.doOnNext(chunk -> emitModelChunk(taskInfo, chunk))

// 统一把异常收敛到失败收尾逻辑,确保状态落库和资源释放不会漏掉。
.doOnError(error -> finishWithFailure(taskInfo, error))

// 执行流自然结束时走成功态收尾逻辑,例如补发引用、推荐问题和最终归档。
.doOnComplete(() -> finishSuccessfully(taskInfo));
}

这段代码做了四件事:

  1. 发送 thinking 状态——先告诉前端"我正在分析",避免用户看到一片空白
  2. 准备执行计划——prepareExecutionPlan(taskInfo) 会完成问题改写、历史压缩、模式判定等一系列准备工作,用了大量的篇幅进行了讲解
  3. 选择并执行执行器——这就是我们要本章节重点要看的内容
  4. 挂载收尾逻辑——不管成功还是失败,都会有对应的收尾处理

这篇就来拆解这个过程:系统是怎么根据不同的问答模式,把请求分发到不同执行器上的?当你在前端选了"当前文档问答"并指定了某个文档,为什么最终会走到 RagChatExecutorexecute 方法?

其中最关键的就是这两行:

ConversationExecutor executor = conversationExecutorRegistry.get(plan.getMode());
return executor.execute(taskInfo);

第一行从注册表里根据执行模式拿到对应的执行器实例,第二行调用执行器的 execute 方法开始真正的问答流程。

要理解这个过程,我们需要搞清楚三个东西:ExecutionMode 枚举有哪些模式?ConversationExecutor 接口长什么样?ConversationExecutorRegistry 是怎么把它们串起来的?

ExecutionMode:执行模式枚举

public enum ExecutionMode {

/**
* 结构图直答模式。
*
* <p>适用于用户只问文档结构关系的问题,例如“这个章节包含哪些小节”、“上一节/下一节是什么”、
* “某章节属于哪个父章节”。该模式通常由 {@code GraphOnlyExecutor} 执行,只查询结构图中的章节、
* 父子关系或兄弟关系,不再进入向量/关键词证据检索,也不调用大模型生成长答案。</p>
*/
GRAPH_ONLY,

/**
* 结构图定位后取证模式。
*
* <p>适用于问题需要先通过结构图定位章节,再读取章节正文或编号项证据的场景,例如“某章节第 3 步是什么”、
* “哪一步要求执行某个动作”。该模式由 {@code GraphThenEvidenceExecutor} 执行,会先根据导航锚点找到
* 目标章节,再在章节树内递归查找 item、关键词命中的步骤或章节正文,最后把结构化证据渲染成回答。</p>
*/
GRAPH_THEN_EVIDENCE,

/**
* 普通知识库检索问答模式。
*
* <p>适用于大多数需要基于知识文档内容回答的问题。该模式由 {@code RagChatExecutor} 执行,会根据规划阶段
* 得到的检索问题、子问题、文档范围,走向量检索、关键词检索、RRF 融合、父块提升、可选 rerank、Prompt
* 预算组装,然后调用模型基于证据流式生成答案。</p>
*/
RETRIEVAL,

/**
* 开放式 ReAct Agent 模式。
*
* <p>适用于固定 RAG 或结构图路径无法覆盖的问题,或者需要 Agent 自主判断是否调用工具的场景。
* 该模式由 {@code ReactAgentExecutor} 执行,会把规划后的 agentQuestion 交给 ReAct Agent,
* 由 Agent 自主进行推理、工具调用和最终回答输出。</p>
*/
REACT_AGENT,

/**
* 澄清模式。
*
* <p>适用于路由阶段发现候选文档、知识范围或用户意图存在歧义,暂时不能稳定选择某个执行路径的场景。
* 该模式由 {@code ClarificationExecutor} 执行,不进行检索或模型生成,而是直接返回澄清问题,
* 引导用户补充更明确的文档名、主题或关键词。</p>
*/
CLARIFICATION,

/**
* 旧版 RAG 对话模式。
*
* <p>该枚举值已废弃,保留它主要是为了兼容历史数据、历史配置或旧路由结果。新的普通知识库问答应使用
* {@link #RETRIEVAL},不要再为新逻辑依赖该模式。</p>
*/
@Deprecated
RAG_CHAT
}

每个枚举值代表一种不同的问答路径:

模式说明
RETRIEVAL知识检索问答,标准的 RAG 路径,先检索文档再基于证据回答
GRAPH_ONLY仅用结构图直接回答,不需要文档检索
GRAPH_THEN_EVIDENCE先用结构图定位,再取证补充
REACT_AGENTReAct Agent 自主执行,可以调用工具
CLARIFICATION路由歧义时向用户发起澄清
RAG_CHAT已废弃的旧模式
重点

当用户在前端选择 "当前文档问答" 模式时,前置编排阶段(prepareExecutionPlan)会把执行计划的 mode 设为 ExecutionMode.RETRIEVAL。这个值决定了后续会走到哪个执行器。

付费内容提示

该文档的全部内容仅对「码力全开」项目实战&技术讲解 知识星球用户开放

加入星球,一次获得完整项目资料、全栈技术知识库和长期答疑服务。

100万+字全栈技术知识库深入讲解技术核心、数据库、中间件和分布式等内容
8套热门的实战项目持续更新的企业级项目覆盖高并发、微服务、数据中台 和 AI Agent 等方向
AI 技术知识大模型面试详解覆盖 AI 模型原理、Agent、RAG、MCP、Skills、Harness 等核心知识点
文档 + 视频两种讲解形式既能系统阅读,也能跟随视频理解核心业务

完整项目实战资料

每套项目均包含从 0 到 1 讲解文档核心业务讲解视频

从基础项目到复杂业务场景,项目资料会持续更新。

8 套项目
  • 01Nexus Agent AI 智能体
  • 02Nexus Agent Pro 完全版
  • 03黑马点评Plus
  • 04大麦
  • 05大麦Pro
  • 06大麦AI
  • 07流量切换
  • 08数据中台

加入后还能获得

进入星球后,即可享受上述所有服务,保证不会再有其他隐藏费用。

从学习、面试到项目启动,都可以继续获得支持。

  • 1 对 1 解答项目和技术问题都可以提问
  • 针对性补充没有讲清楚的内容会继续补充
  • 面试与简历指导梳理回答技巧和项目亮点
  • 中间件云环境项目依赖可以直接接入使用
  • 面试后复盘被问住的问题可以继续交流
  • 远程问题解决项目启动问题可协助排查
知识星球二维码

扫码进入知识星球

  1. 打开微信,扫描左侧二维码,加入「码力全开」项目实战&技术讲解 知识星球
  2. 查看星球使用指导,获取完整项目讲解资料索引
解锁全部付费内容
🎁优惠