:失敗反饋不是新目標,用證據轉向守住原始意圖)
本篇讀取上一篇的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我免費發你。如果你正好在做類似系統、或有工程化難題想找人做也歡迎郵件聊一句——我按實際情況評估能落地的就接單或出方案。評論和郵件都能直接找到我不用跳別的平臺。