多跳问题识别与递归检索方案
项目地址:https://github.com/WiSiW/AI-RAG
摘要
在查询改写之后、正式混合检索之前加入分层复杂度判定:规则特征 → 外部 BERT 分类器 → 轻量 LLM 快速判断。单跳问题继续走现有链路;多跳问题启动最多 3 轮 IRCoT 式检索,按子问题逐步补充证据,最终统一 Rerank 并生成回答。分类与检索轨迹对用户可见,信息不足时在答案末尾附加明确的不确定提示。
复杂度识别
- 新增统一特征提取器,输入改写后的独立问题:
- 比较标记:
相比、更、区别、versus、差异等。 - 逻辑连接:
首先/然后、之前/之后、如果/则、因为/所以等。 - 实体数量与桥梁实体数量:jieba POS、英文专名、引用词和领域术语。
- 问题 token 长度。
- 比较标记:
- 启发式分数由比较、逻辑、桥梁实体、长度和实体数量加权得到,规则结果只作为高置信快速路由。
- 分层判定策略:
- 规则分数
>= 0.75:直接判为多跳。 - 规则分数
<= 0.15且实体数不超过 1:直接判为单跳。 - 中间区间调用外部 BERT:概率
>= 0.8判多跳,<= 0.2判单跳。 - BERT 不确定或服务不可用时调用 enrichment 模型做零样本“是/否”判断;模型请求保持 temperature=0、低 token 输出。
- LLM 也失败时,规则分数
>= 0.4或 BERT 概率>= 0.5判多跳,否则单跳。
- 规则分数
- 记录最终判定来源、规则分数、BERT 概率、LLM 判断和决策原因,供调试与后续训练。
BERT 分类器交付
- 新增独立
multihop_classifier/服务,使用中文 BERT/RoBERTa 基座和分类头;CLS 向量与 5 个数值特征拼接后输出单跳/多跳概率。 - 推理接口:
POST /predict,接收question与规则特征,返回label、multi_hop_probability、model_version、features;提供/health。 - 服务使用独立轻量镜像和 Docker Compose 可选 profile,默认不拖慢主后端;模型权重通过挂载目录提供,不提交仓库。
- 提供训练、评估、导出脚本:
- 数据格式
{question, label, features},标签为single/multi。 - 规则模板生成种子样本,需人工复核至少 500 条后正式训练。
- 训练集/验证集/测试集按 8/1/1 划分,最大长度 128,5 epoch,early stopping 以验证集 F1 为准。
- 输出 Accuracy、Precision、Recall、F1、AUC 和混淆矩阵;多跳召回目标不低于 0.85。
- 数据格式
- 后端新增分类器 URL、超时、高/低阈值配置;无 URL 或请求失败时自动进入规则+LLM 降级,不阻断问答。
递归检索与生成
ChatRequest、SearchRequest增加可选retrieval_mode=auto|single|multi,默认auto;单跳继续使用现有链路。- 多跳流程严格沿用原知识库范围和文档过滤,不跨出用户授权范围。
- 第 1 轮使用改写后的原问题执行现有 BM25、L1/L2/L3、摘要、QA 问题向量召回和 RRF,但不做最终 Rerank。
- 每轮结果按 chunk_id 去重,保留最佳分数、命中表示和来源轮次;每轮默认最多保留 8 个新候选。
- 规划模型复用知识库 enrichment 模型,输入原问题、当前子问题、累计证据摘要和前序实体,返回严格 JSON:
need_more、next_question、key_entities、confidence、reason。 - 仅保存简短决策理由,不保存或展示模型隐式思维链。
- 停止条件:
- 规划模型判断信息已足够。
- 达到最大轮数,默认 3,知识库可配置 2–5。
- 下一问题与历史问题重复。
- 新一轮没有产生新 chunk。
- 累计候选触及上下文 token 预算。
- 所有轮次结束后,用改写后的完整问题对累计候选统一执行一次 Rerank,再应用现有动态父窗口、邻块和上下文预算。
- 规划模型调用失败时不继续生成不可控子问题;保留已收集证据并标记不确定。
- 信息不足或达到最大轮数仍
need_more=true时:- 最终回答末尾追加:“注意:该问题需要多步推理,但当前资料可能不足以完整回答,以下结论仅供参考。”
- SSE 同时发送
notice事件,并在响应/usage 中记录不确定原因。
API、轨迹与页面
- 新增
RetrievalTrace、MultiHopStep、ComplexityDecision类型,包含轮数、每轮子问题、实体、命中 chunk、新 chunk 数、停止原因、分类器概率和模型版本。 - SSE 增加:
retrieval_plan:单跳/多跳、判定来源和置信度。retrieval_step:轮次、查询、命中数量、子问题和是否继续。retrieval_done:总轮数、累计 chunk、停止原因、是否不确定。
ChatResponse增加retrieval_trace与uncertainty_notice;非流式响应完整返回。- 轨迹写入消息
usage,历史会话重新打开后仍可查看。 - Chat 页面增加可折叠“多跳检索轨迹”,展示判定依据、各轮子问题和证据数量,不展示隐式推理过程。
- Search 调试页面展示复杂度判定及递归轮次,用于阈值和分类器调参。
测试与验收
- 特征测试覆盖比较、逻辑连接、实体/桥梁实体、长度和中文/英文混合问题。
- 路由测试覆盖规则高置信、BERT 高/低置信、BERT 不确定转 LLM、服务不可用降级和阈值边界。
- BERT 服务测试
/health、/predict、模型缺失、输入超长和批量推理。 - 递归测试覆盖最大轮数、重复子问题、无新增 chunk、规划模型失败、跨库范围和文档范围。
- 验证只执行一次最终 Rerank,并在最终上下文预算内保留跨轮证据。
- 验证不确定答案提示、SSE notice、轨迹持久化和历史会话恢复。
- 前端验证轨迹折叠、分类标签、递归轮次和构建通过;后端执行 Ruff、全量 pytest。
假设与默认值
- 分类器输入为已完成历史消解的改写问题。
- 多跳规划复用知识库 enrichment 模型,不新增模型类型。
- 默认最大 3 轮、每轮 8 个新候选、分类器多跳阈值 0.8、单跳阈值 0.2。
- BERT 模型权重和正式标注集不提交仓库;仓库交付训练/推理代码、标注规范、种子数据生成器和部署配置。
- 单跳链路、现有 RRF、Rerank、上下文窗口和引用机制保持不变。
最后更新: 2026年11月03日 15:01