Skip to content

プロセス報酬アノテーション

first-errorモードとステップごとモードで、PRM訓練用のステップ単位の報酬シグナルを収集します。PRM、DPO、SWE-benchの訓練形式へ直接エクスポートできます。

v2.4.0の新機能

プロセス報酬モデル(PRM)には、結果レベルのスコア1つではなく、ステップごとの正誤ラベルが必要です。実用的なPRMを訓練するには、マルチステップのトレースのどこでエージェントが誤ったのか、どんな種類のエラーだったのか、そこから立て直せたのかを示すアノテーションを集めることになります。最終結果だけを判定する結果ベースのアノテーションとは、ここが違います。

Potatoには、プロセス報酬データを集める際の速度と詳細さのバランスが異なる2つのアノテーションモードがあります。first-errorモードは素早い二値ラベリング向けで、アノテーターが最初の誤ったステップをクリックすると、それ以降のステップはすべて自動的に汚染されたものとしてマークされます。ステップごとモードでは、アノテーターが各ステップを独立に評価するため、アノテーション時間は増えますが、より情報量の多いシグナルが得られます。

どちらのモードもコーディングトレース表示、エージェントトレース表示、Webエージェント表示と組み合わせられるので、どの種類のエージェントトレースでもプロセス報酬を収集できます。

first-errorモード

first-errorモードでは、アノテーターがトレースを順に読み進め、エージェントが最初に誤ったステップをクリックします。クリックしたステップより前のステップは自動的に正しいとラベル付けされます。クリックしたステップとそれ以降は誤りとしてラベル付けされます(クリックしたステップは「最初のエラー」、残りは「エラーの下流」となります)。

これは二値のPRMを訓練するのに必要なラベル形式そのものです。+1のラベルが並び、エラーの地点で-1になり、残りのステップもすべて-1になります。

設定

yaml
annotation_schemes:
  - name: process_reward
    annotation_type: process_reward
    mode: first_error
    description: "Click the first step where the agent made a mistake"
 
    first_error:
      # Visual styling
      correct_color: "#22c55e"     # green for steps before the error
      error_color: "#ef4444"       # red for the first error step
      downstream_color: "#f97316"  # orange for steps after the error
      unmarked_color: "#6b7280"    # gray for steps not yet reviewed
 
      # Behavior
      require_confirmation: true   # ask "Are you sure?" before marking
      allow_no_error: true         # allow annotator to mark all steps correct
      show_step_content: true      # show step content in the annotation panel
 
      # Labels applied automatically
      labels:
        correct: "+1"
        first_error: "-1 (first error)"
        downstream: "-1 (downstream)"
        all_correct: "+1 (all correct)"

アノテーションの流れ

  1. アノテーターがトレースを上から下へ読む
  2. 各ステップは最初は未マーク(グレー)
  3. アノテーターが最初の誤ったステップをクリックする
  4. ステップ0からN-1が緑(正しい)に変わる
  5. ステップNが赤(最初のエラー)に変わる
  6. ステップN+1から末尾までがオレンジ(下流)に変わる
  7. トレース全体が正しい場合、アノテーターは「All Steps Correct」をクリックする

出力形式

json
{
  "id": "trace_042",
  "annotations": {
    "process_reward": {
      "mode": "first_error",
      "first_error_step": 4,
      "total_steps": 8,
      "labels": [1, 1, 1, 1, -1, -1, -1, -1]
    }
  }
}

アノテーターが全ステップを正しいとマークした場合、first_error_stepnullになり、ラベルの配列はすべて1になります。

ステップごとモード

ステップごとモードでは、アノテーターがトレースの各ステップを独立に評価します。正誤の二択ではなく「部分的に正しい」「不要」といった評価ができるため、より情報量の多いシグナルが得られます。エージェントがエラーから立て直した場合も捉えられますが、これはfirst-errorモードでは表現できません。

設定

