Architecture
System Overview
Package Map
Environment Abstraction
Everything is an EvalEnvironment. Built-in benchmarks, remote Gym servers, NeMo Skills tasks, lm-eval harness tasks, and VLMEvalKit benchmarks all implement the same contract:
Resolution
The registry resolves environment names in order:
- URI scheme —
lm-eval://task,skills://name,gym://host:port,gym://name,vlmevalkit://dataset,container://image#task - Built-in registry — names registered via
@benchmarkor@register
Evaluation Flow
Solver Protocol
Solvers decouple inference strategy from benchmark logic. The eval loop calls solver.solve(task) and receives a response. In YAML configs, solvers are configured via solver.type in each benchmark.
Executor Protocol
All execution backends implement the Executor protocol (executors/__init__.py):
The CLI dispatches via get_executor(config.cluster.type) and detect_executor(output_dir) — no if/elif trees.
SLURM uses node_pools to declare resource topology. Services and sandboxes reference pools by name, enabling heterogeneous jobs (e.g., GPU nodes for model serving + CPU nodes for sandboxes).
Adding a new executor (e.g. Kubernetes) requires only a new class, a metadata file convention, and a registry entry.
Model Deployment
The orchestration/model_server.py module manages model server lifecycle:
All deployments implement start() -> url, health_wait(), and stop().
Observability Data Model
Resilience and Resume
Multi-benchmark suites use CheckpointManager to track per-benchmark completion:
- Failure isolation: A failing benchmark is caught, logged, and skipped. The suite continues to the next benchmark.
- Checkpoint tracking: Each benchmark’s status (completed/failed) is persisted to disk under the output directory.
- Resume:
--resumeskips completed benchmarks and retries failed ones. Without--resume, checkpoints are cleared for a fresh run.
Sharding
Sharding is transparent to the eval loop. problem_range changes the iteration bounds. The merge step recomputes global metrics from concatenated per-shard results.