Interactive Chat Sanity Checks
aiperf chat lets you talk to an OpenAI-compatible endpoint one message at a
time and see per-turn speed stats — time to first token, throughput,
inter-token latency, and prompt-cache hit rate — after every reply. It is a
lightweight sanity-check companion to aiperf profile: handy for confirming an
endpoint is wired up correctly and getting a ballpark feel for performance
before committing to a full benchmark run, and for eyeballing
speculative-decoding or reasoning-model behavior where speedups are
prompt-dependent.
It is deliberately minimal. For real benchmarking — concurrency, request rates,
datasets, sampling knobs, artifacts, and statistical aggregation — use
aiperf profile. Every number aiperf chat prints is produced by the same
metric classes profile uses, so they stay consistent (including
reasoning-token accounting).
Prerequisites
Before you begin, ensure you have:
- AIPerf installed
- An OpenAI-compatible inference server running (e.g. vLLM, SGLang) and
reachable, exposing
/v1/chat/completions
Single-Shot Sanity Check
Send one message and exit with --quick:
Sample Output:
Every reply is followed by the same per-turn stats block, explained next.
Reading the per-turn stats
The block is the same in every mode (single-shot, multi-turn, or
--no-history). All four values come from the same metric classes aiperf profile uses:
- TTFT — time to first token (client-observed).
- TPS — generated tokens divided by end-to-end latency. The vLLM-familiar rate; it includes TTFT, so it blends prefill and decode into one number.
- ITL (inter-token latency) / decode — a decode-focused rate that excludes prefill. Because it ignores TTFT, it stays comparable across turns even when a growing history inflates prefill (where TPS sags). Omitted for single-token replies, where it is undefined.
- Cache — prompt-cache hit rate (
cached / prompt tokens). Prefix caches are server-side and shared across requests and sessions, so a hit does not require a prior turn in this conversation — a shared system prompt or any prefix the server already cached (from earlier requests, other sessions, or other clients) can hit, even on a first or single-shot message. It is read from the server’susage, so it appears only when the server reports prompt caching (see below), and reflects the same countsaiperf profilerecords.
Don’t see the
Cache:line? The server has to report cached tokens in itsusage, which is separate from merely enabling caching. Launch the server accordingly:
- vLLM:
--enable-prefix-cachingand--enable-prompt-tokens-details. The reporting flag is off by default and independent of prefix caching — without it vLLM sendsprompt_tokens_details: nulland noCache:line appears.- SGLang:
--enable-cache-report(off by default).- TRT-LLM: reports
cached_tokensby default; no extra flag.A genuinely novel prefix is a cold miss (
Cache: 0/N … (0.0%)); the rate rises as prefixes are reused — within this session or already resident in the server’s cache. See Vendor Usage Field Reference for the full matrix.
Interactive Multi-Turn Chat
Omit --quick to start an interactive session. History is retained and resent
each turn, so the model has full context (press Ctrl-D to exit). Watching the
same stats evolve turn over turn is the point: TTFT and the cache hit rate climb
as the resent prefix grows, while ITL — the decode-only rate — stays roughly
flat even as the headline TPS sags.
Stateless Turns (--no-history)
By default each turn resends the full conversation. Pass --no-history to make
every message an independent, stateless request instead — the completion-style
flow, where the model has no memory of prior turns:
This is useful for measuring single-turn performance repeatedly without the
prefill cost of a growing history. The same stats block still prints; the cache
hit rate won’t climb from this session’s history (none is resent), but it can
still be non-zero when the server already holds a matching prefix — e.g. a
shared system prompt or a prefix cached from earlier requests. --no-history is
ignored with --quick, which is already a single request.
Reasoning Models
When the endpoint serves a reasoning model, aiperf chat counts reasoning
tokens the same way aiperf profile does. Whether the server emits reasoning in
a dedicated reasoning_content field (via a reasoning parser) or inline as
<think>...</think> in the content, the generated reasoning tokens are included
in the token total, and a separate reasoning count is shown in the TPS line:
Options
Tuning request timeouts
aiperf chat fails fast on an unreachable endpoint but never caps overall
generation time, so long replies are not truncated. Both timeouts are tunable
via environment variables (no total timeout is applied):
AIPERF_CHAT_CONNECT_TIMEOUT(default10.0) — seconds to establish a connection before a turn fails.AIPERF_CHAT_READ_TIMEOUT(default300.0) — seconds to wait for the next streamed chunk before a turn fails (only fires if the server stalls).
See Environment Variables for the full list.
See Also
- Multi-Turn Conversations - Benchmark multi-turn sessions at scale
- Using Local Tokenizers Without HuggingFace
- Metrics Reference - Definitions of TTFT, ITL, OSL, and more