Apply to my task
arXiv:2610.13823 ★ 71 Oct 9, 2026

Run-to-Run Variance: why temperature 0 doesn't give repeatable answers and what to do about it

Key result

Finding: temperature 0 doesn't produce identical answers. Just 0.1% wobbly rows — and across 1,560 rows the chance of getting the same total twice drops to 21%. The method gives you reproducible counts and labeling tables without rerunning the whole task. The trick: disagreement between runs points out the contested rows on its own. You recheck those by voting, leave the rest alone, and record the final verdicts in a table — instead of a new roll of the dice, you get a locked-in answer.

01

TL;DR

The study shows: temperature 0 does not make an LLM's answer identical. If you run the same row-by-row task several times, some of the verdicts change. The cure is not to trust a single run: repeat the contested rows and take the majority, and save the final answers instead of recomputing them.

Here's the pain: you run the same review classification twice, and the "positive" count is 47 one time and 52 the next. Or you calculate the share of complaints, and the number in the report doesn't match yesterday's. The cause is the model call itself. The server processes parallel requests in batches, the order of computation shifts slightly, and a borderline row tips one way or the other. Even two identical requests within the same run diverge just as often as requests from different runs.

Worst of all, errors multiply with the number of rows. If the answer depends on every row (a full list, a table, all matches), then with 0.1% unstable rows and 1,560 pairs, the chance of getting the same result twice is about 21%. Counts and averages dampen some of the wobble, and "first N matches" dampens it even more. What helps is re-querying only the contested rows (cheap) and recording the verdicts you got (then the answer is reproducible).

Want this for your own case? Apply this study to your task: AI adapts its method to what you are working on and writes the prompt.

02

Method Blueprint

STEP 1: Run the row-by-row task 2–3 times (separate requests) → a "row × run" table
STEP 2: Find the rows where verdicts didn't match → a list of contested rows
STEP 3: Run the contested rows 3–5 more times → majority vote
STEP 4: Record the final verdicts in a table → work from it from now on, don't recompute
STEP 5: Report the result with a range, not a single number

