Skip to content
LAM
Read Home Blog
Make Projects HTML Tools Games
Touch grass Notes Resume Links
Home Blog HTML Projects
Tools Games Notes Resume Links
Back GPT-5 Python API - IDE Programming
Download Open
Show description 1,941 chars · Programming

GPT-5 Python API - IDE

GPT-5 Python API - IDE





Explorer




gpt5-python-api





overview.py




text_generation.py




images_vision.py




structured_outputs.py




function_calling.py




using_tools.py




rate_limits.py














GPT-5 Python API Documentation

This document provides a comprehensive guide to using the GPT-5 model via the Python API. It includes model details, endpoints, pricing, and code examples for various features.


Model: GPT-5

GPT-5 is our flagship model for coding, reasoning, and agentic tasks across domains.


Context Window: 400,000 tokens

Max Output Tokens: 128,000 tokens

Knowledge Cutoff: Sep 30, 2024



Pricing




Type

Per 1M tokens






Input

$1.25




Cached Input

$0.125




Output

$10.00






Modalities




Modality

Support






Text

Input and Output




Image

Input only




Audio

Not supported






Endpoints


Chat Completions: v1/chat/completions

Responses: v1/responses

Realtime: v1/realtime

Assistants: v1/assistants

Batch: v1/batch

Fine-tuning: v1/fine-tuning

Embeddings: v1/embeddings

Image Generation: v1/images/generations

Image Edit: v1/images/edits

Speech Generation: v1/audio/speech

Transcription: v1/audio/transcriptions

Translation: v1/audio/translations

Moderation: v1/moderations

Completions (legacy): v1/completions



Features & Tools




Feature

Supported

Tool

Supported





Streaming
✅
Web search
✅


Function calling
✅
File search
✅


Structured outputs
✅
Image generation
✅


Fine-tuning
✅
Code interpreter
✅


Distillation
✅
Computer use
❌


Predicted outputs
✅
MCP
✅





Snapshots

Snapshots let you lock in a specific version of the model. Available snapshots and aliases for GPT-5:


gpt-5

gpt-5-2025-08-07






Text Generation

Use a large language model to generate text from a prompt.…

GPT-5 Python API - IDE

