SAVRN
Search Contact SAVRN

Open-weight model · Text generation

AnuLM-Base-2K-400M

by Pawan Kumar toonist/AnuLM-Base-2K-400M

AnuLM-Base-2K-400M is an open-weight model for text generation from Pawan Kumar, released under Creative Commons Attribution-ShareAlike 4.0. It has 398M parameters. At 16-bit it needs about 1 GB of GPU memory, which fits on 1x MI300X from $1.85 an hour, at the lowest prices in the SAVRN Index.

The three-language base with a 2,048-token context: AnuLM-Base-400M continued for 10,000 steps at block 2,048 with YaRN, on 46M tokens of the same Hindi / English / Python proportions it was originally trained on. Five hours on one RTX 5070 Ti.

Parameters398M
Context
Weights796.5 MB
Licensecc-by-sa-4.0
AccessOpen weights
Monthly Downloads

Runs On

What it takes to serve AnuLM-Base-2K-400M (398M parameters): the memory its weights need at each precision, and the cheapest way to rent enough data-center GPUs to hold them.

PrecisionWeightsMemory neededCheapest setupPer hourAlso fits
16-bit 0.8 GB 1.0 GB 1x MI300X (192 GB)
Vultr
$1.85 1x H100 $1.99 · 1x MI325X $2.00
8-bit 0.4 GB 0.5 GB 1x MI300X (192 GB)
Vultr
$1.85 1x H100 $1.99 · 1x MI325X $2.00
4-bit 0.2 GB 0.2 GB 1x MI300X (192 GB)
Vultr
$1.85 1x H100 $1.99 · 1x MI325X $2.00

Memory is the weights at that precision plus 20% for the runtime and a short context; a long context needs more. Prices are the lowest on-demand hourly rates in the SAVRN Index, read Sep 21, 2026.

AnuLM-Base-2K-400M on every accelerator the SAVRN Index prices, at every precision

Model Card

By Pawan Kumar, published under cc-by-sa-4.0, revision 285bc7eb4c26.

The three-language base with a 2,048-token context: AnuLM-Base-400M continued for 10,000 steps at block 2,048 with YaRN, on 46M tokens of the same Hindi / English / Python proportions it was originally trained on. Five hours on one RTX 5070 Ti. Full log and the honest reading of what it bought: docs/RESULTS.md §28, with the zero-shot measurement it is compared against Hindi and English Wikipedia are CC BY-SA, C4 is ODC-BY, and the Python slice is codeparrot-clean, de-duplicated GitHub Python with mixed licences. Not affiliated with Sarvam AI, AI4Bharat, BharatGen or the Government of India. Every other checkpoint in this project is trained at 512 tokens. This one answers what happens if you…

Read Pawan Kumar's full model card

Model card: AnuLM-Base-2K-400M (ckpt_ctx2k.pt)

The three-language base with a 2,048-token context: AnuLM-Base-400M continued for 10,000 steps at block 2,048 with YaRN, on 46M tokens of the same Hindi / English / Python proportions it was originally trained on. Five hours on one RTX 5070 Ti. Full log and the honest reading of what it bought: docs/RESULTS.md §28, with the zero-shot measurement it is compared against in §27.

Licence: CC BY-SA 4.0, the same as the base and for the same reason: Hindi and English Wikipedia are CC BY-SA, C4 is ODC-BY, and the Python slice is codeparrot-clean, de-duplicated GitHub Python with mixed licences. Not affiliated with Sarvam AI, AI4Bharat, BharatGen or the Government of India.

Why this exists

Every other checkpoint in this project is trained at 512 tokens. This one answers what happens if you train at four times that with the architecture's own long-context mechanism switched on — and the answer, stated plainly because it is the interesting part, is less than you would hope:

loss by position in a 2,048-token window 0–512 1536–2048 last − first
AnuLM-Base-400M, plain RoPE 4.0400 4.1128 +0.0728
AnuLM-Base-400M, YaRN, no training 4.0743 4.0065 −0.0678
this model, trained at 2,048 3.6693 3.5839 −0.0854

A model that gets worse the further into the window it goes is failing to extend; the sign of that last column is the whole question. Zero-shot YaRN already flips it, for free. Five GPU-hours of training moved it from −0.068 to −0.085. If all you want is sane behaviour at 2,048 tokens, apply YaRN to AnuLM-Base-400M and skip this model.

