跳到主要内容

文档导航路由与执行模式判定

上一篇讲完了 AUTO_DOCUMENT 模式的路由追踪记录,这一篇我们来看 prepare 方法的最后一个大环节——文档导航路由,也就是 documentQuestionRouter.route(...) 这个调用。

这一步解决的问题不是"答案是什么",而是"为了得到答案,后面应该走哪种检索策略"。

调用入口

在文档范围(routedDocumentId)确定之后,代码紧接着就进入了执行模式的判定:

// 在文档范围已经确定后,再继续判定最终执行模式:结构图直答、结构图取证还是普通混合检索。
ConversationTraceRecorder.StageHandle routeStage = traceRecorder == null
? null
: traceRecorder.startStage(ConversationTraceStageCode.ROUTE, ExecutionMode.RETRIEVAL.name(), "正在判定图查询还是混合检索。", null);
DocumentNavigationDecision navigationDecision;
try {
navigationDecision = documentQuestionRouter.route(routedDocumentId, question, rewriteResult);
if (traceRecorder != null) {
// 记录最终执行模式、目标章节提示、目标条目和导航摘要,便于调试结构图路由效果。
traceRecorder.completeStage(routeStage, "执行路由完成。", java.util.Map.of(
"executionMode", navigationDecision == null || navigationDecision.getExecutionMode() == null ? "" : navigationDecision.getExecutionMode().name(),
"targetSectionHint", navigationDecision == null || navigationDecision.getStructureAnchor() == null ? "" : StrUtil.blankToDefault(navigationDecision.getStructureAnchor().getTargetSectionHint(), ""),
"targetItemIndex", navigationDecision == null || navigationDecision.getItemAnchor() == null || navigationDecision.getItemAnchor().getItemIndex() == null
? ""
: String.valueOf(navigationDecision.getItemAnchor().getItemIndex()),
"navigationSummary", navigationDecision == null ? "" : StrUtil.blankToDefault(navigationDecision.getSummaryText(), "")
));
}
}
catch (RuntimeException exception) {
if (traceRecorder != null) {
traceRecorder.failStage(routeStage, "执行路由失败。", exception.getMessage(), null);
}
throw exception;
}

这段代码做了三件事:

  1. 开启一个追踪阶段(startStage),标记"正在判定图查询还是混合检索"
  2. 调用 documentQuestionRouter.route(...) 得到导航决策
  3. 把决策结果(执行模式、目标章节、条目索引、摘要)写入追踪记录
注意

这里用了 try/catch 包裹,如果路由过程抛出异常,会先把失败信息写入追踪,再重新抛出。这样即使出错,追踪系统里也有完整的失败记录,方便排查。

route 方法的整体逻辑

进入 DocumentQuestionRouter.route(...) 方法:

public DocumentNavigationDecision route(Long documentId,
String originalQuestion,
RagRewriteResult rewriteResult) {
// 优先使用改写后的问题作为后续导航和检索的主问题;若没有改写结果,则退回原问题。
String rewrittenQuestion = firstNonBlank(
rewriteResult == null ? "" : rewriteResult.getRewrittenQuestion(),
originalQuestion
);
// 子问题列表会作为 retrievalPlan 的一部分保留下来,供后续检索引擎逐个取证。
List<String> subQuestions = normalizeSubQuestions(rewriteResult, rewrittenQuestion);
RetrievalQuestionPlan retrievalPlan = new RetrievalQuestionPlan(rewrittenQuestion, subQuestions);

// routeText 同时保留原问题和改写问题,兼顾用户原始措辞与改写后的清晰结构表达。
String routeText = (safeText(originalQuestion) + " " + rewrittenQuestion).trim();

// 分析型问题通常不适合直接走结构图直答,因为它们往往需要正文证据或综合解释。
boolean analyticQuestion = looksAnalyticQuestion(routeText);
...
}

付费内容提示

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

加入星球后,你可以获得:

  • 超级八股文:100万+字的全栈技术知识库,涵盖技术核心、数据库、中间件、分布式等深度剖析的讲解
  • 讲解文档:超级AI智能体、黑马点评Plus、大麦、大麦pro、大麦AI、流量切换、数据中台的从0到1的详细文档
  • 讲解视频:超级AI智能体、黑马点评Plus、大麦、大麦pro、大麦AI、流量切换、数据中台的核心业务详细讲解
  • 1 对 1 解答:可以对我进行1对1的问题提问,而不仅仅只限于项目
  • 针对性服务:有没理解的地方,文档或者视频还没有讲到可以提出,本人会补充
  • 面试与简历指导:提供面试回答技巧,项目怎样写才能在简历中具有独特的亮点
  • 中间件环境:对于项目中需要使用的中间件,可直接替换成我提供的云环境
  • 面试后复盘:小伙伴去面试后,如果哪里被面试官问住了,可以再找我解答
  • 远程的解决:如果在启动项目遇到问题,本人可以帮你远程解决
进入星球后,即可享受上述所有服务,保证不会再有其他隐藏费用。
知识星球二维码

1. 打开微信 -> 扫描左侧二维码 -> 加入「JavaUp项目实战&技术讲解」知识星球

2. 查看星球使用指导,获取完整项目讲解资料索引

👉 点击解锁全部付费内容
🎁优惠