42,508 bytes · HTML source
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>GPT-5 Python API - IDE</title>
    <style>
        :root {
            --bg-color: #0d1117;
            --sidebar-bg: #161b22;
            --editor-bg: #0d1117;
            --text-color: #c9d1d9;
            --text-secondary-color: #8b949e;
            --header-color: #f0f6fc;
            --border-color: #30363d;
            --accent-color: #58a6ff;
            --active-bg: #1f6feb;
            --active-text: #ffffff;
            --code-bg: #161b22;
            --font-main: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
            --font-mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
        }

        body {
            background-color: var(--bg-color);
            color: var(--text-color);
            font-family: var(--font-main);
            margin: 0;
            height: 100vh;
            overflow: hidden;
            display: flex;
        }

        /* --- Sidebar --- */
        .sidebar {
            width: 280px;
            min-width: 280px;
            background-color: var(--sidebar-bg);
            border-right: 1px solid var(--border-color);
            padding: 10px 0;
            display: flex;
            flex-direction: column;
            overflow-y: auto;
        }

        .sidebar-header {
            padding: 10px 20px;
            font-size: 0.9em;
            font-weight: bold;
            color: var(--text-secondary-color);
            text-transform: uppercase;
            letter-spacing: 1px;
        }

        .file-explorer {
            list-style: none;
            padding: 0;
            margin: 0;
        }

        .file-item, .folder-item {
            display: flex;
            align-items: center;
            padding: 8px 20px;
            cursor: pointer;
            font-size: 0.9em;
            color: var(--text-secondary-color);
            user-select: none;
            border-left: 3px solid transparent;
        }
        
        .file-item:hover, .folder-item:hover {
            background-color: rgba(139, 148, 158, 0.1);
        }

        .file-item.active {
            background-color: var(--active-bg);
            color: var(--active-text);
            border-left-color: var(--accent-color);
        }
        
        .file-item.active .file-icon, .file-item.active .file-name {
             color: var(--active-text);
        }

        .icon {
            margin-right: 10px;
            width: 16px;
            height: 16px;
        }
        
        .file-icon {
            color: var(--accent-color);
        }
        
        .folder-icon {
            color: #79c0ff;
        }

        .file-name, .folder-name {
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }
        
        .folder-content {
            padding-left: 20px;
        }


        /* --- Main Content / Editor --- */
        .main-content {
            flex-grow: 1;
            display: flex;
            flex-direction: column;
            overflow: hidden;
        }

        .tabs {
            display: flex;
            background-color: var(--sidebar-bg);
            border-bottom: 1px solid var(--border-color);
            flex-shrink: 0;
        }

        .tab {
            padding: 10px 15px;
            cursor: pointer;
            border-right: 1px solid var(--border-color);
            color: var(--text-secondary-color);
            display: flex;
            align-items: center;
            font-size: 0.9em;
        }
        
        .tab .file-icon {
            margin-right: 8px;
        }

        .tab.active {
            background-color: var(--editor-bg);
            color: var(--text-color);
            border-bottom: 2px solid var(--accent-color);
            margin-bottom: -1px;
        }

        .editor-area {
            flex-grow: 1;
            overflow-y: auto;
            padding: 20px 40px;
        }
        
        .content-section {
            display: none;
        }
        
        .content-section.active {
            display: block;
        }

        h1, h2, h3, h4 {
            color: var(--header-color);
            border-bottom: 1px solid var(--border-color);
            padding-bottom: 8px;
            margin-top: 20px;
            margin-bottom: 20px;
        }
        
        h1 { font-size: 2em; }
        h2 { font-size: 1.6em; }
        h3 { font-size: 1.3em; border-bottom: none;}
        h4 { font-size: 1.1em; border-bottom: none; }

        a {
            color: var(--accent-color);
            text-decoration: none;
        }
        a:hover {
            text-decoration: underline;
        }

        code {
            background-color: var(--code-bg);
            padding: 0.2em 0.4em;
            margin: 0;
            font-size: 85%;
            border-radius: 6px;
            font-family: var(--font-mono);
        }

        pre {
            background-color: var(--code-bg);
            border: 1px solid var(--border-color);
            border-radius: 6px;
            padding: 16px;
            overflow-x: auto;
            position: relative;
            counter-reset: line;
        }
        
        pre code {
            background-color: transparent;
            padding: 0;
            margin: 0;
            font-size: 100%;
            border: none;
            white-space: pre;
            padding-left: 3.5em;
            display: block;
        }
        
        pre code::before {
            content: counter(line);
            counter-increment: line;
            position: absolute;
            left: 0;
            width: 2.5em;
            padding-right: 1em;
            text-align: right;
            color: var(--text-secondary-color);
            user-select: none;
        }

        table {
            width: 100%;
            border-collapse: collapse;
            margin: 20px 0;
        }

        th, td {
            border: 1px solid var(--border-color);
            padding: 12px;
            text-align: left;
        }

        th {
            background-color: #161b22;
            color: var(--header-color);
        }

        hr {
            border: 0;
            height: 1px;
            background: var(--border-color);
            margin: 40px 0;
        }
        
        .code-block-container {
            position: relative;
        }

        .copy-button {
            position: absolute;
            top: 10px;
            right: 10px;
            background-color: #30363d;
            color: var(--text-color);
            border: 1px solid #444c56;
            padding: 5px 10px;
            border-radius: 5px;
            cursor: pointer;
            font-size: 0.8em;
            opacity: 0.7;
            transition: opacity 0.2s;
        }
        
        .copy-button:hover {
            opacity: 1;
            background-color: #484f58;
        }
    </style>
