Skip to content

Latest commit

 

History

History
332 lines (237 loc) · 12.2 KB

File metadata and controls

332 lines (237 loc) · 12.2 KB

面向 UltraRAG 工作流的结构化排障指南

本文档提供一套面向 UltraRAG 工作流的结构化排查方法,用于分析以下常见情况:

  • 回答结果可疑,但暂时无法判断问题出在哪一步
  • 检索结果表面正常,但最终答案明显偏题或解释错误
  • 多步工作流前半段正常,后半段逐步漂移
  • 会话状态、上下文或历史信息没有被正确继承
  • 本地实验表现正常,部署后结果却明显不一致
  • 错误现象已经出现,但难以快速定位是检索问题、推理问题、状态问题,还是运行环境问题

UltraRAG 提供了灵活的工作流编排能力、可视化的中间步骤追踪能力,以及面向复杂 RAG 场景的案例分析入口。
在实际调试过程中,很多问题并不是单点报错,而是由多个环节共同造成的。与其一开始就大幅修改流程,不如先用一套统一的结构化方法,把问题归到正确层级,再做最小修复。

本文档将排查过程分为四个层级:

  1. 输入与检索
  2. 推理与规划
  3. 状态与上下文
  4. 部署与运行

建议先做定位,再做修复。
先判断问题属于哪一层,再决定修改 prompt、检索配置、工作流结构、状态管理,还是运行环境。

一、适用场景

当你在 UltraRAG 中遇到以下现象时,可以优先参考本指南:

  • 用户问题很明确,但系统命中的知识片段明显偏离主题
  • 检索结果看起来相关,但答案组织方式与证据不一致
  • 前几步节点输出正常,后续节点开始累计偏差
  • 回答语气很肯定,但缺少充分依据或证据连接
  • 相同输入在不同轮次中得到不一致的输出
  • 工作流中的某些状态变量、历史记录或中间结果未按预期传递
  • 新环境首次运行报错,或索引、配置、依赖在部署前后不一致
  • 本地实验正常,但线上调用结果明显变差

二、建议的排查原则

在开始逐项检查之前,建议先遵循以下原则:

1. 先定位层级,再修改实现

不要一上来同时调整检索器、prompt、节点顺序和部署参数。
先判断问题更像发生在输入与检索、推理与规划、状态与上下文,还是部署与运行,然后只改最可能的那一层。

2. 优先看中间输出,不只看最终答案

最终答案只是症状,不一定是根因。
如果可以,请优先检查:

  • 用户输入是否被正确解析
  • 检索 query 是否被改写偏移
  • 命中的片段是否真的支持当前问题
  • 推理链条是否在中途改变方向
  • 中间状态是否被覆盖、丢失或误用
  • 部署后的配置是否与本地实验一致

3. 每次只做最小修复

如果一次修改太多项,很难确认真正起作用的是哪一个改动。
更稳妥的方式是每轮只改一处,然后重新运行并对比结果。

4. 把“看起来像模型问题”的情况,先当作流程问题来排查

很多异常并不是模型能力不足,而是检索、拼接、状态继承、工具调用顺序或部署配置出了问题。
先把流程层排查干净,再判断是否需要更换模型或提高模型能力。

三、四层结构化排查方法


1. 输入与检索

这一层关注的是:问题有没有被正确理解,检索有没有拿到真正相关的上下文。

常见症状

  • 命中的片段与问题主题弱相关
  • 检索结果包含关键词,但语义重心不对
  • 命中了很多内容,但真正有用的信息很少
  • 问题问的是 A,检索结果大多在讲 B
  • 用户表达较复杂时,检索 query 被改写得过于宽泛或过于狭窄
  • 检索片段表面正确,但关键约束条件缺失

常见原因

  • 用户问题没有被正确拆解
  • query rewrite 发生偏移
  • chunk 切分过粗或过细
  • 召回策略把相似但无关的片段也带了进来
  • top-k 设置不合适
  • embedding 空间能找相似文本,但找不到真正支持答案的证据
  • 索引内容本身不完整、过期或未正确更新

