vonjack's picture
Upload 12 files
57462bd verified
|
Raw History Blame Contribute Delete
12.7 kB
---
language:
- en
license: apache-2.0
library_name: transformers
pipeline_tag: text-generation
base_model: sapientinc/HRM-Text-1B
base_model_relation: finetune
datasets:
- pzarzycki/hrm-text-code-tools-sft
inference: false
tags:
- hrm
- hierarchical-reasoning
- prefix-lm
- code
- tool-use
- sft
- transformers
- safetensors
- gguf
- bf16
- q8_0
- llama.cpp
---
# HRM-Text-1B Code and Tool-Use SFT
This repository is a Transformers BF16 conversion of
[`pzarzycki/hrm-text-1b-code-tools-sft`](https://huggingface.co/pzarzycki/hrm-text-1b-code-tools-sft),
a full-parameter Stage A fine-tune of
[`sapientinc/HRM-Text-1B`](https://huggingface.co/sapientinc/HRM-Text-1B).
It also contains canonical BF16 and directly derived Q8_0 GGUF files.
The source checkpoint is a research pilot trained for code generation and a
fixed tool-transcript protocol. It has not undergone downstream benchmark or
production-agent evaluation.
## Model details
| Field | Value |
| --- | --- |
| Architecture | HRM-Text PrefixLM |
| Parameters | 1,182,795,264 |
| Stored dtype | BF16 |
| Hidden size | 1,536 |
| H/L stack depth | 16 layers each |
| Recurrence | `H_cycles=2`, `L_cycles=3` |
| Attention | 12 heads, head dimension 128, gated MHA |
| Intermediate size | 4,096, SwiGLU |
| Context length | 4,096 tokens |
| Vocabulary | 65,536 |
| Position encoding | RoPE, theta 10,000 |
| Normalization | Parameterless pre-RMSNorm |
| Training stage | Stage A pilot, seed 17 |
| Training budget | 10,000,147 response tokens |
| Primary language | English |
Stage B was not trained or published as part of the source revision used here.
## Files
| File | Format | Size | SHA256 |
| --- | --- | ---: | --- |
| `model.safetensors` | Transformers BF16 | 2,365,606,568 bytes | `2bc954894ab677dcdc66331863cf12aa4da8aa719fa56538a816632a3935546b` |
| `gguf/HRM-Text-1B-Code-Tools-SFT-BF16.gguf` | GGUF BF16 | 2,367,996,448 bytes | `4c59b7f0187315ba942088c07e7aeee38339bbfdcc1da05f4e83d3efd3c22cf7` |
| `gguf/HRM-Text-1B-Code-Tools-SFT-Q8_0.gguf` | GGUF Q8_0 | 1,259,127,360 bytes | `b0faf21c398ca4935d458d60decf6d3e60e9bc5d8dbfb1bf92d370b37bc9252e` |
| `gguf/runtime/llama.cpp-hrm_text.patch` | llama.cpp runtime patch | - | See compatibility section |
BF16 is the canonical storage format. Q8_0 was quantized directly from the
BF16 GGUF. No F16 derivative is provided because converting BF16 to F16 would
change 17,119 finite stored values and underflow 87 values to zero.
## Requirements
Use `transformers>=5.9.0`, which includes native `hrm_text` model support.
The conversion and validation environment used Transformers 5.16.1 and
PyTorch 2.13.0.
```bash
pip install --upgrade "transformers>=5.9.0" torch
```
Hosted inference is disabled in the model-card metadata because generic text
generation endpoints do not provide the required PrefixLM `token_type_ids`.
## Transformers usage
The included Jinja template must be applied. It serializes the learned
`direct` condition and the SFT transcript markup; this is not a Qwen/ChatML
prompt despite using a Qwen-compatible tokenizer.
```python
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
model_id = "YOUR_NAMESPACE/HRM-Text-1B-Code-Tools-SFT"
device = torch.device(
"cuda" if torch.cuda.is_available()
else "mps" if torch.backends.mps.is_available()
else "cpu"
)
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(
model_id,
dtype=torch.bfloat16,
).to(device).eval()
messages = [
{
"role": "user",
"content": "Write a Python function that returns the larger of two integers.",
}
]
inputs = tokenizer.apply_chat_template(
messages,
tokenize=True,
add_generation_prompt=True,
return_tensors="pt",
return_dict=True,
).to(device)
# HRM-Text was trained with a bidirectional prompt prefix.
inputs["token_type_ids"] = torch.ones_like(inputs["input_ids"])
with torch.inference_mode():
output_ids = model.generate(
**inputs,
max_new_tokens=256,
do_sample=False,
)
new_ids = output_ids[0, inputs["input_ids"].shape[1]:]
print(tokenizer.decode(new_ids, skip_special_tokens=False))
```
The rendered prompt starts with the following exact envelope:
```text
<|im_start|><|object_ref_start|><user>
Write a Python function that returns the larger of two integers.
</user>
<assistant>
<|im_end|>
```
Do not omit `token_type_ids` when using Transformers. A value of 1 marks a
prompt position as part of the bidirectional prefix block. Omitting it falls
back to pure-causal attention and does not match the training-time objective.
### Tool schemas
Pass OpenAI-style function schemas through the `tools` argument. The template
places them inside the learned `<tools>...</tools>` transcript markup.
```python
tools = [
{
"type": "function",
"function": {
"name": "read_file",
"description": "Read a UTF-8 file relative to the task root.",
"parameters": {
"type": "object",
"properties": {"path": {"type": "string"}},
"required": ["path"],
"additionalProperties": False,
},
},
}
]
prompt = tokenizer.apply_chat_template(
[{"role": "user", "content": "Read README.md and summarize it."}],
tools=tools,
tokenize=False,
add_generation_prompt=True,
)
```
`<user>`, `<assistant>`, `<tools>`, `<tool_call>`, and `<tool_result>` are
ordinary learned text markup, not pretrained HRM control tokens. The model
does not execute tools, validate arguments, or sandbox generated code. A
`system` message is intentionally serialized with the same `<user>` markup;
there is no separately trained system role.
## GGUF compatibility
The GGUF files use `general.architecture = hrm_text` and embed the exact Jinja
template under `tokenizer.chat_template`. Standard unpatched llama.cpp,
Ollama, LM Studio, and llama-cpp-python builds do not support this custom
runtime graph at the time of this release.
Apply the included patch to this exact llama.cpp commit:
```text
6a257d44633d4a752183ed778b88d2924d0a6b9d
```
```bash
git clone https://github.com/ggml-org/llama.cpp
cd llama.cpp
git checkout 6a257d44633d4a752183ed778b88d2924d0a6b9d
git apply /path/to/model/gguf/runtime/llama.cpp-hrm_text.patch
cmake -B build -DGGML_METAL=ON -DGGML_NATIVE=OFF -DLLAMA_BUILD_UI=OFF
cmake --build build --config Release --target llama-cli llama-server llama-quantize -j
```
Ninja is optional. The documented CMake flow works with the default Unix
Makefiles generator, and Metal support is independent of the generator.
Start the server with Jinja explicitly enabled. PrefixLM prefill must process
the complete prompt in one physical batch, so set `--batch-size` and
`--ubatch-size` to at least the maximum prompt length you intend to use. The
example below supports prompts up to 512 tokens. Use `-ngl all` for Metal or
`-ngl 0` for CPU-only inference.
```bash
./build/bin/llama-server \
-m /path/to/model/gguf/HRM-Text-1B-Code-Tools-SFT-Q8_0.gguf \
--alias HRM-Text-1B-Code-Tools-SFT \
--jinja --ctx-size 512 --batch-size 512 --ubatch-size 512 \
--cache-ram 0 --parallel 1 \
-ngl all --host 127.0.0.1 --port 8080
```
Requests to the OpenAI-compatible chat endpoint apply the embedded template:
```bash
curl http://127.0.0.1:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "HRM-Text-1B-Code-Tools-SFT",
"messages": [{"role": "user", "content": "Write a Python max function."}],
"temperature": 0,
"max_tokens": 128,
"cache_prompt": false
}'
```
The patch maps `hrm_text.prefix_lm=true` to llama.cpp's non-causal attention
mask. The complete initial prompt is therefore one bidirectional prefix block.
Autoregressive token-by-token decoding remains causal in effect because the KV
cache contains no future generated positions.
This is deliberately narrower than arbitrary Transformers `token_type_ids`.
Do not split one prefix across multiple physical batches, reuse a KV cache from
a shorter prompt, or enable speculative multi-token decoding. Prompt-cache
reuse is disabled in the command and request above. For the full 4,096-token
context, set `--ctx-size`, `--batch-size`, and `--ubatch-size` to 4096 if the
available memory permits it.
## Conversion validation
| Check | Result |
| --- | --- |
| Source Keras H5 to Transformers BF16 values | 1,182,795,264 checked, 0 bit mismatches |
| Tensor mapping | 259 Keras tensors mapped to 131 fused Safetensors entries |
| Keras vs Transformers FP32, pure causal | Maximum absolute logit difference `7.2718e-06` |
| Keras vs Transformers FP32, direct PrefixLM | Maximum absolute logit difference `2.0981e-05` |
| Author conversion tolerance | Passed at `atol=2e-4`, `rtol=2e-4` |
| BF16 MPS top-1 | All tested positions matched |
| BF16 MPS final-position top-10 | 10/10 overlap |
| BF16 MPS two-step greedy generation | Matched for causal and PrefixLM cases |
| Chat template | Plain and tool-schema cases passed |
| GGUF structure | 259 tensors and embedded Jinja verified for BF16 and Q8_0 |
| BF16 GGUF, Metal | 129/129 layers on MTL0; both two-token continuations matched Transformers PrefixLM baseline |
| BF16 GGUF, CPU | 0/129 layers offloaded; both two-token continuations matched |
| Q8_0 GGUF, Metal | 129/129 layers on MTL0; both two-token continuations matched |
| llama.cpp PrefixLM mask | `prefix_lm=true`, `causal_attn=0`, complete-prompt prefill, prompt cache disabled |
| llama.cpp Jinja | `/apply-template` strings and `/tokenize` IDs matched for plain and tool-schema prompts |
| llama.cpp token ranking | Top-1 matched at all 12 checked steps; top-10 overlap was 9/10 or 10/10 |
| OpenAI-compatible chat route | `/v1/chat/completions` passed with embedded Jinja enabled for all three runtime targets |
BF16 logits are not bit-identical across Keras and Transformers because their
RMSNorm, softmax, and backend arithmetic paths differ. Stored weights are
bit-identical after the audited tensor mapping, FP32 outputs pass the source
author's tolerance, and the tested BF16 token rankings and greedy outputs
match.
The llama.cpp comparisons use the same rendered token IDs and PrefixLM mask on
both sides: every initial prompt token is bidirectional and generated tokens
are causal. The validated two-step continuations were `[26763, 2336]` for the
plain prompt and `[58, 19975]` for the tool-schema prompt on BF16 CPU, BF16
Metal, and Q8_0 Metal.
## Training provenance
| Item | Value |
| --- | --- |
| SFT source repository | `pzarzycki/hrm-text-1b-code-tools-sft` |
| SFT source revision | `ab083a772a29d4999251a437fe4e8b6007f828c3` |
| Source Keras H5 SHA256 | `8ddb10cea110edff99380b360ec569e5dbde0d4a233d1c058b0e292700a42b84` |
| Base model | `sapientinc/HRM-Text-1B` |
| Training dataset | `pzarzycki/hrm-text-code-tools-sft`, canonical v2 Stage A |
| Underlying data source | `nvidia/OpenCodeInstruct` revision `8f3ba5bafe4d6e8db46082cf7ae6741bc370604d` |
| KerasHub reference implementation | `pzarzycki/keras-hub` revision `8e9207acfae1833c25ba6813932b4234b6b84bf9` |
The Stage A selection contains 38,248 rows from the sealed training split.
Training used full-parameter BF16 optimization with a 4,096-token context cap.
See the source model card for the full optimizer setup and telemetry.
## Intended use and limitations
This checkpoint is intended for research on HRM-Text code adaptation,
tool-call transcript generation, conversion fidelity, and local inference.
- No downstream coding or agent benchmark has been reported for this pilot.
- Training loss is not evidence of production coding-agent performance.
- Generated code and tool calls may be incorrect, unsafe, or fabricated.
- Tool execution, argument validation, permissions, and sandboxing must be
implemented by the host application.
- The model is predominantly English and is limited to 4,096 tokens.
- Evaluate task quality and safety independently before deployment.
## License and citation
The model is released under the Apache License 2.0. The Stage A dataset traces
to CC-BY-4.0 data; consult the linked dataset card for its attribution and
usage terms.
Please cite the base HRM-Text work:
```bibtex
@misc{wang2026hrmtextefficientpretrainingscaling,
title={HRM-Text: Efficient Pretraining Beyond Scaling},
author={Guan Wang and Changling Liu and Chenyu Wang and Cai Zhou and Yuhao Sun and Yifei Wu and Shuai Zhen and Luca Scimeca and Yasin Abbasi Yadkori},
year={2026},
eprint={2605.20613},
archivePrefix={arXiv},
primaryClass={cs.CL},
url={https://arxiv.org/abs/2605.20613}
}
```