yaml
annotation_schemes:
  - name: process_reward
    annotation_type: process_reward
    mode: per_step
    description: "Rate each step independently"
 
    per_step:
      # Rating options
      labels:
        - value: "correct"
          display: "Correct"
          color: "#22c55e"
          score: 1.0
        - value: "partially_correct"
          display: "Partially Correct"
          color: "#eab308"
          score: 0.5
        - value: "incorrect"
          display: "Incorrect"
          color: "#ef4444"
          score: -1.0
        - value: "unnecessary"
          display: "Unnecessary"
          color: "#f97316"
          score: -0.5
        - value: "recovery"
          display: "Recovery from Error"
          color: "#3b82f6"
          score: 0.25
 
      # Optional error categorization for incorrect/partially correct steps
      error_categories:
        enabled: true
        categories:
          - "Wrong tool selected"
          - "Correct tool, wrong arguments"
          - "Hallucinated information"
          - "Repeated previous step"
          - "Logic error"
          - "Syntax error"
          - "Missed edge case"
          - "Unnecessary step"
          - "Other"
 
      # Behavior
      require_all_steps: true     # all steps must be rated before submission
      allow_notes: true           # optional text field per step
      show_running_score: true    # show cumulative reward score

アノテーションの流れ

  1. トレースの各ステップの横に評価ウィジェットが表示される
  2. アノテーターが各ステップにラベルを選ぶ
  3. ステップを「Incorrect」または「Partially Correct」と評価し、エラーカテゴリが有効な場合は、エラー種別を選ぶドロップダウンが表示される
  4. 任意入力のメモ欄に自由記述で説明を残せる
  5. 上部の実行中スコアに累積報酬が表示される

出力形式

json
{
  "id": "trace_042",
  "annotations": {
    "process_reward": {
      "mode": "per_step",
      "total_steps": 6,
      "labels": [1.0, 1.0, -1.0, 0.25, 1.0, 1.0],
      "step_details": {
        "0": {"label": "correct"},
        "1": {"label": "correct"},
        "2": {
          "label": "incorrect",
          "error_category": "Wrong tool selected",
          "notes": "Agent used grep when it should have read the file directly"
        },
        "3": {
          "label": "recovery",
          "notes": "Agent recognized the mistake and tried a different approach"
        },
        "4": {"label": "correct"},
        "5": {"label": "correct"}
      },
      "cumulative_score": 2.75
    }
  }
}

設定リファレンス

プロセス報酬アノテーションスキーマの設定オプションの一覧です。

yaml
annotation_schemes:
  - name: process_reward
    annotation_type: process_reward
    mode: first_error              # "first_error" or "per_step"
    description: "Process reward annotation"
 
    # Required for mode: first_error
    first_error:
      correct_color: "#22c55e"
      error_color: "#ef4444"
      downstream_color: "#f97316"
      unmarked_color: "#6b7280"
      require_confirmation: true
      allow_no_error: true
      show_step_content: true
 
    # Required for mode: per_step
    per_step:
      labels:
        - value: "correct"
          display: "Correct"
          color: "#22c55e"
          score: 1.0
        - value: "incorrect"
          display: "Incorrect"
          color: "#ef4444"
          score: -1.0
      error_categories:
        enabled: false
        categories: []
      require_all_steps: true
      allow_notes: false
      show_running_score: false
 
    # Common options
    target: agentic_steps          # bind to trace steps
    keyboard_shortcuts:
      enabled: true
      correct: "1"
      incorrect: "2"
      partially_correct: "3"
      unnecessary: "4"
      next_step: "j"
      prev_step: "k"

訓練用形式へのエクスポート

Potatoは、プロセス報酬のアノテーションを、よく使われるPRM訓練パイプラインの形式に直接エクスポートできます。

PRM訓練形式

PRM訓練用に、ステップ単位の二値ラベルをエクスポートします。

bash
python -m potato.export \
  -i output/ \
  -f prm \
  -o results/prm_training_data.jsonl

出力形式:

json
{
  "trace_id": "trace_042",
  "steps": [
    {"content": "Search for Tokyo population", "label": 1},
    {"content": "Parse search results", "label": 1},
    {"content": "Search for NYC population", "label": -1},
    {"content": "Compare populations", "label": -1}
  ]
}

DPO / RLHFの選好ペア