建议检查项

  • 原始用户输入是什么
  • 工作流中间是否对 query 做了改写
  • 改写后的 query 是否保留了原问题的关键约束
  • 最终命中的片段是否真的回答了用户问题
  • 片段中是否缺少时间、对象、范围、条件等关键限定信息
  • 是否存在高相似但低支持性的片段
  • 如果减少或增加 top-k,结果是否明显变化
  • 索引是否和当前数据版本一致

修复建议

  • 优先修正 query 的表达与约束保留
  • 检查 chunk 策略是否适合当前文档类型
  • 调整召回数量,而不是盲目增大上下文
  • 明确区分“相似内容”和“可作为证据的内容”
  • 必要时为复杂问题补充更稳定的检索前置步骤,例如先拆解问题,再分别检索

2. 推理与规划

这一层关注的是:拿到上下文以后,系统是否沿着正确的方向组织解释、做步骤规划、输出答案。

常见症状

  • 检索片段看起来没问题,但答案仍然明显错误
  • 回答用了命中的材料,却解释出了完全不同的结论
  • 多步流程前几步正常,后几步逐渐偏离原问题
  • 系统在中途开始回答另一个更容易的问题
  • 输出语气很肯定,但论证链条很弱
  • 中间节点都有内容,但节点之间缺少有效衔接

常见原因

  • 推理链条过长,后段发生语义漂移
  • 规划步骤太松散,缺少关键约束
  • 节点之间的输入输出契约不清晰
  • 模型更倾向于“补全一个看起来合理的答案”,而不是忠实根据上下文推导
  • 提示词要求结论,但没有要求校验证据
  • 多步链路中存在局部正确、整体错误的累计偏差

建议检查项

  • 最终答案是否能逐段回溯到对应的检索片段
  • 中间节点输出是否仍围绕原问题
  • 多步工作流中哪一步开始偏离
  • 节点之间传递的是结论、摘要,还是原始证据
  • 提示词是否要求模型给出依据、限制和不确定性
  • 是否出现“回答很像对,但没有真正被证据支撑”的情况

修复建议

  • 缩短不必要的推理链路
  • 在关键节点增加“是否仍然回答原问题”的检查
  • 明确要求模型引用或对齐证据,而不是只产出自然语言结论
  • 让中间节点保留更多结构化信息,减少过度摘要
  • 对高风险步骤增加最小验证,例如重新比对问题、证据与结论是否一致

3. 状态与上下文

这一层关注的是:工作流执行过程中,会话历史、变量、缓存、中间结果、上下文窗口是否被正确保存和继承。

常见症状

  • 相同用户在相邻轮次中得到互相矛盾的回答
  • 系统前面记住了条件,后面突然忘了
  • 某一步已经得到的重要信息,在后续节点中消失
  • 节点输出看起来正常,但下一节点接收到的却不是预期内容
  • 长流程中前半段信息被后半段覆盖
  • 本该保持一致的状态变量,在分支或循环后发生异常

常见原因

  • 历史上下文没有正确注入
  • 中间状态被覆盖或截断
  • 节点之间的数据格式不一致
  • 过长上下文导致关键条件被稀释
  • 分支逻辑中状态继承规则不清晰
  • 缓存命中或复用逻辑与当前任务不匹配

建议检查项

  • 当前轮次真正传入了哪些历史信息
  • 哪些字段是节点输出,哪些字段是状态缓存
  • 状态变量在每一步之后如何变化
  • 分支合流时,是否丢失了某些关键字段
  • 中间结果是原始内容、压缩摘要,还是只剩结论
  • 长上下文中用户的核心约束是否还可见

修复建议

  • 明确每个节点的输入字段与输出字段
  • 减少不必要的状态复用
  • 让关键变量保持结构化,不要只保留自然语言摘要
  • 对长流程增加阶段性重述,重新显式写入关键约束
  • 检查缓存策略,避免错误复用旧结果
  • 对分支和循环单独验证状态继承是否稳定

4. 部署与运行

这一层关注的是:本地实验、测试环境、生产环境之间是否存在依赖、配置、索引、启动顺序或运行状态的不一致。

