feat: Add batch evals api - #725
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 87a15e5e03
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "Codex (@codex) review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "Codex (@codex) address that feedback".
| async def _claim(self, run_id: str, action: str) -> bool: | ||
| result = await self.store.get_or_set(self._key(run_id, "claim", action), b"1") | ||
| return result.created |
There was a problem hiding this comment.
Make action claims recoverable after callback interruption
When a submit, task, scorer, classifier, or finalization callback raises—or the worker stops after this claim but before writing its result—the claim remains permanently stored. Every subsequent poll() sees created=False, skips the incomplete action, and can never satisfy the missing stage record, leaving the run in waiting forever with the memory store and generally until the run itself expires with Redis. Use a recoverable lease/state transition or otherwise permit retrying claims whose corresponding result was not persisted.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
solving this right now is overkill
Adds an experimental workflow evaluation API for asynchronous provider operations that complete through polling or webhooks.
Each task or scorer submits one case/trial and collects one result, following the API in the JavaScript SDK PR.
As each task finishes, its scorers and classifiers can start while other tasks remain pending.
API
define_workflow_eval(...)creates aWorkflowEvalwithstart(),status(run_id),poll(run_id), andprocess_submission_result(run_id, ...).WorkflowTask.submit(item, context)receives oneWorkflowTaskItem;collect(submission, context)returns oneWorkflowTaskResult(output=..., metadata=..., tags=...).WorkflowScorerrequires a name, submits oneWorkflowScorerItem, and collects oneWorkflowScorerResult(score=...).WorkflowSubmissionContextcontainsrun_idandsubmission_id.WorkflowSubmissionCompletionPollorWorkflowSubmissionCompletionWebhook.max_concurrencybounds provider callbacks per invocation and defaults to 10.WorkflowEvalMemoryStoresupports local runs;WorkflowEvalRedisStorepersists state through an existing synchronous or asynchronous redis-py client.Cases need stable IDs, either in the data or supplied by
case_id.Each trial gets its own item and submission IDs.
Submission data and collected values must be JSON serializable.
Task metadata merges into case metadata, and returned tags replace case tags.
Ordinary task functions, scorers, and classifiers can be mixed with workflow processors.
Define a workflow
The
providerbelow is an application-owned adapter illustrating submission, status, and result retrieval.Its methods should be implemented using the application's provider SDK.
A deferred scorer uses the same lifecycle:
Polling and webhooks
Use a shared store to resume across processes:
Each
poll()checks existing polling submissions once, without sleeping.Newly submitted downstream work is checked on a later invocation.
status()reads progress without advancing work.Waiting results include counts of pending polling and webhook submissions; completed results include the saved experiment summary.
Provider callback failures are raised after independent work advances, and polling can be retried.
For webhooks, construct the same definition with webhook completion:
The application routes the event to its persisted run ID and handles provider failure events.
Collection callbacks must tolerate replay, including concurrent webhook delivery.
State records, external-ID lookups, atomic claims, and deduplicated progress sets support resumption and prevent duplicate downstream submissions.
Redis records and progress sets expire after seven days by default, configurable through
ttl_ms.Close the Redis client when the application shuts down.
Validation
nox -s test_typespasses pyright, mypy, and all 22 runtime type tests.test_core: 748 passed, 63 skipped, 12 xfailed, and four failures reproduced on the original PR commit (bb1283b8).Three local HTTP tests receive unexpected 502 responses; the git-metadata test has a cassette mismatch.