Blog

Introducing Lumma-0.6B

A 0.6-billion-parameter foundation model, pre-trained from scratch on 1 trillion tokens, with a 12,288-token context window and a KV cache half the usual size.

Lumma-0.6B: a conventional KV cache storing keys and values, beside a shared cache storing one latent at half the size
Lumma-0.6B keeps one latent in its KV cache where a conventional model keeps two tensors.

Long context is a memory problem long before it is a compute problem. Every token a model has read leaves a trace in its KV cache, and at 12,000 tokens a single conversation already carries a cache nearly as large as the model's own weights. Multiply that by the number of people you serve, and the cache is what decides your hardware bill.

Lumma-0.6B is built around that fact. It is a decoder-only foundation model, pre-trained from scratch on 1 trillion tokens of English and ten Indic languages, with open weights under Apache 2.0 and an architecture that keeps one tensor in memory where others keep two.

This post covers that idea, what it does to memory, how the model reads Indic scripts, and how it measures up, honestly, against models trained on many times more data.

Overview

A Foundation Model for Long Context

Lumma-0.6B is the 0.6-billion-parameter base model of the Lumma family. It was trained from scratch, with no borrowed weights, and it reads up to 12,288 tokens at once.

0.6Bparameters

pre-trained from scratch, bf16 weights

1Ttokens

of pre-training data, English plus ten Indic languages

12,288context

tokens, 6× a 2,048-token window

~50%less KV cache

in shared mode, the default

SpecValue
ArchitectureDecoder-only Transformer, no layer sharing
Layers30
Hidden size1,440
AttentionGrouped-query: 16 query heads, 8 key-value heads, head dimension 90, QK normalization
KV cacheShared (default) or vanilla, switchable at load time
Feed-forwardSwiGLU, intermediate size 3,280
NormalizationRMSNorm, no biases
PositionsRoPE, base 1,000,000
EmbeddingsFactorized (rank 512), input and output tied
Vocabulary131,072 tokens
Context length12,288 tokens
Pre-training1T tokens
LanguagesEnglish, Hindi, Bengali, Tamil, Telugu, Marathi, Gujarati, Kannada, Malayalam, Punjabi, Odia
LicenseApache 2.0

Head dimension is hidden size divided by head count. Source: the Lumma-0.6B-Base model card and its config.

Architecture

The Architecture at a Glance

Here is the whole model in one picture, read from the bottom up: tokens enter at the bottom, pass through 30 blocks, and leave as next-token probabilities at the top. The panel on the right zooms in on the attention layer, where Lumma differs most.

Figure · Lumma-0.6B Decoder Stack

Next-token probabilitiesOutput head, tied embedding512 → 131,072Linear · 1,440 → 512Final RMSNormTransformer block × 30RMSNormShared-KV AttentionGQA 16/8 · QK-NormRMSNormSwiGLU feed-forward1,440 → 3,280 → 1,440Linear · 512 → 1,440Embedding table, 131,072 × 512factorized, shared with the output headToken IDsZoom: shared-KV attentionOutput projectionSoftmax(Q Kᵀ) VRoPE on QQK-NormQ · 16 headsK = RoPE(Norm(L))KV cache holds Lonce per tokenLatent L · 8 × 90V = LHidden stateNo value projection. One latent per token feeds both roles.Keys are rebuilt from L on every read: a little computefor about half the cache memory.Per token, per layerVanilla cache: K and V, 1,440 valuesShared cache: L only, 720 values30 layers · context 12,288 · RoPE base 1,000,000AttentionFeed-forwardWhere Lumma differs
Lumma-0.6B, drawn from its published config. Copper marks where it differs from a conventional decoder: the factorized, tied embedding and the single cached latent.

Shared KV

One Tensor, Two Jobs

Standard attention keeps two things for every token it has read: a key, which says what the token is about, and a value, which says what it contributes. Grouped-query attention shrinks both by sharing them across heads, but it still stores both.

Lumma-0.6B has no separate value projection at all. Each token is projected once, into a single latent. From that latent the model reads two things. The value is the latent exactly as stored. The key is the same latent after a light normalization and a rotary position encoding. One tensor goes into the cache, and two roles come out of it.

Figure 1 · One Latent, Two Roles

Vanilla mode: store bothTokenhidden stateOne Projectionlatent, 8 × 90 = 720Attention16 query headsK · normed and rotatedV · raw latentcache: 1,440 values per token per layerShared mode: store oneTokenhidden stateOne Projectionlatent, 8 × 90 = 720Attention16 query headsL · raw latentstored onceV = LK = RoPE(Norm(L))cache: 720 values per token per layer
The two KV cache modes of Lumma-0.6B. Both run the same attention; they differ in what is kept in memory between steps. Sizes are per token per layer, for 8 key-value heads of width 90.

