Eval¶
Use anvil-serving eval to validate and benchmark one explicit served model.
Preflight¶
Run eval preflight before benchmarking a new serve or changed engine recipe.
It checks the explicit endpoint and served-model identifier without changing
the gateway's alias map.
For a tool-call gate after a genuinely long prompt, include long-tools and
set the nominal calibration target. The gate succeeds only when the endpoint
reports at least 100,000 actual prompt tokens and returns the expected
schema-valid call:
anvil-serving eval preflight `
--base-url http://127.0.0.1:30000/v1 `
--model MODEL `
--checks smoke,json,tools,long-tools `
--long-tool-ctx 131072 `
--confirm
Routed client evaluation¶
Use eval routed after direct preflight when a candidate must be exercised
through an existing router alias and the real OpenClaw or Hermes harness. The
command does not install a router profile, change a client default, or promote
the candidate. Before invoking either client, it reconciles the local OpenClaw
and Pi catalogs from the router's authenticated capability contract and
restarts OpenClaw once for a newly observed router configuration hash. Hermes
receives the same context and output limits through the router's standard
GET /v1/models discovery response. The agent calls still use
invocation-scoped model overrides and write one fail-closed evidence artifact.
The router identity, readiness, tier configuration fingerprint, router
configuration hash, capacity context, and /v1/models discovery context are
checked before reconciliation. Eval then requires the sanitized reconciliation
receipt to name that exact router hash and alias context, re-reads the router,
and refuses client calls if the hash changed during the transaction. OpenClaw
must additionally report that exact context and the requested winner with
fallbackUsed=false. Hermes must record the expected provider and model in its
usage artifact. Each client must use its real shell tool to read a temporary
random nonce that is absent from the prompt, then continue with that exact tool
result. A matching answer from a fallback model or an answer that was merely
copied from the prompt is therefore a failure.
anvil-serving eval routed `
--base-url http://127.0.0.1:8000/v1 `
--model llm.primary `
--api-key-env ANVIL_ROUTER_TOKEN `
--expected-served-model SERVED_MODEL `
--expected-config-fingerprint CONFIG_ID `
--expected-router-config-sha256 ROUTER_CONFIG_SHA256 `
--min-context-tokens 250000 `
--clients openclaw,hermes `
--output artifacts/routed-client-eval.json `
--confirm
Use --dry-run to inspect the client overrides and credential-variable name
without sending a router request, starting a client turn, or writing evidence.
Run this command on the host that owns the selected client harnesses. The
default Hermes selector is anvil; its normalized usage-provider identity is
custom and can be changed explicitly with --hermes-expected-provider.
--no-harness-sync is an explicit diagnostic escape hatch: the router and
real-client gates still run, but eval does not repair a stale OpenClaw/Pi
catalog. A normal qualification should leave reconciliation enabled because
the resulting catalog change makes local client limits truthful to the active
router; it is an exposure synchronization, not a model promotion.
When the operator shell is on another host, dispatch the same command to the declared gateway owner through its controller:
anvil-serving eval routed \
--target host:client-gateway \
--transport controller \
--base-url http://100.64.0.10:8000/v1 \
--model llm.primary \
--api-key-env ANVIL_ROUTER_TOKEN \
--expected-served-model SERVED_MODEL \
--expected-config-fingerprint CONFIG_ID \
--expected-router-config-sha256 ROUTER_CONFIG_SHA256 \
--min-context-tokens 250000 \
--clients openclaw,hermes \
--confirm
Controller dispatch sends only the credential environment-variable name. The
owning controller must expose the typed routed_eval operation and its
topology transport must allow eval-routed. Live evidence defaults to the
owning host's private ~/.anvil-serving/evidence/routed-eval/ directory;
remote --output values are confined to that tree. This transport performs
the same router-hash, catalog, real-client, and no-fallback gates as a local
run; it is not a reduced remote smoke.
Benchmark¶
| Command | Purpose |
|---|---|
eval preflight |
Run functional compatibility checks against an endpoint. |
eval routed |
Reconcile router-derived client limits, then verify one alias through real OpenClaw and Hermes turns. |
eval benchmark context |
Run durable context-degradation jobs on a registered worker. |
eval benchmark agentic |
Run deterministic agentic and recovery jobs. |
eval benchmark swe |
Run pinned mini-SWE-agent plus the official SWE-bench grader. |
eval benchmark capacity |
Measure throughput and latency. |
eval benchmark multimodal |
Run a hash-pinned image/video/mixed-media corpus. |
eval benchmark quality |
Run a repeatable quality suite with retained evidence. |
eval benchmark external |
Import and compare advisory external benchmark priors. |
eval usage |
Summarize local evaluation usage. |
The multimodal runner admits at most four images and one video per corpus case
by default. When qualifying a recipe with higher engine-side media limits,
raise only the recorded corpus ceilings with --max-images-per-request N
(maximum 64) and --max-videos-per-request N (maximum 16). Both selected
ceilings are retained in the evidence artifact; they do not change the serving
recipe or router policy.
Capacity runs use a deterministic context plan by default. Keep the seed, request count, concurrency, context policy, completion cap, and endpoint recipe identical when comparing candidates:
anvil-serving eval benchmark capacity `
--base-url http://127.0.0.1:30002/v1 `
--model MODEL `
--engine vllm `
--gpu <gpu-label> `
--requests 100 `
--concurrency 8 `
--ctx-tokens 4096 `
--max-tokens 512 `
--temperature 1.0 `
--top-p 0.95 `
--response-words 256 `
--controlled-output-policy strict `
--prompt-cache-mode unique `
--request-canaries `
--seed 0 `
--output artifacts/capacity.json `
--confirm
--temperature accepts a finite value from 0 through 2; --top-p accepts a
finite value greater than 0 through 1. Both are optional for capacity and
quality. Without --temperature, the existing 0.0 request behavior remains;
without --top-p, no top_p field is sent. Artifacts retain requested,
effective, and sent sampler values. Comparison and recipe reporting bind those
values, so runs with different or unrecorded sampling are not comparable.
The capacity artifact records the requested context distribution, the sampling
seed, engine/hardware target, completed and failed requests, sanitized failure
classes, and how output tokens were counted. Measurement protocol capacity-v3
uses exact usage.prompt_tokens and usage.completion_tokens to retain
per-request and aggregate TTFT, effective prefill rate, generation duration,
decode rate, TPOT, the backward-compatible mean-inter-token-latency proxy, E2E
latency, and token counts. TPOT and mean_inter_token_latency_ms are the same
request-level mean (generation / (completion tokens - 1)), not raw
token-arrival ITL.
Effective prefill includes queueing, scheduling, prompt processing, and
first-token work; it is not a kernel-only measurement. When exact usage is
unavailable, token-derived rates are null and content-chunk rate is retained
only as a diagnostic.
--controlled-output-policy observe is the backward-compatible default. It
records requested/observed word counts, extra words, capture completeness, and
exact adherence but does not fail a non-exact response. Use strict for
finalist comparisons; it requires nonzero --response-words and excludes a
non-exact or capture-truncated response from performance metrics. The visible
validation capture is capped at 8,192 characters. With
--request-canaries, the response must begin with its own marker and contain
no other ANVIL_REQ marker. Failed and contract-invalid responses retain
sanitized timing and token/finish metadata, never prompts or full response
bodies. An incomplete population is marked performance_eligible: false and
does not publish aggregate throughput_tok_s.
When two independent replicas share one physical host clock, give both runs
the same public-safe --clock-domain-id and the same
--configuration-fingerprint sha256:<64-lowercase-hex> for the normalized
configuration. The artifacts retain nanosecond Unix timestamps, but the
combiner treats them as aligned only when the clock-domain identifiers match;
never reuse one across hosts. The fingerprint is a declared identity binding,
not independent attestation.
Legacy replica artifacts without these fields remain usable as bounded
evidence when they share the same whole-second UTC start and finish buckets.
Their aggregate reports wall-time and throughput ranges, uses the conservative
lower bound in metrics.throughput_tok_s, and labels missing identity or modern
output-validation proof. See Repeatable campaigns.
Quality runs require an explicit built-in suite or an externally authored suite file plus stable candidate and configuration identities:
anvil-serving eval benchmark quality `
--base-url http://127.0.0.1:30002/v1 `
--model MODEL `
--candidate-id MODEL `
--config-id vllm-primary-v1 `
--suite-file suites/quality.json `
--temperature 1.0 `
--top-p 0.95 `
--output artifacts/quality.json `
--confirm
Use --dry-run to resolve and validate either workload without probing the
endpoint or writing an artifact. Flags take precedence over a referenced serves
manifest, which takes precedence over the bundled reference manifest. A direct
target requires both --base-url and --model.
The context, agentic, and SWE family root is the plan/dry-run surface; each
family also provides explicit prepare, preflight, submit, status,
logs, cancel, and artifact operations. Submission is
durable and launches an isolated worker process; --detach returns after that
launch. Use the controller transport for a registered remote worker rather
than SSH. The complete specification, profile costs, evidence semantics, and
examples are in Context, agentic, and SWE benchmark jobs.
Benchmark evidence¶
Run preflight before a benchmark and retain artifact identity, endpoint, served model, hardware, engine, quantization, context, concurrency, failures, and caveats. Evaluation never changes a capability alias or serve automatically.
A nonzero exit means the requested workload did not complete or satisfy its gate. A stream without visible content is a failed request; it is not rewritten as a successful zero-TTFT completion.
Benchmark recipe report¶
Render the measured recipe finder from a reviewed catalog and native capacity artifacts. The command is offline and does not call a model. Numeric values, request counts, workload conditions, and source SHA-256 values come from artifacts; strengths, limitations, and recipe selection are reviewed catalog annotations.
python -m anvil_serving.cli eval benchmark report docs/benchmarks/recipe-catalog.json --root . --output docs/benchmarks/recipe-results.md --confirm
python -m anvil_serving.cli eval benchmark report docs/benchmarks/recipe-catalog.json --root . --output docs/benchmarks/recipe-results.md --check
Without --output, Markdown is written to stdout. Use --format json for
the compact resolved report without prompts or full responses. --check
fails when the generated file differs, including after a source artifact or
catalog edit. Files must stay within --root; outputs cannot overwrite an
input. Publication workflow: Repeatable campaigns.
External benchmarks¶
External benchmark records are advisory priors. Keep their source and snapshot provenance separate from locally recorded preflight and benchmark evidence.