Skip to main content

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.

Run in Colab

Step through this example interactively
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.
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)
Strict mode (strict=True) pushes providers to reject extra fields and invalid enums. When omitted, provider defaults apply.

Raw JSON Schema

If you already have a schema, pass it directly via json_schema_format.
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).
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.
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.