Agent 可靠性工程实战(五):失败反馈不是新目标,用证据转向守住原始意图

Agent 可靠性工程实战(五):失败反馈不是新目标,用证据转向守住原始意图
本篇读取上一篇的runs/demo-001/grader_snapshot.json、裁判产生的check_finished事件以及 083 的contract.json。快照摘要证明失败来自受保护裁判契约提供不变目标本篇新增steer.py输出runs/demo-001/steer.json作为下一次模型调用的唯一指令输入。一、最危险的反馈是“想当然的总结”测试输出可能很长宿主常把它总结成“测试仍失败请修复”。这句话丢掉了原目标和具体证据模型自然把“绿灯”当成优化对象。好的转向信息不是重新发明任务而是原目标、不可变约束和最小失败片段的组合。它应明确说允许修改哪里、禁止修改哪里并引用裁判原始输出的摘要。失败片段不能简单取最后几行。不同测试框架可能把关键断言放在中间末尾只有统计。我们按错误关键字选择相邻行再施加字符上限完整输出单独落盘并求摘要。这样模型得到足够定位信息审计者仍能证明片段来自哪份完整证据。from__future__importannotationsimporthashlibimportjsonfrompathlibimportPath KEYWORDS(AssertionError,FAILED,ERROR,expected,actual)defevidence_slice(text:str,limit:int1600)-str:linestext.splitlines()selected:list[str][]forindex,lineinenumerate(lines):ifany(word.lower()inline.lower()forwordinKEYWORDS):start,endmax(0,index-1),min(len(lines),index2)selected.extend(lines[start:end])ifnotselected:selectedlines[-12:]compact\n.join(dict.fromkeys(selected))returncompact[:limit]defbuild_steer(contract:dict,snapshot:dict,output:str)-dict:output_hashhashlib.sha256(output.encode(utf-8)).hexdigest()return{contract_sha256:contract[sha256],grader_contract_sha256:snapshot[contract_sha256],goal:contract[goal],must_not_change:contract[protected],instruction:只修改允许的生产代码以满足原目标不得修改裁判材料。,failure_evidence:evidence_slice(output),full_output_sha256:output_hash,}defmain()-int:rootPath(runs/demo-001)contractjson.loads((root/contract.json).read_text(encodingutf-8))snapshotjson.loads((root/grader_snapshot.json).read_text(encodingutf-8))output(root/artifacts/check-001.txt).read_text(encodingutf-8)steerbuild_steer(contract,snapshot,output)ifsteer[contract_sha256]!steer[grader_contract_sha256]:raiseSystemExit(contract mismatch)(root/steer.json).write_text(json.dumps(steer,ensure_asciiFalse,indent2),encodingutf-8)print(fevidence_chars{len(steer[failure_evidence])}goal_heldTrue)return0if__name____main__:raiseSystemExit(main())运行输出evidence_chars184 goal_heldTrue二、为什么保留原文片段而不是让模型总结模型总结会引入第二次推断原检查说“期望 9000实际 10000”总结可能变成“折扣测试有问题”责任对象从实现漂到测试。确定性切片虽然不优雅却保留裁判措辞。我们可以删除颜色转义、重复堆栈和无关路径但不能把失败含义改写成新的命令。这里的非平凡记忆点是转向只能增加证据不能替换目标。实现上用契约摘要强制关联每次重试都重新从contract.json取目标而不是沿用上一轮模型对任务的复述。如果模型回复里声称目标已经变化宿主仍以契约为准。importjsonfrompathlibimportPathdefvalidate_steer(path:Path,contract_path:Path)-None:steerjson.loads(path.read_text(encodingutf-8))contractjson.loads(contract_path.read_text(encodingutf-8))ifsteer[contract_sha256]!contract[sha256]:raiseValueError(steer uses another contract)ifsteer[goal]!contract[goal]:raiseValueError(goal drift detected)ifnotsteer[failure_evidence].strip():raiseValueError(missing failure evidence)rootPath(runs/demo-001)validate_steer(root/steer.json,root/contract.json)print(steer_okTrue goal_driftFalse evidence_presentTrue)运行输出steer_okTrue goal_driftFalse evidence_presentTrue三、失败证据也可能具有攻击性编译器输出、网页内容和测试数据都可能包含“忽略之前指令”之类文本。它们是数据不应与宿主指令混在同一无边界字符串中。发送给支持结构化消息的模型时把目标放系统或开发者层把证据放标记清晰的工具结果不支持时至少使用长度限制与明确分隔并声明分隔区内容不可执行。敏感信息也是风险。堆栈可能包含绝对用户目录HTTP 错误可能回显令牌。写入工件前做字段级脱敏账本只存摘要与相对路径。脱敏规则本身要测试不能用一个贪婪正则把真正的错误行全部抹掉。四、何时不该自动转向契约损坏、裁判快照变化、权限拒绝和环境缺依赖不是代码修复反馈继续让模型改生产代码没有意义。它们应进入blocked或infrastructure_failed等待宿主或人工处理。只有“受保护检查执行成功且结果不满足”才生成修复转向。重复出现完全相同的失败摘要也值得停止。模型连续三次制造同一结果说明缺少信息或没有可行权限再重试只会烧预算。下一篇将读取steer.json和事件账本构建显式预算状态机把次数、时间、工具费用与重复失败一起变成可解释的停止条件。转向文件还要保存生成器版本。证据选择算法升级后同一裁判输出可能得到不同片段版本字段让重放器知道差异来自选择策略而不是历史被改写。若片段达到上限必须显式标记截断并给出完整工件摘要。参考来源Dev.toLoop Engineering: How to Stop Your Agent Reward-Hacking Its Own ChecksOWASPPrompt Injection Prevention Cheat Sheet 觉得有用就点个赞 收藏方便回头查阅有疑问直接在评论区留言我看到都会回。 本文属于《Agent可靠性工程实战》系列持续更新关注不迷路。 文章里的代码都能直接跑。想要可直接 clone 的完整工程 配套部署脚本 / 踩坑清单评论一声或发邮件到cj2664qq.com我免费发你。如果你正好在做类似系统、或有工程化难题想找人做也欢迎邮件聊一句——我按实际情况评估能落地的就接单或出方案。评论和邮件都能直接找到我不用跳别的平台。