</head>
<body>

    <aside class="sidebar">
        <div class="sidebar-header">Explorer</div>
        <ul class="file-explorer">
            <li class="folder-item">
                <svg class="icon folder-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"></path></svg>
                <span class="folder-name">gpt5-python-api</span>
            </li>
            <div class="folder-content">
                <li class="file-item active" data-target="overview">
                    <svg class="icon file-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline></svg>
                    <span class="file-name">overview.py</span>
                </li>
                <li class="file-item" data-target="text-generation">
                    <svg class="icon file-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline></svg>
                    <span class="file-name">text_generation.py</span>
                </li>
                <li class="file-item" data-target="images-vision">
                    <svg class="icon file-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline></svg>
                    <span class="file-name">images_vision.py</span>
                </li>
                <li class="file-item" data-target="structured-outputs">
                    <svg class="icon file-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline></svg>
                    <span class="file-name">structured_outputs.py</span>
                </li>
                <li class="file-item" data-target="function-calling">
                    <svg class="icon file-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline></svg>
                    <span class="file-name">function_calling.py</span>
                </li>
                <li class="file-item" data-target="using-tools">
                    <svg class="icon file-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline></svg>
                    <span class="file-name">using_tools.py</span>
                </li>
                 <li class="file-item" data-target="rate-limits">
                    <svg class="icon file-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline></svg>
                    <span class="file-name">rate_limits.py</span>
                </li>
            </div>
        </ul>
    </aside>

    <main class="main-content">
        <div class="tabs">
            <!-- Tabs will be dynamically generated by JS -->
        </div>
        <div class="editor-area">
            <section id="overview" class="content-section active">
                <h1>GPT-5 Python API Documentation</h1>
                <p>This document provides a comprehensive guide to using the GPT-5 model via the Python API. It includes model details, endpoints, pricing, and code examples for various features.</p>

                <h2>Model: GPT-5</h2>
                <p>GPT-5 is our flagship model for coding, reasoning, and agentic tasks across domains.</p>
                <ul>
                    <li><strong>Context Window:</strong> 400,000 tokens</li>
                    <li><strong>Max Output Tokens:</strong> 128,000 tokens</li>
                    <li><strong>Knowledge Cutoff:</strong> Sep 30, 2024</li>
                </ul>
                <hr/>
                <h3>Pricing</h3>
                <table>
                    <thead>
                        <tr>
                            <th>Type</th>
                            <th>Per 1M tokens</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td>Input</td>
                            <td>$1.25</td>
                        </tr>
                        <tr>
                            <td>Cached Input</td>
                            <td>$0.125</td>
                        </tr>
                        <tr>
                            <td>Output</td>
                            <td>$10.00</td>
                        </tr>
                    </tbody>
                </table>
                <hr/>
                <h3>Modalities</h3>
                <table>
                    <thead>
                        <tr>
                            <th>Modality</th>
                            <th>Support</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td>Text</td>
                            <td>Input and Output</td>
                        </tr>
                        <tr>
                            <td>Image</td>
                            <td>Input only</td>
                        </tr>
                        <tr>
                            <td>Audio</td>
                            <td>Not supported</td>
                        </tr>
                    </tbody>
                </table>
                <hr/>
                <h3>Endpoints</h3>
                <ul>
                    <li>Chat Completions: <code>v1/chat/completions</code></li>
                    <li>Responses: <code>v1/responses</code></li>
                    <li>Realtime: <code>v1/realtime</code></li>
                    <li>Assistants: <code>v1/assistants</code></li>
                    <li>Batch: <code>v1/batch</code></li>
                    <li>Fine-tuning: <code>v1/fine-tuning</code></li>
                    <li>Embeddings: <code>v1/embeddings</code></li>
                    <li>Image Generation: <code>v1/images/generations</code></li>
                    <li>Image Edit: <code>v1/images/edits</code></li>
                    <li>Speech Generation: <code>v1/audio/speech</code></li>
                    <li>Transcription: <code>v1/audio/transcriptions</code></li>
                    <li>Translation: <code>v1/audio/translations</code></li>
                    <li>Moderation: <code>v1/moderations</code></li>
                    <li>Completions (legacy): <code>v1/completions</code></li>
                </ul>
                <hr/>
                <h3>Features & Tools</h3>
                <table>
                    <thead>
                        <tr>
                            <th>Feature</th>
                            <th>Supported</th>
                            <th>Tool</th>
                            <th>Supported</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr><td>Streaming</td><td>✅</td><td>Web search</td><td>✅</td></tr>
                        <tr><td>Function calling</td><td>✅</td><td>File search</td><td>✅</td></tr>
                        <tr><td>Structured outputs</td><td>✅</td><td>Image generation</td><td>✅</td></tr>
                        <tr><td>Fine-tuning</td><td>✅</td><td>Code interpreter</td><td>✅</td></tr>
                        <tr><td>Distillation</td><td>✅</td><td>Computer use</td><td>❌</td></tr>
                        <tr><td>Predicted outputs</td><td>✅</td><td>MCP</td><td>✅</td></tr>
                    </tbody>
                </table>
                 <hr/>
                <h3>Snapshots</h3>
                <p>Snapshots let you lock in a specific version of the model. Available snapshots and aliases for GPT-5:</p>
                <ul>
                    <li><code>gpt-5</code></li>
                    <li><code>gpt-5-2025-08-07</code></li>
                </ul>
            </section>
            
            <section id="text-generation" class="content-section">
                <h2>Text Generation</h2>
                <p>Use a large language model to generate text from a prompt. Models can generate code, mathematical equations, structured JSON data, or human-like prose.</p>
                
                <h3>Generate text from a simple prompt</h3>
                <div class="code-block-container">
                    <button class="copy-button">Copy</button>
                    <pre><code>from openai import OpenAI
