跳到主要内容

章节解析三层策略与导航决策构建

上一篇讲了三种执行模式的判定,这一篇来深入看 resolveSection 是怎么定位章节的,以及最终的导航决策对象是怎么构建出来的。

resolveSection:章节解析总入口

不管是哪种执行模式,只要需要定位章节,都会走 resolveSection 这个方法:

/**
* 解析问题对应的目标章节。
* 这是“章节解析总入口”,但它自己并不做具体匹配,而是按可靠性从高到低依次尝试三种实现路径:
*
* 1. `resolveBySectionCode(...)`
* 如果问题里显式出现了类似 `1.2.3` 这样的章节编号,就按编号直接精确查找;
* 这是最强、最可靠的结构信号。
*
* 2. `resolveByNavigationIndex(...)`
* 如果没有显式章节编号,就走专门的导航索引检索;
* 这一步适合处理“开户流程属于哪个章节”“异常处理在哪一节”之类的结构语义问题。
*
* 3. `resolveByLocalStructure(...)`
* 如果索引也没有命中,就退回到本地章节树做模糊文本匹配;
* 这一步更像“弱结构兜底”,通过短语和章节标题/路径/正文去估计最可能的章节。
*
* 如果以上三条路径都没有稳定命中,则最后退回到 `graphService.findBestSection(...)` 做 best effort 兜底。
*
* @param documentId 文档 id
* @param originalQuestion 原始问题
* @param rewrittenQuestion 改写问题
* @return 命中的章节;若无法稳定定位,则返回兜底章节或 null
*/
private GraphSection resolveSection(Long documentId, String originalQuestion, String rewrittenQuestion) {
if (documentId == null) {
// 没有文档 id 时,不存在结构图可定位的前提条件。
return null;
}
// 第一层:显式章节编号命中最可靠,因此优先尝试。
GraphSection byCode = resolveBySectionCode(documentId, originalQuestion, rewrittenQuestion);
if (byCode != null) {
return byCode;
}

// 第二层:如果没有显式编号,再尝试走导航索引。
GraphSection indexedMatch = resolveByNavigationIndex(documentId, originalQuestion, rewrittenQuestion);
if (indexedMatch != null) {
return indexedMatch;
}

// 第三层:再退回到本地结构字段模糊匹配。
List<String> phrases = buildSectionPhrases(originalQuestion, rewrittenQuestion);
GraphSection localMatch = resolveByLocalStructure(documentId, phrases);
if (localMatch != null) {
return localMatch;
}
// 最后让 graphService 自己给一个 best effort 的章节兜底结果。
return graphService.findBestSection(documentId, rewrittenQuestion, "");
}

这是一个典型的"可靠性从高到低依次降级"的策略,一共四层:

层级方法适用场景可靠性
第一层resolveBySectionCode问题里有"1.2.3"这类章节编号最高
第二层resolveByNavigationIndex带结构语义但没有显式编号较高
第三层resolveByLocalStructure前两层都没命中一般
兜底graphService.findBestSection全部失败时的最后保障

第一层:显式章节编号精确命中

/**
* 第一种实现:尝试从问题中直接解析章节编号。
* 适合处理类似下面这种问题:
* 1. “1.2.3 章节讲了什么”
* 2. “3.1.4 这一节属于哪个模块”
* 3. “在 2.4 节里提到的步骤是什么”
*
* 这类问题最大的特点是:用户已经显式给出了章节 code,
* 因此不需要再做语义猜测,直接按编号查图结构是最稳的。
*
* @param documentId 文档 id
* @param originalQuestion 原始问题
* @param rewrittenQuestion 改写问题
* @return 命中的章节;若没有显式章节编号则返回 null
*/
private GraphSection resolveBySectionCode(Long documentId, String originalQuestion, String rewrittenQuestion) {
Matcher matcher = SECTION_CODE_PATTERN.matcher((safeText(originalQuestion) + " " + safeText(rewrittenQuestion)).trim());
while (matcher.find()) {
// 只要问题里出现像“1.2.3”这样的章节编号,就直接按编号精确查找。
// 这里同时扫描原问题与改写问题,避免改写阶段补出的结构编号被漏掉。
GraphSection section = graphService.findSectionByCode(documentId, matcher.group(1));
if (section != null) {
return section;
}
}
return null;
}

付费内容提示

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

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

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. 查看星球使用指导,获取完整项目讲解资料索引
解锁全部付费内容
🎁优惠