Grammar.CreateJsonGrammar(schema)
Build a grammar from any JSON Schema string.
Grammar-constrained decoding turns any local LLM into a structured output
engine. Define a JSON Schema, a BNF grammar, or a typed
TextExtractionElement tree, attach it to your conversation,
and every generated token is forced to fit the grammar. Zero parse
errors. Zero retries. Production-ready structured generation on-device.
Grammar.CreateJsonGrammar(schema)Build a grammar from any JSON Schema string.
Grammar.CreateJsonGrammarFromExtractionElements(...)Typed .NET extraction tree to grammar in one call.
Grammar.CreateGrammarFromValues(values)Constrain output to a fixed set of allowed strings.
Hand-roll grammars for domain-specific syntax.
Most LLM pipelines treat structured output as a parsing problem: ask the model for JSON, hope it produces JSON, regex-extract on failure, retry on parse error. Grammar-constrained decoding eliminates the entire problem class by intervening at the sampler. Every token the model produces is filtered against the grammar's allowed continuations. The output is guaranteed to be valid by construction.
The grammar prunes invalid tokens at generation time. Output passes JsonSerializer.Deserialize on the first try, every time.
Retrying a failing LLM call doubles latency and burns context window. Grammar removes both.
A 4B model with grammar constraints often matches a 70B unconstrained model on structured tasks. Ship local AI on consumer hardware.
Define your output once as a typed schema. The same schema becomes the grammar AND the deserialization target.
using LMKit.Model; using LMKit.TextGeneration; using LMKit.TextGeneration.Sampling; var model = LM.LoadFromModelID("qwen3.5:4b"); string jsonSchema = @" { ""type"": ""object"", ""properties"": { ""name"": { ""type"": ""string"" }, ""amount"": { ""type"": ""number"" }, ""tags"": { ""type"": ""array"", ""items"": { ""type"": ""string"" } } }, ""required"": [""name"", ""amount""] }"; var grammar = Grammar.CreateJsonGrammar(jsonSchema); var chat = new SingleTurnConversation(model) { Grammar = grammar }; var result = chat.Submit("Extract the order: Customer ACME ordered 12 units, tagged urgent and Q4."); // result.Completion is GUARANTEED to parse as the schema above
using LMKit.Extraction; using LMKit.TextGeneration.Sampling; var elements = new List<TextExtractionElement> { new("Vendor", ElementType.String, "Vendor company name"), new("InvoiceNumber", ElementType.String, "Invoice identifier"), new("InvoiceDate", ElementType.Date, "Invoice issue date"), new("Total", ElementType.Float, "Total amount due"), new("LineItems", ElementType.Object, "Line items") { IsArray = true, InnerElements = new List<TextExtractionElement> { new("Description", ElementType.String), new("Quantity", ElementType.Integer), new("UnitPrice", ElementType.Float) } } }; var grammar = Grammar.CreateJsonGrammarFromExtractionElements(elements);
using LMKit.TextGeneration.Sampling; // Constrain output to one of a fixed set of values. // Perfect for classification, routing, or multiple-choice answers. var categories = new[] { "Billing", "Technical", "Sales", "Other" }; var grammar = Grammar.CreateGrammarFromValues(categories); var chat = new SingleTurnConversation(model) { Grammar = grammar }; string ticket = "My credit card was charged twice for the same order."; var result = chat.Submit($"Categorise this support ticket: {ticket}"); // result.Completion is exactly one of: Billing, Technical, Sales, Other
Pull invoices, contracts, forms, and receipts into typed records. Use with TextExtraction for end-to-end document-to-record pipelines.
Wrap an LLM behind your own REST endpoint with a strict response contract. The grammar is your contract.
Force output to a closed set of categories, intents, or labels. No need for prompt engineering or output sanitization.
Generate calls to your tools as strictly-typed JSON. The grammar prevents the model from inventing tool names or argument shapes.
Generate complete form payloads from natural-language descriptions. The grammar enforces field types, required flags, and value ranges.
Define a BNF for your query language. The model can only emit syntactically-valid queries, dramatically reducing the surface for injection bugs.
GrammarStatic factory + instance type. Build from JSON Schema, BNF, extraction elements, or value lists. Attach to SingleTurnConversation or MultiTurnConversation.
SingleTurnConversationOne-shot generation. Set Grammar property to constrain output. Returns TextGenerationResult with the constrained completion.
TextExtractionElementTyped schema element with name, type, description, nesting, and format options. Pair with Grammar.CreateJsonGrammarFromExtractionElements.
Static helpers: Grammar.Json, Grammar.JsonArray, Grammar.Arithmetic, Grammar.List, Grammar.Boolean.
For end-to-end document-to-record extraction with a higher-level API, see Intelligent Data Extraction.
Working console demos on GitHub, step-by-step how-to guides on the docs site, and the API reference for the classes used on this page.
Console demo: typed C# objects from unstructured text via grammar.
Open on GitHub → DemoConsole demo: schema-driven extraction from invoices.
Open on GitHub → How-to guideJSON schema, BNF, deterministic shape from any model.
Read the guide → API referenceGrammar API for grammar-constrained generation.
Open the reference →Grammar-constrained generation, 100% on-device.