client = OpenAI()

completion = client.chat.completions.create(
    model="gpt-5",
    messages=[
        {
            "role": "user",
            "content": "Write a one-sentence bedtime story about a unicorn."
        }
    ]
)

print(completion.choices[0].message.content)</code></pre>
                </div>
                
                <h3>Prompt Engineering</h3>
                <p>Prompt engineering is the process of writing effective instructions for a model. It's recommended to pin production applications to specific model snapshots (like <code>gpt-5-2025-08-07</code>) and build evaluations to monitor prompt performance.</p>

                <h3>Message Roles and Instruction Following</h3>
                <p>You can provide instructions with differing levels of authority using the <code>instructions</code> API parameter and message roles.</p>
                
                <h4>Generate text with instructions</h4>
                <div class="code-block-container">
                    <button class="copy-button">Copy</button>
                    <pre><code>from openai import OpenAI
client = OpenAI()

response = client.responses.create(
    model="gpt-5",
    reasoning={"effort": "low"},
    instructions="Talk like a pirate.",
    input="Are semicolons optional in JavaScript?",
)

print(response.output_text)</code></pre>
                </div>

                <h4>Generate text with messages using different roles</h4>
                <div class="code-block-container">
                    <button class="copy-button">Copy</button>
                    <pre><code>from openai import OpenAI
client = OpenAI()

response = client.responses.create(
    model="gpt-5",
    reasoning={"effort": "low"},
    input=[
        {
            "role": "developer",
            "content": "Talk like a pirate."
        },
        {
            "role": "user",
            "content": "Are semicolons optional in JavaScript?"
        }
    ]
)

print(response.output_text)</code></pre>
                </div>

                <h3>Reusable Prompts</h3>
                <p>In the OpenAI dashboard, you can develop reusable prompts with placeholders that you can use in API requests.</p>
                
                <h4>Generate text with a prompt template</h4>
                <div class="code-block-container">
                    <button class="copy-button">Copy</button>
                    <pre><code>from openai import OpenAI
client = OpenAI()

response = client.responses.create(
    model="gpt-5",
    prompt={
        "id": "pmpt_abc123",
        "version": "2",
        "variables": {
            "customer_name": "Jane Doe",
            "product": "40oz juice box"
        }
    }
)

print(response.output_text)</code></pre>
                </div>
            </section>
            
            <section id="images-vision" class="content-section">
                <h2>Images and Vision</h2>
                <p>Use models to understand or generate images. Vision is the ability for a model to "see" and understand images, including text within them.</p>

                <h3>Analyze Images</h3>
                <p>You can provide images as input via a URL or a Base64 encoded string.</p>

                <h4>Analyze an image from a URL</h4>
                <div class="code-block-container">
                    <button class="copy-button">Copy</button>
                    <pre><code>from openai import OpenAI
