(五):失敗反饋不是新目標,用證據(jù)轉(zhuǎn)向守住原始意圖)
本篇讀取上一篇的runs/demo-001/grader_snapshot.json、裁判產(chǎn)生的check_finished事件以及 083 的contract.json??煺照C明失敗來自受保護裁判契約提供不變目標本篇新增steer.py輸出runs/demo-001/steer.json作為下一次模型調(diào)用的唯一指令輸入。一、最危險的反饋是“想當然的總結(jié)”測試輸出可能很長宿主常把它總結(jié)成“測試仍失敗請修復”。這句話丟掉了原目標和具體證據(jù)模型自然把“綠燈”當成優(yōu)化對象。好的轉(zhuǎn)向信息不是重新發(fā)明任務而是原目標、不可變約束和最小失敗片段的組合。它應明確說允許修改哪里、禁止修改哪里并引用裁判原始輸出的摘要。失敗片段不能簡單取最后幾行。不同測試框架可能把關(guān)鍵斷言放在中間末尾只有統(tǒng)計。我們按錯誤關(guān)鍵字選擇相鄰行再施加字符上限完整輸出單獨落盤并求摘要。這樣模型得到足夠定位信息審計者仍能證明片段來自哪份完整證據(jù)。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:只修改允許的生產(chǎn)代碼以滿足原目標不得修改裁判材料。,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二、為什么保留原文片段而不是讓模型總結(jié)模型總結(jié)會引入第二次推斷原檢查說“期望 9000實際 10000”總結(jié)可能變成“折扣測試有問題”責任對象從實現(xiàn)漂到測試。確定性切片雖然不優(yōu)雅卻保留裁判措辭。我們可以刪除顏色轉(zhuǎn)義、重復堆棧和無關(guān)路徑但不能把失敗含義改寫成新的命令。這里的非平凡記憶點是轉(zhuǎn)向只能增加證據(jù)不能替換目標。實現(xiàn)上用契約摘要強制關(guān)聯(lián)每次重試都重新從contract.json取目標而不是沿用上一輪模型對任務的復述。如果模型回復里聲稱目標已經(jīng)變化宿主仍以契約為準。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三、失敗證據(jù)也可能具有攻擊性編譯器輸出、網(wǎng)頁內(nèi)容和測試數(shù)據(jù)都可能包含“忽略之前指令”之類文本。它們是數(shù)據(jù)不應與宿主指令混在同一無邊界字符串中。發(fā)送給支持結(jié)構(gòu)化消息的模型時把目標放系統(tǒng)或開發(fā)者層把證據(jù)放標記清晰的工具結(jié)果不支持時至少使用長度限制與明確分隔并聲明分隔區(qū)內(nèi)容不可執(zhí)行。敏感信息也是風險。堆棧可能包含絕對用戶目錄HTTP 錯誤可能回顯令牌。寫入工件前做字段級脫敏賬本只存摘要與相對路徑。脫敏規(guī)則本身要測試不能用一個貪婪正則把真正的錯誤行全部抹掉。四、何時不該自動轉(zhuǎn)向契約損壞、裁判快照變化、權(quán)限拒絕和環(huán)境缺依賴不是代碼修復反饋繼續(xù)讓模型改生產(chǎn)代碼沒有意義。它們應進入blocked或infrastructure_failed等待宿主或人工處理。只有“受保護檢查執(zhí)行成功且結(jié)果不滿足”才生成修復轉(zhuǎn)向。重復出現(xiàn)完全相同的失敗摘要也值得停止。模型連續(xù)三次制造同一結(jié)果說明缺少信息或沒有可行權(quán)限再重試只會燒預算。下一篇將讀取steer.json和事件賬本構(gòu)建顯式預算狀態(tài)機把次數(shù)、時間、工具費用與重復失敗一起變成可解釋的停止條件。轉(zhuǎn)向文件還要保存生成器版本。證據(jù)選擇算法升級后同一裁判輸出可能得到不同片段版本字段讓重放器知道差異來自選擇策略而不是歷史被改寫。若片段達到上限必須顯式標記截斷并給出完整工件摘要。參考來源Dev.toLoop Engineering: How to Stop Your Agent Reward-Hacking Its Own ChecksOWASPPrompt Injection Prevention Cheat Sheet 覺得有用就點個贊 收藏方便回頭查閱有疑問直接在評論區(qū)留言我看到都會回。 本文屬于《Agent可靠性工程實戰(zhàn)》系列持續(xù)更新關(guān)注不迷路。 文章里的代碼都能直接跑。想要可直接 clone 的完整工程 配套部署腳本 / 踩坑清單評論一聲或發(fā)郵件到cj2664qq.com我免費發(fā)你。如果你正好在做類似系統(tǒng)、或有工程化難題想找人做也歡迎郵件聊一句——我按實際情況評估能落地的就接單或出方案。評論和郵件都能直接找到我不用跳別的平臺。