Skip to main content

Command Palette

Search for a command to run...

Reliable JSON Responses from LLMs

Published
5 min read
Reliable JSON Responses from LLMs

Getting reliable, structured (JSON) responses from Large Language Models is harder than it looks. The magentic library, paired with Pydantic, lets you define the shape of your expected output as a Python class and receive it back as a validated object — no manual prompt engineering or fragile JSON parsing required.

The Problem

When you call an LLM through its API, the response comes back as free-form text. If your application needs that data in a structured format — say, a JSON object with specific fields — you're left writing brittle prompt instructions like "Please respond in JSON with keys name, age, and summary" and then wrapping everything in try/except json.loads(...).

This leads to:

  • Unreliable outputs — the model may add commentary, change key names, or break JSON syntax.

  • Wasted tokens — lengthy system prompts that explain the desired format eat into your context window.

  • Messy code — parsing logic, validation, and retry handling clutter your business logic.

How Magentic + Pydantic Solve This

The magentic library introduces a simple decorator-based approach:

  1. Define your output schema using a Pydantic model — the same way you'd define any data class in modern Python.

  2. Decorate a function with @prompt, providing your prompt template.

  3. Call the function — magentic handles the system prompt injection, API call, and Pydantic-led response parsing under the hood.

This means:

  • The decorator manages the underlying system prompts that instruct the LLM to return structured data.

  • Pydantic validates and parses the response automatically.

  • Token usage is optimised because the formatting instructions are handled efficiently by the library.

  • Your codebase stays clean — no raw JSON wrangling.

Quick Example (Python + OpenAI API Key)

Install

pip install magentic pydantic openai

Code

"""
Structured Output Binding with Magentic + Pydantic + OpenAI
------------------------------------------------------------
pip install magentic pydantic openai python-dotenv
"""

import os
from dotenv import load_dotenv
from pydantic import BaseModel
from openai import OpenAI
from magentic import prompt

# Load API key from .env file
load_dotenv()


# =============================================
# 1. Define output schemas (shared by both approaches)
# =============================================

class MovieReview(BaseModel):
    title: str
    rating: float
    summary: str


class RecipeSuggestion(BaseModel):
    name: str
    ingredients: list[str]
    steps: list[str]
    prep_time_minutes: int


# =============================================
# APPROACH 1: Direct OpenAI API call (explicit LLM call)
# =============================================

def review_movie_direct(movie_name: str) -> MovieReview:
    """Calls the OpenAI API directly and parses response into a Pydantic model."""
    client = OpenAI()  # uses OPENAI_API_KEY from env

    # This is the actual LLM call ↓
    completion = client.beta.chat.completions.parse(
        model="gpt-4o-mini",
        messages=[
            {"role": "system", "content": "You are a movie critic. Return structured JSON."},
            {"role": "user", "content": f"Give a short review of the movie {movie_name}"},
        ],
        response_format=MovieReview,  # OpenAI parses response into this Pydantic model
    )

    return completion.choices[0].message.parsed


# =============================================
# APPROACH 2: Magentic decorator (hides the LLM call)
# =============================================
# Under the hood, @prompt sends your text to the OpenAI API
# and automatically parses the response into the return type.

@prompt("Give a short review of the movie {movie_name}")
def review_movie_magentic(movie_name: str) -> MovieReview: ...


@prompt("Suggest a simple recipe using {ingredient} as the main ingredient")
def suggest_recipe(ingredient: str) -> RecipeSuggestion: ...


# =============================================
# 3. Run & test
# =============================================

if __name__ == "__main__":
    assert os.environ.get("OPENAI_API_KEY"), "Set OPENAI_API_KEY in your .env file first!"

    # --- Approach 1: Direct OpenAI call ---
    print("=== Movie Review (Direct OpenAI Call) ===")
    review = review_movie_direct("Inception")
    print(f"Title   : {review.title}")
    print(f"Rating  : {review.rating}")
    print(f"Summary : {review.summary}")

    print()

    # --- Approach 2: Magentic decorator ---
    print("=== Movie Review (Magentic Decorator) ===")
    review2 = review_movie_magentic("The Matrix")
    print(f"Title   : {review2.title}")
    print(f"Rating  : {review2.rating}")
    print(f"Summary : {review2.summary}")

    print()

    print("=== Recipe Suggestion (Magentic Decorator) ===")
    recipe = suggest_recipe("chicken")
    print(f"Name        : {recipe.name}")
    print(f"Ingredients : {', '.join(recipe.ingredients)}")
    print(f"Prep Time   : {recipe.prep_time_minutes} min")
    print("Steps:")
    for i, step in enumerate(recipe.steps, 1):
        print(f"  {i}. {step}")

Formatted Output

=== Movie Review (Direct OpenAI Call) ===
Title   : Inception
Rating  : 9.0
Summary : Inception is a mind-bending thriller directed by Christopher Nolan that explores the intricacies of dreams and the subconscious. With a stellar cast led by Leonardo DiCaprio, the film masterfully blends action, science fiction, and emotional depth. Its intricate plot and stunning visuals keep audiences engaged, while the haunting score by Hans Zimmer heightens the tension throughout. A thought-provoking narrative that challenges perceptions of reality, Inception remains a landmark achievement in modern cinema.

=== Movie Review (Magentic Decorator) ===
Title   : The Matrix
Rating  : 4.8
Summary : The Matrix is a groundbreaking science fiction film that blends mind-bending action with philosophical depth. Directed by the Wachowskis, it introduces a dystopian future where reality is simulated by AI, and human resistance fights against the machine overlords. The film's innovative special effects, particularly the iconic 'bullet-time' sequences, and its exploration of themes such as freedom, reality, and identity make it a landmark in cinematic history. With a stellar performance by Keanu Reeves as Neo, The Matrix has become a cultural phenomenon and a must-watch for any sci-fi fan.

What Happens Behind the Scenes

  1. @prompt sends your template (plus automatic formatting instructions) to the OpenAI API.

  2. The LLM returns structured data matching the MovieReview schema.

  3. Magentic parses and validates the response through Pydantic before handing it back to you as a Python object.

No manual JSON parsing. No retry loops. No prompt gymnastics.

Key Takeaways

Benefit Without Magentic With Magentic
Output format Free text / fragile JSON Validated Pydantic model
Prompt overhead Manual formatting instructions Handled by decorator
Parsing code json.loads + validation Automatic
Token efficiency Extra tokens for format prompts Optimised
Code cleanliness Scattered parsing logic Single decorated function