client = OpenAI()

response = client.chat.completions.create(
    model="gpt-4.1-mini",
    messages=[{
        "role": "user",
        "content": [
            {"type": "text", "text": "What's in this image?"},
            {
                "type": "image_url",
                "image_url": {
                    "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg",
                },
            },
        ],
    }],
)

print(response.choices[0].message.content)</code></pre>
                </div>
                
                <h4>Analyze a Base64 encoded image</h4>
                <div class="code-block-container">
                    <button class="copy-button">Copy</button>
                    <pre><code>import base64
from openai import OpenAI

client = OpenAI()

# Function to encode the image
def encode_image(image_path):
    with open(image_path, "rb") as image_file:
        return base64.b64encode(image_file.read()).decode("utf-8")

# Path to your image
image_path = "path_to_your_image.jpg"

# Getting the Base64 string
base64_image = encode_image(image_path)

completion = client.chat.completions.create(
    model="gpt-4.1",
    messages=[
        {
            "role": "user",
            "content": [
                { "type": "text", "text": "what's in this image?" },
                {
                    "type": "image_url",
                    "image_url": {
                        "url": f"data:image/jpeg;base64,{base64_image}",
                    },
                },
            ],
        }
    ],
)

print(completion.choices[0].message.content)</code></pre>
                </div>
                
                 <h3>Calculating Costs</h3>
                <p>Image inputs are metered and charged in tokens. The cost depends on image dimensions and the model used. For detailed formulas and examples, refer to the official pricing page and its FAQ section.</p>
            </section>
            
            <section id="structured-outputs" class="content-section">
                <h2>Structured Model Outputs</h2>
                <p>Ensure model responses adhere to a JSON schema you define using Pydantic in Python. This provides reliable type-safety and simpler prompting.</p>

                <h3>Getting a structured response with Pydantic</h3>
                 <div class="code-block-container">
                    <button class="copy-button">Copy</button>
                    <pre><code>from pydantic import BaseModel
from openai import OpenAI

client = OpenAI()

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

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

event = completion.choices[0].message.parsed
print(event)</code></pre>
                </div>

                <h3>Example: Chain-of-thought Math Tutoring</h3>
                <div class="code-block-container">
                    <button class="copy-button">Copy</button>
                    <pre><code>from pydantic import BaseModel
from openai import OpenAI

client = OpenAI()

class Step(BaseModel):
    explanation: str
    output: str

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

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

math_reasoning = completion.choices[0].message.parsed
print(math_reasoning.model_dump_json(indent=2))</code></pre>
                </div>

                <h3>Example: Structured Data Extraction</h3>
                 <div class="code-block-container">
                    <button class="copy-button">Copy</button>
                    <pre><code>from pydantic import BaseModel
from openai import OpenAI

client = OpenAI()

class ResearchPaperExtraction(BaseModel):
    title: str
    authors: list[str]
    abstract: str
    keywords: list[str]

completion = client.chat.completions.parse(
    model="gpt-4o-2024-08-06",
    messages=[
        {"role": "system", "content": "You are an expert at structured data extraction. You will be given unstructured text from a research paper and should convert it into the given structure."},
        {"role": "user", "content": "..."} # Add research paper text here
    ],
    response_format=ResearchPaperExtraction,
)

research_paper = completion.choices[0].message.parsed
print(research_paper)</code></pre>
                </div>

                <h3>Example: Moderation</h3>
                <div class="code-block-container">
                    <button class="copy-button">Copy</button>
                    <pre><code>from enum import Enum
from typing import Optional
from pydantic import BaseModel
from openai import OpenAI

client = OpenAI()

class Category(str, Enum):
    violence = "violence"
    sexual = "sexual"
    self_harm = "self_harm"

class ContentCompliance(BaseModel):
    is_violating: bool
    category: Optional[Category]
    explanation_if_violating: Optional[str]

