Guided Generation#
Note
Swift Equivalent: This guide covers concepts that correspond to the Generable protocol and GenerationSchema in the Swift Foundation Models Framework.
Guided generation lets you constrain the model’s output to follow specific structures, formats, or schemas. This ensures applications receive structured, predictable data.
Overview#
The Foundation Models SDK provides powerful guided generation capabilities:
Type-safe responses using Python classes
JSON schema validation for structured data
Guides like value ranges, enums, and patterns
Nested structures for complex data models
The @generable Decorator#
The @generable decorator transforms a Python class into a generable type equivalent to
a Swift Generable.
Only classes decorated with @generable can be used for guided generation in
LanguageModelSession.respond(prompt, generating: ). Under the hood, @generable applies
Python dataclasses
to your decorated class, so your class must be compatible with dataclass
features for the @generable decorator to work.
Basic Example#
import apple_fm_sdk as fm
from typing import List
@fm.generable("Product review analysis")
class ProductReview:
sentiment: str = fm.guide("Overall sentiment", anyOf=["positive", "negative", "neutral"])
rating: float = fm.guide("Product rating", range=(1.0, 5.0))
keywords: List[str] = fm.guide("Key features mentioned", count=3)
async def analyze_review():
session = fm.LanguageModelSession(instructions="You are a product review analyzer.")
result = await session.respond(
"This laptop is amazing! Great performance and battery life.",
generating=ProductReview
)
print(f"Sentiment: {result.sentiment}") # for example, "positive"
print(f"Rating: {result.rating}") # for example, 4.5
print(f"Keywords: {result.keywords}") # for example, ["performance", "battery", "laptop"]
Available Constraints#
The fm.guide() function supports various constraints:
anyOf - Enum Values#
Limit output to specific options:
import apple_fm_sdk as fm
@fm.generable("Classification")
class Category:
type: str = fm.guide("Category type", anyOf=["tech", "sports", "politics"])
priority: str = fm.guide("Priority level", anyOf=["high", "medium", "low"])
range - Numeric Ranges#
Constrain numbers to a specific range:
import apple_fm_sdk as fm
@fm.generable("Temperature reading")
class Temperature:
celsius: float = fm.guide("Temperature in Celsius", range=(-50.0, 50.0))
confidence: float = fm.guide("Confidence score", range=(0.0, 1.0))
count - List Length#
Specify exact list length:
import apple_fm_sdk as fm
from typing import List
@fm.generable("Top items")
class TopItems:
items: List[str] = fm.guide("Top 5 items", count=5)
tags: List[str] = fm.guide("Exactly 3 tags", count=3)
regex - Pattern Matching#
Constrain strings to match a regex pattern. Note that the SystemLanguageModel only supports
simple regex patterns like d+ for digits or w+ for word characters.
import apple_fm_sdk as fm
@fm.generable("Contact information")
class Contact:
name: str = fm.guide("Full name", regex=r"\w+\s\w+")
age: str = fm.guide("Age", regex=r"\d+")
Complex Structures#
Nested Objects#
Create complex nested structures:
import apple_fm_sdk as fm
@fm.generable("Habitat information")
class Habitat:
location: str = fm.guide("Geographic location")
climate: str = fm.guide("Climate type", anyOf=["temperate", "tropical", "arid", "polar"])
vegetation: str = fm.guide("Primary vegetation")
@fm.generable("Hedgehog profile")
class Hedgehog:
name: str = fm.guide("Hedgehog name")
age: int = fm.guide("Age in years", range=(0, 10))
weight: float = fm.guide("Weight in grams", range=(200.0, 1200.0))
habitat: Habitat = fm.guide("Natural habitat")
diet: str = fm.guide("Primary diet")
async def extract_hedgehog_info():
session = fm.LanguageModelSession("Extract hedgehog information from the prompt")
result = await session.respond(
"Spike is a 3-year-old hedgehog weighing 800 grams. "
"He lives in temperate European woodlands with mixed vegetation "
"and primarily eats insects.",
generating=Hedgehog
)
print(f"Name: {result.name}")
print(f"Climate: {result.habitat.climate}")
print(f"Diet: {result.diet}")
Lists of Objects#
Generate lists of structured objects:
import apple_fm_sdk as fm
from typing import List
@fm.generable("Task item")
class Task:
title: str = fm.guide("Task title")
priority: str = fm.guide("Priority", anyOf=["high", "medium", "low"])
completed: bool = fm.guide("Completion status")
@fm.generable("Task list")
class TaskList:
tasks: List[Task] = fm.guide("List of tasks", count=3)
total_count: int = fm.guide("Total number of tasks")
async def extract_tasks():
session = fm.LanguageModelSession("Extract tasks from text.")
result = await session.respond(
"I need to: 1) Buy groceries (high priority), "
"2) Call dentist (medium), 3) Read book (low)",
generating=TaskList,
)
for task in result.tasks:
print(f"- {task.title} [{task.priority}]")
Schema Compatibility with Swift#
When evaluating Swift app features, ensure your Python schemas match your Swift schemas for accurate comparison.
Swift to Python Schema Mapping#
The Python @generable decorator creates schemas compatible with Swift’s Generable protocol:
Swift Code:
import FoundationModels
@Generable(description: "Product review")
struct ProductReview {
@Guide(description: "Sentiment")
var sentiment: String
@Guide(description: "Rating", .range(1.0...5.0))
var rating: Double
@Guide(description: "Keywords", .count(3))
var keywords: [String]
Equivalent Python Code:
import apple_fm_sdk as fm
from typing import List
@fm.generable("Product review")
class ProductReview:
sentiment: str = fm.guide("Sentiment")
rating: float = fm.guide("Rating", range=(1.0, 5.0))
keywords: List[str] = fm.guide("Keywords", count=3)
Validating Schema Compatibility#
To ensure your Python schemas match your Swift schemas:
Export Swift schemas to JSON:
let schema = ProductReview.generationSchema let jsonData = try JSONEncoder().encode(schema) try jsonData.write(to: URL(fileURLWithPath: "schema.json"))
Load and use in Python:
import json import apple_fm_sdk as fm # Load Swift schema with open("schema.json", "r") as f: swift_schema = json.load(f) # Use in a LanguageModelSession session = fm.LanguageModelSession(instructions="Generate a product review.") result = await session.respond( "This laptop is amazing! Great performance and battery life.", json_schema=swift_schema )
Error Handling#
Handle errors specific to guided generation:
import apple_fm_sdk as fm
from typing import Optional
async def safe_guided_generation(prompt: str, MyGenerable: Optional[type] = None):
try:
if MyGenerable:
return await fm.LanguageModelSession().respond(
prompt, generating=MyGenerable
)
else:
return await fm.LanguageModelSession().respond(prompt)
except fm.InvalidGenerationSchemaError as e:
print(f"Schema error: {e}")
except fm.UnsupportedGuideError as e:
print(f"Unsupported constraint: {e}")
except Exception as e:
print(f"Generation error: {e}")