Keys and values are produced from the same token, so they are not independent, and letting them share a source costs little. The benchmark results below suggest that at this scale it does cost little, while halving what has to be remembered.

Position is the subtle part. RoPE rotates a key by an amount that depends on where its token sits in the sequence, so the cache holds the latent before rotation, and the model applies the key norm and the rotation to the history as it reads it. Values are never rotated.

That is the trade: memory for arithmetic. Reading the cache costs a little more compute per step, and in exchange the cache is half the size. For long context, where decoding is limited by how much memory has to be moved, that is the right side of the trade.

It is one switch. Set model.config.kv_cache_mode to "shared" for about 50% lower KV-cache memory, slightly higher compute and the best fit for long context, or to "vanilla" for a conventional cache with lower compute and the broadest framework compatibility. Same weights either way.

If the idea sounds familiar, it is a relative of our Grouped Value Attention research, which starts from the same observation, that keys and values are not independent, and takes a different route to a cache about half the size of grouped-query attention.

Memory

What Half a Cache Looks Like

The arithmetic is short. Each layer caches 8 key-value heads of width 90, which is 720 values per token. In vanilla mode that is stored twice, once for keys and once for values. Across 30 layers in bf16, that comes to 86.4 KB per token in vanilla mode and 43.2 KB in shared mode.

Figure 2 · Cache Per Sequence, by Context Length

0.5 GB1.0 GBVanilla: keys and values cachedShared: one latent cached0.180.092,048 tokens0.350.184,096 tokens0.710.358,192 tokens1.060.5312,288 tokens
KV cache per sequence in gigabytes, computed from the published config in bf16. Real serving adds framework overhead, so treat these as the cache itself, not the whole footprint.

At the full 12,288-token window, one sequence needs about 1.06 GB of cache in vanilla mode and about 0.53 GB in shared mode. Serve 32 full-length conversations at once and the cache is 34 GB against 17 GB. That is memory you can spend on more users instead.

Block

The Rest of the Block

Around the shared cache sits a modern, stable core, with a few choices made for long windows and a small budget.

Attention

QK Normalization

RMSNorm on queries and keys, per head, before RoPE. A standard stabilizer for attention scores over long sequences.

Embeddings

Factorized and Tied

A 131,072 × 512 table plus small projections, about 69M parameters. A full-width table would hold about 189M.

Position and heads

Wide RoPE Base

A rotary base of 1,000,000 spaces the frequencies for a 12,288-token window, and grouped-query attention shares 8 key-value heads across 16 query heads.

Languages

A Long Window Only Helps If Your Language Fits

Context length is counted in tokens, not words. A tokenizer that splits Indic scripts into many fragments quietly shrinks the window: 12,288 tokens is a long document in English and a short one in Telugu. Lumma-0.6B uses the same Indic-first tokenizer as Nandi-Mini, with a 131,072-token vocabulary built for English and ten Indic languages together.

The chart shows what that means for the window. In English the tokenizers are level. In Indic languages, a 12,288-token window holds between about 4 and 8 times as many words as it does under Qwen3-0.6B's tokenizer.

Figure 3 · Words in the Window, by Language

Lumma-0.6BQwen3-0.6BEnglish10,41410,593Hindi9,3092,391Tamil5,9941,124Telugu6,942918Malayalam5,994844Words in a 12,288-token window · higher is better
Words that fit in the 12,288-token window, from tokens per word on the Lumma-0.6B model card. Our arithmetic: 12,288 divided by tokens per word.
Show tokens per word and the arithmetic
Tokens per word and words that fit in the context window
LanguageLumma tokens per wordQwen3-0.6B tokens per wordLumma words in 12,288 tokensQwen3-0.6B words in 12,288 tokens
English1.181.1610,41410,593
Hindi1.325.149,3092,391
Tamil2.0510.935,9941,124
Telugu1.7713.386,942918
Malayalam2.0514.565,994844

The tokenizer does not win everywhere. Sarvam-1 needs fewer tokens per word on Hindi (1.25 against 1.32) and on Odia (2.18 against 2.68). On Bengali, Gujarati, Kannada, Malayalam, Punjabi, Tamil, Telugu and Assamese, Lumma-0.6B's tokenizer is ahead of Sarvam-1, and on Assamese the gap is large: 1.51 tokens per word against 4.31.

Results

One Trillion Tokens, Measured Honestly

We evaluated Lumma-0.6B-Base on five standard tasks, next to the half-billion-parameter models closest to it. The most important column is not accuracy but tokens: Lumma-0.6B saw 1 trillion, and its comparisons saw between 1.3 and 18.

44.47average, five tasks

