Skip to content

Process-Reward-Annotation

Reward-Signale pro Schritt für das Training von Process Reward Models erheben, im First-Error-Modus oder pro Schritt. Direkter Export in die Trainingsformate PRM, DPO und SWE-bench.

Neu in v2.4.0

Process Reward Models (PRMs) brauchen Korrektheitslabels pro Schritt statt einer einzigen Bewertung des Endergebnisses. Ein brauchbares PRM zu trainieren heißt, Annotationen zu sammeln, die genau festhalten, an welcher Stelle eines mehrstufigen Trace der Agent falsch abgebogen ist, welche Art von Fehler auftrat und ob eine Erholung möglich war. Das unterscheidet sich von der ergebnisbasierten Annotation, bei der nur das Endresultat beurteilt wird.

Potato bietet zwei Annotationsmodi, die auf unterschiedliche Abwägungen zwischen Tempo und Detailtiefe beim Sammeln von Process-Reward-Daten ausgelegt sind. Der First-Error-Modus ist auf schnelles binäres Labeling ausgelegt: Der Annotator klickt den ersten inkorrekten Schritt an, alle nachfolgenden Schritte werden automatisch als verdorben markiert. Der Modus pro Schritt verlangt vom Annotator eine eigenständige Bewertung jedes Schritts und liefert reichhaltigere Signale, kostet dafür aber mehr Annotationszeit.

Beide Modi arbeiten mit der Coding-Trace-Anzeige, der Agent-Trace-Anzeige und der Web-Agent-Anzeige zusammen, sodass sich Process Rewards für jede Art von Agent-Trace erheben lassen.

First-Error-Modus

Im First-Error-Modus liest der Annotator den Trace der Reihe nach durch und klickt auf den ersten Schritt, in dem der Agent einen Fehler gemacht hat. Alle Schritte vor dem angeklickten werden automatisch als korrekt gelabelt. Der angeklickte Schritt und alle folgenden werden als inkorrekt gelabelt (der angeklickte als „erster Fehler", der Rest als „Folge des Fehlers").

Daraus entsteht genau das Labelformat, das für das Training binärer PRMs gebraucht wird: eine Folge von +1-Labels, dann eine -1 an der Fehlerstelle und -1 für alle übrigen Schritte.

Konfiguration

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)"

Annotationsablauf

  1. Der Annotator liest den Trace von oben nach unten
  2. Die Schritte sind zunächst unmarkiert (grau)
  3. Der Annotator klickt den ersten inkorrekten Schritt an
  4. Die Schritte 0 bis N-1 werden grün (korrekt)
  5. Schritt N wird rot (erster Fehler)
  6. Die Schritte N+1 bis zum Ende werden orange (Folge des Fehlers)
  7. Ist der gesamte Trace korrekt, klickt der Annotator auf „All Steps Correct"

Ausgabeformat

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]
    }
  }
}

Markiert der Annotator alle Schritte als korrekt, ist first_error_step gleich null und das Label-Array enthält ausschließlich 1.

Modus pro Schritt

Im Modus pro Schritt bewertet der Annotator jeden Schritt des Trace eigenständig. Das liefert reichhaltigere Signale, denn ein Schritt kann „teilweise korrekt" oder „überflüssig" sein statt nur korrekt oder inkorrekt. Außerdem lassen sich damit Fälle erfassen, in denen sich der Agent von einem Fehler erholt, was der First-Error-Modus nicht abbilden kann.

Konfiguration

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

Annotationsablauf

  1. Neben jedem Schritt des Trace steht ein Bewertungselement
  2. Der Annotator wählt für jeden Schritt ein Label
  3. Ist ein Schritt als „Incorrect" oder „Partially Correct" bewertet und sind Fehlerkategorien aktiviert, erscheint ein Dropdown zur Auswahl des Fehlertyps
  4. Ein optionales Notizfeld erlaubt eine Erklärung im Freitext
  5. Ein laufender Punktestand oben zeigt den kumulativen Reward

Ausgabeformat

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
    }
  }
}

Konfigurationsreferenz

Alle Konfigurationsoptionen des Process-Reward-Annotationsschemas:

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"

Export in Trainingsformate

Potato exportiert Process-Reward-Annotationen direkt in die Formate, die gängige PRM-Trainingspipelines verwenden.

PRM-Trainingsformat

Binäre Labels auf Schrittebene für das PRM-Training exportieren:

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

Ausgabeformat:

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}
  ]
}

Präferenzpaare für DPO / RLHF

Liegen mehrere annotierte Traces zur selben Aufgabe vor, lassen sich paarweise Präferenzen für DPO- oder RLHF-Training exportieren. Der Exporter paart Traces, bei denen einer einen höheren kumulativen Reward hat als der andere:

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

Ausgabeformat:

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-kompatible Ergebnisse

Evaluationsergebnisse in einem Format exportieren, das mit Einreichungen für das SWE-bench-Leaderboard kompatibel ist:

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

Das erzeugt das übliche SWE-bench-Evaluations-JSON mit Instanz-IDs, Modell-Patches und dem Lösungsstatus, abgeleitet aus den Urteilen der Annotatoren.

Auswertung

Potato bringt Hilfsfunktionen für die Auswertung von Process-Reward-Annotationen mit:

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}")

Visualisierung

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"
)

Forschungskontext

Die Process-Reward-Annotation in Potato ist darauf ausgelegt, Forschung zum Training und zur Evaluation von Reward-Modellen für agentische Systeme zu unterstützen. Mehrere aktuelle Arbeitslinien motivieren dieses Feature:

  • AgentPRM zeigt, dass Process Reward Models, die auf Labels pro Schritt trainiert wurden, Outcome Reward Models beim Steuern von Coding-Agenten während der Suche deutlich übertreffen.
  • ToolRM und ToolRL zeigen, dass auf Tool-Nutzungsschritte spezialisierte Reward-Modelle die Agentenleistung bei API-Aufrufen und Codegenerierung verbessern können.
  • DeepSWE wendet Process Reward Models auf Software-Engineering-Aufgaben im Maßstab von SWE-bench an und trainiert mit Labels pro Schritt Verifizierer, die die Baumsuche des Agenten steuern.
  • Step-level RLHF zeigt in der Forschung, dass menschliches Feedback pro Schritt sample-effizientere Reward-Modelle liefert als Feedback auf Episodenebene.

Der First-Error-Modus und der Modus pro Schritt bilden die Labelformate dieser Ansätze direkt ab. Die Export-Pipeline liefert trainingsfertige Daten ohne zusätzliche Vorverarbeitung.

Siehe auch

Implementierungsdetails stehen in der Quelldokumentation.