Answers · AI evidence
Why does an LLM give different answers at temperature 0, and how do I prove what it actually said?
Last updated
TL;DR: Temperature 0 means greedy decoding — always pick the most likely next token — so in theory the same prompt gives the same answer. In practice hosted APIs and self-hosted servers still vary, and the main cause is not randomness in sampling. Thinking Machines Lab (Horace He, "Defeating Nondeterminism in LLM Inference", September 10, 2025) shows that the forward pass of an inference server is run-to-run deterministic, but its kernels are not batch-invariant: the numbers computed for your request depend on how many other requests were batched with it, and that depends on server load you can't see. In their test, 1,000 temperature-0 completions of "Tell me about Richard Feynman" from Qwen3-235B-A22B-Instruct-2507 produced 80 different completions; all were identical for the first 102 tokens, then 992 said Feynman was born in "Queens, New York" and 8 said "New York City". With batch-invariant kernels all 1,000 were identical. OpenAI's API reference also calls seed best effort and says determinism is not guaranteed. So a re-run is not evidence of what a model said earlier: if a customer, reviewer or court asks, a fresh run can honestly come out different. Keep the original: save the full request and response as they were sent and received, hash them, and record the hashes with a timestamp at the time of the run. record_ai_run does that in a signed receipt, and verify_ai_run checks a saved output against it later. This page is about why temperature 0 isn't reproducible. Proving which model version and settings produced an output, replaying an agent run from a recorded call order, and detecting drift over time are covered on separate pages.
What should I check, step by step?
1. Don't promise anyone that re-running the same prompt at temperature 0 will reproduce an answer. Treat every hosted response as a one-off observation.
- Save the exact request body (model, messages, tools, temperature, top_p, seed, max tokens) and the full raw response, not a copy-paste of the text.
- Hash both files (SHA-256) right after the call and record the hashes, the model value the API returned, any system_fingerprint or equivalent, and the time — before anyone disputes the answer.
- When an answer is questioned, compare the saved response with the recorded hash. Use a re-run only as a fresh sample, and say so.
- If you need repeatability for tests or evals, sample several times and report the spread, or replay recorded model outputs instead of calling the model again.
- If you self-host and need bit-identical outputs, look at batch-invariant inference (the Thinking Machines post demonstrates it on vLLM) and expect a speed cost: their unoptimized deterministic run took 55 s against 26 s for default vLLM, 42 s with an improved attention kernel.
- Record the serving stack you controlled (engine, version, GPU type, batch-invariant mode on or off) next to the output hash, because changing any of them can change outputs.
Why does an LLM give different answers at temperature 0?
The usual explanation is "floating point plus concurrency": GPU threads finish in random order, so sums come out slightly differently. The Thinking Machines post says that's not the full picture. Floating-point addition isn't associative, so adding the same numbers in a different order can give a different result, but the kernels in an LLM's forward pass don't use the order-dependent atomic adds that would make a single run random. Run the same batch twice and you get the same bits.
- What changes is the batch. Matrix multiplication, RMSNorm and attention kernels pick different reduction strategies for different batch sizes, so the result for your request depends on the batch size it was computed in. You don't control the batch size; server load does. From your side the system is nondeterministic even though the server is deterministic for any fixed set of requests.
- It isn't only GPUs. The post notes the same issue applies to endpoints served from CPUs or TPUs, and Anthropic's September 17, 2025 postmortem describes a separate case: in December 2024 its TPU implementation would occasionally drop the most probable token when temperature was zero, which it worked around at the time.
Can re-running a prompt prove what an AI model said earlier?
A re-run tells you what the model says now, on today's backend and today's load. It can't confirm or refute what it said last week. Small early differences also compound: in the Feynman test the completions agreed for 102 tokens and then split.
- Seeds don't fix this on hosted APIs. OpenAI documents seed as best effort and tells you to compare system_fingerprint to see whether the backend configuration changed between requests.
- So the evidence for "the model said X" has to be created when it said X: the saved request and response, hashed and recorded at the time, with the model value the API returned.
How does Rightshold record what an AI model said so it can be checked later?
record_ai_run takes the model, provider, the SHA-256 of the request and of the response, your settings and the time you ran it, and returns a receipt signed by Rightshold with an issued_at set when it was recorded. The prompt and output stay with you; only the hashes and fields you send are stored.
- Later, verify_ai_run takes the receipt, its signature and the saved output text, and confirms the signature, that the receipt is on record, and that the text matches the recorded hash. It does not call the model again.
How do I ask Rightshold about this (free, no key)?
Add the MCP server https://www.rightshold.com/mcp to Claude, Cursor, ChatGPT, Grok or VS Code, then ask: “Record a signed receipt for this temperature-0 answer before anyone questions it: the model value the API returned, the hashes of the exact request and raw response, the settings and when it ran.”
{
"tool": "record_ai_run",
"arguments": {
"model": "<model value returned in the response>",
"provider": "<provider>",
"prompt_sha256": "<sha256 of the exact request body>",
"output_sha256": "<sha256 of the raw response>",
"params": {
"temperature": 0,
"top_p": 1,
"seed": 7,
"system_fingerprint": "<if returned>",
"note": "single hosted call; re-runs may differ (batching)"
},
"ran_at": "2026-11-09T12:00:00Z"
}
}- Needs an API key. Send hashes, not the text: the request and response stay on your side.
- params is kept as params_sha256 over sorted-key canonical JSON (up to 4,000 bytes), so keep the exact params object.
- verify_ai_run is free and keyless: send the receipt and signature exactly as returned plus the saved output to check the signature, that it is on record, and that the output matches output_sha256.
- ledger_verify is free and keyless and checks the public ledger the receipt sits on.
Rightshold doesn't call the model for you in recorded mode, make inference deterministic, or judge whether an answer was right. It signs and timestamps the hashes and fields you send. A receipt proves what you recorded and when, not that the provider's backend behaved a certain way. Not legal advice.
What are the sources?
- Thinking Machines Lab (Horace He): Defeating Nondeterminism in LLM Inference (September 10, 2025)
- Anthropic: A postmortem of three recent issues (September 17, 2025; December 2024 temperature-zero token-drop workaround)
- OpenAI API reference: Create chat completion (seed, system_fingerprint)
- Verified AI Runs on Rightshold
Related
- How to prove what an AI model said at a specific time
- How to prove which model version, prompt and settings produced an AI output
- How to replay an AI agent run deterministically from a recorded call order
- How to make LLM eval results reproducible and tamper-evident
Not legal advice. JSON · Markdown · All answers
Get a free API key in one call
No card and no email needed. 100 free credits; the license and policy checks stay free without a key.
curl -s -X POST https://www.rightshold.com/v1/accounts/signup -H "Content-Type: application/json" -d '{"accept_terms":true}'
export RIGHTSHOLD_API_KEY=rs_... # the api_key from the reply (shown once)
curl -s https://www.rightshold.com/v1/licenses/check -H "Authorization: Bearer $RIGHTSHOLD_API_KEY" \
-H "Content-Type: application/json" -d '{"license":"MIT","intended_use":{"commercial_use":true}}'