同じタスクについてアノテーション済みのトレースが複数ある場合、DPOやRLHFの訓練用にペアワイズの選好をエクスポートできます。エクスポーターは、一方の累積報酬がもう一方より高いトレース同士をペアにします。

bash
python -m potato.export \
  -i output/ \
  -f dpo \
  -o results/dpo_pairs.jsonl \
  --min-score-gap 0.5

出力形式:

json
{
  "prompt": "Fix the failing test in test_parser.py",
  "chosen": [
    {"role": "assistant", "content": "Step 1: Read the test file..."},
    {"role": "assistant", "content": "Step 2: Identify the bug..."}
  ],
  "rejected": [
    {"role": "assistant", "content": "Step 1: Run all tests..."},
    {"role": "assistant", "content": "Step 2: Edit a random file..."}
  ]
}

SWE-bench互換の結果

SWE-benchのリーダーボード提出と互換の形式で、評価結果をエクスポートします。

bash
python -m potato.export \
  -i output/ \
  -f swebench \
  -o results/swebench_results.json

これにより、インスタンスID、モデルのパッチ、そしてアノテーターの判定から導かれた解決ステータスを含む、標準のSWE-bench評価JSONが生成されます。

分析

Potatoには、プロセス報酬のアノテーションを分析するためのユーティリティ関数が用意されています。

python
from potato.analysis import load_annotations, process_reward_stats
 
# Load annotations
annotations = load_annotations("output/")
 
# Step-level accuracy statistics
stats = process_reward_stats(annotations)
 
print(f"Total traces annotated: {stats['total_traces']}")
print(f"Traces with no errors: {stats['all_correct_count']} ({stats['all_correct_pct']:.1f}%)")
print(f"Average first-error position: step {stats['avg_first_error_step']:.1f}")
print(f"Average steps before error: {stats['avg_correct_prefix_length']:.1f}")
 
# Error distribution by step position
for position, count in stats['error_by_position'].items():
    print(f"  Step {position}: {count} errors")
 
# Error category distribution (per-step mode only)
if 'error_categories' in stats:
    for category, count in stats['error_categories'].items():
        print(f"  {category}: {count}")
 
# Inter-annotator agreement on first-error step
if stats['multi_annotator']:
    print(f"First-error agreement (exact): {stats['first_error_exact_agreement']:.2f}")
    print(f"First-error agreement (within 1): {stats['first_error_near_agreement']:.2f}")

可視化

python
from potato.analysis import plot_error_distribution
 
# Plot error position distribution across all traces
plot_error_distribution(
    annotations,
    output_path="figures/error_distribution.png",
    normalize_by_trace_length=True,
    title="Where Do Agents First Go Wrong?"
)
 
# Plot per-step reward curves
from potato.analysis import plot_reward_curves
 
plot_reward_curves(
    annotations,
    output_path="figures/reward_curves.png",
    group_by="agent_model",
    title="Cumulative Reward by Model"
)

研究上の背景

Potatoのプロセス報酬アノテーションは、エージェント型システム向けの報酬モデルの訓練と評価に関する研究を支えることを想定して設計されています。この機能の背景には、近年のいくつかの研究の流れがあります。

  • AgentPRMは、ステップ単位のラベルで訓練したプロセス報酬モデルが、探索中のコーディングエージェントを導くうえで結果報酬モデルを大きく上回ることを示しています。
  • ToolRMToolRLは、ツール使用のステップに特化した報酬モデルが、API呼び出しやコード生成のタスクでエージェントの性能を高められることを示しています。
  • DeepSWEは、SWE-bench規模のソフトウェアエンジニアリングタスクにプロセス報酬モデルを適用し、ステップごとのラベルでエージェントの木探索を導く検証器を訓練しています。
  • ステップレベルRLHFの研究では、ステップごとの人間のフィードバックが、エピソード単位のフィードバックよりサンプル効率の良い報酬モデルを生むことが示されています。

Potatoのfirst-errorモードとステップごとモードは、これらの手法が使うラベル形式に直接対応しています。エクスポートのパイプラインは、前処理を追加しなくても訓練にそのまま使えるデータを出力します。

参考資料

実装の詳細については、ソースドキュメントを参照してください。