I built smallwords, a small MIT-licensed Python package for controlled-vocabulary LLM output.
The practical problem is drift. A project may describe its allowed language in a prompt, encode it again in a grammar, approximate it in JSON Schema, and then write separate validation logic. smallwords keeps one WordlistSpec at the center and derives all four surfaces from it:
The package includes source-backed English lists plus playful caveman, pirate, and cowboy remixes. For the current example, I used Granite 4.2 locally through llama-server to rewrite a compressed line from the missile-guidance monologue.
Simple
The missile is now where it is.
The missile should be where it should be.
The difference tells the missile how far to move.
Pirate
First place is where the ship is now.
Second place is where it should be.
Difference tells the crew which way to sail.
Cowboy
Where the cattle are now is the first place.
Where the ranch is is the second place.
The difference tells the cowboy which way to ride.
These are sampled model outputs under generated GBNF. Each output passes the focused grammar contract and the complete v0.2.0 preset. The runnable example prints every prompt, grammar, schema, model response, and validation report.
pip install smallwords
I would be interested in feedback from people using constrained decoding with local models, particularly around multilingual vocabularies, grammar size, and additional output shapes.