> ## Documentation Index
> Fetch the complete documentation index at: https://docs.perceptron.inc/llms.txt
> Use this file to discover all available pages before exploring further.

# Structured outputs

> Constrain model replies to Pydantic, JSON schemas or regex for reliable parsing.

<Card icon="play" title="Run in Colab" href="https://colab.research.google.com/github/perceptron-ai-inc/perceptron/blob/main/cookbook/recipes/capabilities/perceptron-mk1/structured-outputs.ipynb">
  Step through this example interactively
</Card>

Perceptron supports constrained decoding so replies always adhere to the shape you expect. Provide a Pydantic class, JSON Schema or regex pattern and the inference server ensures the outputs adhere to the structure without additional prompt engineering.

## Helpers overview

* `pydantic_format(MyModel, name=None, strict=None)`: Generate the schema from a Pydantic v2 model; optionally override the schema name; set `strict=True` for strict enforcement.
* `json_schema_format(schema, name="response", strict=None)`: Wrap a JSON Schema dict to enforce keys, enums, and structure—set `strict=True` for strict enforcement.
* `regex_format(pattern)`: Constrain short outputs (yes/no, IDs, emails) with a regex instead of a full schema.

All helpers feed into the same `response_format` argument available on `perceive`, `async_perceive`, `Client.generate`, and `Client.stream`.

## Pydantic-backed responses

Use Pydantic models to define the target shape, then pass `pydantic_format` so the response is guaranteed to match. You can parse the result directly into the model for type-safe handling.

```python theme={null}
from perceptron import image, perceive, pydantic_format, text
from pydantic import BaseModel, Field
from typing import Literal


class SceneAnalysis(BaseModel):
  scene_type: str = Field(description="outdoor, indoor, urban, nature")
  main_subjects: list[str]
  mood: Literal["calm", "energetic", "dramatic", "peaceful", "tense"]
  time_of_day: Literal["morning", "afternoon", "evening", "night", "unknown"]


@perceive(response_format=pydantic_format(SceneAnalysis))
def analyze_scene(path: str):
  return image(path) + text("Analyze this scene and return JSON.")


result = analyze_scene("scene.jpg")
analysis = SceneAnalysis.model_validate_json(result.text)
print(analysis.time_of_day)
```

<Callout type="info">
  Strict mode (`strict=True`) pushes providers to reject extra fields and invalid enums. When omitted, provider defaults apply.
</Callout>

## Raw JSON Schema

If you already have a schema, pass it directly via `json_schema_format`.

```python theme={null}
from perceptron import image, json_schema_format, perceive, text

schema = {
  "type": "object",
  "properties": {
    "title": {"type": "string"},
    "keywords": {"type": "array", "items": {"type": "string"}},
    "confidence": {"type": "number"}
  },
  "required": ["title", "keywords", "confidence"],
  "additionalProperties": False
}

@perceive(response_format=json_schema_format(schema, name="summary", strict=True))
def summarize(path: str):
  return image(path) + text("Summarize the image and include keywords.")


resp = summarize("frame.png")
print(resp.text)  # Valid JSON matching the schema
```

## Regex constraints for short answers

Use `regex_format` when a compact pattern is enough (e.g., binary decisions, IDs, or numeric ranges).

```python theme={null}
from perceptron import image, perceive, regex_format, text

@perceive(response_format=regex_format(r"yes|no"))
def quick_check(path: str):
  return image(path) + text("Is there a stop sign in this photo? Respond yes or no.")


print(quick_check("frame.jpg").text)
```

## Streaming with structure

`Client.stream` and `async_perceive(stream=True)` support the same `response_format`. Streamed deltas arrive as text; the final event still respects your schema so you can parse once the stream completes.

<Callout type="tip">
  Schema compilation can add latency the first time you use a new shape. Reuse the same schema object or Pydantic model to benefit from provider-side caching.
</Callout>
