Diagrams — Module FT15: CoT Distillation and Rejection-Sampling FT

Module: FT15 — CoT Distillation and Rejection-Sampling FT Diagram count: 5 Tool: Mermaid (primary). Each diagram validated in Mermaid Live Editor.


Diagram 1 — CoT Distillation Flow (teacher generates → student SFTs)

Type: Mechanism / pipeline Purpose: The one move that produced R1-Distill-Qwen-32B — a strong reasoning teacher emits <think>…</think> traces, the traces are curated, and a smaller student SFTs on them. No RL in the training loop. Reading the diagram: Top path is data generation (teacher does the expensive search once). Bottom is student training (ordinary SFT). The teacher is not in the loop at train time — only its traces are.

flowchart TD
  Problems["Problem set\n(math, code, reasoning)\n~800K samples for R1-Distill"]
  Problems --> Teacher["STRONG REASONING TEACHER\nDeepSeek-R1 / o1 / Claude-GPT w/ thinking"]

  Teacher --> Traces["&lt;think&gt;...reasoning...&lt;/think&gt;\n&lt;answer&gt;...&lt;/answer&gt;\ntraces generated ONCE\nat data-gen time"]

  Traces --> Curate["CURATE\nfilter for correctness\n(verify the answer)\ndeduplicate, balance difficulty"]
  Curate --> SFTdata["Distillation dataset\n(problem, think, answer) tuples"]

  SFTdata --> Student["SMALLER STUDENT\nQwen-32B base\n(or 1.5B / 7B / 70B)"]
  Student --> SFT["SFT on the traces\nordinary supervised FT\nNO reward model\nNO policy gradient\nNO KL anchor"]
  SFT --> Reasoner["Reasoning student\nemits &lt;think&gt; at inference\nbefore committing to answer"]

  Teacher -.->|"NOT in train loop\nonly its traces are"| NoteT["teacher did the\nexpensive search once"]
  SFT -.->|"ceiling = teacher\nstudent cannot exceed it"| NoteS["limit: imitation only\nfor pushing past teacher → RFT/GRPO"]

  style Problems fill:#14141f,stroke:rgba(255,255,255,0.12),color:#e4e4e8
  style Teacher fill:#14141f,stroke:#5eead4,stroke-width:2px,color:#5eead4
  style Traces fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#5eead4
  style Curate fill:#08080c,stroke:rgba(94,234,212,0.4),color:#e4e4e8
  style SFTdata fill:#14141f,stroke:rgba(94,234,212,0.5),color:#e4e4e8
  style Student fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#e4e4e8
  style SFT fill:#14141f,stroke:#5eead4,stroke-width:2px,color:#5eead4
  style Reasoner fill:#14141f,stroke:rgba(130,224,170,0.6),color:#82e0aa
  style NoteT fill:#08080c,stroke:rgba(148,148,160,0.4),color:#9494a0
  style NoteS fill:#08080c,stroke:rgba(240,168,104,0.5),color:#f0a868

Diagram 2 — The RFT Loop (generate → filter by reward → retrain on winners)

Type: Iterative loop Purpose: Rejection-sampling FT — the middle path. Generate candidates with the current model, keep only the ones the verifiable reward accepts, SFT on the winners, repeat. No policy gradient; SFT stability throughout. Reading the diagram: A cycle. Each iteration the model improves by training only on its own positively-rewarded outputs. Failures are discarded, not gradient-penalized — the structural difference from GRPO.

