Expand description
HRM two-timescale reasoning core — a faithful candle port of the reference
python/splade/hrm_core.py + spo_tagger.py::HRMTagger.
This is the architecture the reference actually uses, and it is not a stack of transformer layers:
- the backbone is BERT’s embeddings only (word + position + type) — no encoder. With a 128-dim, 30522-token vocabulary that is ~3.9M parameters, which is where the “4M model” comes from;
- on top sits
HrmCore, two coupled recurrent timescales — a fastLstream that iteratesT_innertimes against the injected input, and a slowHstream that steps back once per cycle to integrate whatLproduced. Depth comes fromN_cycles × T_innerrefinement passes rather than from more weights; - gradients flow only through the final L+H step (the reference wraps the earlier cycles in
no_gradand detaches the carry). That one-step gradient approximation is what makes recurrent depth affordable, and it is reproduced here withdetach().
Heads are independent linear maps off the shared refined state: BIO span typing, the epistemic
reading, and (via HrmTagger::hidden) span pooling for the biaffine relation head. Adding a head
costs one matrix, not another encoder.
Faithfulness notes: Block is pre-norm RMSNorm → MHA → RMSNorm → SwiGLU, matching the reference.
Dropout is omitted — the reference uses 0.1 on the residual branches, which regularises a long
training run but changes no shapes or values at eval; it is the one deliberate deviation.
Structs§
- Bert
Embeddings Only - BERT’s embedding table on its own (word + position + token-type, then LayerNorm) — the reference uses
BertModel.from_pretrained(base).embeddingsand discards the encoder entirely. candle keeps itsBertEmbeddingsprivate, so this is implemented directly, which also lets it load the checkpoint’sbert.embeddings.*tensors verbatim. - HrmConfig
- Shape/behaviour knobs, defaulting to the reference’s
cycles=2, t_inner=2, layers=2, heads=4. - HrmCore
- The two-timescale core.
Literates fast against the injected input;Hsteps back once per cycle to integrateL’s state. Output iszH + reps, a residual refinement of the embeddings. - HrmTagger
- The reference tagger: embeddings → HRM refinement → independent linear heads. Each head is one matrix over the shared refined state, so adding a dimension of the Vocabulary Space costs a matrix rather than another encoder.
- RmsNorm
x * rsqrt(mean(x²) + eps) * w— the reference’s RMSNorm (no mean subtraction, learned gain).