Skip to main content
Applies to:
  • Plan -
  • Deployment -

Summary

Goal: Make interrupted eval workers resume onto the same experiment rows instead of appending duplicates. Features: upsert_id (TypeScript Eval), experiment.log() with stable id, _object_delete insert flag, attemptId metadata tagging.

Configuration steps

Step 1: Set a stable row ID in TypeScript Eval

Use upsert_id on each EvalCase, derived from a value that is stable across retries (e.g., sample ID or input hash).
Retries that supply the same upsert_id land on the same logical row in the UI.

Step 2: Set a stable row ID when logging manually

If you are using lower-level experiment logging instead of the Eval API, pass the stable key as id.
This applies to both TypeScript and Python when calling experiment.log() directly.

Step 3: Understand Python Eval limitations

Eval() in Python does not expose an equivalent upsert_id field on EvalCase. Options:
  • Use lower-level experiment.log() with a stable id (see Step 2).
  • Implement resume logic in your worker to skip already-completed cases before starting the eval.

Step 4: Tag every span with a unique attemptId

Stable row IDs do not automatically remove child spans from a prior interrupted attempt. Tag every span (root and children) with an attempt-scoped value so stale spans can be identified later.

Step 5: Delete stale child spans from a prior attempt

Query for spans with the old attemptId, then delete them via the insert endpoint.
Repeat for each stale child span from the interrupted attempt.

Step 6: Alternative — use a fresh experiment per attempt

If managing stale span cleanup is too complex, create a new experiment for each retry attempt and designate the final successful experiment as canonical. This avoids orphan span cleanup entirely.

Behavior notes

  • Experiment inserts are append-only. Reusing a stable id does not rewrite history; it creates a new version. The UI displays the latest version per row.
  • Reusing a stable row id on retry does not delete child spans from the previous attempt. Orphan spans must be removed explicitly using _object_delete.
  • Do not manually set span_id or root_span_id as the primary deduplication strategy. The high-level Eval runner manages these internally, and overriding them can produce rows with multiple traces.