Skip to content
Guides2 min read

從評估到訓練資料:用於 SFT 和 DPO 的軌跡編輯

大多數智慧體評估止步於一個分數。Potato 2.6 的 trajectory_edit 模式讓標註者重寫錯誤的步驟,而不是給它打分,並將每次修正匯出為監督微調目標和 DPO 偏好對。

Potato Team

智慧體評估通常以一個數字收場。標註者讀完一條軌跡,判定第三步出了錯,於是記下一個低分或標記一種錯誤類型。這個數字對於衡量智慧體失敗的頻率很有用,但對於修復智慧體卻幫助不大,因為"第三步錯了"並沒有告訴模型第三步本該是什麼。

即將釋出的 Potato 2.6 加入了一種索要答案而非評分的模式。藉助 trajectory_edit,標註者可以重寫 agent trace(智慧體軌跡)中的步驟——修正搞砸的推理步驟、修復打錯的 tool call(工具呼叫),或加強薄弱的最終答案——而 Potato 會把修正後的軌跡保留在原始軌跡旁邊。隨後,trajectory_correction 匯出器會把每個 (original, corrected) 對轉化為訓練資料:監督微調 目標和 直接偏好最佳化 偏好對。

這正是本文要講的轉變。它把一個評估工具變成了訓練資料生產工具,也改變了人類標註者的時間所產出的東西:不再是一個標籤,而是一個學習訊號。

一個智慧體步驟,顯示為只讀的原始內容和可編輯的修正框,並帶有逐詞差異對比軌跡修正編輯器

編輯而非打分

每個智慧體步驟都呈現為一張卡片,分為兩半:原始文本(只讀),以及一個預填了原始內容的可編輯修正框。標註者直接編輯修正框。在輸入時,會同時發生三件事:

  • 即時的逐詞差異對比,以綠色高亮新增內容、以紅色刪除線標記刪除內容,
  • 統計被改動的詞數和字元數,以及
  • 任何發生改動的欄位上都會出現一個"已編輯"標記。

如果標註者改變主意,"Reset"按鈕可以將某個欄位恢復為原始內容。關鍵在於,所有內容都不是必填的。讀完一條軌跡後認為它正確的標註者只需原樣放著不動,而未經編輯的軌跡不會產生任何訓練對。訊號只來自真實的修正。

配置

該模式指向你資料中的步驟列表,並指定哪些欄位可編輯:

yaml
annotation_schemes:
  - annotation_type: trajectory_edit
    name: corrected_trajectory
    description: "Fix any wrong steps, then correct the final answer"
    steps_key: steps          # instance field holding the step list
    step_text_key: action     # the default per-step editable field
    editable_fields:          # which fields get an editor
      - action
      # - thought             # add to also edit reasoning
    show_diff: true
    show_edit_distance: true
    allow_reset: true
    require_reason_on_edit: false   # add a per-field "reason" input
    edit_final_answer: true
    final_answer_key: final_answer

預設情況下,只有每個步驟的 action 是可編輯的。當你希望標註者既修正智慧體的動作、也修正它的推理時,把 thought 加入 editable_fields;當你希望為每次改動附上書面理由時,設定 require_reason_on_edit: true,這在修正本身也需要被審查時很有幫助。

資料格式就是你的軌跡原本的樣子。該模式從 steps_key 指定的欄位讀取步驟;每個步驟都是一個物件,其欄位可被編輯:

json
{
  "id": "traj_001",
  "task_description": "Find the weather in San Francisco.",
  "steps": [
    {"thought": "Look it up.", "action": "web_search(queyr='SF weather')"},
    {"thought": "Open it.",    "action": "open_url(results[0])"}
  ],
  "final_answer": "It is sunny."
}

queyr 中的拼寫錯誤正是標註者會在修正框中修復的那類問題,它會產生一個只改一個 token 的修正,供模型學習。

從倉庫根目錄執行內建示例:

bash
python potato/flask_server.py start examples/agent-traces/trajectory-correction/config.yaml -p 8000

從修正到訓練檔案

trajectory_correction 匯出器會寫出三個檔案,分別用於不同的下游用途:

  • trajectory_corrections.json 儲存完整記錄:original_trace、重建後的 corrected_trace,以及帶有編輯距離和理由的逐欄位 edits。這是你的審計追蹤。
  • trajectory_sft.jsonl 每條被編輯的軌跡佔一行,{"prompt": <task>, "completion": <corrected_trace>}。修正後的軌跡成為模型被微調去復現的目標。
  • trajectory_dpo.jsonl 每條被編輯的軌跡佔一行,{"prompt": <task>, "chosen": <corrected_trace>, "rejected": <original_trace>}。人類的編輯定義了偏好:修正版優於原始版。

一條軌跡流經差異編輯器,分流成 SFT 和 DPO 檔案,未編輯的軌跡被跳過編輯如何變成 SFT 和 DPO 訓練資料

Anatomy of a DPO record: a shared prompt, the chosen corrected trace, and the rejected original traceOne edit produces one preference pair

DPO 檔案是這裡白送的部分。在普通的偏好資料流水線中,你必須生成或收集一個更差的響應,來與更好的響應配對。而在這裡,更差的響應已經存在(就是智慧體產出的那條原始軌跡),人類的編輯就是修正版被偏好的證據。一次標註同時產出一個 SFT 目標和一個 DPO 對。

哪些會被跳過,以及為什麼重要

未編輯的軌跡會被計數,但會從 SFT 和 DPO 檔案中排除。在未改動的軌跡上訓練對模型毫無教益,更糟的是,它會讓偏好資料集充斥著 chosen == rejected 的對,平添噪聲。被跳過的數量仍會出現在匯出統計中,因此你能看到這一批中有多少已經是正確的——這本身就是關於智慧體品質的有用訊號。在多名標註者的情形下,每個對某條軌跡做過編輯的標註者都會產出一條 SFT/DPO 記錄,因此各自獨立的修正都會貢獻進來。

幾處需要留意的稜角

  • 差異對比是逐詞的。對於不含空格、形似程式碼的工具呼叫,即使只改一個字元,單個 token 也可能顯示為整體被改。在這些情況下,字元距離計數器才是精確的訊號;對於密集的工具呼叫,請相信它而非視覺化的差異對比。
  • 編輯天然與打分搭配。如果你還想在同一條軌跡上獲得逐步的正確性標籤或一套錯誤分類,可以讓一個步驟級的打分模式與編輯器並行執行,這樣一遍處理就能同時產出診斷和修復。

為什麼這很重要

智慧體調優迴圈在"它本該怎麼做"這一步上一直存在瓶頸。分數告訴你模型在哪裡失敗;它們並不產出可供訓練的修正後行為,於是團隊最終要麼撰寫合成修正,要麼為第二輪標註付費。軌跡編輯把這一步併入了評估本身。本來會去給軌跡打分的同一個人,轉而去修復它,而這份修復就是訓練資料。

軌跡編輯隨 Potato 2.6 釋出。完整選項列表見 軌跡編輯文件,編輯前快速閱讀軌跡請看 eval_trace 顯示,匯出器細節請見 匯出格式參考