Skip to main content
Prerequisites: Quick Start complete, pip install mellea, Ollama running locally. Mellea provides two paths to structured output. Choose based on how the call fits into your code: Both paths enforce the declared schema at generation time using constrained decoding where the backend supports it, and retry with the IVR loop if parsing fails.

Pattern 1: @generative with typed returns

Classification with Literal

The model is constrained to return exactly one of the four allowed values.

Simple Pydantic extraction

List returns

Return a list of typed values or Pydantic models:

Nested models

Complex structured extraction works naturally with nested Pydantic models:

Pattern 2: instruct(format=...)

When you need structured output alongside dynamic prompts, grounding context, or user variables, use the format parameter on instruct():
The format parameter triggers constrained decoding. The result is a ModelOutputThunk whose .value is a JSON string matching the schema. Parse it with PydanticModel.model_validate_json(str(result)).

Validating structured output content

Constrained decoding enforces schema validity — the output is always parseable JSON matching your model. To enforce semantic constraints (e.g., “the list must contain at least 2 names”), combine format with a custom validation function:
The check(None, ...) idiom creates a validation-only requirement that is never embedded in the prompt. This avoids biasing the model while still gating the output on your semantic constraint.

Requirements on @generative output

You can also apply requirements to @generative output. When the return type is a Pydantic model, the requirements operate on the JSON string representation:
With @generative, the output is parsed into the Pydantic model automatically. You receive a Summary instance, not a JSON string.

Choosing between the two patterns

Use @generative when:
  • The function is reusable and called from multiple places.
  • The input and output types are stable.
  • You want a clean function signature with IDE type-checking.
  • You prefer direct attribute access (person.name) over manual JSON parsing.
Use instruct(format=...) when:
  • The prompt is built dynamically with user_variables or grounding_context.
  • You are retrofitting structured output onto an existing instruct() call.
  • You need fine-grained control over requirements and sampling alongside formatting.
Both patterns support the full IVR loop, requirements, sampling strategies, and SamplingResult inspection.
See also: Generative Functions | The Requirements System