flowchart LR
  Model["Current model\n(student, iter N)"]
  Model --> Gen["1. GENERATE\nsample N candidates per problem\ntemperature > 0\nseveral rollouts each"]
  Gen --> Reward["2. FILTER by reward\nverifiable only:\nmath checks? code passes?\nanswer matches ground truth?"]
  Reward -->|"positively rewarded"| Keep["KEEP the winners\nthe accepted candidates"]
  Reward -->|"rejected"| Drop["DISCARD failures\nNOT used for training\n(not a penalty — just dropped)"]
  Keep --> Retrain["3. RETRAIN\nSFT on accepted candidates only\ncross-entropy, no policy gradient\nsame optimizer as plain SFT"]
  Retrain --> NewModel["New model\n(iter N+1)\nimproved by training\non its own successes"]
  NewModel --> Model

  Retrain -.->|"stable: SFT does not\ndiverge like policy gradients"| NoteS["worst case: small accepted set\n(diagnosable data problem)"]
  Drop -.->|"vs GRPO: GRPO learns\nfrom BOTH success & failure\nvia advantage × log-prob"| NoteG["RFT trades expressivity\n(ignores failures) for\nstability + diagnosability"]

  style Model fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#e4e4e8
  style Gen fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#e4e4e8
  style Reward fill:#08080c,stroke:rgba(94,234,212,0.5),color:#e4e4e8
  style Keep fill:#14141f,stroke:rgba(130,224,170,0.6),color:#82e0aa
  style Drop fill:#08080c,stroke:rgba(240,128,128,0.4),color:#f08080
  style Retrain fill:#14141f,stroke:#5eead4,stroke-width:2px,color:#5eead4
  style NewModel fill:#14141f,stroke:rgba(130,224,170,0.6),color:#82e0aa
  style NoteS fill:#08080c,stroke:rgba(130,224,170,0.4),color:#82e0aa
  style NoteG fill:#08080c,stroke:rgba(148,148,160,0.4),color:#9494a0

Diagram 3 — The Decision Tree: Distillation vs RFT vs GRPO

Type: Decision flow Purpose: The judgment the module exists to teach. Three axes: strong teacher available? reward verifiable? compute/stability constraints? Choose the cheapest technique that meets the need. Reading the diagram: Top-down. First question gates distillation. Second gates RFT/GRPO. Third picks between them. Escalate only when the cheaper option plateaus.

flowchart TD
  Start["Goal: reasoning in a small model"]

  Start --> Q1{"Strong reasoning\nteacher available?\n(R1, o1, Claude/GPT\nwith thinking)"}
  Q1 -->|"YES"| Distill["DISTILLATION\ncheapest path\nSFT on teacher's traces\nNO RL"]
  Q1 -->|"NO"| Q2{"Reward\nverifiable?\n(math checks, code\npasses tests)"}

  Q2 -->|"NO"| Pref["Preference territory → FT13\n(DPO, not reasoning FT)\nRFT/GRPO do not apply"]
  Q2 -->|"YES"| Q3{"Compute budget &\nstability requirement?"}

  Q3 -->|"constrained / must-not-diverge"| RFT["RFT / RAFT\nmiddle ground\ngenerate → filter → SFT\nSFT stability, reward-filtered data"]
  Q3 -->|"large budget, willing to tune KL,\npush the frontier"| GRPO["GRPO (FT14)\nmost powerful, most expensive\nfull RL on verifiable rewards"]

  Distill -.->|"if it plateaus &\nteacher is the ceiling"| Escalate["escalate to RFT"]
  RFT -.->|"if it plateaus &\nbudget remains"| Escalate2["escalate to GRPO"]
  Escalate --> RFT
  Escalate2 --> GRPO

  Distill --> OutD["ceiling = teacher\ncheap, stable"]
  RFT --> OutR["self-improvement\nno teacher ceiling\nstable"]
  GRPO --> OutG["pushes past both\nmost expensive\nmost unstable"]

  style Start fill:#14141f,stroke:rgba(255,255,255,0.12),color:#e4e4e8
  style Q1 fill:#08080c,stroke:rgba(94,234,212,0.5),color:#e4e4e8
  style Q2 fill:#08080c,stroke:rgba(94,234,212,0.5),color:#e4e4e8
  style Q3 fill:#08080c,stroke:rgba(94,234,212,0.5),color:#e4e4e8
  style Distill fill:#14141f,stroke:rgba(130,224,170,0.7),stroke-width:1.5px,color:#82e0aa
  style RFT fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#5eead4
  style GRPO fill:#14141f,stroke:rgba(240,168,104,0.7),stroke-width:1.5px,color:#f0a868
  style Pref fill:#08080c,stroke:rgba(148,148,160,0.4),color:#9494a0
  style Escalate fill:#08080c,stroke:rgba(240,168,104,0.4),color:#f0a868
  style Escalate2 fill:#08080c,stroke:rgba(240,168,104,0.4),color:#f0a868
  style OutD fill:#08080c,stroke:rgba(130,224,170,0.4),color:#82e0aa
  style OutR fill:#08080c,stroke:rgba(94,234,212,0.4),color:#5eead4
  style OutG fill:#08080c,stroke:rgba(240,168,104,0.4),color:#f0a868