completion = client.chat.completions.parse(
    model="gpt-4o-2024-08-06",
    messages=[
        {"role": "system", "content": "Determine if the user input violates specific guidelines and explain if they do."},
        {"role": "user", "content": "How do I prepare for a job interview?"}
    ],
    response_format=ContentCompliance,
)

compliance = completion.choices[0].message.parsed
print(compliance)</code></pre>
                </div>

                <h3>Refusals with Structured Outputs</h3>
                <p>If the model refuses to respond for safety reasons, the response will contain a <code>refusal</code> field instead of the parsed content.</p>
                <div class="code-block-container">
                    <button class="copy-button">Copy</button>
                    <pre><code># ... Pydantic class definition ...
completion = client.chat.completions.parse(...)
message = completion.choices[0].message

if message.refusal:
    print(f"Request refused: {message.refusal}")
else:
    print("Parsed content:", message.parsed)
</code></pre>
                </div>

                <h3>Streaming Structured Outputs</h3>
                <p>Use streaming to process parts of the structured response as they are generated.</p>
                <div class="code-block-container">
                    <button class="copy-button">Copy</button>
                    <pre><code>from typing import List
from pydantic import BaseModel
from openai import OpenAI

class EntitiesModel(BaseModel):
    attributes: List[str]
    colors: List[str]
    animals: List[str]

client = OpenAI()

with client.beta.chat.completions.stream(
    model="gpt-4.1",
    messages=[
        {"role": "system", "content": "Extract entities from the input text"},
        {"role": "user", "content": "The quick brown fox jumps over the lazy dog with piercing blue eyes"},
    ],
    response_format=EntitiesModel,
) as stream:
    for event in stream:
        if event.type == "content.delta":
            if event.parsed is not None:
                print("content.delta parsed:", event.parsed)
        elif event.type == "content.done":
            print("content.done")
        elif event.type == "error":
            print("Error in stream:", event.error)

final_completion = stream.get_final_completion()
print("Final completion:", final_completion)</code></pre>
                </div>

                <h3>JSON Mode (Legacy)</h3>
                <p>For older models, you can use JSON mode by setting <code>response_format={"type": "json_object"}</code>. This ensures the output is valid JSON but does not guarantee it adheres to a specific schema. You must instruct the model to produce JSON in the prompt and handle edge cases like incomplete responses.</p>
            </section>
            
            <section id="function-calling" class="content-section">
                <h2>Function Calling & Tools</h2>
                <p>Give models access to external functionality and data. This involves defining tools (functions), letting the model request to call them, executing the tool's logic, and sending the results back to the model.</p>

                <h3>Function Tool Example</h3>
                <p>End-to-end example of a multi-step tool-calling flow.</p>
                <div class="code-block-container">
                    <button class="copy-button">Copy</button>
                    <pre><code>from openai import OpenAI
import json

client = OpenAI()

# 1. Define a list of callable tools for the model
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_horoscope",
            "description": "Get today's horoscope for an astrological sign.",
            "parameters": {
                "type": "object",
                "properties": {
                    "sign": {
                        "type": "string",
                        "description": "An astrological sign like Taurus or Aquarius",
                    },
                },
                "required": ["sign"],
            },
        }
    },
]

# Create a running list of messages
messages = [
    {"role": "user", "content": "What is my horoscope? I am an Aquarius."}
]

# 2. First request to the model
response = client.chat.completions.create(
    model="gpt-5",
    messages=messages,
    tools=tools,
    tool_choice="auto",
)
response_message = response.choices[0].message
messages.append(response_message) # extend conversation with assistant's reply

# 3. Check if the model wants to call a function
if response_message.tool_calls:
    # 4. Call the function
    def get_horoscope(sign):
        return f"{sign}: Next Tuesday you will befriend a baby otter."

    available_functions = {"get_horoscope": get_horoscope}
    
    for tool_call in response_message.tool_calls:
        function_name = tool_call.function.name
        function_to_call = available_functions[function_name]
        function_args = json.loads(tool_call.function.arguments)
        function_response = function_to_call(sign=function_args.get("sign"))
        
        # 5. Send the info back to the model
        messages.append(
            {
                "tool_call_id": tool_call.id,
                "role": "tool",
                "name": function_name,
                "content": function_response,
            }
        )
    
    # 6. Get a new response from the model where it can use the function output
    second_response = client.chat.completions.create(
        model="gpt-5",
        messages=messages,
    )
    print(second_response.choices[0].message.content)
