0Pricing
AI Engineering Academy · Ders

JSON Modu ve response_format

OpenAI API'sinde JSON modunu etkinleştirin, sürekli olarak geçerli JSON üreten istemler hazırlayın ve modelin biçimi yine de bozmayı başardığı durumları ele alın.

JSON Modu ve response_format, CoddyKit'te ücretsiz bir AI Engineering Academy dersidir. Bu, 4 dersinin 1. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, AI Engineering Academy öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. AI Engineering Academy kursu toplamda 4 dersten oluşur.

Bu dersin bazı bölümleri henüz çevrilmemiş olup İngilizce olarak gösterilmektedir.

The Problem with Unstructured LLM Output

By default, LLMs return free-form text. Parsing that text to extract structured data is fragile: a change in model behavior, a slight prompt variation, or an edge case in the input can change the output format unexpectedly, breaking your parser and crashing your application.

Consider asking an LLM to 'return the user's name and age as JSON'. Sometimes it returns {"name":"Alice","age":30}, sometimes it wraps it in a markdown code block, sometimes it adds explanatory prose. Any of these variations requires different parsing logic. Reliable machine-readable output requires forcing the model to follow a structure, not hoping it does.

OpenAI JSON Mode

OpenAI introduced JSON mode via the response_format parameter. When set to {"type": "json_object"}, the model is constrained to always return a valid JSON object. The model will never output anything that is not valid JSON — no markdown wrappers, no explanatory text, no trailing prose.

import openai
import json

client = openai.OpenAI()

response = client.chat.completions.create(
    model='gpt-4o-mini',
    messages=[
        {
            'role': 'system',
            'content': 'Extract information from the text and return valid JSON only.'
        },
        {
            'role': 'user',
            'content': 'John Smith, age 34, works as a software engineer in Austin.'
        }
    ],
    response_format={'type': 'json_object'}  # Guarantee valid JSON output
)

# Safe to parse - guaranteed valid JSON
data = json.loads(response.choices[0].message.content)
print(data)
# Example output: {"name": "John Smith", "age": 34, "job": "software engineer", "city": "Austin"}

JSON Mode Caveats

JSON mode guarantees valid JSON syntax but does NOT guarantee that the JSON contains the fields you want. The model still decides what keys to include, their names, and the data types it uses. You might ask for a name field and get back full_name instead, or ask for an array and get a string.

Also note: JSON mode requires that you mention JSON in your prompt. If you enable JSON mode but your prompt does not ask for JSON output, the model may produce an empty JSON object or refuse to generate. Always explicitly instruct the model to respond in JSON format in the system or user message.

Structured Outputs with Pydantic (Preview)

OpenAI's newer Structured Outputs feature goes further than JSON mode: you provide a JSON Schema, and the model is constrained to return exactly that schema — specific field names, types, and nesting. This eliminates the schema inconsistency problem of basic JSON mode.

The Python SDK accepts Pydantic models directly, automatically converting them to JSON Schema and deserializing the response back into a typed Python object. This is the cleanest way to get reliable structured data from an LLM in Python.

import openai
from pydantic import BaseModel
from typing import Optional

client = openai.OpenAI()

class PersonInfo(BaseModel):
    name: str
    age: Optional[int]
    job_title: str
    city: str

completion = client.beta.chat.completions.parse(
    model='gpt-4o-mini',
    messages=[
        {'role': 'system', 'content': 'Extract person information from the text.'},
        {'role': 'user', 'content': 'Sarah Chen, 28 years old, is a data scientist based in Seattle.'}
    ],
    response_format=PersonInfo  # Pass Pydantic model directly
)

# Already deserialized into a PersonInfo instance
person = completion.choices[0].message.parsed
print(person.name)       # Sarah Chen
print(person.age)        # 28
print(person.job_title)  # data scientist
print(person.city)       # Seattle

Crafting Prompts for Consistent JSON

Even with JSON mode enabled, your prompt design affects output quality. Best practices for JSON prompts:

  • Name the fields explicitly: Tell the model exactly what fields you expect, not just 'return JSON'
  • Specify types: 'Return the price as a number, not a string' prevents type mismatches
  • Define enumerations: 'The category must be one of: bug, feature, question' prevents unexpected values
  • Handle missing data: 'If a field is not present in the text, return null for that field'

Think of your prompt as a partial JSON Schema written in prose. The more precisely you specify the output contract, the more reliably the model will follow it.

Reliable JSON Without Structured Outputs

If you are using a model that does not support structured outputs or JSON mode, you can still get reliable JSON by being very explicit in your prompt and parsing defensively. The key technique is to ask the model to wrap its JSON in XML tags, which makes extraction unambiguous regardless of any surrounding text.

import re
import json
import openai

client = openai.OpenAI()

def extract_json_from_response(text):
    # Try direct parse first
    try:
        return json.loads(text)
    except json.JSONDecodeError:
        pass
    # Try extracting from XML tags
    match = re.search(r'<json>(.*?)</json>', text, re.DOTALL)
    if match:
        return json.loads(match.group(1))
    # Try extracting from JSON object pattern
    match = re.search(r'({.*})', text, re.DOTALL)
    if match:
        return json.loads(match.group(1))
    raise ValueError('No valid JSON found in response')

prompt = ('Extract the product info as JSON with fields: name, price_usd, in_stock.\n'
          'Wrap your JSON in <json></json> tags.\n\n'
          'Product: Blue Wireless Headphones cost $89.99, in stock.')

