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

# Function Calling Structured Outputs

> This article explains how to use structured outputs with the OpenAI API for consistent, machine-readable responses.

Structured outputs ensure your application receives well-defined, machine-readable responses every time. By enforcing formats such as JSON, CSV, or custom Pydantic models, you gain:

| Benefit           | Description                                                   |
| ----------------- | ------------------------------------------------------------- |
| Type Safety       | Guarantees fields are present and correctly typed             |
| Explicit Refusals | Model clearly indicates when it can’t comply                  |
| Simpler Prompting | Remove guesswork—just specify the format                      |
| Exact Formats     | Enforce JSON, CSV, or any structure your application requires |

***

## 1. Structured Outputs with Pydantic

Define a Pydantic model for your desired schema and instruct the API to parse directly into that model.

```python theme={null}
from pydantic import BaseModel
from openai import OpenAI

client = OpenAI()

class CalendarEvent(BaseModel):
    name: str
    date: str
    participants: list[str]

completion = client.beta.chat.completions.parse(
    model="gpt-4-2024-08-06",
    messages=[
        {"role": "system", "content": "Extract the event information."},
        {"role": "user",   "content": "Alice and Bob are going to a science fair."}
    ],
    response_format=CalendarEvent,
)

event = completion.choices[0].message.parsed
print(event)
# CalendarEvent(name='Science Fair Visit', date='2024-08-10', participants=['Alice', 'Bob'])
```

<Callout icon="lightbulb" color="#1CB2FE">
  Make sure you’re using the `openai` Python package version that supports `.parse()` (e.g., v0.27+).\
  See [Pydantic documentation](https://docs.pydantic.dev/latest/) for detailed model usage.
</Callout>

***

## 2. Step-by-Step Reasoning as Structured Output

You can capture a chain of thought or intermediate steps by defining a Pydantic model that holds your reasoning.

```python theme={null}
from pydantic import BaseModel
from openai import OpenAI

client = OpenAI()

class MathReasoning(BaseModel):
    steps: list[str]
    final_answer: str

completion = client.beta.chat.completions.parse(
    model="gpt-4-2024-08-06",
    messages=[
        {"role": "system", "content": "You are a helpful math tutor. Guide the user."},
        {"role": "user",   "content": "How can I solve 8x + 7 = -23?"}
    ],
    response_format=MathReasoning,
)

math = completion.choices[0].message.parsed
print("Steps:", math.steps)
print("Answer:", math.final_answer)
```

***

## 3. Building a Recipe Generator with JSON Output

Prompt the model to output strict JSON so downstream services can ingest it without additional parsing.

```python theme={null}
from openai import OpenAI

client = OpenAI(api_key="sk-REPLACE_WITH_YOUR_KEY")

def recipe_gen(ingredients: list[str]) -> str:
    messages = [{"role": "user", "content": ing} for ing in ingredients]
    messages.extend([
        {"role": "system",    "content": "JSON Format Required"},
        {"role": "assistant", "content": "You are a high-end chef. Generate a recipe in JSON!"}
    ])

    response = client.chat.completions.create(
        model="gpt-4",
        messages=messages,
        max_tokens=300,
        temperature=0.9
    )
    return response.choices[0].message.content

if __name__ == "__main__":
    ingredients = []
    while True:
        ing = input("Enter an ingredient (or type done): ")
        if ing.strip().lower() == "done":
            break
        ingredients.append(ing)

    print(recipe_gen(ingredients))
```

Run the script:

```bash theme={null}
$ python recipe_generator.py
Enter an ingredient (or type done): chocolate
Enter an ingredient (or type done): grapes
Enter an ingredient (or type done): pizza dough
Enter an ingredient (or type done): done
```

Example JSON response:

```json theme={null}
{
  "recipe": {
    "title": "Chocolate-Infused Grape Pizza Tacos",
    "servings": 4,
    "ingredients": [
      { "name": "Corn tortillas",   "quantity": 8,   "unit": "pieces" },
      { "name": "Pizza dough",      "quantity": 1,   "unit": "pound" },
      { "name": "Dark chocolate",   "quantity": 100, "unit": "grams", "type": "finely chopped" },
      { "name": "Red grapes",       "quantity": 200, "unit": "grams", "type": "halved" },
      { "name": "Mozzarella cheese","quantity": 200, "unit": "grams", "type": "shredded" },
      { "name": "Ricotta cheese",   "quantity": 100, "unit": "grams" },
      { "name": "Fresh basil leaves","quantity": 12,  "unit": "leaves" }
    ]
  }
}
```

<Callout icon="triangle-alert" color="#FF6B6B">
  Never commit your API keys to public repositories. Use environment variables or a secure vault.
</Callout>

***

## 4. Switching to CSV Output

Simply update the system prompt to request CSV, then process the comma-separated response.

```python theme={null}
from openai import OpenAI

client = OpenAI(api_key="sk-REPLACE_WITH_YOUR_KEY")

def recipe_gen_csv(ingredients: list[str]) -> str:
    messages = [{"role": "user", "content": ing} for ing in ingredients]
    messages.extend([
        {"role": "system",    "content": "CSV Format Required"},
        {"role": "assistant", "content": "You are a high-end chef. Generate a CSV recipe!"}
    ])

    response = client.chat.completions.create(
        model="gpt-4",
        messages=messages,
        max_tokens=300,
        temperature=0.9
    )
    return response.choices[0].message.content

if __name__ == "__main__":
    ingredients = []
    while True:
        ing = input("Enter an ingredient (or type done): ")
        if ing.strip().lower() == "done":
            break
        ingredients.append(ing)

    print(recipe_gen_csv(ingredients))
```

Sample CSV output:

```csv theme={null}
Ingredient,Quantity,Preparation
Chicken Breast,2 pieces,Cut into cubes
Potatoes,2 medium,Peeled and diced
Eggs,4,Hard-boiled and sliced
Olive Oil,2 Tbsp,For cooking
Garlic,2 cloves,Minced
Onion,1 medium,Finely chopped
Salt,1 tsp,To taste
Black Pepper,1/2 tsp,To taste
Paprika,1/2 tsp,To taste
Fresh Parsley,2 tbsp,Chopped for garnish
```

You can even mix formats—return cooking steps as CSV:

```text theme={null}
Step 1,Heat olive oil in a large pan over medium heat.
Step 2,Add chicken and onion; sauté until translucent.
Step 3,Add garlic, potatoes, and paprika; cook until tender.
Step 4,Stir in eggs until heated through.
Step 5,Garnish with parsley and serve.
```

***

By specifying your desired output format in the `system` and `assistant` messages, you guarantee consistency and simplify downstream processing. For more advanced examples, see the [OpenAI Structured Outputs Guide](https://platform.openai.com/docs/guides/structured-outputs).

## Links and References

* [OpenAI API Documentation](https://platform.openai.com/docs/)
* [Pydantic Documentation](https://docs.pydantic.dev/latest/)

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/introduction-to-openai/module/42afe984-cd3e-4b3c-b1e0-8e9093f57a63/lesson/69e43059-3653-4c78-8216-84ef4ceefe3c" />
</CardGroup>
