feat: push eval runs to the platform with uv run eval --push#1947
Draft
mikasenghaas wants to merge 14 commits into
Draft
feat: push eval runs to the platform with uv run eval --push#1947mikasenghaas wants to merge 14 commits into
uv run eval --push#1947mikasenghaas wants to merge 14 commits into
Conversation
Convert each in-memory v1 Trace to the platform's (v0) eval-sample format and upload the finished run over the /evaluations/ API (create -> push samples -> finalize), the same contract `prime eval push` uploads a saved run through. Off by default; gated behind --push. Covers v1, server, and v0 legacy runs (all three converge on list[Trace]). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Move the Trace -> platform (v0) eval-sample conversion into a dependency-light `verifiers/v1/samples.py` so it can be shared with the prime-rl monitor's sample upload (companion PR), keeping one canonical "old format" mapping. Bake in a non-finite-float guard (`drop_non_finite`) so NaN/Inf rewards/metrics can't emit invalid JSON on the eval push or land as bad sample data in either producer. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Non-finite rewards/metrics only arise from custom numpy aggregations over empty inputs (rare, author-specific) and would fail the push loudly rather than corrupt data. Keep the shared converter single-purpose. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Conservative test additions: the converter is exercised end-to-end by eval --push and the prime monitor's sample upload. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
push_traces uploaded only the mean reward as the run's metrics, dropping every env-recorded metric and the error rate - the platform summary no longer matched the eval dashboard. Aggregate per-key means over the traces that recorded each metric and the errored fraction, matching v0's avg_reward/avg_metrics/avg_error accumulators. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- push: emit run metrics in the platform's canonical {reward, metrics, error}
shape (was avg_reward/avg_metrics/avg_error); the metrics breakdown now
includes the per-reward-function values, not just env metrics.
- push: put model + counts in evaluation metadata so the overview resolves the
model (was Unknown Model) instead of only setting model_name.
- samples: drop num_steps (rendered as stray custom state) and carry the
per-reward-function / metric breakdown in info.reward_signals, the recognized
nested key, since the platform folds unknown top-level sample fields into info.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…promote sample columns) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The platform promotes a numeric sample field to a per-rollout reward column only when its name ends in reward / reward_func / score (the v0 reward-function naming); anything else folds into the sample's info. v1 reward functions (e.g. 'solved') lack that suffix, so they were being buried in info. trace_to_sample now flattens each sub-reward under a reward_column_name() key (appending _reward_func when a v1 name lacks a recognized suffix), and push_traces declares the same names in metadata.avg_metrics so the overview lines up. Env metrics stay in the nested metrics field / info, as they do for v0. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The run has already finished and results are saved by the time push_traces runs, so a network blip or platform 4xx/5xx (raise_for_status) / JSON decode error must not propagate. Wrap the HTTP flow in try/except that logs and returns None; on the non-rich path this also preserves the final per-trace JSON output, which prints after the push call. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Remove the per-branch `reward` from each trajectory entry (redundant with the sample-level reward; not needed by consumers). - Drop `reward_column_name` / `_REWARD_COLUMN_SUFFIXES`: flatten sub-rewards under their raw function names instead of appending `_reward_func`, and aggregate the same raw names in `metadata.avg_metrics`. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
config.num_tasks is None for a full run, leaving num_examples blank in the uploaded evaluation metadata. Use the number of distinct example ids among the pushed traces so num_examples * rollouts_per_example matches the samples. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
| "avg_error": sum(t.has_error for t in traces) / n if n else 0.0, | ||
| } | ||
|
|
||
| env_name = config.taskset.id or config.id |
There was a problem hiding this comment.
🟡 Medium v1/push.py:77
env_name is set to config.taskset.id or config.id and sent to the platform as the environment name in the /environmentshub/resolve call. When the id is a hub-style plugin id like org/name@version, the resolve request uses that raw plugin id instead of the canonical package name, so the run gets attached to the wrong environment and won't match what prime eval push and other producers upload. Consider normalizing env_name with the same env_name(...) transformation used elsewhere in the codebase before sending it to the API.
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @verifiers/v1/push.py around line 77:
`env_name` is set to `config.taskset.id or config.id` and sent to the platform as the environment name in the `/environmentshub/resolve` call. When the id is a hub-style plugin id like `org/name@version`, the resolve request uses that raw plugin id instead of the canonical package name, so the run gets attached to the wrong environment and won't match what `prime eval push` and other producers upload. Consider normalizing `env_name` with the same `env_name(...)` transformation used elsewhere in the codebase before sending it to the API.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
--pushflag touv run eval(off by default) that uploads a finished run to the Prime Intellect platform's private Evaluations tab at the end of the eval.verifiers/v1/samples.py:trace_to_sample, the canonical per-trace → platform (v0) eval-sample converter. Extracted so it is the single source of truth for the "old format" mapping and can be shared with the prime-rl monitor (see companion PR).verifiers/v1/push.py: a tiny sync client (push_traces) that does the/evaluations/flow — resolve env by name (get-or-create) → create evaluation → push samples → finalize — then logs the evaluation id. Auth + base URL reuse the existing CLI plumbing ($PRIME_API_KEY/~/.prime/config.json, team-scoped). No new dependencies; no dependency onprime/prime-evals(would be circular).verifiers/v1/cli/eval/main.pywhere all three execution paths (v1 in-process,--server, and v0 legacy--id) have producedlist[Trace], so one hook covers every run type.Platform record shape
Matched to what the platform's Evaluations UI reads, verified by round-tripping real pushes against
api.primeintellect.ai:model,num_examples(distinct examples uploaded —config.num_tasksisNoneon a full run),rollouts_per_example, and theavg_reward/avg_metrics/avg_errortriple go in the evaluationmetadata, which the overview reads.metricsfield /info.num_stepsand the per-branchrewardare not emitted (stray custom state / redundant).Crash safety
The upload runs after the eval has finished and saved results, so
push_traceswraps the HTTP flow in a try/except that logs and returnsNone— a network blip or platform 4xx/5xx never crashes the run (and on the non-rich path never swallows the final per-trace JSON output).Companion PR
prime-rl's monitor pushes training-run samples through its own hand-rolled copy of this conversion. The companion PR switches it to
verifiers.v1.samples.trace_to_sampleso both producers stay aligned on one canonical record shape:PrimeIntellect-ai/prime-rl#2974
Verification
Live smoke runs against
api.primeintellect.ai(deepseek/deepseek-v4-flash), all COMPLETED; each withmetadata.modelandnum_examplespopulated:uv run eval gsm8k_v1 --push -n 4 -r 2):https://app.primeintellect.ai/dashboard/evaluations/mvh563t4vtgkjulr8toze5ni
uv run eval --id gsm8k --push -n 2 -r 1):https://app.primeintellect.ai/dashboard/evaluations/y7v4jwd69mm2grlo9uco581e
uv run eval code-golf-v1 --push -n 2 -r 2— 3 reward funcscorrect/most_concise/fastest):https://app.primeintellect.ai/dashboard/evaluations/l9f7gw6m3ru8u8akz348zjku
uv run eval gsm8k_v1 --harness.id rlm --push -n 2 -r 1— harness metrics inavg_metrics+info.metrics):https://app.primeintellect.ai/dashboard/evaluations/fm16rw1nw6h2pe0h6vroe1nk
uv run eval terminal-bench-2-v1 --taskset.tasks '["fix-git"]' --harness.runtime.type docker --push -r 1):https://app.primeintellect.ai/dashboard/evaluations/e4684w1hkiw0lbz3ajmamtsl
… --harness.id rlm --harness.summarize_at_tokens 4000 --harness.runtime.type docker --push -r 1— compacted, 2 trajectory branches):https://app.primeintellect.ai/dashboard/evaluations/oprmzd1plk4srcc42zesqy2m
Without
--push, behavior is unchanged.ruff check,ruff format, andtests/v1/test_configs.pypass.