Diagram 4 — The R1-Distill Headline Result

Type: Evidence / benchmark comparison Purpose: The single fact that made distillation the standard, accessible technique — R1-Distill-Qwen-32B, trained via SFT on ~800K curated reasoning samples (no RL on the student), beats OpenAI o1-mini on several benchmarks. Reading the diagram: The teacher (R1, full RL) generates traces. The student (Qwen-32B base) SFTs on them. The result outperforms a frontier compressed-reasoning product on AIME 2024 and MATH-500.

flowchart TD
  R1["DeepSeek-R1\nTEACHER\nfrontier reasoner\ntrained with full RL\non verifiable rewards\n(the FT14 lineage)"]
  R1 -->|"generates & curates\n~800K reasoning samples\nmath + code + general"| Data["Distillation corpus\n&lt;think&gt; traces\nverified correct"]
  Data -->|"SFT only — no RL\non the student"| Qwen32["DeepSeek-R1-Distill-Qwen-32B\n32B student\nplain SFT on distilled data"]

  Qwen32 --> Bench["BENCHMARK RESULT"]
  Bench --> AIME["AIME 2024\nR1-Distill-Qwen-32B\nBEATS o1-mini"]
  Bench --> MATH["MATH-500\nR1-Distill-Qwen-32B\nBEATS o1-mini"]

  Qwen32 -.->|"the headline fact:\nSFT on a strong teacher's traces\nbeat a frontier reasoning product\nNO student-side RL"| Note["this is why distillation became\nthe default accessible recipe\nfor small reasoning models"]

  style R1 fill:#14141f,stroke:#5eead4,stroke-width:2px,color:#5eead4
  style Data fill:#14141f,stroke:rgba(94,234,212,0.5),color:#e4e4e8
  style Qwen32 fill:#14141f,stroke:rgba(130,224,170,0.7),stroke-width:2px,color:#82e0aa
  style Bench fill:#08080c,stroke:rgba(255,255,255,0.12),color:#e4e4e8
  style AIME fill:#14141f,stroke:rgba(130,224,170,0.6),color:#82e0aa
  style MATH fill:#14141f,stroke:rgba(130,224,170,0.6),color:#82e0aa
  style Note fill:#08080c,stroke:rgba(130,224,170,0.5),color:#82e0aa

Diagram 5 — The Thinking-Mode Toggle (hybrid models)

Type: Mechanism / adaptive compute Purpose: Hybrid models (Qwen3) can toggle thinking on or off per request from the same weights — avoiding the always-on latency tax. Thinking budgets allocate compute adaptively. Reading the diagram: One model, two modes, selected per request. The toggle is a control token / system instruction, not a separate model. The thinking budget makes it continuous: spend N tokens thinking, then answer.