常见症状

  • 本地运行正常,部署后结果异常
  • 首次调用失败,但重试后偶尔恢复
  • 配置文件看起来一致,行为却不同
  • 检索系统可用,但索引结果与预期不一致
  • 工作流结构没改,但上线后输出质量下降
  • 节点、模型、服务或依赖在不同环境中版本不一致

常见原因

  • 初始化顺序错误
  • 索引尚未准备完成就开始调用
  • 配置文件、环境变量、模型名、路径或权限不一致
  • 本地与线上依赖版本不同
  • 缓存、服务状态或外部资源在新环境中不可用
  • 部署脚本执行成功,但部分资源并未真正就绪

建议检查项

  • 当前环境使用的配置是否与本地一致
  • 模型、索引、向量库、reranker、服务地址是否一致
  • 新环境是否完成了所有初始化步骤
  • 首次调用前,依赖资源是否已经 ready
  • 是否存在“表面部署完成,实际资源未就绪”的情况
  • 日志中是否能定位到第一处失败环节

修复建议

  • 优先检查初始化顺序与依赖就绪状态
  • 把关键资源的 ready 状态显式化,不要依赖隐式成功
  • 核对模型名、路径、环境变量、索引版本、服务端点
  • 在部署后先做最小验收,再放大到完整流程
  • 对首次运行异常单独建一个最小复现实验

四、从案例分析到最小修复的建议流程

如果你已经在 UltraRAG 的案例分析或中间输出追踪中发现某个回答可疑,可以按下面顺序操作:

第一步:锁定可疑样本

先选一个最能稳定复现问题的输入,不要一次看太多案例。
目标是找到一个可以重复触发异常的样本。

第二步:观察中间步骤

按工作流顺序查看:

  • 输入是否被正确解析
  • query 是否发生偏移
  • 检索片段是否真的支持问题
  • 中间节点是否逐步偏离原始目标
  • 状态变量是否被覆盖或丢失
  • 最终答案是否还能回溯到证据

第三步:给问题归层

把当前异常优先归到以下四类之一:

  • 输入与检索
  • 推理与规划
  • 状态与上下文
  • 部署与运行

如果一时无法完全确定,就先归到“最早开始出现异常的那一层”。

第四步:只做一个最小修复

例如:

  • 修正 query rewrite
  • 调整 top-k
  • 修改一个关键节点的提示词
  • 明确一个状态字段的传递规则
  • 修正一个部署配置或初始化顺序

每次只改一处,然后重新运行。

第五步:重新对比结果

对比修复前后的中间输出与最终答案:

  • 错误是否提前消失
  • 偏移是否减弱
  • 证据与答案的一致性是否提高
  • 是否引入了新的副作用

如果问题仍在,再继续下一轮最小修复。

五、快速排查清单

当你时间有限时,可以先用下面这份简版清单:

输入与检索

  • 问题有没有被错误改写
  • 检索到的片段是否真的支持答案
  • 召回数量是否过多或过少
  • 索引内容是否完整且最新

推理与规划

  • 答案能否回溯到证据
  • 中间节点是否偏离原问题
  • 是否存在“语气自信但依据不足”的情况
  • 多步流程中哪一步开始漂移

状态与上下文

  • 历史上下文是否被正确注入
  • 关键变量是否被覆盖或截断
  • 分支与循环后的状态是否一致
  • 中间结果是否只剩结论、缺少证据

部署与运行

  • 本地与线上配置是否一致
  • 初始化顺序是否正确
  • 首次运行前依赖资源是否 ready
  • 模型、索引、服务和版本是否一致

六、边界说明

本文档是一份面向调试与案例分析的实践性排障指南。
它的目标不是替代实验设计、评测体系或正式监控工具,而是在问题已经出现时,帮助使用者更快地判断问题层级,并优先采取最小修复。

对于复杂问题,四个层级之间可能会相互影响。
例如,检索偏差可能进一步诱发推理偏差,状态管理异常也可能放大部署后的不一致行为。
因此,建议始终优先定位“最早出现异常”的层级,而不是只关注最终答案。

七、致谢

致谢:本文档的结构化排障思路参考了社区贡献者 @onestardao 的相关实践。