Refresh README; document sft-c16 (latent-only reasoning, c=16, learned stop)
Browse files
README.md
CHANGED
|
@@ -14,51 +14,71 @@ tags:
|
|
| 14 |
- chain-of-thought
|
| 15 |
---
|
| 16 |
|
| 17 |
-
|
| 18 |
|
| 19 |
-
|
| 20 |
-
[`nvidia/DeepSeek-V4-Flash-NVFP4`](https://huggingface.co/nvidia/DeepSeek-V4-Flash-NVFP4)
|
| 21 |
-
backbone. It learns a compact latent representation of the model's chain-of-thought
|
| 22 |
-
and injects it back into the backbone so the model **reasons from a compressed
|
| 23 |
-
latent** rather than emitting a long token-by-token trace.
|
| 24 |
|
| 25 |
-
|
| 26 |
-
> checkpoint) are useless without the DeepSeek-V4-Flash backbone. You must load
|
| 27 |
-
> the backbone separately.
|
| 28 |
|
| 29 |
-
*
|
| 30 |
-
tokens by ~40%** and shrinks the **longest trace by ~4Γ** while serving at
|
| 31 |
-
**~65 tok/s** on the compile-safe fast path β with no separate reasoning model.
|
| 32 |
-
Task-accuracy numbers are small-n (n=30) and reported below with caveats.
|
| 33 |
|
| 34 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
|
| 36 |
---
|
| 37 |
|
| 38 |
-
##
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
| `config.json` | Top-level architecture description. |
|
| 47 |
-
| `PAPER.md` | Short technical report (method, serving, results). |
|
| 48 |
-
| `results/` | Raw eval JSON + HTML bar charts backing the results table. |
|
| 49 |
|
| 50 |
-
|
| 51 |
-
|
|
|
|
|
|
|
| 52 |
|
| 53 |
-
> **
|
| 54 |
-
>
|
| 55 |
-
>
|
| 56 |
|
| 57 |
---
|
| 58 |
|
| 59 |
-
## Architecture
|
| 60 |
|
| 61 |
-
Three components,
|
| 62 |
|
| 63 |
```
|
| 64 |
layer 35 hidden (4096-d)
|
|
@@ -68,6 +88,9 @@ Three components, all bundled in each checkpoint:
|
|
| 68 |
β Linear 4096β2048 Β· SiLU β
|
| 69 |
β Linear 2048β2048 Β· SiLU β
|
| 70 |
β Linear 2048β2048 β [mu, log_sigma] (1024-d) β
|
|
|
|
|
|
|
|
|
|
| 71 |
βββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 72 |
β mu (1024-d latent)
|
| 73 |
βΌ LayerNorm
|
|
@@ -77,67 +100,53 @@ Three components, all bundled in each checkpoint:
|
|
| 77 |
β Linear 2048β4096 β hidden vector (4096-d) β
|
| 78 |
βββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 79 |
β
|
| 80 |
-
βΌ injected
|
| 81 |
DeepSeek-V4-Flash backbone (frozen)
|
| 82 |
```
|
| 83 |
|
| 84 |
-
- **`target_proj`** β a frozen `Linear(4096, 1024, bias=False)`
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
- **
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
|
| 92 |
-
|
|
| 93 |
-
|
|
| 94 |
-
|
|
| 95 |
-
|
|
| 96 |
-
|
|
| 97 |
-
|
|
| 98 |
-
|
|
| 99 |
-
| activation | SiLU |
|
| 100 |
-
| checkpoint format | v2 bundle
|
| 101 |
|
| 102 |
---
|
| 103 |
|
| 104 |
-
## Checkpoint layout
|
| 105 |
|
| 106 |
-
|
| 107 |
-
|
| 108 |
|
| 109 |
```
|
| 110 |
-
reasoning_head.net.0.weight
|
| 111 |
-
reasoning_head.net.2.weight
|
| 112 |
-
reasoning_head.net.4.weight
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
decoder.net.
|
| 116 |
-
|
|
|
|
|
|
|
| 117 |
```
|
| 118 |
|
| 119 |
-
The geometry is
|
| 120 |
-
`
|
| 121 |
|
| 122 |
---
|
| 123 |
-
**FAQ**:
|
| 124 |
|
| 125 |
-
|
| 126 |
-
| Question | Answer |
|
| 127 |
-
|---|---|
|
| 128 |
-
| What does this repo provide? | A **CoLaR-style reasoning compression head** that attaches to the frozen [`nvidia/DeepSeek-V4-Flash-NVFP4`](https://huggingface.co/nvidia/DeepSeek-V4-Flash-NVFP4) backbone. It learns a compact latent representation of the model's chain-of-thought and injects it back into the backbone so the model **reasons from a compressed latent** rather than emitting a long token-by-token trace. |
|
| 129 |
-
| Which checkpoint is recommended for production use? | Use the `grpo` checkpoint (e.g., `grpo/colar_head_grpo.safetensors`). The `sft` checkpoint is the pre-RL stage, useful for comparison/ablation. |
|
| 130 |
-
| What license applies? | Other β see [`LICENSE`](./LICENSE) file. |
|
| 131 |
-
| Which backbone model does CoLaR require? | The frozen DeepSeek-V4-Flash-NVFP4 backbone (~136 MB per checkpoint); these weights are useless without the backbone, which must be loaded separately. |
|
| 132 |
-
| How do I load the head weights without importing the repository? | Load using `safe_open` and `load_file` (see the self-contained loader snippet in README); the code requires only PyTorch, safetensors, and torch.nn.functional β no first-party imports. |
|
| 133 |
-
| Is this compatible with vLLM or other inference engines? | Not yet β vLLM support is planned in a fork; full details are in [`PAPER.md`](./PAPER.md). |
|
| 134 |
-
| What improvements does CoLaR bring compared to the base model? | Median "thinking" tokens drop by **~40%** and the longest trace shrinks **~4Γ**, with service speed **~65 tok/s** on the compile-safe fast path; preliminary lm_eval shows **10β20% better results** (GSM8K n=30). |
|
| 135 |
-
| What are the known limitations or caveats of using CoLaR? | Evaluation is **small-n (30 docs, GSM8K only)**; no full-benchmark or multi-task evaluation yet; closed-loop latent decoding (generating a step with no token id) is future work; current injection is at the prompt/`` position only. |
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
---
|
| 139 |
-
|
| 140 |
-
## Load the head (self-contained, no repo import)
|
| 141 |
|
| 142 |
```python
|
| 143 |
import json
|
|
@@ -147,10 +156,10 @@ from torch import nn
|
|
| 147 |
from safetensors.torch import load_file
|
| 148 |
from safetensors import safe_open
|
| 149 |
|
| 150 |
-
CKPT = "
|
| 151 |
|
| 152 |
class ReasoningCompressionHead(nn.Module):
|
| 153 |
-
def __init__(self, hidden_size, latent_dim, mlp_dim=None):
|
| 154 |
super().__init__()
|
| 155 |
mlp_dim = mlp_dim or hidden_size // 2
|
| 156 |
self.net = nn.Sequential(
|
|
@@ -158,10 +167,19 @@ class ReasoningCompressionHead(nn.Module):
|
|
| 158 |
nn.Linear(mlp_dim, mlp_dim), nn.SiLU(),
|
| 159 |
nn.Linear(mlp_dim, 2 * latent_dim),
|
| 160 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 161 |
def forward(self, h):
|
| 162 |
mu, log_sigma = self.net(h).chunk(2, dim=-1)
|
| 163 |
return mu, log_sigma.clamp(-10.0, 2.0)
|
| 164 |
|
|
|
|
|
|
|
|
|
|
| 165 |
class LatentDecoder(nn.Module):
|
| 166 |
def __init__(self, hidden_size, latent_dim, mlp_dim=None):
|
| 167 |
super().__init__()
|
|
@@ -183,73 +201,79 @@ flat = load_file(CKPT)
|
|
| 183 |
def sub(prefix):
|
| 184 |
return {k[len(prefix):]: v for k, v in flat.items() if k.startswith(prefix)}
|
| 185 |
|
| 186 |
-
|
| 187 |
-
|
|
|
|
|
|
|
| 188 |
target_proj = nn.Linear(hs, ld, bias=False); target_proj.load_state_dict(sub("target_proj."))
|
| 189 |
|
| 190 |
-
#
|
| 191 |
-
#
|
| 192 |
-
#
|
|
|
|
| 193 |
```
|
| 194 |
|
| 195 |
---
|
| 196 |
|
| 197 |
-
## How it's served
|
| 198 |
|
| 199 |
-
DeepSeek-V4 uses **hash-based MoE expert routing keyed on `input_ids`**, so
|
| 200 |
-
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
with
|
| 204 |
-
|
| 205 |
-
|
| 206 |
-
addon itself is not released yet.
|
| 207 |
|
| 208 |
---
|
| 209 |
|
| 210 |
-
## Results (preliminary)
|
| 211 |
|
| 212 |
GSM8K, 8-shot, temperature 0, DeepSeek-V4-Flash-NVFP4 backbone, GRPO head.
|
| 213 |
-
**n = 30 documents** β accuracy is small-n and noisy; the **robust signal is the
|
| 214 |
-
|
| 215 |
|
| 216 |
| Metric | Base (no injection) | +Head (2k budget) | +Head (14.5k budget) |
|
| 217 |
|---|---|---|---|
|
| 218 |
-
| exact-match | 40.0 / 33.3 | 40.0 | 46.7 |
|
| 219 |
| closed `</think>` % | 97β100 | 30 | 40 |
|
| 220 |
| median think tokens | 146β187 | 106 | **103** |
|
| 221 |
| max think tokens | 1740β2048 | 472 | **415** |
|
| 222 |
|
| 223 |
- **~40% fewer median thinking tokens** and a **~4Γ shorter worst-case trace.**
|
| 224 |
-
- The head **never skips** reasoning (skip% = 0) β it compresses it.
|
| 225 |
-
- The low closed-`</think>`% is a **formatting artifact**:
|
| 226 |
-
|
| 227 |
-
|
| 228 |
-
|
| 229 |
-
- For context only,
|
| 230 |
-
|
| 231 |
-
base column is the same backbone under our small-n thinking-mode harness).
|
| 232 |
|
| 233 |
Raw numbers and bar charts are in [`results/`](./results).
|
| 234 |
|
| 235 |
---
|
| 236 |
|
| 237 |
-
## Limitations
|
| 238 |
|
| 239 |
- Evaluation is **small-n (30 docs, GSM8K only)**; treat accuracy as directional.
|
| 240 |
- No full-benchmark or multi-task evaluation yet.
|
| 241 |
-
-
|
| 242 |
-
|
| 243 |
- Measured on 2Γ RTX PRO 6000 (96 GiB); usable context β 15.8k tokens on that box.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 244 |
|
| 245 |
-
## Citation
|
| 246 |
|
| 247 |
-
Method after CoLaR β Compressed Latent Reasoning:
|
| 248 |
|
| 249 |
```bibtex
|
| 250 |
@article{colar2025,
|
| 251 |
-
title
|
| 252 |
journal = {arXiv preprint arXiv:2505.16552},
|
| 253 |
-
year
|
| 254 |
}
|
| 255 |
```
|
|
|
|
| 14 |
- chain-of-thought
|
| 15 |
---
|
| 16 |
|
| 17 |
+
<div align="center">
|
| 18 |
|
| 19 |
+
# π§ DeepSeek-V4-Flash Β· CoLaR Reasoning Compression Head
|
|
|
|
|
|
|
|
|
|
|
|
|
| 20 |
|
| 21 |
+
**Reason in a compact latent space β not a long token-by-token trace.**
|
|
|
|
|
|
|
| 22 |
|
| 23 |
+
*A lightweight adapter for the frozen [`nvidia/DeepSeek-V4-Flash-NVFP4`](https://huggingface.co/nvidia/DeepSeek-V4-Flash-NVFP4) backbone.*
|
|
|
|
|
|
|
|
|
|
| 24 |
|
| 25 |
+
[](https://arxiv.org/abs/2505.16552)
|
| 26 |
+
[](https://huggingface.co/nvidia/DeepSeek-V4-Flash-NVFP4)
|
| 27 |
+
[](#-this-is-an-adapter)
|
| 28 |
+
[](#-checkpoint-layout)
|
| 29 |
+
|
| 30 |
+
</div>
|
| 31 |
+
|
| 32 |
+
---
|
| 33 |
+
|
| 34 |
+
The **CoLaR reasoning compression head** learns a compact latent representation of the
|
| 35 |
+
model's chain-of-thought and feeds it back into the backbone, so the model **reasons from
|
| 36 |
+
a compressed latent** instead of spelling out every reasoning token. The backbone stays
|
| 37 |
+
frozen; only this small head (~136 MB) is trained.
|
| 38 |
+
|
| 39 |
+
Method: **CoLaR β Compressed Latent Reasoning** ([arXiv:2505.16552](https://arxiv.org/abs/2505.16552)).
|
| 40 |
+
|
| 41 |
+
> ### β οΈ This is an adapter
|
| 42 |
+
> These weights are **useless on their own**. You must load the
|
| 43 |
+
> [`nvidia/DeepSeek-V4-Flash-NVFP4`](https://huggingface.co/nvidia/DeepSeek-V4-Flash-NVFP4)
|
| 44 |
+
> backbone separately and attach this head to it.
|
| 45 |
|
| 46 |
---
|
| 47 |
|
| 48 |
+
## π¦ Checkpoints
|
| 49 |
+
|
| 50 |
+
| Variant | Path | Stage | Reasoning mode |
|
| 51 |
+
|---|---|---|---|
|
| 52 |
+
| **`sft-c16`** β¨ *latest* | `sft-c16/` | closed-loop SFT, `c = 16` | **Latent-only reasoning** β see below |
|
| 53 |
+
| `grpo` | `grpo/` | SFT β GRPO (latent-policy RL) | Prompt-position latent injection |
|
| 54 |
+
| `sft` | `sft/` | SFT (soft-MSE latent regression) | Prompt-position latent injection |
|
| 55 |
+
|
| 56 |
+
Each variant folder holds `colar_head_sft.{safetensors,pt}` (identical weights, two formats)
|
| 57 |
+
and a `config.json` with its geometry.
|
| 58 |
+
|
| 59 |
+
### β¨ `sft-c16` β latent-only reasoning
|
| 60 |
|
| 61 |
+
`sft-c16` is the newest head and works differently from the earlier checkpoints. It is a
|
| 62 |
+
**latent-only reasoning** head: the model performs its *entire* reasoning phase inside the
|
| 63 |
+
compressed latent space β one latent step stands in for **`c = 16`** reasoning tokens β and
|
| 64 |
+
a **learned stop head** decides when the reasoning is complete and the model should begin
|
| 65 |
+
emitting its answer. There is no accompanying token-by-token thinking trace to read; the
|
| 66 |
+
reasoning happens in the latents, and the model surfaces only the final answer.
|
|
|
|
|
|
|
|
|
|
| 67 |
|
| 68 |
+
This is what the extra `stop_head` sub-module (present only in `sft-c16`) provides: a small
|
| 69 |
+
classifier over the running latent state that fires a learned "end-of-reasoning" signal, so
|
| 70 |
+
the latent phase self-terminates at a variable, content-dependent depth rather than running
|
| 71 |
+
a fixed number of steps.
|
| 72 |
|
| 73 |
+
> **Serving parameters (temperature, stop threshold, latent budget, etc.) are intentionally
|
| 74 |
+
> not prescribed here.** They interact with your prompts and decoding setup β find the
|
| 75 |
+
> settings that work best for your use case.
|
| 76 |
|
| 77 |
---
|
| 78 |
|
| 79 |
+
## ποΈ Architecture
|
| 80 |
|
| 81 |
+
Three components, bundled in every checkpoint (`sft-c16` adds a fourth, the stop head):
|
| 82 |
|
| 83 |
```
|
| 84 |
layer 35 hidden (4096-d)
|
|
|
|
| 88 |
β Linear 4096β2048 Β· SiLU β
|
| 89 |
β Linear 2048β2048 Β· SiLU β
|
| 90 |
β Linear 2048β2048 β [mu, log_sigma] (1024-d) β
|
| 91 |
+
β β
|
| 92 |
+
β stop_head (sft-c16 only): β
|
| 93 |
+
β Linear 4096β1024 Β· SiLU Β· Linear 1024β1 β β learned end-of-reasoning
|
| 94 |
βββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 95 |
β mu (1024-d latent)
|
| 96 |
βΌ LayerNorm
|
|
|
|
| 100 |
β Linear 2048β4096 β hidden vector (4096-d) β
|
| 101 |
βββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 102 |
β
|
| 103 |
+
βΌ injected back into the residual stream
|
| 104 |
DeepSeek-V4-Flash backbone (frozen)
|
| 105 |
```
|
| 106 |
|
| 107 |
+
- **`target_proj`** β a frozen `Linear(4096, 1024, bias=False)` defining the SFT regression
|
| 108 |
+
target (a stable readout of the layer-42 hidden state). Kept for reproducibility; not
|
| 109 |
+
needed at inference.
|
| 110 |
+
- **`stop_head`** β *(`sft-c16` only)* the learned end-of-reasoning classifier that enables
|
| 111 |
+
latent-only reasoning.
|
| 112 |
+
|
| 113 |
+
| Config | `sft` / `grpo` | `sft-c16` |
|
| 114 |
+
|---|---|---|
|
| 115 |
+
| base model | `nvidia/DeepSeek-V4-Flash-NVFP4` | β same |
|
| 116 |
+
| hidden_size | 4096 | 4096 |
|
| 117 |
+
| latent_dim | 1024 | 1024 |
|
| 118 |
+
| mlp_dim | 2048 | 2048 |
|
| 119 |
+
| source_layer / target_layer | 35 / 42 | 35 / 42 |
|
| 120 |
+
| **compression_factor** | **4** | **16** |
|
| 121 |
+
| learned stop head | β | β
|
|
| 122 |
+
| activation | SiLU | SiLU |
|
| 123 |
+
| checkpoint format | v2 bundle | v3 bundle (adds `stop_head`) |
|
| 124 |
|
| 125 |
---
|
| 126 |
|
| 127 |
+
## ποΈ Checkpoint layout
|
| 128 |
|
| 129 |
+
Each `.safetensors` file holds a single flat tensor dict; the sub-modules are distinguished
|
| 130 |
+
by key prefix. For `sft-c16`:
|
| 131 |
|
| 132 |
```
|
| 133 |
+
reasoning_head.net.0.weight [2048, 4096] reasoning_head.net.0.bias [2048]
|
| 134 |
+
reasoning_head.net.2.weight [2048, 2048] reasoning_head.net.2.bias [2048]
|
| 135 |
+
reasoning_head.net.4.weight [2048, 2048] reasoning_head.net.4.bias [2048]
|
| 136 |
+
reasoning_head.stop_head.0.weight [1024, 4096] reasoning_head.stop_head.0.bias [1024] β sft-c16 only
|
| 137 |
+
reasoning_head.stop_head.2.weight [1, 1024] reasoning_head.stop_head.2.bias [1] β sft-c16 only
|
| 138 |
+
decoder.net.0.weight [2048, 1024] decoder.net.0.bias [2048]
|
| 139 |
+
decoder.net.2.weight [2048, 2048] decoder.net.2.bias [2048]
|
| 140 |
+
decoder.net.4.weight [4096, 2048] decoder.net.4.bias [4096]
|
| 141 |
+
target_proj.weight [1024, 4096]
|
| 142 |
```
|
| 143 |
|
| 144 |
+
The geometry is mirrored in the safetensors metadata (`config`, `format_version`,
|
| 145 |
+
`subdicts`) and in the sibling `config.json`.
|
| 146 |
|
| 147 |
---
|
|
|
|
| 148 |
|
| 149 |
+
## π Load a head (self-contained β no repo import)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 150 |
|
| 151 |
```python
|
| 152 |
import json
|
|
|
|
| 156 |
from safetensors.torch import load_file
|
| 157 |
from safetensors import safe_open
|
| 158 |
|
| 159 |
+
CKPT = "sft-c16/colar_head_sft.safetensors" # or grpo/β¦, sft/β¦
|
| 160 |
|
| 161 |
class ReasoningCompressionHead(nn.Module):
|
| 162 |
+
def __init__(self, hidden_size, latent_dim, mlp_dim=None, stop_head=False):
|
| 163 |
super().__init__()
|
| 164 |
mlp_dim = mlp_dim or hidden_size // 2
|
| 165 |
self.net = nn.Sequential(
|
|
|
|
| 167 |
nn.Linear(mlp_dim, mlp_dim), nn.SiLU(),
|
| 168 |
nn.Linear(mlp_dim, 2 * latent_dim),
|
| 169 |
)
|
| 170 |
+
# sft-c16 (v3): learned end-of-reasoning classifier over the latent state
|
| 171 |
+
self.stop_head = nn.Sequential(
|
| 172 |
+
nn.Linear(hidden_size, latent_dim), nn.SiLU(),
|
| 173 |
+
nn.Linear(latent_dim, 1),
|
| 174 |
+
) if stop_head else None
|
| 175 |
+
|
| 176 |
def forward(self, h):
|
| 177 |
mu, log_sigma = self.net(h).chunk(2, dim=-1)
|
| 178 |
return mu, log_sigma.clamp(-10.0, 2.0)
|
| 179 |
|
| 180 |
+
def stop_logit(self, h):
|
| 181 |
+
return self.stop_head(h) # sigmoid(stop_logit) > threshold β end reasoning
|
| 182 |
+
|
| 183 |
class LatentDecoder(nn.Module):
|
| 184 |
def __init__(self, hidden_size, latent_dim, mlp_dim=None):
|
| 185 |
super().__init__()
|
|
|
|
| 201 |
def sub(prefix):
|
| 202 |
return {k[len(prefix):]: v for k, v in flat.items() if k.startswith(prefix)}
|
| 203 |
|
| 204 |
+
has_stop = any(k.startswith("reasoning_head.stop_head.") for k in flat)
|
| 205 |
+
head = ReasoningCompressionHead(hs, ld, stop_head=has_stop)
|
| 206 |
+
head.load_state_dict(sub("reasoning_head.")); head.eval()
|
| 207 |
+
decoder = LatentDecoder(hs, ld); decoder.load_state_dict(sub("decoder.")); decoder.eval()
|
| 208 |
target_proj = nn.Linear(hs, ld, bias=False); target_proj.load_state_dict(sub("target_proj."))
|
| 209 |
|
| 210 |
+
# One latent step, given h35 = layer-35 hidden at the current position, shape (B, 4096):
|
| 211 |
+
# mu, _ = head(F.layer_norm(h35, (hs,)))
|
| 212 |
+
# inject = decoder(F.layer_norm(mu, (ld,))) # (B, 4096) β back into the residual stream
|
| 213 |
+
# p_stop = head.stop_logit(F.layer_norm(h35, (hs,))).sigmoid() # sft-c16: end reasoning when high
|
| 214 |
```
|
| 215 |
|
| 216 |
---
|
| 217 |
|
| 218 |
+
## π¬ How it's served (design note)
|
| 219 |
|
| 220 |
+
DeepSeek-V4 uses **hash-based MoE expert routing keyed on `input_ids`**, so vLLM's native
|
| 221 |
+
`prompt_embeds` injection path crashes the engine (`hash MoE routing requires input_ids`).
|
| 222 |
+
Injection instead uses an **`embed_tokens` forward hook** that overwrites the embedding at
|
| 223 |
+
the chosen position with the decoded latent while token ids keep flowing for routing.
|
| 224 |
+
Combined with a compile-safe capture buffer, this runs on the **cudagraph fast path** rather
|
| 225 |
+
than `enforce_eager`. Full details in [`PAPER.md`](./PAPER.md). *The serving addon is not
|
| 226 |
+
released yet.*
|
|
|
|
| 227 |
|
| 228 |
---
|
| 229 |
|
| 230 |
+
## π Results (preliminary)
|
| 231 |
|
| 232 |
GSM8K, 8-shot, temperature 0, DeepSeek-V4-Flash-NVFP4 backbone, GRPO head.
|
| 233 |
+
**n = 30 documents** β accuracy is small-n and noisy; the **robust signal is the reduction
|
| 234 |
+
in reasoning length**, not the exact-match score.
|
| 235 |
|
| 236 |
| Metric | Base (no injection) | +Head (2k budget) | +Head (14.5k budget) |
|
| 237 |
|---|---|---|---|
|
| 238 |
+
| exact-match | 40.0 / 33.3 | 40.0 | **46.7** |
|
| 239 |
| closed `</think>` % | 97β100 | 30 | 40 |
|
| 240 |
| median think tokens | 146β187 | 106 | **103** |
|
| 241 |
| max think tokens | 1740β2048 | 472 | **415** |
|
| 242 |
|
| 243 |
- **~40% fewer median thinking tokens** and a **~4Γ shorter worst-case trace.**
|
| 244 |
+
- The head **never skips** reasoning (skip% = 0) β it *compresses* it.
|
| 245 |
+
- The low closed-`</think>`% for `grpo` is a **formatting artifact**: its token-F1 reward
|
| 246 |
+
never rewarded emitting the closing tag (a larger 78Γ budget did not make traces close,
|
| 247 |
+
confirming it is not truncation). The `sft-c16` head's learned **stop** addresses exactly
|
| 248 |
+
this by terminating the latent phase on a learned signal.
|
| 249 |
+
- For context only, published DeepSeek-V4-Flash-Base scores **90.8** on GSM8K under its own
|
| 250 |
+
full harness β **not** a baseline reproduced here.
|
|
|
|
| 251 |
|
| 252 |
Raw numbers and bar charts are in [`results/`](./results).
|
| 253 |
|
| 254 |
---
|
| 255 |
|
| 256 |
+
## β οΈ Limitations
|
| 257 |
|
| 258 |
- Evaluation is **small-n (30 docs, GSM8K only)**; treat accuracy as directional.
|
| 259 |
- No full-benchmark or multi-task evaluation yet.
|
| 260 |
+
- `sft` / `grpo` inject at the prompt/`<think>` position only. `sft-c16` runs the full
|
| 261 |
+
latent-only closed loop with a learned stop; broader eval of it is ongoing.
|
| 262 |
- Measured on 2Γ RTX PRO 6000 (96 GiB); usable context β 15.8k tokens on that box.
|
| 263 |
+
- **Code is not released yet.** Training scripts and the vLLM serving addon will be
|
| 264 |
+
published separately; this repo ships weights + docs, and the loader above needs no
|
| 265 |
+
first-party code.
|
| 266 |
+
|
| 267 |
+
---
|
| 268 |
|
| 269 |
+
## π Citation
|
| 270 |
|
| 271 |
+
Method after **CoLaR β Compressed Latent Reasoning**:
|
| 272 |
|
| 273 |
```bibtex
|
| 274 |
@article{colar2025,
|
| 275 |
+
title = {CoLaR: Compressed Latent Reasoning},
|
| 276 |
journal = {arXiv preprint arXiv:2505.16552},
|
| 277 |
+
year = {2025}
|
| 278 |
}
|
| 279 |
```
|