Structured Output / pydantic

AI/LLM

extract.py

from pydantic import BaseModel, Field
from openai import OpenAI

client = OpenAI()

class Contact(BaseModel):
    """One person pulled out of free-form text."""
    name: str
    email: str | None = None
    role: str | None = Field(None, description="job title if mentioned")

def extract_contact(text: str) -> Contact:
    resp = client.responses.parse(
        model="gpt-4o-mini",
        input=[
            {"role": "system", "content": "Extract the contact. Leave unknown fields null."},
            {"role": "user", "content": text},
        ],
        text_format=Contact,  # schema is enforced by the API
    )
    return resp.output_parsed  # already a validated Contact

main.py — FastAPI

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class ExtractIn(BaseModel):
    text: str

@app.post("/extract", response_model=Contact)
def extract(body: ExtractIn) -> Contact:
    return extract_contact(body.text)  # FastAPI validates in AND out