Overview
Constrained generation allows you to:- Define structured output formats using Swift types
- Get compile-time validation of your type definitions
- Generate JSON responses that are guaranteed to match your Swift structures
- Decode responses directly into type-safe Swift objects
Setup
To use constrained generation, import the SDK:Installation
When adding LeapSDK via Swift Package Manager, the constrained generation macros are automatically available. No additional setup is required.Constrained generation requires Swift 5.9+ and uses Swift macros for compile-time code generation.
Defining Structured Types
Use the@Generatable and @Guide macros to define types for structured output:
Basic Example
What the Macros Do
The@Generatable macro automatically generates:
- Conformance to the
GeneratableTypeprotocol - A
typeDescriptionproperty with your provided description - A
jsonSchema()method that creates a JSON schema from your type
@Guide macro provides descriptions for individual properties that help the AI understand what each field should contain.
Using Constrained Generation
Once you’ve defined your types, use them withGenerationOptions:
Note:completion.message.contentcan contain multiple fragments (text, audio, images). The JSON payload you need for decoding typically lives in the.textfragments. Filter and join those fragments before decoding, as shown above.
Advanced Examples
Complex Nested Structures
You can define complex types with arrays, optionals, and nested objects:Mathematical Problem Solving
Data Analysis Results
How It Works
The constrained generation system works through a three-step process:- Compile-time: The
@Generatablemacro analyzes your Swift type and generates a JSON schema based on property types and@Guidedescriptions - Runtime:
GenerationOptions.setResponseFormat()configures the AI model with the generated schema to constrain its output - Generation: The LLM produces valid JSON that conforms to your structure, which you can decode directly into your Swift type
The JSON schema generation happens at compile time, not runtime, ensuring optimal performance.
Best Practices
1. Use Descriptive Guide Annotations
Good@Guide descriptions help the AI understand what each field should contain:
2. Keep Structures Focused
Smaller, well-defined types work better than large complex ones:3. Handle Optional Fields Appropriately
UseOptional types when fields might not always be present:
4. Test with Different Prompts
Ensure your types work across various use cases and prompt styles:5. Validate Generated Output
Always handle potential parsing errors gracefully:Error Handling
Common issues and solutions:Compile-time Errors
Runtime Parsing Errors
Handle cases where the AI generates invalid JSON:Troubleshooting
”Cannot find type ‘GeneratableType’ in scope”
Make sure you’ve imported the constrained generation package:“External macro implementation could not be found”
This typically means there’s an issue with the macro plugin. Try:- Clean your build folder (Cmd+Shift+K)
- Restart Xcode
- Ensure you’re using Swift 5.9 or later
Generated JSON doesn’t match expected format
- Check your
@Guidedescriptions are clear and specific - Try adjusting the temperature in
GenerationOptions(lower values like 0.3-0.5 can improve structured output) - Ensure your prompt clearly requests JSON format output