Overview

GLRMask is a grammar-constrained decoding library for high-throughput LLM serving. It is optimized for fast mask computation with extremely low tail latency, even for complex grammars.

GLRMask supports general context-free grammars, including ambiguous ones. It accepts JSON schemas and Lark grammars. GLRM is its internal grammar format.

Benchmarks

Care about compile times? Try dynamic mode.

GLRMask’s dynamic mode trades some mask-generation speed for lower cold-start latency. It is heavily based on llguidance.

Time between masks

Hover or tap to inspect. When focused, use left and right arrows to inspect the tail; Escape dismisses values.

Statistics

Lower is better.

Time between masks

· µs
Statistic GLRMaskstatic llguidance
mean 3.0 25.9
2.5 10.6
5.1 40.7
12.9 289.9
27.5 1092.6
40.0 3549.0
77.0 6931.5

Time to first mask

· ms
Statistic GLRMaskstatic llguidance
mean 35.5 1.2
p50 13.5 0.8
p90 81.7 1.8
p99 312.9 11.1
max 1390.1 231.0
Measurement details

Measured on AWS c8i.8xlarge (Intel Xeon 6975P-C, Linux) with the Llama 3.1 8B Instruct vocabulary. TTFM covers 8,326 schemas with successful builds and timings across all four engines. TBM covers 11,277 complete valid trajectories accepted by all four engines (1,734,930 token positions); failed, incorrect and incomplete trajectories are excluded. Timings use one wall-clock pass per engine; memory limits differed. See methodology and source data.

Full-run outcomes

ModeBuild OKBuild errorsRuntime-error examples
GLRMask93252330
GLRMask dynamic93262320
GLRMask Balanced93262320
llg 1.8.0833212266

How it works

Getting started

Installation

python -m pip install glrmask

Python quickstart

import glrmask

vocab = glrmask.Vocab.from_id_to_bytes({0: b"hello", 1: b" ", 2: b"world"})
grammar = glrmask.Grammar.from_ebnf('start ::= "hello" " " "world"')
constraint = grammar.compile(vocab)
state = constraint.start()
for token_id, expected in [(0, [True, False, False]),
                           (1, [False, True, False]),
                           (2, [False, False, True])]:
    assert state.mask().tolist() == expected
    state.commit_token(token_id)
assert state.is_accepting()

Python masks are NumPy Boolean arrays indexed by original model token ID.

Rust quickstart

use glrmask::{Grammar, Vocab};

fn main() -> glrmask::Result<()> {
    let vocab = Vocab::new(vec![
        (0, b"hello".to_vec()), (1, b" ".to_vec()), (2, b"world".to_vec()),
    ]);
    let grammar = Grammar::from_ebnf(r#"start ::= "hello" " " "world""#);
    let constraint = grammar.compile(&vocab)?;
    let mut state = constraint.start();
    for (token_id, expected) in [(0, 1), (1, 2), (2, 4)] {
        assert_eq!(state.mask()[0] & 7, expected);
        state.commit_token(token_id)?;
    }
    assert!(state.is_accepting());
    Ok(())
}

Rust masks are packed u32 bitsets. Bit token_id % 32 of word token_id / 32 indicates whether that token is allowed.

Core concepts

GLRMask has four core types:

  • Grammar: source grammar semantics and bindings.
  • PreparedGrammar: reusable vocabulary-specific compiled machinery, which can still have unresolved bindings.
  • Constraint: a closed, runnable grammar compiled against a vocabulary.
  • ConstraintState: the mutable state for one generated sequence.

Compile a Grammar directly, or use prepare() and link() for reusable components. Create a state with start(), then compute the next-token mask, sample an allowed token, and commit it.

Grammar and PreparedGrammar keep reusable definitions with mutable bindings. bind() fills one declared slot on the handle. Clones and previously attached children retain independent binding snapshots; a failed bind leaves the handle unchanged.

Full guide · Python API reference · Rust API reference