Show description
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
<!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": ["<vector_store_id>"]
}]
)
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>