Skip to main content

Modalities

Each modality is a dedicated load client aimed at an OpenAI-compatible path. Inputs are JSONL. The sections below show the shapes and a compact working example against the dummy server from the Quickstart.

Authoritative flag lists: CLI Reference and live --help.


LLM​

Measures chat or completion latency, TTFT (streaming), ITL/TPOT, and token throughput against /v1/chat/completions or completions.

Prompt JSONL

{"prompt":"Write a haiku about latency."}
{"prompt":"Summarize coordinated omission in one sentence."}
metrum-ai-bench-cli-llm \
--url http://127.0.0.1:18321/v1/chat/completions \
--api-key dummy \
--scenario example \
--num-requests 100 \
--concurrency 8 \
--prompts prompts.jsonl \
--mode chat \
--streaming \
--model example \
--max-tokens 64 \
--data-log results.jsonl \
--seed 7 \
--warmup-requests 8 \
--request-rate 20 \
--arrival poisson \
--max-concurrency 64 \
--slo ttft=250ms \
--slo e2e=2s

--mode is chat or completion. LLM uses one global --max-tokens (per-request caps are out of scope). In streaming chat and VLM, TTFT defaults to the first reasoning or visible delta for choice 0; visible-answer timing is separate. A reasoning-only length finish is reasoning_truncated, unanswered but non-failing by default; strict mode and --ci-safety reject it. Other completed no-answer streams are no_output_token errors. --ttft-fallback first-token is a deprecated redundant alias; --allow-missing-ttft relaxes the audit. --infer-ttft-from-first-byte is a labelled HTTP header approximation, not a token. Current request/summary output uses v5; compatible consumers can read historical v4 and v3 logs. For accelerator measurements, strongly recommend the Metrum AI all-smi fork.

--extra-body-json merges a JSON object into supported request bodies. A top-level null removes that key rather than sending explicit null; arrays, scalars, and other non-object JSON are rejected. For example, removing max_tokens allows a server-specific max_completion_tokens field. Output token accounting and length validation remain unchanged.

For corpus mixes selected by ISL/OSL statistics, see Prompt library.


VLM​

Same measurement surface as LLM, plus image payload accounting, for vision chat endpoints that accept image_url / image_urls.

Prompt JSONL

{"prompt":"Describe the image.","image_urls":["https://example.com/a.png"]}
{"prompt":"Name the shapes and the word.","image_url":"test-data/vlm/shapes-512.png"}

Source image bytes are sent unchanged unless --max-image-dimension forces a resize or --reencode-jpeg is requested; modality_metrics.image_bytes reflects what the server received. VLM honors --system-prompt (empty disables), --min-tokens, and --tokenizer like the LLM binary. --tokenizer requires a Cargo build with feature tokenizer (not enabled in GitHub Release archives - see Platforms).

metrum-ai-bench-cli-vlm \
--url http://127.0.0.1:18321/v1/chat/completions \
--api-key dummy \
--scenario vlm \
--num-requests 4 \
--concurrency 2 \
--prompts test-data/vlm/prompts.jsonl \
--model dummy \
--max-tokens 16 \
--data-log /tmp/vlm.jsonl.out \
--streaming

ASR​

Benchmarks /v1/audio/transcriptions. Input is JSONL with audio location and duration metadata.

Input JSONL

{"id":"1089-134686-0030","path":"test-data/asr/1089-134686-0030.wav","format":"wav","duration":2.715}
{"id":"sample-2","url":"https://example.com/clip.wav","format":"wav","duration":1.5}

Optional ground truth is JSONL with matching id and transcript. WER/CER use --normalizer:

ValueBehavior
whisper-english (default)Case, punctuation, and bracketed fillers folded; contractions expanded; small numerals digitized
whisper-basicCase, punctuation, and bracketed fillers only
noneRaw string comparison

The choice is recorded in config.normalizer. Scores from different normalizers are not comparable.

Client RTFx is audio_seconds / client_request_seconds (modality_metrics.rtfx_client). This is the sole RTFx definition; legacy whole-run aggregates are not emitted.

metrum-ai-bench-cli-asr \
--url http://127.0.0.1:18321/v1/audio/transcriptions \
--api-key dummy \
--scenario asr \
--num-requests 4 \
--concurrency 2 \
--input test-data/asr/input.jsonl \
--ground-truth test-data/asr/truth.jsonl \
--model dummy \
--data-log /tmp/asr.jsonl.out

Image generation​

Benchmarks /v1/images/generations. Clap-required flags include --scenario, --model, --num-requests, --concurrency, and --data-log (plus --url or an endpoints path). Pass --prompt once, or --prompts JSONL:

{"id":"p0","prompt":"a red cube on a table"}
{"prompt":"a blue sphere","negative_prompt":"blurry","size":"512x512"}

Latency is time until response body bytes are fully read. Decode, hash, and artifact writes happen after the timer stops. Artifact SHA-256 digests appear in modality_labels.artifact_N_sha256 on request records.

metrum-ai-bench-cli-imagegen \
--url http://127.0.0.1:18321/v1 \
--api-key dummy \
--scenario img \
--num-requests 2 \
--concurrency 1 \
--prompt "a square" \
--model dummy \
--size 64x64 \
--data-log /tmp/img.jsonl

Dummy server coverage​

The Go dummy model server in this repository can exercise LLM, VLM, ASR, and imagegen without a real model. See the repository dummy-model-server/README.md for modality-specific flags beyond the Quickstart defaults.

For strategic sweeps, embeddings, and rerank, use the Rust metrum-ai-bench-cli-mock-server instead - see Strategic benchmarking.