SanSi: Looped Typed Decisions
A single-pass decision model can struggle when evidence must be followed step by step; SanSi repeatedly applies a shared language-model stack and reads trained option probabilities after every loop.
Read the paper ↗What it is
- Looped typed decisions SanSi repeatedly reuses one language-model stack to refine an internal state, while keeping the output a probability over declared choices.
- Readouts at every step After each reuse of the stack, a trained readout produces a decision, so a caller can choose an early or later result.
- Training every decision depth Each step’s probabilities are trained against the target, using scoring rules that reward matching the target probabilities.
Why it matters
A difficult decision may need more computation than one pass, but callers still need a typed answer rather than generated reasoning. SanSi makes intermediate computation budgets usable by training a probability readout at every loop.
Before we get into the mechanics, here is the basic idea: SanSi lets a model revisit its own internal state using the same stack, and it can give you a probability over the choices after each revisit. That means you can spend more computation on a hard decision without changing the model’s output contract into a block of generated reasoning.
-
More computation for chained evidence: A single pass can struggle when a decision depends on following several statements in order. The paper’s motivating liar-chain example is exactly this kind of task: to decide whether Ben tells the truth, you have to follow the statements one at a time. A bigger model or generated reasoning can also help, but brings different costs—more parameters and memory, or extra generated tokens and latency.
-
Keep the typed interface: The model receives a state, a question, and explicit options, then returns probabilities over those options and no text. The canonical example is a verifier choosing between “yes” and “no” about whether a candidate answer follows from a passage. It can make the same kind of call for classification or a multiple-choice question. The limit of this example is that some items are not answerable from the state, so the right output may express uncertainty rather than pick a factual answer.
-
Make intermediate results usable: Repeating a computation is only useful to a caller if the caller can read a decision before the final step. Think of revising a notebook: you can inspect the current page after each pass. That analogy breaks because the model is not literally storing a human-readable chain of thoughts; the state is internal.
So the key move is to reuse one transformer stack, feeding its updated state back into that same stack. In the reported Ouro backbone, the normalized state from one loop becomes the input to the next; the original tokens are not injected again. More loops mean more passes through the stack, not a separately parameterized stack for every pass. The paper’s pages state this mechanism but do not print its state-update equation.
The readout is what turns those passes into selectable budgets. At every loop, SanSi computes probabilities for the declared options using a loop-specific readout. In the Figure 2 example, the first loop leans toward the wrong answer and later loops move toward the right one. The point is not that an early answer must already be right; it is that the early answer has a trained probability readout and can be used if the budget calls for it.
But what teaches those early readouts to be decisions rather than incidental snapshots? SanSi trains every loop toward the target option distribution with cross-entropy and Brier score. In plain terms, the losses reward probabilities that match the target; targets can represent a correct option, insufficient evidence, or annotator disagreement. Training only the final loop does not give the earlier outputs the same supervision. In the reported comparison, the all-loop training setup reaches 58.4% at loop one, while last-loop-only training reaches 35.6% there.
The tradeoff is straightforward: you get decisions at several computation depths, but running deeper costs additional passes. The reported eight-loop configuration costs 7.7 times a single pass. Also, more computation is not automatically better-calibrated confidence: the paper reports confidence continuing to rise after answers settle. So the remaining question is when a caller should stop, not whether every item needs the maximum depth.
Read the deep dive
Why People Wanted It
A typed decision model takes a state, a question, and a declared set of options, then returns probabilities over those options without generating an explanation. That contract is useful for classification, verification, and judging—but a single pass can fall short when the answer depends on following evidence through a chain. The real question is not only how to make the model think longer. It is how to add computation while preserving the typed decision interface, and how to make an answer available at intermediate computation budgets.
The Core Move
SanSi repeatedly applies one shared, loop-pretrained language-model stack to its evolving internal state, with a trained option-probability readout after every loop. The supplied pages do not give the state-update or readout equations, so the mechanism can be stated without adding formulas: each loop updates the state; each loop’s readout turns that state into probabilities over the declared options.
Why Looping Adds Computation Without Adding a New Stack
Here is the part that gets technical: the loop is a repeated application of the same transformer stack, not a sequence of separately parameterized stacks. Ouro-1.4B uses one stack of 24 transformer layers repeatedly; its normalized state after a loop becomes the input to the next, and the original input tokens are not injected again. Consequently, running more loops costs additional passes through that stack but does not add parameters. This preserves the typed contract: the model still returns option probabilities rather than generated reasoning text.
The backbone is frozen during SanSi training. LoRA adapters are trained on the attention and feed-forward projections, alongside the readouts. The paper reports 60.6M adapter parameters shared across loops and 0.27M readout parameters. These are implementation details of the reported setup, not requirements of looping in general.
Why Every Loop Needs Its Own Trained Readout
Now the deeper issue is what makes intermediate computation useful to a caller: SanSi reads option probabilities after every loop, with a separate small readout at each depth. A single run therefore exposes decisions at successive budgets rather than only a final answer. The option logits use the frozen language-model head’s rows for the option letters, with a trained low-rank correction and scale for each loop.
The paper’s Figure 2 illustrates why this matters: on its example, the first loop prefers the wrong option, while later loops prefer the correct one. Training only the last loop would leave early readouts without the same direct learning signal. In the reported comparison, training every loop gives 58.4% accuracy at loop one, while training only the last loop gives 35.6% there. The early result is not merely an accidental view of an unfinished hidden state; it has been trained as a decision.
Why Proper Scoring Rules Train More Than the Final Answer
Here is the training machinery: every loop is trained toward the target option distribution using the sum of cross-entropy and Brier score. Cross-entropy penalizes probability assigned away from the correct option, with a particularly heavy penalty for a confident error; the Brier score evaluates probabilities across all options and is bounded. Both are proper scoring rules: their minimum occurs when the predicted probabilities match the target distribution.
Targets are not always one-hot. They are one-hot for an item with a correct option, uniform when the evidence is insufficient, and the annotators’ label distribution for crowd-labelled items. Losses from the loops are backpropagated through the preceding loops. This couples the readouts to a shared evolving computation while directly supervising each available decision depth.
Minimal Causal Code
This sketch makes the repeated state update and per-loop readout visible. It leaves out the paper’s prompt construction, frozen head, LoRA details, and exact loss implementation.
state = embed(prompt)
probabilities_by_loop = []
for loop in range(num_loops):
state = shared_stack(state) # same stack, applied again
option_logits = readouts[loop](state)
probabilities = option_logits.softmax(dim=-1)
probabilities_by_loop.append(probabilities)
What You Gain, and What You Lose
You gain a typed decision at selectable depths: callers can use an early readout or spend more computation on later loops. Reusing one stack adds computation without adding a new stack of parameters, and training every readout makes intermediate budgets meaningful. In the reported setup, loop three already captures 88% of the accuracy gain from loop one to loop eight.
You pay for repeated passes: the reported eight-loop model costs 7.7 times the computation of a single pass. More loops do not guarantee that confidence remains well calibrated; confidence can keep rising after answers settle. Nor does looping create a new stopping rule by itself: SanSi tests existing choices, including Ouro’s frozen exit gate. The tradeoff is extra iterative computation and multiple usable readouts, not a free replacement for a single-pass model.
SanSi makes extra thinking a sequence of trained decisions: one shared stack, many loop depths, and a probability readout at each.