Lumma-0.6B-Base, trained on 1T tokens

12×fewer tokens

than Qwen-2-0.5B, with a higher average (44.47 against 44.02)

5 of 5tasks ahead

of MobiLlama-0.5B, which saw 30% more tokens (1.3T)

−3.3points

behind Qwen2.5-0.5B (47.78), which saw 18× the data

Figure 4 · Score Against Training Data

4044481T2T5T10T20TPre-training tokens · log scaleAverage scorelevel average, one twelfth of the tokensMobiLlama-0.5B · 1.3T · 40.07Qwen-2-0.5B · 12T · 44.02Qwen2.5-0.5B · 18T · 47.78Lumma-0.6B-Base · 1T · 44.47
Average score across HellaSwag, Winogrande, OpenBookQA, ARC-Easy and ARC-Challenge, against pre-training tokens. Data from the Lumma-0.6B-Base model card.

Figure 5 · Five Tasks and the Average

MobiLlama-0.5BQwen-2-0.5BQwen2.5-0.5BLumma-0.6BHellaSwag39.6549.0152.1646.25Winogrande53.6757.6956.8254.14OpenBookQA30.6033.2035.4032.80ARC-Easy52.8254.7964.6460.60ARC-Challenge23.6325.4229.8628.58Average40.0744.0247.7844.47
Benchmark scores, one panel per task. Each panel has its own scale, so bars are comparable within a panel, not across panels. Best score in each panel in bold. Source: the Lumma-0.6B-Base model card.
Show the full table
Benchmark results
ModelTokens (T)HellaSwagWinograndeOBQAARC-eARC-cAvg.
MobiLlama-0.5B-Base1.339.6553.6730.6052.8223.6340.07
Qwen-2-0.5B-Base1249.0157.6933.2054.7925.4244.02
Qwen2.5-0.5B-Base1852.1656.8235.4064.6429.8647.78
Lumma-0.6B-Base146.2554.1432.8060.6028.5844.47

Read it plainly. Lumma-0.6B beats MobiLlama-0.5B on every task with fewer tokens. Against Qwen-2-0.5B it leads on the two ARC tasks and trails on HellaSwag, Winogrande and OpenBookQA, which nets out to a slightly higher average on one twelfth of the data. Against Qwen2.5-0.5B, trained on eighteen times as much, it is behind on all five. This is a base model, and the point of these numbers is that a strong foundation does not need the largest token budget.

Family

The Lumma Family

Lumma-0.6B-Base is the foundation of the 0.6B family, with open weights on Hugging Face.

Base

Lumma-0.6B-Base

The pre-trained foundation model described in this post.

Related

Lumma-Fev

The Lumma name also carries our decision models, which score your options in one pass.

The full set is in the Lumma collection.

Run

Run It Yourself

The architecture is custom, so loading it needs trust_remote_code=True. The cache mode is a one-line setting.

# pip install transformers==5.4.0
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch

model_name = "FrontiersMind/Lumma-0.6B-Base"

tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(
    model_name, trust_remote_code=True, dtype=torch.bfloat16
).eval()

# Memory-efficient mode (default): one cached latent per token
model.config.kv_cache_mode = "shared"
# Standard mode: keys and values cached separately
# model.config.kv_cache_mode = "vanilla"

inputs = tokenizer("The world is a strange place", return_tensors="pt").to(model.device)
outputs = model.generate(**inputs, max_new_tokens=50, do_sample=True,
                         temperature=0.3, top_p=0.95, top_k=20,
                         repetition_penalty=1.1)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))

For serving, Lumma-0.6B-Base runs on vLLM and SGLang with OpenAI-compatible endpoints, and on Docker Model Runner with one command:

docker model run hf.co/FrontiersMind/Lumma-0.6B-Base

The exact serving commands are on the model card.

Fit

Where Lumma Fits

Reach for Lumma-0.6B when context and memory are the constraint: long documents in English or Indic languages, many concurrent sessions on limited accelerators, or on-premises serving where every gigabyte of cache is a gigabyte you own and pay for. It is a good base for fine-tuning, and the instruct, tool and extraction releases are there when you want a starting point that already follows directions.

Know its edges. It is a base model, and base models are not recommended for conversation without post-training: supervised fine-tuning, RLHF or continued pre-training. On general benchmarks it sits behind Qwen2.5-0.5B, which saw far more data. And its tokenizer trails Sarvam-1 on Hindi and Odia.

The Takeaway

Lumma-0.6B asks a simple question of the KV cache: why remember two things when one will do? Keys and values read from a single stored latent, a cache half the size, and a window that stays useful in the languages it was built for. It was trained from scratch, it is open, and it runs on hardware you own. That is Sovereign Superintelligence in a small package.