Model reference · open weights
huginn-0125 is an open-weight language model from tomg-group-umd. huginn-0125 (FP32) weighs 7.8 GB; the smallest configuration that runs it is RTX 3060 12 GB.
For self-hosting, compare this build's requirements below with the GPU you plan to rent.
Summary of the tomg-group-umd/huginn-0125 model card, 2026-10-01
What it is
| Released by | tomg-group-umd |
|---|---|
| Released | 2025-01-08 |
| Parameters | 3.9B |
| VRAM | 7.8 GB for the weights |
What it runs on
| Card | Requests at once | Context max | Memory | |
|---|---|---|---|---|
| 8K each | 32K each | |||
| RTX 3060 12 GB | 2 | 17K | 11.6 GB | |
| RTX 4060 Ti 16 GB | 4 | 1 | 39K | 15.4 GB |
| RTX 3090 24 GB | 10 | 2 | 85K | 23.4 GB |
| RTX 4090 24 GB | 10 | 2 | 85K | 23.4 GB |
| RTX 5090 32 GB | 16 | 4 | 128K | 31.0 GB |
| L40S 48 GB | 25 | 6 | 128K | 44.0 GB |
| A100 80 GB | 50 | 12 | 128K | 78.2 GB |
| H100 80 GB | 47 | 11 | 128K | 78.1 GB |
| RTX PRO 6000 Blackwell 96 GB | 59 | 14 | 128K | 93.8 GB |
| DGX Spark (GB10) 128 GB unified | 68 | 17 | 128K | 107 GB |
| H200 141 GB | 90 | 22 | 128K | 138 GB |
| B200 180 GB | 117 | 29 | 128K | 176 GB |
| Requests at once | 8K tokens each | 32K tokens each |
|---|---|---|
| 1 | 9.9 GB | 14.1 GB |
| 5 | 15.5 GB | 36.2 GB |
| 8 | 19.6 GB | 52.8 GB |
| 16 | 30.7 GB | 97.1 GB |
| 32 | 52.8 GB | 186 GB |
| 64 | 97.1 GB | 363 GB |
One card, with vLLM's small-card settings.
From the model card
This is Huginn, version 01/25, a latent recurrent-depth model with 3.5B parameters, trained for 800B tokens on AMD MI250X machines. This is a proof-of-concept model, but surprisingly capable in reasoning and code given its training budget and size. All details on this model can be found in the tech report: "Scaling up Test-Time Compute with Latent Reasoning: A Recurrent Depth Approach." (https://www.arxiv.org/abs/2502.05171) For more information, see the paper page: https://huggingface.co/papers/2502.05171.
8 intermediate checkpoints of the model can be found in its collection. Additional intermediate checkpoints are available upon request while we find a place to host all ~350 of them. The data used to train this model is publicly available (entirely on Hugging Face), and scripts provided with the pretraining code at https://github.com/seal-rg/recurrent-pretraining can be used to repeat our preprocessing and our entire training run.
Load the model like this:
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, GenerationConfig
model = AutoModelForCausalLM.from_pretrained("tomg-group-umd/huginn-0125", torch_dtype=torch.bfloat16, trust_remote_code=True)
tokenizer = AutoTokenizer.from_pretrained("tomg-group-umd/huginn-0125")
By providing the argument num_steps, the model will execute a forward pass with that amount of compute:
input_ids = tokenizer.encode("The capital of Westphalia is", return_tensors="pt", add_special_tokens=True).to(device)
model.eval()
model.to(device)
model(input_ids, num_steps=32)
The model has about 1.5B parameters in its non-recurrent layers (prelude+coda), 0.5B parameters in the embedding, and 1.5B recurrent parameters, so, as a guideline,
the number of materialized parameters is num_steps * 1.5B + 2B. Playing with this parameter is what makes this model interesting, and different from fixed-depth transformers!
The model is trained to accept an arbitrary number of steps. However, using fewer than 4 steps will result in very coarse answers. If given enough context to reason about, benchmarks show the model improving up to around num_steps=64. Beyond that, more steps generally do not hurt, but we see no further improvements.
Note: Due to an upload issue the model is currently stored on HF with 2 copies of the tied embedding, instead of just one. This will be fixed in a future release.
The model was trained with bfloat16-mixed precision, so we recommend using bfloat16 to run inference (or AMP bfloat16-mixed precision, if you really want). All benchmarks were evaluated in pure bfloat16.
The model can be used like a normal HF model to generate text with KV-caching working as expected. You can provide num_steps directly to the generate call, for example:
model.eval()
config = GenerationConfig(max_length=256, stop_strings=["", ""],
use_cache=True,
do_sample=False, temperature=None, top_k=None, top_p=None, min_p=None,
return_dict_in_generate=True,
eos_token_id=65505,bos_token_id=65504,pad_token_id=65509)
input_ids = tokenizer.encode("The capital of Westphalia is", return_tensors="pt", add_special_tokens=True).to(device)
outputs = model.generate(input_ids, config, tokenizer=tokenizer, num_steps=16)
Note: num_steps and other model arguments CANNOT be included in the GenerationConfig, they will shadow model args at runtime.
The model was not finetuned or post-trained, but due to inclusion of instruction data during pretraining, natively understand its chat template. You can chat with the model like so
messages = []
messages.append({"role": "system", "content" : "You are a helpful assistant."})
messages.append({"role": "user", "content" : "What do you think of Goethe's Faust?"})
chat_input = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
print(chat_input)
input_ids = tokenizer.encode(chat_input, return_tensors="pt", add_special_tokens=False).to(device)
model.generate(input_ids, config, num_steps=64, tokenizer=tokenizer)
The model requires its own KV-cache implementation HuginnDynamicCache, otherwise the KV-caches of later calls to the recurrent block will overwrite the earlier ones.
The current implementation will always try to inject this Cache implementation, but that may break with huggingface updates. If you do not use generate, but implement your own generation, use a pattern like this:
# first step:
past_key_values = None
outputs = model(input_ids=input_ids, use_cache=True, past_key_values=past_key_values)
past_key_values = outputs.past_key_values # Should be an instance of HuginnDynamicCache
# next step
outputs = model(input_ids=input_ids, use_cache=True, past_key_values=past_key_values)
When generating, you can use a variable amount of compute per-token. The model is not trained for this, so this is a proof-of-concept, that it can do this task zero-shot.
You can pick between a few sane stopping rules, entropy-diff, latent-diff,kl and argmax-stability, via criterion=.... The exit threshold can be modified via exit_threshold=5e-4.
We suggest using kl for interesting exits and argmax-stability for conservative exits. Note that using these variables overrides the default generation function. Not all arguments that are valid for the normal generate call are valid here. To make this more explicit, you can also directly call `generate_with_adaptive
Quoted from the model card on Hugging Face. The full card is behind the Hugging Face link above.