后端拒绝被解包成未捕获异常,模型失去修正机会¶
隔离探针评测中发现的问题,按当时的报告结论记录。报告把修复列为建议,本次整理没有核验修复是否已落地。
探针设计¶
探针要回答的问题:终态提交工具这条机制在该模型通道上是否可用。为了不动产品代码、让观察到的行为来自真实工具链,探针的全部脚本和运行记录都放在一个临时诊断目录里,Go 后端保持只读。
探针用了一个低成本模型,配置:
parallel_tool_calls = False # 关闭并行工具调用
output_schema = None # 不附加 response_format
max_turns = 8
max_retries = 0
output_schema 取 None 有历史原因:这个通道此前出现过"有工具就直接 stop"的问题,不附加 response_format 之后链路恢复,探针沿用这个设定。工具是三个标准知识工具(检索、打开文档、取证)加一个提交工具,提交工具的参数复用产品的输出 schema。内核的 finalize 在探针里设成恒等函数,提交后的参数拿到线下做两层校验,这样能把工具调用通道本身的行为和产品终态校验分开观察。
按探针纪律最多运行两次,用来区分偶发行为和系统性行为。
第一次运行:中断在第 3 轮¶
第一次运行的工具调用序列是检索、检索、打开文档、打开文档、取证、取证,第 6 次工具调用后中断,没有走到提交。用量约 9.9 万 token。
中断点在第 3 轮请求。虽然配置里关了并行工具调用,通道仍然在同一轮里连续返回了两个取证调用,第二个调用把已打开的另一份文档的段落标识混进了当前文档的请求里。Go 后端返回的是正常业务拒绝:
这个拒绝本身是对的——混入其他文档的段落本来就该被拒绝。问题在产品 handler:_extract_knowledge_evidence 没有检查返回里的 ok,直接调用 collect_successful_evidence 按成功路径解包证据数组。拒绝响应里没有可解包的成功证据,解包抛出未捕获的 RuntimeError,内核的轮次循环没有兜住,整个 turn 在提交工具被调用前终止。模型不知道哪一次调用错了、错在哪个参数,无法修正后重试。
对照运行与 finalize 校验¶
第二次运行完整跑通:5 次请求、约 29 万 token,模型在第 4 轮主动调用提交工具,探针返回 {"status": "submitted"},模型收到确认后正常结束。两次运行合起来看,可以排除"通道整体不可用"的判断:链路本身走得通,缺陷集中在错误处理路径。
对照运行还暴露了 finalize 层的校验,这层拦截是对的。提交的内容有 10 条 claims,前 9 条引用的都是本轮成功取证的段落标识,第 10 条引用了一个打开阶段见过、但从未成功取证的段落标识,终态校验拒绝了这次提交。两层线下校验的结果:
第二层的机制是:finalize 把每条 claim 的 evidence_ids 和本轮上下文里"取证成功"的证据集合逐一对照,打开过的段落不在集合里。这层校验区分了"打开过的"和"取证成功的",正是 handler 缺的检查。报告还据此加了一条提示词约束:claims 的 evidence_ids 只能取自取证工具返回的数组,不能引用打开阶段看到的段落标识。
报告结论¶
报告的修复方向:后端业务失败必须转换为模型可见的工具错误返回,保留循环内的自修正机会;同时约束并发工具调用——关闭并行工具调用的配置下,该通道仍可能单轮返回多个工具调用,这是多文档场景下参数混淆的诱因。
第二次运行只验证了成功路径,不能证明异常分支已修复;handler 的修复在报告中是待办项,没有落码和回归记录。