本文档提供一套面向 UltraRAG 工作流的结构化排查方法,用于分析以下常见情况:
- 回答结果可疑,但暂时无法判断问题出在哪一步
- 检索结果表面正常,但最终答案明显偏题或解释错误
- 多步工作流前半段正常,后半段逐步漂移
- 会话状态、上下文或历史信息没有被正确继承
- 本地实验表现正常,部署后结果却明显不一致
- 错误现象已经出现,但难以快速定位是检索问题、推理问题、状态问题,还是运行环境问题
UltraRAG 提供了灵活的工作流编排能力、可视化的中间步骤追踪能力,以及面向复杂 RAG 场景的案例分析入口。
在实际调试过程中,很多问题并不是单点报错,而是由多个环节共同造成的。与其一开始就大幅修改流程,不如先用一套统一的结构化方法,把问题归到正确层级,再做最小修复。
本文档将排查过程分为四个层级:
- 输入与检索
- 推理与规划
- 状态与上下文
- 部署与运行
建议先做定位,再做修复。
先判断问题属于哪一层,再决定修改 prompt、检索配置、工作流结构、状态管理,还是运行环境。
当你在 UltraRAG 中遇到以下现象时,可以优先参考本指南:
- 用户问题很明确,但系统命中的知识片段明显偏离主题
- 检索结果看起来相关,但答案组织方式与证据不一致
- 前几步节点输出正常,后续节点开始累计偏差
- 回答语气很肯定,但缺少充分依据或证据连接
- 相同输入在不同轮次中得到不一致的输出
- 工作流中的某些状态变量、历史记录或中间结果未按预期传递
- 新环境首次运行报错,或索引、配置、依赖在部署前后不一致
- 本地实验正常,但线上调用结果明显变差
在开始逐项检查之前,建议先遵循以下原则:
不要一上来同时调整检索器、prompt、节点顺序和部署参数。
先判断问题更像发生在输入与检索、推理与规划、状态与上下文,还是部署与运行,然后只改最可能的那一层。
最终答案只是症状,不一定是根因。
如果可以,请优先检查:
- 用户输入是否被正确解析
- 检索 query 是否被改写偏移
- 命中的片段是否真的支持当前问题
- 推理链条是否在中途改变方向
- 中间状态是否被覆盖、丢失或误用
- 部署后的配置是否与本地实验一致
如果一次修改太多项,很难确认真正起作用的是哪一个改动。
更稳妥的方式是每轮只改一处,然后重新运行并对比结果。
很多异常并不是模型能力不足,而是检索、拼接、状态继承、工具调用顺序或部署配置出了问题。
先把流程层排查干净,再判断是否需要更换模型或提高模型能力。
这一层关注的是:问题有没有被正确理解,检索有没有拿到真正相关的上下文。
- 命中的片段与问题主题弱相关
- 检索结果包含关键词,但语义重心不对
- 命中了很多内容,但真正有用的信息很少
- 问题问的是 A,检索结果大多在讲 B
- 用户表达较复杂时,检索 query 被改写得过于宽泛或过于狭窄
- 检索片段表面正确,但关键约束条件缺失
- 用户问题没有被正确拆解
- query rewrite 发生偏移
- chunk 切分过粗或过细
- 召回策略把相似但无关的片段也带了进来
- top-k 设置不合适
- embedding 空间能找相似文本,但找不到真正支持答案的证据
- 索引内容本身不完整、过期或未正确更新
- 原始用户输入是什么
- 工作流中间是否对 query 做了改写
- 改写后的 query 是否保留了原问题的关键约束
- 最终命中的片段是否真的回答了用户问题
- 片段中是否缺少时间、对象、范围、条件等关键限定信息
- 是否存在高相似但低支持性的片段
- 如果减少或增加 top-k,结果是否明显变化
- 索引是否和当前数据版本一致
- 优先修正 query 的表达与约束保留
- 检查 chunk 策略是否适合当前文档类型
- 调整召回数量,而不是盲目增大上下文
- 明确区分“相似内容”和“可作为证据的内容”
- 必要时为复杂问题补充更稳定的检索前置步骤,例如先拆解问题,再分别检索
这一层关注的是:拿到上下文以后,系统是否沿着正确的方向组织解释、做步骤规划、输出答案。
- 检索片段看起来没问题,但答案仍然明显错误
- 回答用了命中的材料,却解释出了完全不同的结论
- 多步流程前几步正常,后几步逐渐偏离原问题
- 系统在中途开始回答另一个更容易的问题
- 输出语气很肯定,但论证链条很弱
- 中间节点都有内容,但节点之间缺少有效衔接
- 推理链条过长,后段发生语义漂移
- 规划步骤太松散,缺少关键约束
- 节点之间的输入输出契约不清晰
- 模型更倾向于“补全一个看起来合理的答案”,而不是忠实根据上下文推导
- 提示词要求结论,但没有要求校验证据
- 多步链路中存在局部正确、整体错误的累计偏差
- 最终答案是否能逐段回溯到对应的检索片段
- 中间节点输出是否仍围绕原问题
- 多步工作流中哪一步开始偏离
- 节点之间传递的是结论、摘要,还是原始证据
- 提示词是否要求模型给出依据、限制和不确定性
- 是否出现“回答很像对,但没有真正被证据支撑”的情况
- 缩短不必要的推理链路
- 在关键节点增加“是否仍然回答原问题”的检查
- 明确要求模型引用或对齐证据,而不是只产出自然语言结论
- 让中间节点保留更多结构化信息,减少过度摘要
- 对高风险步骤增加最小验证,例如重新比对问题、证据与结论是否一致
这一层关注的是:工作流执行过程中,会话历史、变量、缓存、中间结果、上下文窗口是否被正确保存和继承。
- 相同用户在相邻轮次中得到互相矛盾的回答
- 系统前面记住了条件,后面突然忘了
- 某一步已经得到的重要信息,在后续节点中消失
- 节点输出看起来正常,但下一节点接收到的却不是预期内容
- 长流程中前半段信息被后半段覆盖
- 本该保持一致的状态变量,在分支或循环后发生异常
- 历史上下文没有正确注入
- 中间状态被覆盖或截断
- 节点之间的数据格式不一致
- 过长上下文导致关键条件被稀释
- 分支逻辑中状态继承规则不清晰
- 缓存命中或复用逻辑与当前任务不匹配
- 当前轮次真正传入了哪些历史信息
- 哪些字段是节点输出,哪些字段是状态缓存
- 状态变量在每一步之后如何变化
- 分支合流时,是否丢失了某些关键字段
- 中间结果是原始内容、压缩摘要,还是只剩结论
- 长上下文中用户的核心约束是否还可见
- 明确每个节点的输入字段与输出字段
- 减少不必要的状态复用
- 让关键变量保持结构化,不要只保留自然语言摘要
- 对长流程增加阶段性重述,重新显式写入关键约束
- 检查缓存策略,避免错误复用旧结果
- 对分支和循环单独验证状态继承是否稳定
这一层关注的是:本地实验、测试环境、生产环境之间是否存在依赖、配置、索引、启动顺序或运行状态的不一致。
- 本地运行正常,部署后结果异常
- 首次调用失败,但重试后偶尔恢复
- 配置文件看起来一致,行为却不同
- 检索系统可用,但索引结果与预期不一致
- 工作流结构没改,但上线后输出质量下降
- 节点、模型、服务或依赖在不同环境中版本不一致
- 初始化顺序错误
- 索引尚未准备完成就开始调用
- 配置文件、环境变量、模型名、路径或权限不一致
- 本地与线上依赖版本不同
- 缓存、服务状态或外部资源在新环境中不可用
- 部署脚本执行成功,但部分资源并未真正就绪
- 当前环境使用的配置是否与本地一致
- 模型、索引、向量库、reranker、服务地址是否一致
- 新环境是否完成了所有初始化步骤
- 首次调用前,依赖资源是否已经 ready
- 是否存在“表面部署完成,实际资源未就绪”的情况
- 日志中是否能定位到第一处失败环节
- 优先检查初始化顺序与依赖就绪状态
- 把关键资源的 ready 状态显式化,不要依赖隐式成功
- 核对模型名、路径、环境变量、索引版本、服务端点
- 在部署后先做最小验收,再放大到完整流程
- 对首次运行异常单独建一个最小复现实验
如果你已经在 UltraRAG 的案例分析或中间输出追踪中发现某个回答可疑,可以按下面顺序操作:
先选一个最能稳定复现问题的输入,不要一次看太多案例。
目标是找到一个可以重复触发异常的样本。
按工作流顺序查看:
- 输入是否被正确解析
- query 是否发生偏移
- 检索片段是否真的支持问题
- 中间节点是否逐步偏离原始目标
- 状态变量是否被覆盖或丢失
- 最终答案是否还能回溯到证据
把当前异常优先归到以下四类之一:
- 输入与检索
- 推理与规划
- 状态与上下文
- 部署与运行
如果一时无法完全确定,就先归到“最早开始出现异常的那一层”。
例如:
- 修正 query rewrite
- 调整 top-k
- 修改一个关键节点的提示词
- 明确一个状态字段的传递规则
- 修正一个部署配置或初始化顺序
每次只改一处,然后重新运行。
对比修复前后的中间输出与最终答案:
- 错误是否提前消失
- 偏移是否减弱
- 证据与答案的一致性是否提高
- 是否引入了新的副作用
如果问题仍在,再继续下一轮最小修复。
当你时间有限时,可以先用下面这份简版清单:
- 问题有没有被错误改写
- 检索到的片段是否真的支持答案
- 召回数量是否过多或过少
- 索引内容是否完整且最新
- 答案能否回溯到证据
- 中间节点是否偏离原问题
- 是否存在“语气自信但依据不足”的情况
- 多步流程中哪一步开始漂移
- 历史上下文是否被正确注入
- 关键变量是否被覆盖或截断
- 分支与循环后的状态是否一致
- 中间结果是否只剩结论、缺少证据
- 本地与线上配置是否一致
- 初始化顺序是否正确
- 首次运行前依赖资源是否 ready
- 模型、索引、服务和版本是否一致
本文档是一份面向调试与案例分析的实践性排障指南。
它的目标不是替代实验设计、评测体系或正式监控工具,而是在问题已经出现时,帮助使用者更快地判断问题层级,并优先采取最小修复。
对于复杂问题,四个层级之间可能会相互影响。
例如,检索偏差可能进一步诱发推理偏差,状态管理异常也可能放大部署后的不一致行为。
因此,建议始终优先定位“最早出现异常”的层级,而不是只关注最终答案。
致谢:本文档的结构化排障思路参考了社区贡献者 @onestardao 的相关实践。