flowchart LR
  Req["Incoming request\n(easy or hard?)"]
  Req --> Toggle{"thinking mode?\n(control token /\nsystem instruction)"}

  Toggle -->|"OFF — easy query"| Fast["NON-THINKING mode\nanswer directly\nlow latency\n'capital of France?'"]
  Toggle -->|"ON — hard query"| Slow["THINKING mode\nemit &lt;think&gt; trace\nthen answer\nhigh accuracy\n'prove integral converges'"]

  Slow --> Budget{"thinking budget?\nadaptive compute"}
  Budget -->|"small N tokens"| Easy["spend little\nconverge fast"]
  Budget -->|"large N tokens"| Hard["spend more\nhard problems\nworth the latency"]

  Fast --> Out1["one deployed model\nsame weights"]
  Easy --> Out2["one deployed model\nsame weights"]
  Hard --> Out2

  Toggle -.->|"NOT a separate model\nsame weights, steered\nby a flag"| Note["hybrid = one model\nserving both the cheap-fast\nand expensive-accurate paths"]
  Budget -.->|"trains on a MIX of\nthinking + non-thinking traces"| NoteT["distillation data must\ninclude both modes\nfor a hybrid student"]

  style Req fill:#14141f,stroke:rgba(255,255,255,0.12),color:#e4e4e8
  style Toggle fill:#08080c,stroke:rgba(94,234,212,0.5),color:#e4e4e8
  style Fast fill:#14141f,stroke:rgba(130,224,170,0.6),color:#82e0aa
  style Slow fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#5eead4
  style Budget fill:#08080c,stroke:rgba(94,234,212,0.4),color:#e4e4e8
  style Easy fill:#08080c,stroke:rgba(130,224,170,0.4),color:#82e0aa
  style Hard fill:#08080c,stroke:rgba(94,234,212,0.4),color:#5eead4
  style Out1 fill:#14141f,stroke:rgba(148,148,160,0.4),color:#9494a0
  style Out2 fill:#14141f,stroke:rgba(148,148,160,0.4),color:#9494a0
  style Note fill:#08080c,stroke:rgba(94,234,212,0.4),color:#5eead4
  style NoteT fill:#08080c,stroke:rgba(148,148,160,0.4),color:#9494a0

Validation notes

# Diagrams — Module FT15: CoT Distillation and Rejection-Sampling FT

