GLRMask Isaac Breen

Grammar-constrained generation

Grammar constraints, compiled.

GLRMask is a Rust and Python library for JSON Schema and general context-free grammars. It moves lexer, parser, and tokenizer work ahead of generation, then turns the current parse state into a next-token mask.

python -m pip install glrmask cargo add glrmask
Compile onceRun per token
Inputgrammar + vocabulary
Compilerlexer / parser structure
Precomputedweighted automata
Terminal DWAstack effectsParser DWA
Runtime statelexer + weighted GSS
Outputmodel-token mask
4.06 µsJSON median TBM
20.7 µsJSON p99.9 TBM
40.9 µsJavaScript median · tuned corpus
< 0.5 msJavaScript maximum · tuned corpus

The shape of it

Do the awkward work before the GPU needs an answer.

A normal grammar-constrained decoder has to reconcile model tokens with lexer and parser state while decoding. GLRMask deliberately makes compilation heavier so that mask generation has much less structure left to discover online.

Runtime

The parser is still there. It just isn’t being replayed across the vocabulary.

Committing a sampled token advances the incremental GLR parser. Generating the next mask takes a different path: a deterministic weighted automaton reads the compact parser state and returns the vocabulary mask directly.

01

MaskRead the current weighted graph-structured stack and produce the legal model-token set.

02

SampleApply the mask to model logits. The sampler cannot choose a token outside the constraint.

03

CommitAdvance lexer and GLR parser state only for the token that was actually chosen.

vocabulary slicemask(state)
"name""oops: {] true ??? null)
legal tokens4 / 9 shown

Good fit

Reuse the constraint.

GLRMask makes the most sense when a compiled constraint will serve many requests, or when low and predictable mask latency matters enough to pay compilation up front.

See the trade-off

Different fit

One schema, one request.

For a brand-new JSON Schema used once, a decoder with very small startup cost can be the better total-latency choice. GLRMask also has a dynamic path for cases where a cached compilation is unavailable.

Crate page