docs(tutorials): add Inspect AI evaluation tutorial and notebook - #628
Conversation
Adds a tutorial and Colab notebook for evaluating OpenEnv agents with Inspect AI via InspectAIHarness. Uses a unified solver design that works transparently with OpenAI, Anthropic, and HF Inference Providers — the HF path calls InferenceClient via run_in_executor and bypasses generate() while still producing a structured EvalResult. Also adds model_base_url parameter support to InspectAIHarness. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Simplifies the Inspect AI tutorial and notebook to support only OpenAI and Anthropic via their APIs. The HF path (InferenceClient bypass) triggered local model weight downloads when users misused the hf/ prefix, and InferenceClient is not natively supported by Inspect AI's model routing. Removing it eliminates the confusion and keeps the notebook straightforward. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…apacity-limited envs The free HF Space echo_env only allows 1 concurrent WebSocket session. Inspect AI's default concurrency tries all samples in parallel, causing CAPACITY_REACHED errors for samples 2-5. Adding max_connections=1 to eval_parameters serializes processing. Also adds max_connections to the InspectAIHarness forwarded parameter list. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
max_connections limits model API concurrency, not env WebSocket concurrency. Inspect AI still dispatches all samples concurrently, causing all 5 to attempt simultaneous WebSocket connections against the single-session HF Space. A module-level Semaphore(1) in the solver ensures env connections are opened one at a time, regardless of Inspect AI's internal scheduling. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
EvalConfig stores the Task object in eval_parameters for harness routing, but Task is not JSON-serializable. Use a fallback encoder that str()-ifies any non-serializable type instead of crashing. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
….5B) Shows how to evaluate a local HuggingFace model via Inspect AI's hf/ prefix, covering both Hub IDs and local checkpoint paths from TRL training. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…grade for hf/ backend Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…rmers line Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…_CONCURRENT_ENVS Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ebsite - Use ECHO_ENV_URL variable in EvalConfig (notebook and .md now identical) - Add temperature comment noting it should be omitted for hf/ backend - Fix Next Steps links in notebook and .md to point to meta-pytorch.org/OpenEnv instead of raw GitHub .md file URLs Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Greptile SummaryThis PR adds a new Inspect AI evaluation tutorial ( Confidence Score: 4/5Safe to merge; only a P2 style concern in the notebook's API-key cell. All code changes are correct and minimal. The single P2 finding (hardcoded API key placeholder pattern in the notebook) is a best-practice concern, not a functional defect. P2s alone cap at 4/5. examples/evaluation_inspect.ipynb — API key cell pattern. Important Files Changed
Sequence DiagramsequenceDiagram
participant User
participant InspectAIHarness
participant inspect_eval
participant Solver
participant MCPToolClient
User->>InspectAIHarness: run_from_config(EvalConfig)
InspectAIHarness->>inspect_eval: eval(task, model, max_connections, model_base_url, ...)
loop For each Sample
inspect_eval->>Solver: solve(state, generate)
Solver->>Solver: generate(state) [LLM call]
Solver->>MCPToolClient: reset()
Solver->>MCPToolClient: call_tool("echo_message", ...)
MCPToolClient-->>Solver: echoed result
Solver->>MCPToolClient: close()
Solver-->>inspect_eval: updated TaskState
end
inspect_eval-->>InspectAIHarness: EvalLog[]
InspectAIHarness->>InspectAIHarness: _extract_scores(logs[0])
InspectAIHarness-->>User: EvalResult { scores: {accuracy: 1.0} }
Prompt To Fix All With AIFix the following 1 code review issue. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 1
examples/evaluation_inspect.ipynb:60
**Hardcoded API key placeholder encourages insecure notebook hygiene**
Setting the key as a string literal in a cell trains users to put their real secret at the same position — notebooks get accidentally committed or shared, leaking credentials. Using `getpass` prompts for the key at runtime and avoids storing it in the cell output or notebook JSON.
```suggestion
import getpass, os
os.environ.setdefault("OPENAI_API_KEY", getpass.getpass("OpenAI API key: "))
MODEL = "openai/gpt-4o-mini"
```
Reviews (1): Last reviewed commit: "docs(tutorials): sync notebook with .md ..." | Re-trigger Greptile |
…laceholder Replaces `os.environ["KEY"] = "sk-..."` with `os.environ.setdefault(KEY, getpass.getpass(...))`. Keys are prompted at runtime and never stored in cell output or notebook JSON. `setdefault` makes the prompt a no-op when the var is already in the environment. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…utorial Adds a tip block encouraging users to run eval before training to establish a baseline. Updates model references from gpt-4o-mini to gpt-5-mini. Adds end-to-end walkthrough and SFT warm-up tutorial links to the Next steps section. Removes the time/difficulty/gpu metadata note from the header. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
burtenshaw
left a comment
There was a problem hiding this comment.
Approved per maintainer merge request after required checks passed.
burtenshaw
left a comment
There was a problem hiding this comment.
Approved per maintainer merge request after required checks passed.
Summary
Adds
docs/source/tutorials/evaluation-inspect.mdand a matchingexamples/evaluation_inspect.ipynbColab notebook covering how to evaluate OpenEnv agents with Inspect AI'sInspectAIHarness. The tutorial walks through defining aTask(dataset + solver + scorer), usingasyncio.Semaphoreto serialise concurrent env connections, and running a structuredEvalResultviaInspectAIHarness. Also addsmodel_base_urlandmax_connectionsforwarding toInspectAIHarness.run(), discovered as needed while writing the tutorial.Type of Change
Alignment Checklist
Before submitting, verify:
.claude/docs/PRINCIPLES.mdand this PR aligns with our principles.claude/docs/INVARIANTS.mdand no invariants are violated/pre-submit-pr(orbash .claude/hooks/lint.shand tests) and addressed all issuesRFC Status
Test Plan
cd docs && make html, then opendocs/_build/html/tutorials/evaluation-inspect.htmlhttps://meta-pytorch.org/OpenEnv/tutorials/examples/evaluation_inspect.ipynbin Jupyter (or Colab); run all cells with a valid OpenAI or Anthropic API key — expected result:{'accuracy': 1.0}printed after the harness runPYTHONPATH=src:envs uv run pytest tests/core/test_evals/test_inspect_harness.py -v— all 23 passuv run ruff format src/openenv/core/evals/inspect_harness.py --check && uv run ruff check src/openenv/core/evals/inspect_harness.pyClaude Code Review
Automated Checks
inspect_harness.pywas reformatted as part of this PR; pre-existing failures inchat_env,repl_env,textarena_envare not in scopeOpen RFCs Context
agentic-harnesses) covers theEvalHarnessinfrastructure this tutorial builds on. Changes here are additive and compatible — no conflicts.Tier 1: Fixes Required
None.
Tier 2: Alignment Discussion
None identified. The tutorial uses
MCPToolClient(correct for MCP envs), keeps all reward logic inside the environment, and does not expose reset controls to the agent. The harness change is a transparent parameter pass-through toinspect_ai.eval().Summary