</code></pre>
                </div>
                
                <h3>Defining Functions with Pydantic</h3>
                <p>The SDK includes helpers to convert Pydantic models into the required JSON schema.</p>
                <div class="code-block-container">
                    <button class="copy-button">Copy</button>
                    <pre><code>from openai import OpenAI, pydantic_function_tool
from pydantic import BaseModel, Field

client = OpenAI()

class GetWeather(BaseModel):
    location: str = Field(
        ...,
        description="City and country e.g. Bogotá, Colombia"
    )

tools = [pydantic_function_tool(GetWeather)]

completion = client.chat.completions.create(
    model="gpt-4.1",
    messages=[{"role": "user", "content": "What's the weather like in Paris today?"}],
    tools=tools
)

print(completion.choices[0].message.tool_calls)</code></pre>
                </div>

                <h3>Streaming Function Calls</h3>
                <p>You can stream function calls to get partial progress and arguments in real-time.</p>
                 <div class="code-block-container">
                    <button class="copy-button">Copy</button>
                    <pre><code>from openai import OpenAI

client = OpenAI()

# ... (tools definition) ...

stream = client.chat.completions.create(
    model="gpt-4.1",
    messages=[{"role": "user", "content": "What's the weather like in Paris today?"}],
    tools=tools,
    stream=True
)

for chunk in stream:
    delta = chunk.choices[0].delta
    if delta.tool_calls:
        print(delta.tool_calls)</code></pre>
                </div>
                
                <h3>Custom Tools with Grammars</h3>
                <p>For more control, custom tools can use a context-free grammar (CFG) to constrain the model's text input. Both Lark and Regex syntaxes are supported.</p>
                <h4>Lark CFG Example</h4>
                <div class="code-block-container">
                    <button class="copy-button">Copy</button>
                    <pre><code>from openai import OpenAI
client = OpenAI()
grammar = """
start: expr
expr: term (SP ADD SP term)* -> add
term: factor (SP MUL SP factor)* -> mul
factor: INT
SP: " "
ADD: "+"
MUL: "*"
%import common.INT
"""
response = client.responses.create(
    model="gpt-5",
    input="Use the math_exp tool to add four plus four.",
    tools=[
        {
            "type": "custom",
            "name": "math_exp",
            "description": "Creates valid mathematical expressions",
            "format": {
                "type": "grammar",
                "syntax": "lark",
                "definition": grammar,
            },
        }
    ]
)
print(response.output)</code></pre>
                </div>
            </section>
            
            <section id="using-tools" class="content-section">
                <h2>Using Built-in Tools</h2>
                <p>Extend model capabilities using built-in tools like web search or file search.</p>
                
                <h3>Web Search</h3>
                <div class="code-block-container">
                    <button class="copy-button">Copy</button>
                    <pre><code>from openai import OpenAI
client = OpenAI()

response = client.responses.create(
    model="gpt-5",
    tools=[{"type": "web_search_preview"}],
    input="What was a positive news story from today?"
)

print(response.output_text)</code></pre>
                </div>

                <h3>File Search</h3>
                 <div class="code-block-container">
                    <button class="copy-button">Copy</button>
                    <pre><code>from openai import OpenAI
client = OpenAI()

response = client.responses.create(
    model="gpt-4.1",
    input="What is deep research by OpenAI?",
    tools=[{
        "type": "file_search",
        "vector_store_ids": ["&lt;vector_store_id&gt;"]
    }]
)
print(response)</code></pre>
                </div>

                <h3>Remote MCP</h3>
                <div class="code-block-container">
                    <button class="copy-button">Copy</button>
                    <pre><code>from openai import OpenAI

client = OpenAI()

