Five families of knobs
You met the request lifecycle last lesson. Now we sort the dials on the dashboard. The goal isn't to memorize every flag — it's to classify any control by what it actually changes: the work done, the token chosen, what you can see, how it's delivered, or the shape it must fit.
The single skill of this lesson
Given any API parameter, classify it as a generation limit, a sampling control, an observability option, a transport choice, or constrained decoding — and predict its operational effect on cost, latency, or output shape.
Why the family matters more than the name
Names drift between servers: max_tokens in vLLM is max_completion_tokens in newer APIs. But the family is stable. Once you know which family a knob belongs to, you know whether it touches compute, the chosen token, your visibility, the delivery, or the form.
One trap to retire now
Two of these families look like they change the answer but don't change model compute: transport (streaming) only changes delivery, and observability (logprobs, usage) only changes what you can see. Keep them separate from the knobs that truly reshape the work or the token.
Keywords — tap to unfold the plain meaning
Five families: limits, sampling, observability, transport, constrained decoding. Classify the knob, then you can predict its effect.
Bound the request
The first family is about boundaries. A generation has to stop somewhere, and several different mechanisms can end it. Get these wrong and a single abandoned request will quietly burn capacity long after the user has left.
The output ceiling
A generated-token ceiling — max_tokens in vLLM, max_completion_tokens in newer APIs — caps computational work by limiting how many tokens the model is allowed to produce. It's the most direct dial on cost per request.
The context limit is a different cap
The context limit (the context window) restricts total tokens — prompt plus output combined. It's not the same as max_tokens: one bounds the whole sequence, the other bounds only the new tokens you generate.
Natural and configured stops
The model emits an EOS (end-of-sequence) token to signal it's done — a special token that ends generation naturally. You can also supply stop sequences: configured strings that end generation early, before max_tokens is reached.
Cancellation must propagate
Timeouts and cancellation have to reach the engine. If they don't, an abandoned request that is not cancelled keeps decoding into the void — holding KV cache memory and a batch slot — even though no one is listening.
Keywords — tap to unfold the plain meaning
max_tokens ceiling, holding KV cache and a batch slot the whole time. max_tokens caps the damage, but it is not a substitute for admission control or a total-context check — set server-side timeouts so cancellation actually frees the slot.
Limits cap work: max_tokens bounds output, the context window bounds prompt+output, stop and EOS end it, and cancellation must propagate or the slot stays busy.
Control sampling
This is the family people reach for first and understand least. The key distinction: temperature changes the shape of every token's probability, while top-p and top-k only decide which candidates survive. They are not interchangeable.
Temperature reshapes the logits
Temperature reshapes the logits before softmax. At T = 0.2 the distribution is sharp and near-greedy; at T = 1.0 you get the model's own spread; at T = 1.8 it flattens toward random. It touches every token's probability at once.
Top-k is a fixed count
top-k truncates the candidate set to a fixed number. top-k = 3 keeps exactly the 3 most likely candidates and drops the rest — then sampling happens among only those.
Top-p is a cumulative mass
top-p (nucleus sampling) truncates by cumulative probability mass. top-p = 0.9 keeps candidates, highest first, until their probabilities add up to 90% — a set that grows or shrinks with how confident the model is.
Seed helps, but never promises
A seed can improve repeatability of sampling, but it does not guarantee identical output across engines, hardware, batching, or versions. Treat it as a nudge toward reproducibility, not a contract.
Keywords — tap to unfold the plain meaning
Math, decoded
- zithe raw logit for token i, before temperature touches it
- Ttemperature — divide every logit by it before softmax
- T < 1divides up: gaps widen, distribution sharpens toward greedy (e.g. T=0.2)
- T > 1divides down: gaps shrink, distribution flattens toward random (e.g. T=1.8)
- pithe reshaped probability — top-p/top-k then cut this set before drawing
Temperature divides the logits before softmax, so it rescales every probability at once. Top-p and top-k come after: they only crop which candidates remain, then one token is drawn from the survivors.
Temperature reshapes the whole distribution; top-p/top-k only truncate the candidate set; the token is drawn from what's left. Seed nudges repeatability — it doesn't guarantee it.
Choose transport & observability
These two families are the ones most often mistaken for performance wins. Streaming feels faster; logprobs feel like a deeper look. Both are real and useful — but it's important to know exactly what they do and don't change.
Streaming is delivery, not speed
Streaming reduces time to visible text — the user sees tokens as they're produced. But it does not reduce the model's compute time. The work is identical; only the moment of first visible output moves earlier.
Logprobs cost a little extra
logprobs expose the token scores — the raw next-token probabilities — at some extra payload or compute cost. They're how you inspect the distribution you met earlier, but they aren't free, and they don't change the chosen token.
Usage counters are for accounting
Usage counters report tokens consumed and produced. They're necessary for enforcing limits and for billing — observability that feeds your controls and your invoices, not the generation itself.
Keywords — tap to unfold the plain meaning
Transport (streaming) changes delivery, not compute. Observability (logprobs, usage) changes what you see, for a little extra cost. Neither reshapes the answer.
Constrain the output
The last knob family forces the output into a shape. It's powerful: it eliminates whole classes of parse errors. But it carries a sharp limit that trips up almost everyone — it guarantees the structure, and says nothing about whether the values are true.
It masks invalid tokens as it decodes
JSON schema, grammars, and structured-output modes work by masking invalid next tokens during decoding. At each step, tokens that would break the required form are forbidden, so the model can only continue down valid paths.
What it guarantees
Constrained decoding guarantees syntax, required keys, types, and enums. It eliminates parse errors and retries — a perfectly-formed object comes back every time.
What it can never guarantee
It does not guarantee correct, current, or truthful field values. A perfectly-formed object can still hold a wrong number. As the source puts it: structure validity is not factual validity.
Keywords — tap to unfold the plain meaning
Constrained decoding masks invalid tokens to enforce syntax, keys, types, and enums — but a well-formed object can still be wrong. Structure validity is not factual validity.
Treat controls as a contract
The knobs only behave if the server agrees to honor them. Support varies by model and server, so the operator's job is to turn a pile of optional parameters into a stable, enforced contract — one that holds even when a client sends something odd.
Validate and bound on the server
Validate unsupported parameter combinations and reject them clearly. Set server-side ceilings so a client can never request more work than you'll allow — client values are requests, not guarantees.
Document the defaults
Document the defaults every control falls back to. When a parameter is unset or unsupported, callers need to know exactly what they'll get — undocumented defaults are silent behavior changes.
Client max_tokens is not admission control
A client max_tokens is not a substitute for admission control or a total context check. It caps one request's output, but only server-side admission control protects the cluster from overload.
Try it on the 4×H100 box — one request, several families at once
curl localhost:8000/v1/completions -d '{ "model": "Qwen3.6-27B-FP8", "prompt": "List two Kubernetes scheduler components as JSON.", "max_tokens": 64, "stop": ["\n\n"], "temperature": 0.2, "top_p": 0.9, "seed": 42, "logprobs": 5, "stream": false }'
max_tokens + stop (limits), temperature + top_p + seed (sampling), logprobs (observability), and stream (transport). Add a JSON schema and you've used all five. On the cluster, the server still applies its own ceilings on top — the client values here are requests, not the final word.
Keywords — tap to unfold the plain meaning
Check yourself
- Which family does each knob belong to — max_tokens, temperature, streaming, logprobs, JSON schema?
- Temperature vs top-p/top-k: which reshapes the whole distribution, and which only truncates the candidate set?
- What does constrained decoding guarantee, and what can it never guarantee?
- Why is a client's max_tokens not a substitute for server-side admission control?
Controls are a contract: validate combinations, set server-side ceilings, document defaults. A client max_tokens is never a substitute for admission control.