What the training did buy is general quality, because it is 82M tokens on top of the base's 148M — 55% more compute:

bits/byte, held-out Hindi English Python
AnuLM-Base-400M 0.6001 1.5208 1.0433
this model 0.5323 1.3897 0.8102

Nothing regressed in any language, which is the usual risk of a continuation. Python gains most because the base saw the least of it.

What it does

Continues text in Hindi, English or Python, in the register it is given, over a window four times longer than any other checkpoint here. It is a base model: not tuned to answer questions, follow instructions, chat or translate. Everything factual in its output is invented.

What it sounds like

Better compression did not make it a better writer. Six prompts across the three languages, temperature 0.8, top-k 50, 120 tokens each:

distinct-token ratio repeated 4-grams
AnuLM-Base-400M 0.335 32.5%
this model 0.425 33.3%

More varied by one measure, the same by the other. Both degenerate: a third of their 4-grams are repeats, which is what a 398M base model does when asked to free-run. Greedy decoding is worse for both. Samples from this model, at temperature 0.8:

मुंबई          -> बिग साइड (Red Dock) एक ऐसा एक प्रकार के साइड है, जो एक ही साइड के
                  एक साथ काम करता है। यह साइड सबसे पहले 1880 में सामने आया।
The history of -> microscopic computers, which are part of the CuOi and are used for
computing         the development of a complex network of computers.
def quicksort  -> x = x - 1 / y = y - 1 / y = X - y - 1 / y = X - y - 1 / ...
(arr):

Fluent-shaped, factually invented, and prone to looping — the English holds together longest, the Python loops fastest. Use a repetition penalty and a short generation if you want something readable; serve.py does.

Data

46.0M tokens (306 MB) mixed in the base's own proportions by mix_corpus.py:

part source size
Hindi Hindi Wikipedia dump (fetch_hindi.py --keep-prob 0.3) 189 MB, 21,897 articles
English C4 (fetch_web.py) 79 MB, 23,611 pages
Python codeparrot-clean (fetch_code.py) 38 MB, 4,902 files

mix_corpus.py holds out data/bench_{hindi,english,python}.txt, which is what every number above is measured on. No data is redistributed; docs/DATASETS.md lists each source with its licence, and the exact commands are in docs/RESULTS.md §28.

Training

from AnuLM-Base-400M, upcast to float32
steps 10,000 at batch 2 × grad-accum 4 × block 2,048 = 8,192 tokens/step
tokens 82M, about 2 epochs of the mix
context 2,048, with YaRN: yarn_original_context=512, yarn_factor=4.0
learning rate 1e-4 cosine to 1e-5, 200 warmup
precision bf16 autocast over float32 weights, gradient checkpointing, grouped-GEMM MoE
hardware one RTX 5070 Ti, ~1.7 s/step, 4 h 52 min unattended
result val 4.3031 at step 250 → 4.0501 best (ctx2k_curve.csv, 40 points)

yarn_original_context is pinned to 512 rather than left at the block size. That is the field docs/ARCHITECTURE.md §4 calls the most-often-mis-set part of a rope_scaling block: the NTK-by-parts correction range has to be measured against the length the model was trained at, not the one it is being extended to.

The selected checkpoint is step 7,499, not 10,000, and the difference is 0.0004 against a standard error of 0.0289 — best-val selection choosing between numbers inside their own noise, exactly as docs/RESULTS.md §26 describes. Treat them as the same model.

Architecture

Identical to every 400M AnuLM checkpoint except the context: 20 layers, hidden 1,024, GQA with 16 query / 4 key-value heads and QK-norm, RoPE θ = 1,000,000, sliding window 256 on layers 0–9, a dense SwiGLU MLP on layer 0 and 24 routed experts of 192 with top-4 routing on layers 1–19, aux-loss-free bias balancing, no shared expert, 32,768-entry vocabulary, untied embeddings. 397.7M parameters, 173.5M active per token. Context 2,048 with YaRN enabled in the config, where the others are 512 without it. Tokenizer multi32k, unchanged from the base.

How to load

With transformers

from transformers import AutoModelForCausalLM, AutoTokenizer

