GizStack
View .mdOpen in ChatGPTOpen in Claude

gizml:grammar

the texts a model may write, for constrained decoding. A Grammar is compiled once from a JSON schema (or is any JSON object); a Recognizer reads a text byte by byte and says whether the text so far can still become one the grammar allows, and whether it is one already. A sampler masks each token whose bytes the recognizer refuses (gizml:llm), so the answer is JSON of the schema. The recognizer keeps each reading that is still possible (anyOf, enum values and object keys with a common start), so it needs no lookahead.

gizlang
import * as Grammar from "gizml:grammar";

Types

Node

gizlang
type Node = { kind: i64; keys: Vec<string>; values: Vec<i64>; required: Vec<bool>; extra: bool; items: i64; least: i64; most: i64; texts: Vec<bytes>; options: Vec<i64>; }

A node of a grammar: its kind and, by kind, its keys and their nodes, the keys it needs and whether other keys may come (OBJECT); its items' node and bounds (ARRAY); its texts as compact JSON (LITERAL: true, null, an enum's values); its options (CHOICE).

  • kind: i64
  • keys: Vec<string>
  • values: Vec<i64>
  • required: Vec<bool>
  • extra: bool
  • items: i64
  • least: i64
  • most: i64
  • texts: Vec<bytes>
  • options: Vec<i64>

Grammar

gizlang
type Grammar = { nodes: Vec<Node>; }

A grammar: its nodes, the first the whole text's.

  • nodes: Vec<M22.Node>

Frame

gizlang
type Frame = { node: i64; kind: i64; phase: i64; seen: Vec<bool>; keys: Vec<i64>; free: bool; pos: i64; count: i64; texts: Vec<i64>; sub: i64; }

One step of a reading: the grammar node, the state of the value that it reads, and what it has seen.

  • node: i64
  • kind: i64
  • phase: i64
  • seen: Vec<bool>
  • keys: Vec<i64>
  • free: bool
  • pos: i64
  • count: i64
  • texts: Vec<i64>
  • sub: i64

Reading

gizlang
type Reading = { frames: Vec<Frame>; space: i64; }

One reading of a text so far: its stack of frames and the space that the grammar allows next.

  • frames: Vec<M22.Frame>
  • space: i64

Recognizer

gizlang
type Recognizer = { readings: Vec<Reading>; }

The readings of a text so far by a grammar: none when the grammar allows no text that starts so.

  • readings: Vec<M22.Reading>

Functions

anyObject

gizlang
function anyObject(): Grammar

Any JSON object, as OpenAI's response_format json_object asks.

Effects: fail.

fromSchema

gizlang
function fromSchema(schema: JsonValue): Grammar throws string

The grammar of a JSON schema: type (one or a list), properties, required, additionalProperties (false when not given, as vLLM's strict mode), items, minItems, maxItems, enum, const, anyOf, oneOf and $ref to #/$defs or #/definitions. Other keywords (pattern, format, lengths, bounds of numbers) are not enforced.

Effects: fail.

Methods

Grammar.start

gizlang
function Grammar.start(self: Grammar): Recognizer

The recognizer of g before any byte. The text starts with its value: no white space before it.

Effects: fail.

Recognizer.live

gizlang
function Recognizer.live(self: Recognizer): bool

Whether the text so far can still become one the grammar allows.

Recognizer.done

gizlang
function Recognizer.done(self: Recognizer): bool

Whether the text so far is one the grammar allows (white space may still follow).

Effects: fail.

Recognizer.feed

gizlang
function Recognizer.feed(self: Recognizer, g: Grammar, text: bytes): Recognizer

The recognizer of grammar g after the bytes of text; not live when g refuses one.

Effects: fail.

Recognizer.allows

gizlang
function Recognizer.allows(self: Recognizer, g: Grammar, text: bytes): bool

Whether text may come next by grammar g: the recognizer stays live after it.

Effects: fail.