Steps 1–3 require separate requests or simple automation (for example, a Make or n8n scenario written with an LLM's help). Everything is done with ordinary prompts.

03

Example in Practice

Task: A marketer at a sneaker brand is going through 400 Amazon reviews. They need to calculate the share of negative ones for a report to their manager. One run gave 18%, a second run 22%. Which number should they trust?

Prompt (step 1, identical for all runs):

You are labeling customer reviews of sneakers on Amazon.
For each review, output exactly one label: POSITIVE, NEGATIVE, or MIXED.
Negative — if the customer is unhappy with the product, sizing, quality, or delivery
and doesn't recommend buying. If there are both pros and cons — MIXED.

Answer format — table only: # | label. No explanations.

Reviews:
1. "Ordered a 9, they run small, the sole squeaks. Already filed a return."
2. "Killer value for the price, been wearing them three months, nothing's come unglued."
3. "They look awesome, but the toe cracked after two weeks."
...

Prompt (steps 2–3, reconciliation):

Below are two label tables for the same reviews from two independent runs.
List only the numbers where the labels didn't match, in the format: # | label 1 | label 2.
Don't show the rest. At the end, write the total number of mismatches.

Then you send the contested reviews 3–5 more times in new, separate chats (or requests), take the label that came up most often, and enter it in the table.

Result: After two runs you'll have label tables. Reconciliation will show a short list of contested numbers. These are usually borderline "mixed" reviews. After the vote, you'll have a final table and a negative share you can reproduce, because the verdicts are recorded. In the report, it's worth giving the number with a caveat: "about 20%, with this many contested reviews."

04

Why It Works

The weakness. For each row, the model doesn't produce "the one correct answer" but an answer drawn from a probability distribution. For obvious rows, the distribution is narrow and the answer is stable. For borderline rows, two options are almost equally likely. Temperature 0 picks the most likely one, but on the server, tiny computational noise can still tip the scales.

The strength. Not all rows are unstable, only a small fraction, and specifically the ones where models also disagree with each other. In other words, instability reflects genuine ambiguity in the row. That's why contested rows are easy to find: they diverge between runs.

How the method exploits this. Disagreement between runs works as an ambiguity detector. Instead of an expensive full rerun, you spend money only on the contested rows. Recording the final verdicts turns a random answer into a fixed one, and from then on you work with it, not with a new roll of the dice.

Levers: - Number of runs in step 1 (2 → 3): more runs reveal more unstable rows. The share of changing rows keeps growing with the number of runs and doesn't plateau. - Number of repeats for contested rows (3 → 5 → 9): more means a more stable majority, but costs more. - Task type: ratings on a 1–5 scale and free text change more than looking up facts stated directly in the text. Budget more repeats for scales. - What you return as the answer: counts and shares are more robust than a full list, because opposite errors cancel each other out.

05

Prompt Template

Task: {what_to_determine_for_each_row}.
Allowed labels: {label_list}.
Borderline rule: {how_to_decide_contested_cases}.

Answer format — table only: # | label. No explanations.

Rows:
{numbered_list_of_rows}

Run reconciliation:

Below are {number} label tables from independent runs for the same rows.
List only the numbers where the labels didn't match: # | label 1 | label 2 | ...
At the end — the number of mismatches and their share of the total rows.

{run_tables}

Fill in: what exactly is decided per row, a closed list of labels, an explicit rule for borderline cases (it narrows the ambiguity), and numbered rows. Do the runs in separate chats, otherwise the second answer will adjust itself to the first.

🚀 Quick start — paste into a chat:

Here is a template for row labeling with a stability check. Adapt it to my task: {your task}.
Ask me questions to fill in the fields.

[paste the template above]

The LLM will ask what the rows are, which labels are allowed, and how to decide borderline cases. This is needed to remove ambiguity from the rule itself: the sharper the boundary, the fewer borderline rows and the fewer mismatches between runs.

06

Limitations

⚠️ Voting doesn't remove variability: it reduces it but doesn't zero it out. The result can still differ slightly on a full recompute.

⚠️ It depends on the model: the share of changing rows differs by two orders of magnitude across models. In the study, the reasoning model was noticeably less stable than the plain one, and commercial models vary too. You need to test your own model on your own data.

⚠️ A chat isn't a lab: in a regular chat you don't know or set the temperature. The scale of the problem there may differ from the study.

⚠️ Confidence signals require API access: predictors of "which row will flip" (the margin between the top two tokens) come from log probabilities. Chats don't expose them. The simple approach works: compare runs.

⚠️ Only text and tables were tested: images and audio weren't studied. The paper's text on voting and cascades isn't provided in full; I'm relying on the stated conclusions.

⚠️ One model can be consistently wrong: agreement between runs doesn't mean correctness. If a model has a systematic bias, it repeats it every time. For accuracy, you need a check against a labeled sample.

07

How They Studied It

An IBM team took three existing benchmarks for "semantic" database queries, where an LLM judges each row: SemBench, LRO-Bench, and UDA-Bench. They reran them unchanged on eight model deployments (open-weight and commercial) and recorded 1.2 million model calls, every answer for every row. Previously, benchmarks published only the final quality. Separately, the authors re-analyzed SemBench's published results: five runs of Gemini 2.5 Flash.

The findings were unexpected. At temperature 0, between 0.07% and 10.2% of rows changed across five runs, up to 24% on one task. In SemBench's published results, 21% of text cells changed in quality from run to run, even for engines with a deterministic plan. In Movie Q3 (counting positive reviews), gpt-oss-120B returned four different numbers over ten runs. Llama-3.3-70B on two different servers gave stable but different numbers: the deployment affects the result.

The main observation: it's not about "between runs." Identical requests within the same run diverge just as often. And the rows that change are the ones models argue about with each other. On UDA-Bench, a few percent of changed values altered about two-thirds of the final answers. This matched the prediction of a mathematical "possible worlds" model. The practical takeaway: one run is one roll of the dice, not a measurement.

08

Adaptations and Extrapolations

These are my ideas; the paper didn't test them.

🔧 Technique: a different model instead of repeats → catches systematic errors

The paper shows that unstable rows are the ones where models disagree with each other. So you can find contested rows not by repeating one model, but by running them through a second model (for example, Claude and GPT). Send the mismatches for manual review.

Below are label tables from two different models. List only the rows with a mismatch
and briefly (up to 10 words) explain what makes the row ambiguous.

Extrapolation: a rule for an agent. If an agent in Cursor or Claude Code does bulk labeling or extraction, add this to its instructions:

Always save the results of row-by-row classification and extraction to a file
(CSV). Don't recompute them on follow-up questions — read from the file.
If the task requires a share or a list, first do two independent runs,
list the mismatches, and recheck only those separately.
09

Resources

  • Paper: Same Query, Different Answer: Run-to-Run Variance in Semantic Query Processing
  • Authors: Oktie Hassanzadeh, Dharmashankar Subramanian, IBM (Yorktown Heights, NY, USA)
  • Benchmarks: SemBench, LRO-Bench, UDA-Bench
  • Engines: LOTUS, Palimpzest, ThalamusDB, BigQuery

Research digest

Key result

Finding: temperature 0 doesn't produce identical answers. Just 0.1% wobbly rows — and across 1,560 rows the chance of getting the same total twice drops to 21%. The method gives you reproducible counts and labeling tables without rerunning the whole task. The trick: disagreement between runs points out the contested rows on its own. You recheck those by voting, leave the rest alone, and record the final verdicts in a table — instead of a new roll of the dice, you get a locked-in answer.

Principle

A three-move process: run it 2-3 times → find the mismatches → settle the contested ones by vote. Then you record the verdicts and never recompute them. You work with the table, not the model. Stability comes not from the model but from the recorded result. It's like a referee in sports: the call is made and entered in the official record. Nobody replays the play, or you'd get a new score every time. One more rule: separate chats for each run. Otherwise the second answer adjusts to the first, and you won't see the mismatches.

Why it works

For each row, the model doesn't produce the single correct answer but an option drawn from a probability distribution. Obvious rows give a narrow distribution, and the answer is stable. For borderline rows, two options are nearly equal. Temperature 0 takes the most likely one. But the server computes parallel requests in batches, the order of computation shifts slightly, and tiny noise tips the balance. Here's the kicker: two identical requests within the same run diverge just as often as requests from different runs. So the issue isn't "runs," it's the call itself. Only a small fraction of rows are unstable. And they're the rows where the models themselves disagree with each other. Instability is genuine ambiguity in the row, not a random glitch, so it's easy to find by comparing runs. Errors multiply with the number of rows. If the answer depends on every row (a full list, a table), the odds of a match melt away fast. Counts and shares are more robust: errors in opposite directions cancel each other out. "First N matches" dampens the wobble even more. Levers: - More runs in step 1 (2 → 3): you find more wobbly rows. Their share grows with the number of runs and doesn't plateau. - More repeats for contested rows (3 → 5 → 9): the majority is more stable, but costs more. - 1-5 scales and free text wobble more than looking up facts stated directly in the text. They need more repeats.

When to apply

Row-by-row labeling and classification → reviews, support requests, tickets, surveys → especially when the number goes into a report and yesterday the same report had a different one. Also good for computing shares and tables that you later cross-check with colleagues. The method is needed most when ratings are on a scale or free-form: that's where mismatches are most common. NOT suitable if you need accuracy rather than repeatability. Agreement between runs isn't the same as correctness. If a model has a systematic bias, it repeats it every time. For accuracy, you need a check against a labeled sample. Also not suitable for images and audio: the study didn't test them.

Mini recipe

1. Close the label list: for example POSITIVE, NEGATIVE, or MIXED. No "kinda good." 2. Spell out a borderline rule: one sentence on how to decide contested cases. The sharper the boundary, the fewer borderline rows. 3. Do 2-3 runs in separate chats: answer format — table only `# | label`, no explanations. Number the rows. 4. Reconcile the tables: `Below are two label tables from independent runs. List only the numbers where the labels didn't match: # | label 1 | label 2. At the end — the number of mismatches.` 5. Settle the contested ones: send only those 3-5 more times in new chats. Take the label that came up most often. 6. Lock it in: record the final verdicts in a table and compute from it from then on. Don't recompute through the model. 7. Report with a range: not "18%" but "about 20%, with this many contested reviews." Lots of repeats and don't feel like doing them by hand? Ask an LLM to write a Make or n8n scenario, and it'll run everything for you. Quick start, paste into a chat: `Here is a template for row labeling with a stability check. Adapt it to my task: {your task}. Ask me questions to fill in the fields.`

Examples

[BAD]: `Determine how many of these 400 reviews are negative and give the share as a percentage.` The first time you get 18%, the second 22%. Whatever came out last goes into the report. [GOOD]: `You are labeling customer reviews of sneakers. For each one, output one label: POSITIVE, NEGATIVE, or MIXED. If there are both pros and cons — MIXED. Answer format — table only: # | label. No explanations.` You run it twice in different chats. Then: `List only the numbers where the labels didn't match, in the format: # | label 1 | label 2. At the end, write the number of mismatches.` You run the contested reviews (usually borderline "mixed" ones) 3-5 more times and take the label that came up most often. You record the verdicts in a table. Result: the negative share is reproducible, and the report says "about 20%, 14 contested reviews."

In plain words

Set temperature=0 and expect ironclad determinism? Forget it, that's an illusion. Even at zero, the model works with a probability distribution, and microscopic computational noise on the provider's servers nudges the weights by fractions of a percent. If a token sits right on the edge of a choice, that invisible shift can easily flip the verdict upside down.

It's like a tired judge at a weigh-in: with a heavy weight on the scale, they won't get it wrong, but when the difference is a milligram, the verdict depends on which side of the bed they woke up on. As a result, one labeling run gives 18% negative reviews, and a second run on the same data gives 22%. You bring your boss pretty charts while your "analytics" is quietly playing roulette behind the scenes.

The cure for this chaos is engineering: majority voting and strict result caching. Contested borderline rows should be run 3-5 times to build consensus instead of trusting the blind luck of a single call. And the main hygiene rule: once you get a stable answer, save it to the database right away instead of recomputing it on every request.

The study looked at data labeling, but the trap is waiting everywhere. Automated content moderation, lead scoring, support ticket tagging, or semantic search — any batch processing on an LLM suffers from this bug. Without filtering out the borderline cases, your rock-solid reports turn into a random number generator.

Bottom line: an LLM isn't a SQL database, it's a probabilistic machine pretending to be a calculator. Stop trusting whatever run comes first on critical data: double-check the doubtful cases and lock the result in for good. Otherwise you'll be red-faced in front of your boss for a long time, explaining where the extra 4% of screwups came from out of nowhere.

AI lab assistant

Apply this study to your task

Describe what you're working on. AI takes the method and the measured results from this paper and adapts them to your case, or writes a ready prompt built on them.

Based on Run-to-Run Variance: why temperature 0 doesn't give repeatable answers and what to do about it arXiv:2610.13823

Sign in to apply this study New accounts get 50 free credits.