图_4RAG工作流模块 · 详细实现
对应 [[4_代码实现_RAG Pipeline]]。按图 1 模板粒度,只写主要实现步骤。
读图方式
- 蓝底是文件,紫底是类,灰底是函数;标题与主要步骤分开,框宽随文字收紧。简单函数一句,复杂函数按主要处理阶段分步。
- 实线箭头表示调用(含 LangGraph 的节点调度),虚线箭头表示数据或对象传递。远距离用
〔调用 F07〕/〔传递 F07:2〕引用,避免拉长线。 - F / C / P 分别表示函数、类、文件;冒号后的数字指目标步骤。编号只用于定位,不表示执行次序。
- 省略普通返回、逐字段转换和重复异常处理;保留会影响业务走向的降级、HITL、终止等分支。
文件与函数索引
P01 · backend/rag/pipeline.py
RAG 检索、评分与路由工作流。
- F01
_get_grader_model()(源码 29 行):获取证据评分模型。 - F02
_get_complexity_model()(源码 45 行):获取复杂度规划模型。 - F03
_format_docs()(源码 151 行):整理带来源的证据上下文。 - F04
_copy_jsonable_doc()(源码 163 行):复制证据字段(未接入主流程)。 - F05
_copy_jsonable_docs()(源码 178 行):批量复制证据(未接入主流程)。 - F06
_is_hitl_result()(源码 182 行):判断是否需要用户补充。 - F07
_build_hitl_resume_state()(源码 191 行):构建跨轮恢复快照。 - F08
_refined_question_for_hitl()(源码 204 行):把用户补充合入原问题。 - F09
_emit()(源码 214 行):上报 RAG 进度。 - F10
_initial_state()(源码 225 行):初始化图状态。 - F11
retrieve_initial()(源码 264 行):执行首次检索。 - F12
_route_after_initial()(源码 312 行):初检后路由(未接入主流程)。 - F13
_route_after_grade()(源码 316 行):决定是否进入改写。 - F14
_retrieval_status_for_route()(源码 322 行):将路由映射为展示状态。 - F15
_default_hitl_prompt()(源码 336 行):生成用户补充提示。 - F16
_grade_for_no_docs()(源码 346 行):无证据时跳过评分模型。 - F17
_resolve_route()(源码 357 行):按确定性规则校正路由。 - F18
_grade_update()(源码 400 行):整理评分与路由更新。 - F19
grade_documents_node()(源码 417 行):评分证据并决定下一步。 - F20
rewrite_question_node()(源码 471 行):在一次预算内改写问题。 - F21
retrieve_rewritten()(源码 529 行):按新 Query 再次检索。 - F22
_simple_question_fast_path_reason()(源码 659 行):本地识别明确的简单问题。 - F23
classify_complexity()(源码 681 行):判断复杂度并规划子问题。 - F24
prepare_sub_questions()(源码 723 行):准备并展示子问题。 - F25
_route_after_complexity()(源码 735 行):选择简单或复杂路径。 - F26
_fanout_sub_questions()(源码 742 行):分发并行子任务。 - F27
rag_sub_agent()(源码 857 行):执行单个子问题。 - F28
synthesis()(源码 761 行):汇总子问题证据。 - F29
build_rag_graph()(源码 879 行):组装 LangGraph 工作流。 - F30
_state_from_resume()(源码 930 行):按快照重建检索状态。 - F31
_retrieve_resume_query()(源码 964 行):补充问题的针对性检索。 - F32
resume_rag_from_hitl()(源码 1013 行):跨轮补充后的恢复入口。 - F33
run_rag_graph()(源码 1028 行):正常 RAG 执行入口。 - C01
EvidenceGrade:证据评分协议。 - C02
ComplexityResult:问题规划协议。 - C03
RAGState:图执行共享状态。
调用与对象传递对照
| 出发位置 | 目标 | 类型 | 关系 |
|---|---|---|---|
| P01 · 第 2 步 | F29 build_rag_graph |
实线 · 调用 | 调用 |
| F33 · 第 1 步 | F10 _initial_state |
实线 · 调用 | 调用 |
| F33 · 第 2 步 | F06 _is_hitl_result |
实线 · 调用 | 调用 |
| F33 · 第 2 步 | F07 _build_hitl_resume_state |
实线 · 调用 | 调用 |
| F23 · 第 1 步 | F22 _simple_question_fast_path_reason |
实线 · 调用 | 调用 |
| F23 · 第 2 步 | F02 _get_complexity_model |
实线 · 调用 | 调用 |
| F11 · 第 2 步 | F03 _format_docs |
实线 · 调用 | 调用 |
| F19 · 第 1 步 | F16 _grade_for_no_docs |
实线 · 调用 | 调用 |
| F19 · 第 1 步 | F01 _get_grader_model |
实线 · 调用 | 调用 |
| F19 · 第 2 步 | F17 _resolve_route |
实线 · 调用 | 调用 |
| F19 · 第 2 步 | F18 _grade_update |
实线 · 调用 | 调用 |
| F18 · 第 1 步 | F14 _retrieval_status_for_route |
实线 · 调用 | 调用 |
| F18 · 第 1 步 | F15 _default_hitl_prompt |
实线 · 调用 | 调用 |
| F27 · 第 1 步 | F11 retrieve_initial |
实线 · 调用 | 调用 |
| F27 · 第 1 步 | F19 grade_documents_node |
实线 · 调用 | 调用 |
| F26 · 第 1 步 | F10 _initial_state |
实线 · 调用 | 调用 |
| F32 · 第 1 步 | F30 _state_from_resume |
实线 · 调用 | 调用 |
| F32 · 第 2 步 | F31 _retrieve_resume_query |
实线 · 调用 | 调用 |
| F32 · 第 3 步 | F07 _build_hitl_resume_state |
实线 · 调用 | 调用 |
| F30 · 第 1 步 | F08 _refined_question_for_hitl |
实线 · 调用 | 调用 |
| F30 · 第 2 步 | F10 _initial_state |
实线 · 调用 | 调用 |
| F31 · 第 2 步 | F19 grade_documents_node |
实线 · 调用 | 调用 |
| F05 · 第 1 步 | F04 _copy_jsonable_doc |
实线 · 调用 | 调用 |
| P01 · 第 2 步 | F33:1 run_rag_graph |
虚线 · 传递 | 编译后的 rag_graph |
| F23 · 第 2 步 | F25:1 _route_after_complexity |
虚线 · 传递 | complexity 分类结果 |
| F19 · 第 2 步 | F13:1 _route_after_grade |
虚线 · 传递 | route 决策结果 |
| F20 · 第 3 步 | F21:1 retrieve_rewritten |
虚线 · 传递 | rewritten_query |
| F25 · 第 1 步 | F11 retrieve_initial |
实线 · 调用 | LangGraph 路由调度 |
| F25 · 第 1 步 | F24 prepare_sub_questions |
实线 · 调用 | LangGraph 路由调度 |
| F24 · 第 1 步 | F26 _fanout_sub_questions |
实线 · 调用 | LangGraph 路由调度 |
| F26 · 第 2 步 | F27 rag_sub_agent |
实线 · 调用 | LangGraph 路由调度 |
| F21 · 第 2 步 | F19 grade_documents_node |
实线 · 调用 | LangGraph 路由调度 |
[[source/_posts/LLM/2_RAG/project/img/详细实现/项目实现|查看项目实现总图]]。概要图仍保留在“实现”文件夹。
Excalidraw Data
Text Elements
backend/:本模块的后端实现 ^8103f4b7
rag/:召回并组织证据决策工作流 ^dfad06b7
[[4_代码实现_RAG Pipeline|P01 pipeline.py:RAG 检索、评分与路由工作流]] ^3ad149b8
-
定义图状态、复杂度与证据评分协议。 ^cc708838
-
注册节点与路由,编译共享 rag_graph。 〔调用 F29〕 〔传递 F33:1〕 ^1270fa4a
C01 EvidenceGrade:证据评分协议 ^57549a3f
-
属性:相关性、可回答性、歧义、置信度与路由。 ^2bbed9f7
-
补充信息:评分原因、缺失条件、追问与选项。 ^d3a089bf
C02 ComplexityResult:问题规划协议 ^685788bd
-
属性:simple / complex、判断原因、子问题列表。 ^584dccde
-
约束:最多 4 个子问题。 ^f5f5c538
启动、状态与快照 ^349ed8d2
F33 run_rag_graph():正常 RAG 执行入口 ^ad26e4bd
- 调用共享 rag_graph。 ^a460aea5
F29 build_rag_graph():组装 LangGraph 工作流 ^f11f4118
-
注册图节点,以复杂度判断为入口。 ^1557a65e
-
简单链:初检 → 评分 → 可选一次改写再检索。 ^ea1376d7
-
复杂链:并行子检索与评分 → 汇总;编译工作流。 ^8d85d4e6
F10 _initial_state():初始化图状态 ^8692447c
-
设置问题、Query、证据与路由等初始值。 ^71958b60
-
绑定请求 ctx,初始化改写次数和子问题状态。 ^d34d57be
F06 _is_hitl_result():是否需要用户补充 ^0fe17a9d
- 根据结果或 Trace 中的状态、路由识别 HITL ^9a664a0a
F07 _build_hitl_resume_state():保存HITL快照 ^cbb90c8f
-
从结果/rag trace 提取: query、路由结果、检索状态、 重写次数、复杂度、复杂度原因、子问题 ^21778e9f
-
将提取结果包装校验为对象 [调用外部对象] ^38343500
F09 _emit():上报 RAG 进度 ^15b1218c
- 通过请求 ctx 发送步骤与子问题分组信息。 ^b651f1c2
分类、召回与并行子问题 ^9808b1fd
F23 classify_complexity():判断复杂度并规划子问题 ^6e0cc41f
-
先尝试本地简单问题规则。 〔调用 F22〕 ^4db0ab6c
-
未命中时调用 复杂度判断模型,若为复杂问题则最多分成 4 个子问题。 〔调用 F02〕 ^8b0b83b1
F22 _simple_question_fast_path_reason():本地识别明确的简单问题 ^7123fbef
-
根据长度、简单事实与复杂意图标记判断。 ^7635bdb9
-
明确简单时命中快速路径,其余交给模型。 ^4da1e7df
F02 _get_complexity_model():获取复杂度规划模型 ^05653920
- 按需创建并复用 FAST_MODEL。 ^5a6f354d
F11 retrieve_initial():执行首次检索 ^ff62a9c0
-
调用检索入口获取证据与检索信息。 ^d7305222
-
将证据整理为上下文。 〔调用 F03〕 ^fe22b78b
-
写入初检 Trace,并上报检索步骤。 ^95529ef7
F03 _format_docs():整理证据 ^eac753b4
- 给证据编号,拼接来源、页码与正文。 ^bf84fe22
F24 prepare_sub_questions():整理子问题 ^ef2dc074
- 整理已规划的子问题,逐条上报。 〔调用 F26〕 ^1efc76b2
F25 _route_after_complexity():选择简单或复杂路径 ^75a26195
- 简单问题进入初检;复杂问题进入子问题分发。 〔调用 F11 / F24〕 ^d077e0b0
F26 _fanout_sub_questions():分发并行子任务 ^f17ba3ab
-
每个子问题创建独立状态,共享 ctx〔调 F10〕 ^04c2746e
-
通过 Send 分发到 rag_sub_agent〔调 F27〕 ^512e6055
F27 rag_sub_agent():执行单个子问题 ^e7a84dfb
证据评分与决策路由 ^af74498d
F19 grade_documents_node():评分证据并决定下一步 ^69088ca8
F16 _grade_for_no_docs():无证据时的评分 ^6975cb38
- 直接生成无知识的评分结果(自定义协议类) ^0c06dca8
F01 _get_grader_model():获取证据评分模型 ^3d829ed2
- 按需创建并复用 GRADE_MODEL。 ^a7c88c9f
F17 _resolve_route():按确定性规则校正路由 ^9850ce21
-
无证据或主题无关:no_knowledge ^c8d31906
-
有歧义: ^221d83d5
F18 _grade_update():根据路由结果和评分结果更新信息 ^59e16459
F14 _retrieval_status_for_route():将路由映射为展示状态 ^d15d1396
- 将 answer / rewrite / HITL / no_knowledge 转为检索状态: 可回答、需要重写、需要补充、需要选择、无证据 ^970cab0a
F15 _default_hitl_prompt():生成用户补充提示 ^3fa325dd
- 优先采用评分模型的追问,否则按路由结果或评分结果输出: 选择提示词 / 补充提示词 ^08bb435d
F13 _route_after_grade():是否进入重写 ^34cc6afa
重写、恢复与收尾 ^b2cbb88e
F20 rewrite_question_node():重写query ^c25bf0e6
- 增加改写次数,新 Query与trace 〔传递 F21:1〕 ^27414422
F21 retrieve_rewritten():按新 Query 再次检索 ^510b715b
-
用改写后的 Query 调用检索入口。 ^8e1f5b7a
-
更新证据、上下文与改写检索 Trace。 〔调用 F19〕 ^044aade4
F28 synthesis():汇总子问题证据 ^2280d23a
F32 resume_rag_from_hitl():跨轮补充后的恢复入口 ^4964dc16
-
根据快照与用户补充重建状态。 〔调用 F30〕 ^62aea5a2
-
执行针对性检索与评分,跳过复杂度判断。 〔调用 F31〕 ^c3c87f8f
-
仍需补充时生成下一轮快照。 〔调用 F07〕 ^61c093f4
F30 _state_from_resume():按快照重建检索状态 ^728900de
-
校验快照,将用户补充合入原问题。 〔调用 F08〕 ^02566997
-
初始化新状态,恢复改写次数、规划信息和恢复 Trace。 〔调用 F10〕 ^7d77383e
F08 _refined_question_for_hitl():把用户补充合入原问题 ^817c48d6
- 合并原问题与本轮补充,避免重复拼接。 ^132187ed
F31 _retrieve_resume_query():补充问题的针对性检索 ^cbfd7b57
-
按补充后的问题检索,整理证据与上下文。[调用检索接口] ^bb43a849
-
记录针对性检索 Trace,再执行证据评分。 〔调用 F19〕 ^aff5a6ad
F12 _route_after_initial():初检后路由(未接入主流程) ^89e1a727
- 指定下一步为证据评分。 ^b5ebfb01
F05 _copy_jsonable_docs():批量复制证据(未接入主流程) ^a3b8a56e
- 逐条调用证据字段复制函数。 〔调用 F04〕 ^308ad419
F04 _copy_jsonable_doc():复制证据字段(未接入主流程) ^05bcf399
-
按白名单复制正文、来源和分数字段。 ^3fb6fa9f
-
初始化本轮状态 〔调用 F10〕 ^a34VlZgE
-
需要用户补充时附上恢复快照。 〔调用 F06 / F07〕 ^fTJtPyva
C03 RAGState:图执行共享状态 ^hWDGFlbn
-
检索:原问题、当前 Query、证据、上下文。 ^4zDb8tcj
-
决策:评分、路由、改写次数、复杂度。 ^A1gjUIak
-
并行:子问题与子结果;运行时:请求 ctx 与步骤分组。 ^ZIxWIgna
-
判断下一步路由 ^w0WeaVn4
-
手动调用检索〔调用 F11〕 ^IcAJipaj
-
手动调用子问题评分〔调用 F19〕 ^JfuJYX6k
-
汇集该题证据与状态,交给汇总节点 ^UWj20mcE
-
无证据直接生成无知识评分〔调用 F16 〕 ^UD4UAT0y
-
校正模型路由〔调用 F17 〕 ^bZjIFpL8
-
更新评分状态与 Trace。 〔调用F18〕 ^SO57R47f
-
有证据调用评分模型 〔调用 F01〕 ^BY4810HQ
-
根据评分结果(路由,相关性)返回下一步路由: ^vxKnja8v
-
方向不唯一:scope_select ^4Mhk5SEk
-
缺条件:clarify ^SHOS8ywT
-
证据足够,且主题相关,且路由为回答:answer ^72MFIWsc
-
当前问题为子问题: ^klEuGFra
-
证据足够或部分足够:answer ^JDoAaMPm
-
无证据:no_knowledge ^J9vB82ac
-
路由为重写: ^3D26POGE
-
之前没重写过:rewrite ^dWg1tE8P
-
之前重写过: ^Mxb2GlrE
-
证据部分足够:clarify ^VgLoaDSd
-
无证据:no_knowledge ^mX9OgRmk
-
证据部分足够:: ^EjxvLbvj
-
之前没重写过:rewrite ^7LYm9CX7
-
之前重写过:clarify ^k0gDvRVm
-
证据足够,且主题相关:answer ^R1B1Lc2e
-
根据路由结果和评分结果更新当前检索状态 〔调用 F14〕 ^CtcbAI1g
-
若路由结果是clarify / scope select就需要hitl信息〔调 F15〕 ^Mwl6aSdp
-
更新全局状态包括评分、缺失条件、选项等状态字段 ^8T5QfbGG
-
评分后有五种路由状态: 1. answer:检索完成,返回检索结果给agent 2. clarify:结束rag,等待用户补充 3. select:结束rag,等待用户补充 4. no_knowledge:结束rag ^zZQihL5E
-
rewrite:重写(仅这一个路由还在rag中) ^wDcJMPdF
-
若无重写预算则返回no_knowledge ^A4Jit9O2
-
调用重写接口Step-back / HyDE [调用utilis.py] ^ivMVof6D
-
收集所有子问题的执行结果
-
只保留 可回答/部分可回答 的证据 ^U1uY62GR
^DK4zrwck
-
多个子证据有重复chunk,调用去重接口 ^wqDDoC81
-
整理证据 [调用F03] ^6koxu6cm
-
合并子问题的rag trace [调用外部函数] ^DusplYJZ
-
更新下一步路由: ^YePnl3Cc
-
合并后有evidence,路由到回答分支 ^UtVHpNDu
-
无evidence,有HITL ^RSaMgfLR
-
优先select情况,合并所有选项,路由到scope_select ^Nv4vUYmF
-
其次clarify情况,合并子问题clarify提示,路由到clarify ^TgbTMw6K
-
无HITL,路由到no_knowledge ^ArInciQc
恢复 ^mIOKjBzm
复杂度判断 ^DUjc9Ncd
模型判断 ^jFfFMyt2
{ "complexity": "simple", "complexity_reason": "obvious_simple_fast_path:short_single_intent" } ^8suPzxxJ
简单规则判断 ^HDOWIDzx
{ "complexity": "simple", "complexity_reason": "单一事实查询", "sub_questions": [] } ^AlL0i1An
简单 ^4VnDWnjL
{ "complexity": "complex", "complexity_reason": "涉及多维度比较", "sub_questions": [ "子问题1", "子问题2", ] } ^0DdaqwxF
复杂 ^gIRAkrRT
RAG Pipeline:节点执行后 rag_trace 的字段变化 ^wCJ7T7qp
灰底框是节点;白底框是字段。未列出的字段沿用上一步,… 表示列表内容省略。 ^ngSjxkme
原样例的三个分支是 RAGState 更新,此时 rag_trace 仍为 None。 ^NqaSkq4y
完整字段见 [[RAGTrace_字段解释表]]。 ^tDTFE6ue
后续白框只写新增 / 覆盖项;/ 分隔可能取值,单次只取一种。 ^bSICufTz
首次检索 ^2Qedlhsp
{ "tool_used": true, "tool_name": "search_knowledge_base", "query": "原问题", "complexity": "simple", "complexity_reason": "前面的分类理由", "retrieval_stage": "initial", "retrieved_chunks": [初检片段…], "initial_retrieved_chunks": [同一批初检片段…] } 同时写入本次召回、合并、精排的参数和计数。 尚无 route、retrieval_status 和评分字段。 ^X0SI9InP
证据评分 ^NVEjo0HL
{ "evidence_relevance": "none / weak / strong", "evidence_answerability": "none / partial / sufficient", "evidence_ambiguity": "none / missing_slot / multiple_candidates", "evidence_confidence": 0.0 ~ 1.0, "evidence_reason": "判断理由", "missing_slots": [缺失条件…], "hitl_prompt": "追问文本,非 HITL 时为空串", "hitl_options": [可选方向…] } route / retrieval_status 按以下分支确定。 没有片段:不调用模型;三项评级均 none,confidence=1.0, reason="no_retrieved_documents",直接 no_knowledge。 ^5W4Ux0tY
证据足够 → 结束 { "route": "answer", "retrieval_status": "answerable" } 保留 retrieved_chunks、initial 阶段和初检快照。 ^La3m6pDK
缺少条件 → 等待用户补充 { "route": "clarify", "retrieval_status": "needs_clarification", "retrieved_chunks": [] } 初检快照保留;恢复快照在 Trace 外。 ^Io3luAG1
多个候选方向 → 等待用户选择 { "route": "scope_select", "retrieval_status": "needs_scope_selection", "retrieved_chunks": [] } 初检快照保留;恢复快照在 Trace 外。 ^zQlWSJHr
没有可用知识 → 结束 { "route": "no_knowledge", "retrieval_status": "no_knowledge" } docs 清空;Trace 里的候选可仍保留, initial 阶段和初检快照也保留。 ^rfiRUZ4G
需要换一种问法 { "route": "rewrite", "retrieval_status": "needs_rewrite" } 旧证据、评分和 initial 阶段暂时保留。 后续只选一种改写方法。 ^O7g2xbHY
查询改写(最多一次) ^XkM2Lywa
Step-back { "rewrite_method": "step_back", "step_back_question": "抽象问题", "rewritten_query": "组合后的新查询", "rewrite_count": 1 } ^oCJEHUG8
HyDE { "rewrite_method": "hyde", "hyde_document": "假设文档", "rewritten_query": "组合后的新查询", "rewrite_count": 1 } ^qwONjInb
用新查询再次检索 ^F9WSkcKa
{ "query": "仍是原问题", "retrieval_stage": "rewritten", "retrieved_chunks": [本次重检片段…], "rewrite_retrieved_chunks": [同一批重检片段…] } 初检快照和改写字段保留;检索参数 / 计数覆盖为本次值。 旧评分仍在,等下一节点覆盖。 ^gD1aYbnz
再次评分 ^npPHq9io
本次评分覆盖 evidence_* / missing_slots / HITL 字段。
{ "retrieval_stage": "rewritten", "route": "answer / clarify / scope_select / no_knowledge", "retrieval_status": "answerable / needs_clarification / needs_scope_selection / no_knowledge" }
证据保留 / 清空规则仍同左侧四种结果,不再正常进入改写。 初检快照、重检快照、改写信息和本次检索计数都保留。 raw rewrite_count=1 会在对外规范化时被过滤。 ^mYpQuFGV
整理子问题并分发 ^itX9L2t4
父任务:rag_trace 仍为 None。 每个子任务新建状态: { "question": "本子问题", "is_sub_agent": true, "rewrite_count": 0, "complexity": null, "rag_trace": null } 子任务不继承父任务的复杂度和 Trace。 ^SkyMr2Lq
子 Agent:首次检索 ^Ob9oEkSE
每个子问题各有一份 rag_trace: { "tool_used": true, "tool_name": "search_knowledge_base", "query": "本子问题", "complexity": null, "complexity_reason": null, "retrieval_stage": "initial", "retrieved_chunks": [本题初检片段…], "initial_retrieved_chunks": [同一批初检片段…] } 另带本次检索参数 / 计数;此时父 Trace 仍为 None。 ^HRjLt50P
子 Agent:证据评分 ^Fa7NSYFy
评分字段同左侧证据评分;阶段仍为 initial。
① sufficient → answer / answerable ② partial → answer / partial 保留本题片段,交给合成;子题不走改写。 ③ 缺条件 / 多方向 → clarify / scope_select status 与主链相同,retrieved_chunks=[]。 ④ 空召回 / 不相关 → no_knowledge / no_knowledge docs 清空;Trace 候选可保留。
缺条件 / 多方向的路由优先于 partial 可回答规则。 本题初检快照和检索参数 / 计数保留。 ^QHLDpOna
汇集子任务结果 ^S0qlzEhK
写入父 RAGState.sub_results: [ { "question": "子问题", "docs": [可用片段…], "route": "本题路由", "retrieval_status": "本题状态", "rag_trace": {本题完整 Trace…} }, … ] 此时父 rag_trace 还未生成;这是运行时结果包。 ^LkReOnAZ
子问题合成 ^vdgOyqb1
只收 answerable / partial 子题的 docs,合并后保序去重。 新建父 rag_trace: { "tool_used": true, "tool_name": "search_knowledge_base", "query": "父任务原问题", "complexity": "complex", "complexity_reason": "父分类理由", "sub_questions": [父规划列表…], "retrieval_stage": "synthesis", "retrieved_chunks": [去重后的总片段…], "sub_agent_count": 汇集的子结果数, "synthesis_merged_count": 去重前片段数, "sub_traces": [规范化后的各子 Trace…], "evidence_confidence": null } 不汇总检索计数和初检 / 改写快照,不再调用评分模型。 顶层不写 evidence_ambiguity / evidence_reason / missing_slots。 ^r6qW6OUY
有总片段,至少一个子状态 partial { "route": "answer", "retrieval_status": "partial", "evidence_relevance": "strong", "evidence_answerability": "partial", "hitl_prompt": "", "hitl_options": [] } ^zELORZxq
有总片段,没有子状态 partial { "route": "answer", "retrieval_status": "answerable", "evidence_relevance": "strong", "evidence_answerability": "sufficient", "hitl_prompt": "", "hitl_options": [] } 即使其他子题失败 / HITL,也不要求全部成功。 ^mnaIqdxn
无总片段,有子题 HITL { "route": "clarify / scope_select", "retrieval_status": "needs_clarification / needs_scope_selection", "evidence_relevance": "none", "evidence_answerability": "none", "hitl_prompt": "去重合并的子追问", "hitl_options": [去重的子选项…] } scope_select 优先,路由与状态对应。 ^4EI31oKp
无总片段,也无子题 HITL { "route": "no_knowledge", "retrieval_status": "no_knowledge", "evidence_relevance": "none", "evidence_answerability": "none", "hitl_prompt": "", "hitl_options": [] } ^xYV0Pgbf
两条主链结束后:统一输出与规范化 ^JELtxQ8Z
返回结果 ^Ojbnktqa
普通结束:返回 rag_trace、docs/context 和状态。 HITL 结束:结果顶层另附 hitl_resume_state, 它与 rag_trace 并列,不是 Trace 的字段。 快照保存问题、路由 / 状态、改写次数和父规划;不保存证据。 ^3hjXwEVO
对外规范化 Trace ^OpALaPQr
normalize_rag_trace()
- 只保留 59 个协议字段;raw rewrite_count 被过滤。
- 去除 None;false / 0 / 空串 / [] 保留。
- 证据元素只留六个协议字段。
- 子 Trace 已在 synthesis 中先规范化。
因此“字段不存在”“null”“空列表”不是同一种状态。 ^LIBNfvWH
用户补充后的 HITL 恢复:只检索并评分,不重新分类 / 分发 / 合成 ^BdYLy8VV
恢复状态 ^hGDJgteC
新建 rag_trace: { "tool_used": true, "tool_name": "search_knowledge_base", "query": "合并用户补充后的问题", "hitl_resumed": true, "hitl_answer": "本轮补充", "hitl_resume_from_route": "上轮路由", "hitl_resume_from_status": "上轮状态" } 父复杂度 / 理由 / 子规划有值才带回。 此时还没有 stage、证据和评分。 改写预算从快照恢复,存于 RAGState。 ^0EgTz39u
针对性重新检索 ^cUr7URoM
{ "retrieval_stage": "hitl_targeted_retrieval", "hitl_resume_strategy": "targeted_retrieval", "retrieved_chunks": [本次片段…], "hitl_targeted_retrieved_chunks": [同一批片段…] } 写入本次召回 / 合并 / 精排参数和计数。 即使沿用 complex 标签,也不重新分解子问题。 ^xV7FkdAc
评分并返回 ^Hqih2rxO
覆盖 evidence_* / route / status / HITL 字段, 保留 targeted 检索阶段和恢复字段。 清空证据规则同主链评分。
可能得到 answer / clarify / scope_select / no_knowledge,甚至 rewrite / needs_rewrite。 但恢复函数直接返回,不执行后续改写节点。
仍需 HITL:顶层附下一轮恢复快照。 结果再经上方规范化;不回到完整 RAG 图。 ^6y7X4Tgd
Element Links
3ad149b8: [[4_代码实现_RAG Pipeline]]
tDTFE6ue: [[RAGTrace_字段解释表]]
%%
Drawing
1 | N4KAkARALgngDgUwgLgAQQQDwMYEMA2AlgCYBOuA7hADTgQBuCpAzoQPYB2KqATLZMzYBXUtiRoIACyhQ4zZAHoFAc0JRJQgEYA6bGwC2CgF7N6hbEcK4OCtptbErHALRY8RMpWdx8Q1TdIEfARcZgRmBShcZQUebR4ATm0ARho6IIR9BA4oZm4AbXAwUDBSiBJuCGIEgBYEAAZNTVw00shYRErA7CiOZWDWssxuGvr+MphuZIA2AFZxyAoSdW4A |
%%