model = AutoModelForCausalLM.from_pretrained("toonist/AnuLM-Base-2K-400M",
                                             trust_remote_code=True)
tok = AutoTokenizer.from_pretrained("toonist/AnuLM-Base-2K-400M")

ids = tok("भारत की राजधानी", return_tensors="pt")
print(tok.decode(model.generate(**ids, max_new_tokens=80, do_sample=False)[0]))

Load it in float32, which the config asks for by default. Do not force dtype=torch.bfloat16: the router keeps a per-expert bias whose differences decide which experts fire, and rounding it to 16 bits changes the routing — the output collapses into repeated tokens rather than degrading. Use torch.autocast over float32 weights for speed.

With the AnuLM repository

hf download toonist/AnuLM-Base-2K-400M --local-dir AnuLM-Base-2K-400M
python serve.py  --ckpt AnuLM-Base-2K-400M
python sample.py --ckpt AnuLM-Base-2K-400M --prompt "हिन्दी साहित्य

"

Limitations

  • A base model. No instruction, chat, QA or translation ability. For those, AnuLM-Hindi-QA-400M and AnuLM-Translate-400M.
  • The long-context gain is mostly YaRN, not this training. See the table at the top; the honest version of the claim is in docs/RESULTS.md §28.
  • Benchmarks flatter it slightly. Its held-out benches are a slice of its own corpus, and a fresh out-of-sample draw for the base it is compared against, though both come from the same public sources.
  • It invents facts. Every date, name and number in its output is fiction.
  • Trained on a single consumer GPU for a total of about 9 GPU-hours across both stages. It is a 398M model, and reads like one.

How to load

With transformers (the modelling code travels with the weights, so trust_remote_code=True is required and there is nothing to clone):

from transformers import AutoModelForCausalLM, AutoTokenizer
model = AutoModelForCausalLM.from_pretrained("toonist/AnuLM-Base-2K-400M", trust_remote_code=True)
tok = AutoTokenizer.from_pretrained("toonist/AnuLM-Base-2K-400M")
ids = tok("def is_prime(n):", return_tensors="pt")
print(tok.decode(model.generate(**ids, max_new_tokens=60)[0]))

Greedy output is identical to this repository's own generate, cached or not; test_model.py holds the two paths together. Batches must be unpadded, and beam search is not supported.

Or with the AnuLM repository, which is what every script here expects:

hf download toonist/AnuLM-Base-2K-400M --local-dir AnuLM-Base-2K-400M
python serve.py  --ckpt AnuLM-Base-2K-400M          # web page at http://127.0.0.1:8000
python sample.py --ckpt AnuLM-Base-2K-400M --prompt "def is_prime(n):"
from model import load_checkpoint, AnuLM
ck = load_checkpoint("AnuLM-Base-2K-400M")
m = AnuLM(ck["cfg"]).eval(); m.load_state_dict(ck["model"])

Weights: model.safetensors, bfloat16, 397.7M parameters. Tokenizer: tokenizer.multi32k.json. Byte-level BPE in this repository's own JSON format (bpe.py), not the tokenizers library format. Load it with bpe.BPE.load(path).

Configuration

Architecture
AnuLMForCausalLM
Stored precision
float32
Model type
anulm

Identity and Version

Repository
toonist/AnuLM-Base-2K-400M
Publisher
Pawan Kumar
Task
Text generation
Modality
Text
Library
Not stated by the source
Parameters
398M parameters
Languages
hi, en
Revision
285bc7eb4c26f5669b9677c5ef409f1a1906b1ac
First published
2026-09-19
Last updated
2026-09-19

Files and Weights

10 files, 798.5 MB in total. The weights are 1 file totalling 796.5 MB in safetensors.

Weights1 file · 796.5 MB
Configuration4 files · 64.8 KB
Tokenizer3 files · 1.9 MB
Documentation1 file · 9.7 KB
Repository1 file · 1.5 KB
Every file
FileTypeSizeSHA-256
model.safetensorsWeights796.5 MB fa7fccf895e4
config.jsonConfiguration2.1 KB
configuration_anulm.pyConfiguration3.1 KB
model.pyConfiguration47.2 KB
modeling_anulm.pyConfiguration12.3 KB
README.mdDocumentation9.7 KB
.gitattributesRepository1.5 KB
tokenizer.jsonTokenizer1.5 MB
tokenizer.multi32k.jsonTokenizer413.1 KB
tokenizer_config.jsonTokenizer232 B

