Files
wehub-resource-sync 593b94c120
pytest / Unit Tests (push) Has been cancelled
pytest / Integration (integration_tests_a) (push) Has been cancelled
pytest / Integration (integration_tests_b) (push) Has been cancelled
pytest / Integration (integration_tests_c) (push) Has been cancelled
pytest / Integration (integration_tests_d) (push) Has been cancelled
pytest / Integration (integration_tests_e) (push) Has been cancelled
pytest / Integration (integration_tests_f) (push) Has been cancelled
pytest / Integration (integration_tests_g) (push) Has been cancelled
pytest / Integration (integration_tests_h) (push) Has been cancelled
pytest / Integration (integration_tests_i) (push) Has been cancelled
pytest / Integration (integration_tests_j) (push) Has been cancelled
pytest / Distributed (distributed_a) (push) Has been cancelled
pytest / Distributed (distributed_b) (push) Has been cancelled
pytest / Distributed (distributed_c) (push) Has been cancelled
pytest / Distributed (distributed_d) (push) Has been cancelled
pytest / Distributed (distributed_e) (push) Has been cancelled
pytest / Distributed (distributed_f) (push) Has been cancelled
pytest / Minimal Install (push) Has been cancelled
pytest / Event File (push) Has been cancelled
pytest (slow) / py-slow (push) Has been cancelled
Publish JSON Schema / publish-schema (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:49:20 +08:00
..

Structured and Constrained LLM Output

Open In Colab

Why constrained decoding matters

Large language models are trained to produce fluent text, but they have no built-in guarantee that their output follows a particular format. When you ask an LLM to return JSON, classify into one of three labels, or follow a grammar, it may occasionally hallucinate, add extra text, or produce a structurally invalid response.

Constrained decoding solves this by modifying the token sampling process at inference time. A constraint (JSON schema, regular expression, or context-free grammar) is compiled into a set of masks that are applied to the model's logit distribution at each step. Tokens that would violate the constraint are assigned negative infinity logit, so the model can only ever produce valid output.

Ludwig supports three forms of constrained output:

Constraint type Use case Config key
JSON schema Structured data extraction, tool-call responses decoder.json_schema
Regex Classification, fixed-format fields decoder.regex
Grammar (EBNF) Complex structured formats decoder.grammar

Quick start

pip install "ludwig[llm]"

Entity extraction (JSON schema)

python run_structured.py

Or use the Ludwig API directly with one of the provided configs:

import pandas as pd
from ludwig.api import LudwigModel

model = LudwigModel(config="config_json_schema.yaml")
preds, _, _ = model.predict(dataset=pd.DataFrame({"text": ["Apple was founded by Steve Jobs in Cupertino."]}))
print(preds["output_predictions"].iloc[0])
# -> {"entities": [{"text": "Apple", "type": "ORG"}, ...]}

Sentiment classification (regex)

model = LudwigModel(config="config_constrained.yaml")
preds, _, _ = model.predict(dataset=pd.DataFrame({"text": ["I loved this product!"]}))
print(preds["sentiment_predictions"].iloc[0])
# -> positive

Files

File Description
structured_output.ipynb Interactive notebook (Colab-compatible)
config_json_schema.yaml Ludwig config for JSON schema entity extraction
config_constrained.yaml Ludwig config for regex-constrained sentiment classification
run_structured.py Standalone script showing all three features

Models used

Both configs use freely available models that fit on a free Colab GPU (T4, 16 GB):

Further reading