resp = client.responses.create(
    model="gpt-4.1",
    tools=[
        {
            "type": "mcp",
            "server_label": "deepwiki",
            "server_url": "https://mcp.deepwiki.com/mcp",
            "require_approval": "never",
        },
    ],
    input="What transport protocols are supported in the 2025-03-26 version of the MCP spec?",
)

print(resp.output_text)</code></pre>
                </div>
            </section>
            
            <section id="rate-limits" class="content-section">
                <h2>Rate Limits</h2>
                <p>Your usage tier determines your rate limits for requests per minute (RPM) and tokens per minute (TPM).</p>
                <table>
                    <thead>
                        <tr>
                            <th>Tier</th>
                            <th>RPM</th>
                            <th>TPM</th>
                            <th>Batch Queue Limit</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td>Free</td>
                            <td>Not supported</td>
                            <td>Not supported</td>
                            <td>Not supported</td>
                        </tr>
                        <tr>
                            <td>Tier 1</td>
                            <td>500</td>
                            <td>30,000</td>
                            <td>90,000</td>
                        </tr>
                        <tr>
                            <td>Tier 2</td>
                            <td>5,000</td>
                            <td>450,000</td>
                            <td>1,350,000</td>
                        </tr>
                        <tr>
                            <td>Tier 3</td>
                            <td>5,000</td>
                            <td>800,000</td>
                            <td>100,000,000</td>
                        </tr>
                        <tr>
                            <td>Tier 4</td>
                            <td>10,000</td>
                            <td>2,000,000</td>
                            <td>200,000,000</td>
                        </tr>
                        <tr>
                            <td>Tier 5</td>
                            <td>15,000</td>
                            <td>40,000,000</td>
                            <td>15,000,000,000</td>
                        </tr>
                    </tbody>
                </table>
            </section>
        </div>
    </main>

    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const fileItems = document.querySelectorAll('.file-item');
            const contentSections = document.querySelectorAll('.content-section');
            const tabsContainer = document.querySelector('.tabs');
            let openTabs = {};

            function switchContent(targetId) {
                // Switch content
                contentSections.forEach(section => {
                    section.classList.toggle('active', section.id === targetId);
                });

                // Update sidebar active state
                fileItems.forEach(item => {
                    item.classList.toggle('active', item.dataset.target === targetId);
                });
                
                // Update tab active state
                document.querySelectorAll('.tab').forEach(tab => {
                    tab.classList.toggle('active', tab.dataset.target === targetId);
                });
            }

            function openTab(targetId, fileName) {
                if (!openTabs[targetId]) {
                    const tab = document.createElement('div');
                    tab.className = 'tab';
                    tab.dataset.target = targetId;
                    tab.innerHTML = `
                        <svg class="icon file-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline></svg>
                        <span>${fileName}</span>
                    `;
                    tabsContainer.appendChild(tab);
                    openTabs[targetId] = tab;

                    tab.addEventListener('click', (e) => {
                        e.stopPropagation();
                        switchContent(targetId);
                    });
                }
            }

            fileItems.forEach(item => {
                item.addEventListener('click', () => {
                    const targetId = item.dataset.target;
                    const fileName = item.querySelector('.file-name').textContent;
                    openTab(targetId, fileName);
                    switchContent(targetId);
                });
            });
            
            // Initialize with the first file open
            const initialFile = document.querySelector('.file-item.active');
            if(initialFile) {
                 const targetId = initialFile.dataset.target;
                 const fileName = initialFile.querySelector('.file-name').textContent;
                 openTab(targetId, fileName);
                 switchContent(targetId);
            }


            // Copy button functionality
            document.querySelectorAll('.copy-button').forEach(button => {
                button.addEventListener('click', () => {
                    const pre = button.closest('.code-block-container').querySelector('pre');
                    const code = pre.querySelector('code');
                    navigator.clipboard.writeText(code.innerText).then(() => {
                        button.textContent = 'Copied!';
                        setTimeout(() => {
                            button.textContent = 'Copy';
                        }, 2000);
                    }).catch(err => {
                        console.error('Failed to copy: ', err);
                    });
                });
            });
        });
    </script>
</body>
</html>