**Module**: FT15 — CoT Distillation and Rejection-Sampling FT
**Diagram count**: 5
**Tool**: Mermaid (primary). Each diagram validated in [Mermaid Live Editor](https://mermaid.live).

---

## Diagram 1 — CoT Distillation Flow (teacher generates → student SFTs)

**Type**: Mechanism / pipeline
**Purpose**: The one move that produced R1-Distill-Qwen-32B — a strong reasoning teacher emits `<think>…</think>` traces, the traces are curated, and a smaller student SFTs on them. No RL in the training loop.
**Reading the diagram**: Top path is data generation (teacher does the expensive search once). Bottom is student training (ordinary SFT). The teacher is not in the loop at train time — only its traces are.

```mermaid
flowchart TD
  Problems["Problem set\n(math, code, reasoning)\n~800K samples for R1-Distill"]
  Problems --> Teacher["STRONG REASONING TEACHER\nDeepSeek-R1 / o1 / Claude-GPT w/ thinking"]

  Teacher --> Traces["&lt;think&gt;...reasoning...&lt;/think&gt;\n&lt;answer&gt;...&lt;/answer&gt;\ntraces generated ONCE\nat data-gen time"]

  Traces --> Curate["CURATE\nfilter for correctness\n(verify the answer)\ndeduplicate, balance difficulty"]
  Curate --> SFTdata["Distillation dataset\n(problem, think, answer) tuples"]

  SFTdata --> Student["SMALLER STUDENT\nQwen-32B base\n(or 1.5B / 7B / 70B)"]
  Student --> SFT["SFT on the traces\nordinary supervised FT\nNO reward model\nNO policy gradient\nNO KL anchor"]
  SFT --> Reasoner["Reasoning student\nemits &lt;think&gt; at inference\nbefore committing to answer"]

  Teacher -.->|"NOT in train loop\nonly its traces are"| NoteT["teacher did the\nexpensive search once"]
  SFT -.->|"ceiling = teacher\nstudent cannot exceed it"| NoteS["limit: imitation only\nfor pushing past teacher → RFT/GRPO"]

  style Problems fill:#14141f,stroke:rgba(255,255,255,0.12),color:#e4e4e8
  style Teacher fill:#14141f,stroke:#5eead4,stroke-width:2px,color:#5eead4
  style Traces fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#5eead4
  style Curate fill:#08080c,stroke:rgba(94,234,212,0.4),color:#e4e4e8
  style SFTdata fill:#14141f,stroke:rgba(94,234,212,0.5),color:#e4e4e8
  style Student fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#e4e4e8
  style SFT fill:#14141f,stroke:#5eead4,stroke-width:2px,color:#5eead4
  style Reasoner fill:#14141f,stroke:rgba(130,224,170,0.6),color:#82e0aa
  style NoteT fill:#08080c,stroke:rgba(148,148,160,0.4),color:#9494a0
  style NoteS fill:#08080c,stroke:rgba(240,168,104,0.5),color:#f0a868
```

---

## Diagram 2 — The RFT Loop (generate → filter by reward → retrain on winners)

**Type**: Iterative loop
**Purpose**: Rejection-sampling FT — the middle path. Generate candidates with the current model, keep only the ones the verifiable reward accepts, SFT on the winners, repeat. No policy gradient; SFT stability throughout.
**Reading the diagram**: A cycle. Each iteration the model improves by training only on its own positively-rewarded outputs. Failures are discarded, not gradient-penalized — the structural difference from GRPO.

```mermaid
flowchart LR
  Model["Current model\n(student, iter N)"]
  Model --> Gen["1. GENERATE\nsample N candidates per problem\ntemperature > 0\nseveral rollouts each"]
  Gen --> Reward["2. FILTER by reward\nverifiable only:\nmath checks? code passes?\nanswer matches ground truth?"]
  Reward -->|"positively rewarded"| Keep["KEEP the winners\nthe accepted candidates"]
  Reward -->|"rejected"| Drop["DISCARD failures\nNOT used for training\n(not a penalty — just dropped)"]
  Keep --> Retrain["3. RETRAIN\nSFT on accepted candidates only\ncross-entropy, no policy gradient\nsame optimizer as plain SFT"]
  Retrain --> NewModel["New model\n(iter N+1)\nimproved by training\non its own successes"]
  NewModel --> Model

  Retrain -.->|"stable: SFT does not\ndiverge like policy gradients"| NoteS["worst case: small accepted set\n(diagnosable data problem)"]
  Drop -.->|"vs GRPO: GRPO learns\nfrom BOTH success & failure\nvia advantage × log-prob"| NoteG["RFT trades expressivity\n(ignores failures) for\nstability + diagnosability"]

  style Model fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#e4e4e8
  style Gen fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#e4e4e8
  style Reward fill:#08080c,stroke:rgba(94,234,212,0.5),color:#e4e4e8
  style Keep fill:#14141f,stroke:rgba(130,224,170,0.6),color:#82e0aa
  style Drop fill:#08080c,stroke:rgba(240,128,128,0.4),color:#f08080
  style Retrain fill:#14141f,stroke:#5eead4,stroke-width:2px,color:#5eead4
  style NewModel fill:#14141f,stroke:rgba(130,224,170,0.6),color:#82e0aa
  style NoteS fill:#08080c,stroke:rgba(130,224,170,0.4),color:#82e0aa
  style NoteG fill:#08080c,stroke:rgba(148,148,160,0.4),color:#9494a0
```

---

## Diagram 3 — The Decision Tree: Distillation vs RFT vs GRPO

**Type**: Decision flow
**Purpose**: The judgment the module exists to teach. Three axes: strong teacher available? reward verifiable? compute/stability constraints? Choose the cheapest technique that meets the need.
**Reading the diagram**: Top-down. First question gates distillation. Second gates RFT/GRPO. Third picks between them. Escalate only when the cheaper option plateaus.

```mermaid
flowchart TD
  Start["Goal: reasoning in a small model"]

  Start --> Q1{"Strong reasoning\nteacher available?\n(R1, o1, Claude/GPT\nwith thinking)"}
  Q1 -->|"YES"| Distill["DISTILLATION\ncheapest path\nSFT on teacher's traces\nNO RL"]
  Q1 -->|"NO"| Q2{"Reward\nverifiable?\n(math checks, code\npasses tests)"}

  Q2 -->|"NO"| Pref["Preference territory → FT13\n(DPO, not reasoning FT)\nRFT/GRPO do not apply"]
  Q2 -->|"YES"| Q3{"Compute budget &\nstability requirement?"}

  Q3 -->|"constrained / must-not-diverge"| RFT["RFT / RAFT\nmiddle ground\ngenerate → filter → SFT\nSFT stability, reward-filtered data"]
  Q3 -->|"large budget, willing to tune KL,\npush the frontier"| GRPO["GRPO (FT14)\nmost powerful, most expensive\nfull RL on verifiable rewards"]

  Distill -.->|"if it plateaus &\nteacher is the ceiling"| Escalate["escalate to RFT"]
  RFT -.->|"if it plateaus &\nbudget remains"| Escalate2["escalate to GRPO"]
  Escalate --> RFT
  Escalate2 --> GRPO

  Distill --> OutD["ceiling = teacher\ncheap, stable"]
  RFT --> OutR["self-improvement\nno teacher ceiling\nstable"]
  GRPO --> OutG["pushes past both\nmost expensive\nmost unstable"]

  style Start fill:#14141f,stroke:rgba(255,255,255,0.12),color:#e4e4e8
  style Q1 fill:#08080c,stroke:rgba(94,234,212,0.5),color:#e4e4e8
  style Q2 fill:#08080c,stroke:rgba(94,234,212,0.5),color:#e4e4e8
  style Q3 fill:#08080c,stroke:rgba(94,234,212,0.5),color:#e4e4e8
  style Distill fill:#14141f,stroke:rgba(130,224,170,0.7),stroke-width:1.5px,color:#82e0aa
  style RFT fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#5eead4
  style GRPO fill:#14141f,stroke:rgba(240,168,104,0.7),stroke-width:1.5px,color:#f0a868
  style Pref fill:#08080c,stroke:rgba(148,148,160,0.4),color:#9494a0
  style Escalate fill:#08080c,stroke:rgba(240,168,104,0.4),color:#f0a868
  style Escalate2 fill:#08080c,stroke:rgba(240,168,104,0.4),color:#f0a868
  style OutD fill:#08080c,stroke:rgba(130,224,170,0.4),color:#82e0aa
  style OutR fill:#08080c,stroke:rgba(94,234,212,0.4),color:#5eead4
  style OutG fill:#08080c,stroke:rgba(240,168,104,0.4),color:#f0a868
```

---

## Diagram 4 — The R1-Distill Headline Result

**Type**: Evidence / benchmark comparison
**Purpose**: The single fact that made distillation the standard, accessible technique — R1-Distill-Qwen-32B, trained via SFT on ~800K curated reasoning samples (no RL on the student), beats OpenAI o1-mini on several benchmarks.
**Reading the diagram**: The teacher (R1, full RL) generates traces. The student (Qwen-32B base) SFTs on them. The result outperforms a frontier compressed-reasoning product on AIME 2024 and MATH-500.

```mermaid
flowchart TD
  R1["DeepSeek-R1\nTEACHER\nfrontier reasoner\ntrained with full RL\non verifiable rewards\n(the FT14 lineage)"]
  R1 -->|"generates & curates\n~800K reasoning samples\nmath + code + general"| Data["Distillation corpus\n&lt;think&gt; traces\nverified correct"]
  Data -->|"SFT only — no RL\non the student"| Qwen32["DeepSeek-R1-Distill-Qwen-32B\n32B student\nplain SFT on distilled data"]

  Qwen32 --> Bench["BENCHMARK RESULT"]
  Bench --> AIME["AIME 2024\nR1-Distill-Qwen-32B\nBEATS o1-mini"]
  Bench --> MATH["MATH-500\nR1-Distill-Qwen-32B\nBEATS o1-mini"]

  Qwen32 -.->|"the headline fact:\nSFT on a strong teacher's traces\nbeat a frontier reasoning product\nNO student-side RL"| Note["this is why distillation became\nthe default accessible recipe\nfor small reasoning models"]

  style R1 fill:#14141f,stroke:#5eead4,stroke-width:2px,color:#5eead4
  style Data fill:#14141f,stroke:rgba(94,234,212,0.5),color:#e4e4e8
  style Qwen32 fill:#14141f,stroke:rgba(130,224,170,0.7),stroke-width:2px,color:#82e0aa
  style Bench fill:#08080c,stroke:rgba(255,255,255,0.12),color:#e4e4e8
  style AIME fill:#14141f,stroke:rgba(130,224,170,0.6),color:#82e0aa
  style MATH fill:#14141f,stroke:rgba(130,224,170,0.6),color:#82e0aa
  style Note fill:#08080c,stroke:rgba(130,224,170,0.5),color:#82e0aa
```

---

## Diagram 5 — The Thinking-Mode Toggle (hybrid models)

**Type**: Mechanism / adaptive compute
**Purpose**: Hybrid models (Qwen3) can toggle thinking on or off per request from the same weights — avoiding the always-on latency tax. Thinking budgets allocate compute adaptively.
**Reading the diagram**: One model, two modes, selected per request. The toggle is a control token / system instruction, not a separate model. The thinking budget makes it continuous: spend N tokens thinking, then answer.

```mermaid
flowchart LR
  Req["Incoming request\n(easy or hard?)"]
  Req --> Toggle{"thinking mode?\n(control token /\nsystem instruction)"}

  Toggle -->|"OFF — easy query"| Fast["NON-THINKING mode\nanswer directly\nlow latency\n'capital of France?'"]
  Toggle -->|"ON — hard query"| Slow["THINKING mode\nemit &lt;think&gt; trace\nthen answer\nhigh accuracy\n'prove integral converges'"]

  Slow --> Budget{"thinking budget?\nadaptive compute"}
  Budget -->|"small N tokens"| Easy["spend little\nconverge fast"]
  Budget -->|"large N tokens"| Hard["spend more\nhard problems\nworth the latency"]

  Fast --> Out1["one deployed model\nsame weights"]
  Easy --> Out2["one deployed model\nsame weights"]
  Hard --> Out2

  Toggle -.->|"NOT a separate model\nsame weights, steered\nby a flag"| Note["hybrid = one model\nserving both the cheap-fast\nand expensive-accurate paths"]
  Budget -.->|"trains on a MIX of\nthinking + non-thinking traces"| NoteT["distillation data must\ninclude both modes\nfor a hybrid student"]

  style Req fill:#14141f,stroke:rgba(255,255,255,0.12),color:#e4e4e8
  style Toggle fill:#08080c,stroke:rgba(94,234,212,0.5),color:#e4e4e8
  style Fast fill:#14141f,stroke:rgba(130,224,170,0.6),color:#82e0aa
  style Slow fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#5eead4
  style Budget fill:#08080c,stroke:rgba(94,234,212,0.4),color:#e4e4e8
  style Easy fill:#08080c,stroke:rgba(130,224,170,0.4),color:#82e0aa
  style Hard fill:#08080c,stroke:rgba(94,234,212,0.4),color:#5eead4
  style Out1 fill:#14141f,stroke:rgba(148,148,160,0.4),color:#9494a0
  style Out2 fill:#14141f,stroke:rgba(148,148,160,0.4),color:#9494a0
  style Note fill:#08080c,stroke:rgba(94,234,212,0.4),color:#5eead4
  style NoteT fill:#08080c,stroke:rgba(148,148,160,0.4),color:#9494a0
```

---

## Validation notes

- All five diagrams use the course design system colors: `#14141f` panel fill, `#5eead4` (`--accent`) for the primary/learned path, `rgba(94,234,212,0.4–0.5)` for decision diamonds, `#f08080` (`--danger`) for the discarded/anti-pattern path, `#f0a868` (`--warn`) for the most-expensive/must-tune path (GRPO, escalation), `#82e0aa` (`--ok`) for the recommended/success path, `#e4e4e8`/`#9494a0` for text.
- Paste each into [Mermaid Live Editor](https://mermaid.live) to render. All use stable Mermaid syntax (`flowchart LR/TD`, decision diamonds `{}`, dashed `-.label.->` annotation links) supported in current Mermaid (v10.4+).
- Diagram 2 uses a back-edge (`NewModel --> Model`) to depict the iterative loop — valid in Mermaid `flowchart LR`.
- For the slide deck (artifact 03), these are rendered as static captures from Mermaid Live, inlined into reveal.js.