License and Download

License
cc-by-sa-4.0
Access
Open weights, no gate
Download size
796.5 MB
Download from Pawan Kumar

Released by Pawan Kumar through its official repository on Hugging Face. Read the license.

Built From

  • Derived from toonist/AnuLM-Base-400M

Memory Requirements

PrecisionWeights in memory
As published796.5 MB
16-bit0.8 GB
8-bit0.4 GB
4-bit0.2 GB

Weights only, from the published parameter count; the key-value cache and runtime add to this.

Questions About AnuLM-Base-2K-400M

How much GPU memory does AnuLM-Base-2K-400M need?

About 1 GB at 16-bit and 0.2 GB at 4-bit: the weights (398M parameters) plus a working margin. A long context needs more.

What is the cheapest GPU to run AnuLM-Base-2K-400M on?

At 16-bit, 1x MI300X from $1.85 an hour; at 4-bit, 1x MI300X from $1.85 an hour, at the lowest on-demand prices the SAVRN Index lists.

Can I use AnuLM-Base-2K-400M commercially?

Yes. AnuLM-Base-2K-400M is released under Creative Commons Attribution-ShareAlike 4.0. CC BY-SA 4.0 permits sharing and adapting, including commercially, with credit to the creator, and requires adaptations to be released under the same license.

Similar Models

Model · Text generation

SMOLM2Prover

Convergent Intelligence

SmolLM2Prover is a specialized, fine-tuned version of prithivMLmods/SmolLM2-CoT-360M. While retaining the strong conversational abilities of its base model, this version has been specifically enhanced to excel at deep thinking, logical reasoning, and higher-level mathematics, with a focus on generating step-by-step proofs and explanations (Chain-of-Thought). The model was fine-tuned using multiple rounds of Supervised Fine-Tuning (SFT) with the TRL library on a curated dataset, enhancing its ability to follow complex instructions and reason through problems. This model is intended to be used for text generation tasks that require logical reasoning or advanced conversation. The easiest way…

Open weights apache-2.0 362M parameters 8,192 tokens transformers

Model · Text generation

title

Desert Ant Labs

Suggest a title and description for any text. On-device titles and descriptions: a short factual title and a one- to two-sentence description for any passage of text. Swift (requirements) Then add the Title product to your target. The MLX trait is required: without it the module compiles as a stub. Get a title and a one or two sentence description for any passage of text, on device. Fine-tuned on transcript clips, but it works on any prose. The register is deliberately plain, with no emoji, no hashtags and no clickbait, and a description is meant to identify this passage rather than its topic. An MLX model directory. Load the folder, not a single file. The chat template is not incidental. A…

Open weights other 352M parameters 32,768 tokens mlx

Model · Text generation

Qwen2.5-0.5B-Instruct

Qwen

Qwen2.5 is the latest series of Qwen large language models. For Qwen2.5, we release a number of base language models and instruction-tuned language models ranging from 0.5 to 72 billion parameters. Qwen2.5 brings the following improvements upon Qwen2: - Significantly more knowledge and has greatly improved capabilities in coding and mathematics, thanks to our specialized expert models in these domains. - Significant improvements in instruction following, generating long texts (over 8K tokens), understanding structured data (e.g, tables), and generating structured outputs especially JSON. More resilient to the diversity of system prompts, enhancing role-play implementation and…

Open weights apache-2.0 494M parameters 32,768 tokens transformers

Model · Text generation

Qwen2.5-0.5B

Qwen

Qwen2.5 is the latest series of Qwen large language models. For Qwen2.5, we release a number of base language models and instruction-tuned language models ranging from 0.5 to 72 billion parameters. Qwen2.5 brings the following improvements upon Qwen2: - Significantly more knowledge and has greatly improved capabilities in coding and mathematics, thanks to our specialized expert models in these domains. - Significant improvements in instruction following, generating long texts (over 8K tokens), understanding structured data (e.g, tables), and generating structured outputs especially JSON. More resilient to the diversity of system prompts, enhancing role-play implementation and…

Open weights apache-2.0 494M parameters 32,768 tokens transformers