The Global Batch API processes large volumes of requests asynchronously at 50% lower cost compared to real-time endpoints, with a 24-hour SLA for completion.
| Criteria | Batch | Real-Time |
|---|---|---|
| Latency tolerance | Hours acceptable | Milliseconds needed |
| Volume | 1,000+ requests | Individual requests |
| Cost sensitivity | High — need savings | Performance > cost |
| Use cases | Document processing, bulk classification, dataset generation | Chat, search, live apps |
from openai import AzureOpenAI
import json
client = AzureOpenAI(
azure_endpoint="https://my-openai.openai.azure.com/",
api_version="2024-08-01-preview",
)
# Step 1: Prepare the JSONL input file
requests = [
{
"custom_id": f"doc-{i}",
"method": "POST",
"url": "/chat/completions",
"body": {
"model": "gpt-4o",
"messages": [
{"role": "system", "content": "Summarize the document in 2 sentences."},
{"role": "user", "content": doc_text},
],
"max_tokens": 200,
},
}
for i, doc_text in enumerate(documents)
]
with open("batch_input.jsonl", "w") as f:
for req in requests:
f.write(json.dumps(req) + "\n")
# Step 2: Upload the input file
batch_file = client.files.create(file=open("batch_input.jsonl", "rb"), purpose="batch")
# Step 3: Create the batch job
batch_job = client.batches.create(
input_file_id=batch_file.id,
endpoint="/chat/completions",
completion_window="24h",
metadata={"project": "document-processing", "owner": "data-team"},
)
print(f"Batch job created: {batch_job.id}")
# Step 4: Poll for completion
import time
while True:
status = client.batches.retrieve(batch_job.id)
print(f"Status: {status.status} | Completed: {status.request_counts.completed}/{status.request_counts.total}")
if status.status in ("completed", "failed", "expired"):
break
time.sleep(60)
# Step 5: Download results
if status.status == "completed":
result_file = client.files.content(status.output_file_id)
results = [json.loads(line) for line in result_file.text.strip().split("\n")]
for r in results:
print(f"{r['custom_id']}: {r['response']['body']['choices'][0]['message']['content']}")
Streaming delivers tokens as they’re generated, reducing perceived latency for chat applications.
stream = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Explain distributed systems in detail."},
],
stream=True,
)
full_response = ""
for chunk in stream:
if chunk.choices[0].delta.content:
token = chunk.choices[0].delta.content
print(token, end="", flush=True)
full_response += token
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
app = FastAPI()
@app.post("/chat")
async def chat(request: ChatRequest):
async def generate():
stream = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": request.message}],
stream=True,
)
for chunk in stream:
if chunk.choices[0].delta.content:
token = chunk.choices[0].delta.content
yield f"data: {json.dumps({'token': token})}\n\n"
yield "data: [DONE]\n\n"
return StreamingResponse(generate(), media_type="text/event-stream")
async function streamChat(message, onToken) {
const response = await fetch("/chat", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ message }),
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const text = decoder.decode(value);
const lines = text.split("\n").filter((l) => l.startsWith("data: "));
for (const line of lines) {
const data = line.slice(6);
if (data === "[DONE]") return;
const parsed = JSON.parse(data);
onToken(parsed.token);
}
}
}
// Usage
streamChat("Explain AI", (token) => {
document.getElementById("output").textContent += token;
});
import asyncio
from openai import AsyncAzureOpenAI
async_client = AsyncAzureOpenAI(
azure_endpoint="https://my-openai.openai.azure.com/",
api_version="2024-08-01-preview",
)
async def process_document(doc: str) -> str:
response = await async_client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": f"Summarize: {doc}"}],
)
return response.choices[0].message.content
async def process_batch_async(documents: list[str], max_concurrent: int = 10):
semaphore = asyncio.Semaphore(max_concurrent)
async def limited_process(doc):
async with semaphore:
return await process_document(doc)
results = await asyncio.gather(*[limited_process(d) for d in documents])
return results
Tip: Use the Global Batch API for non-urgent workloads — it’s 50% cheaper than real-time. For interactive apps, use streaming to improve perceived performance. For moderate concurrency (10-100 docs), use async Python with semaphores to stay within rate limits.