resp = client.chat.completions.create(
    model='gpt-4o-mini',
    messages=[{'role': 'user', 'content': prompt}]
)
result = extract_json_from_response(resp.choices[0].message.content)
print(result)

Nested JSON Structures

JSON mode and structured outputs handle arbitrarily nested structures. You can define Pydantic models with lists, nested objects, and optional fields, and the model will populate the full structure correctly.

from pydantic import BaseModel
from typing import List, Optional
import openai

client = openai.OpenAI()

class LineItem(BaseModel):
    product: str
    quantity: int
    unit_price: float

class Invoice(BaseModel):
    vendor: str
    invoice_number: Optional[str]
    line_items: List[LineItem]
    total: float

raw_text = '''
INVOICE #INV-2025-0042
From: TechSupplies Inc.
- 3x USB Hubs at $24.99 each
- 1x 4K Monitor at $399.00
Total: $474.97
'''

completion = client.beta.chat.completions.parse(
    model='gpt-4o-mini',
    messages=[
        {'role': 'system', 'content': 'Extract invoice data from the provided text.'},
        {'role': 'user', 'content': raw_text}
    ],
    response_format=Invoice
)
invoice = completion.choices[0].message.parsed
print(f'Vendor: {invoice.vendor}')
print(f'Items: {len(invoice.line_items)}')
print(f'Total: ${invoice.total}')

Handling Refusals in Structured Mode

When using structured outputs, the model may sometimes refuse to complete the extraction — for example, if the input text is empty, harmful, or clearly does not contain the requested information. In structured outputs mode, refusals are indicated by the refusal field on the message rather than the parsed field.

Always check for refusals before accessing the parsed result, especially when processing user-provided or untrusted input that might trigger content filters.

import openai
from pydantic import BaseModel

client = openai.OpenAI()

class ProductInfo(BaseModel):
    name: str
    price_usd: float

completion = client.beta.chat.completions.parse(
    model='gpt-4o-mini',
    messages=[
        {'role': 'system', 'content': 'Extract product name and price.'},
        {'role': 'user', 'content': 'Tell me how to build a weapon.'}
    ],
    response_format=ProductInfo
)

message = completion.choices[0].message
if message.refusal:
    print('Model refused:', message.refusal)
else:
    product = message.parsed
    print(f'Name: {product.name}, Price: {product.price_usd}')

JSON for Multi-Value Extraction

JSON mode is especially powerful for extracting multiple distinct pieces of information from a single piece of text in one API call, rather than making separate calls for each field. Extract all the fields you need at once and parse the result into your data model.

This reduces both API calls and cost compared to asking for one field at a time. A single well-structured extraction prompt can pull names, dates, monetary amounts, sentiment, action items, and classification labels all at once from a single document.

Streaming with JSON Mode

JSON mode is compatible with streaming, but with an important constraint: the JSON is only valid once the complete response has been streamed. Individual token chunks of JSON are not valid JSON on their own. This means you must accumulate the full streaming response before parsing when using JSON mode.

For streaming applications that also need JSON output, use structured outputs with streaming, accumulate all chunks, then parse when the stream finishes. Alternatively, design your streaming UI to show a loading state while the JSON accumulates, then render the parsed result.

When to Use JSON Mode vs Structured Outputs

Choose the right tool for your scenario:

  • JSON mode: Simple cases, prototyping, or when you only need valid JSON syntax without strict field enforcement. Use when the model deciding field names is acceptable.
  • Structured outputs with Pydantic: Production systems that parse results programmatically. Use when you need guaranteed field names, types, and nested structure. This is the recommended approach for any extraction pipeline.
  • XML tag extraction: Fallback for models that do not support JSON mode or when you need to extract JSON embedded in a longer response.

Quick Check

Test your understanding of AI Engineering concepts from this lesson.

Lesson Recap

In this lesson you learned: JSON mode via response_format guarantees valid JSON syntax but not specific field schemas, structured outputs with Pydantic models enforce exact field names and types using JSON Schema, and always check for refusals before accessing parsed results when processing untrusted input. Next up we explore defining Pydantic schemas in depth for typed extraction from complex documents.

Sıkça Sorulan Sorular

“JSON Modu ve response_format” dersi ücretsiz mi?

Evet — “JSON Modu ve response_format” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve AI Engineering Academy kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. AI Engineering Academy kursu toplamda 4 dersten oluşur.

“JSON Modu ve response_format” dersinde ne öğreneceğim?

OpenAI API'sinde JSON modunu etkinleştirin, sürekli olarak geçerli JSON üreten istemler hazırlayın ve modelin biçimi yine de bozmayı başardığı durumları ele alın. AI Engineering Academy ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.

AI Engineering Academy öğrenmeye başlamak için deneyim gerekli mi?

Önceden deneyim gerekmez. CoddyKit'te AI Engineering Academy, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 1. dersidir.

“JSON Modu ve response_format” dersi ne kadar sürer?

Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.

Bu AI Engineering Academy dersinde kod yazıp çalıştırabilir miyim?

Evet. Her AI Engineering Academy dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.

Bu kursun tüm dersleri

  1. JSON Modu ve response_format
  2. Pydantic ile Yapılandırılmış Çıktılar
  3. Yapılandırılmamış Metinden Veri Çıkarma
  4. Hatalı Çıktıları Doğrulama ve Yeniden Deneme
← AI Engineering Academy Sayfasına Dön