Calling LLM APIs
Time to write code. We'll use OpenAI's API (the most common), but the concepts apply to Claude, Gemini, and others.
Get an OpenAI API key from platform.openai.com. You'll need a few cents of credit to follow along.
---
Setup
pip install openai python-dotenv
Create a .env file:
OPENAI_API_KEY=sk-your-key-here
---
Your First API Call
from openai import OpenAI
from dotenv import load_dotenv
load_dotenv()
client = OpenAI() # Automatically reads OPENAI_API_KEY
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "user", "content": "What is Python?"}
]
)
print(response.choices[0].message.content)
That's it. You just called an LLM.
---
Understanding the Request
Key Parameters
response = client.chat.completions.create(
model="gpt-4o-mini", # Which model to use
messages=[...], # Conversation history
temperature=0.7, # Creativity (0-2)
max_tokens=500, # Max response length
)
| Parameter | What it does | Typical value |
|---|---|---|
| model | Which LLM to use | "gpt-4o-mini" (cheap), "gpt-4o" (smart) |
| messages | Conversation history | [{role, content}, ...] |
| temperature | Randomness/creativity | 0 = focused, 1 = creative |
| max_tokens | Response length limit | 500-2000 for most tasks |
---
The Messages Array
This is the most important part. Messages have three roles:
Sets behavior, personality, rules. "You are a helpful assistant..."
The human's input. Questions, requests, data.
The AI's previous responses. For conversation history.
messages = [
{
"role": "system",
"content": "You are a senior Python developer. Be concise."
},
{
"role": "user",
"content": "How do I read a JSON file?"
}
]
---
Understanding the Response
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Hi!"}]
)
# The response object
print(response.choices[0].message.content) # The actual text
print(response.choices[0].finish_reason) # "stop" = completed normally
print(response.usage.prompt_tokens) # Tokens in your request
print(response.usage.completion_tokens) # Tokens in response
print(response.usage.total_tokens) # Total (for billing)
Tokens are chunks of text (roughly 4 characters or 0.75 words). You pay per token. "Hello world" = 2 tokens. Always monitor usage.total_tokens in production.
---
A Practical Example: Ticket Classifier
Let's build something real - a support ticket classifier:
from openai import OpenAI
import json
client = OpenAI()
def classify_ticket(ticket_text: str) -> dict:
response = client.chat.completions.create(
model="gpt-4o-mini",
temperature=0, # Deterministic for classification
messages=[
{
"role": "system",
"content": """Classify support tickets into categories.
Return JSON with: category, priority, summary
Categories: billing, technical, account, general
Priorities: low, medium, high, urgent"""
},
{
"role": "user",
"content": ticket_text
}
],
response_format={"type": "json_object"} # Ensures valid JSON
)
return json.loads(response.choices[0].message.content)
# Test it
ticket = "I've been charged twice for my subscription this month!"
result = classify_ticket(ticket)
print(result)
# {"category": "billing", "priority": "high", "summary": "Duplicate charge"}
---
Error Handling
Production code needs proper error handling:
from openai import OpenAI, APIError, RateLimitError, APITimeoutError
import time
client = OpenAI()
def call_llm_with_retry(messages, max_retries=3):
for attempt in range(max_retries):
try:
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=messages,
timeout=30.0 # 30 second timeout
)
return response.choices[0].message.content
except RateLimitError:
# Wait and retry
wait_time = 2 ** attempt # Exponential backoff
print(f"Rate limited. Waiting {wait_time}s...")
time.sleep(wait_time)
except APITimeoutError:
print("Request timed out. Retrying...")
continue
except APIError as e:
print(f"API error: {e}")
raise
raise Exception("Max retries exceeded")
---
Cost Management Tips
gpt-4o-mini is 20x cheaper than gpt-4o. Use the smallest model that works.
Prevent runaway responses. Most tasks need 500-1000 tokens max.
Same input = same output (with temp=0). Cache aggressively.
Log every call with token counts. Set billing alerts.
---
Model Comparison (2025)
| Model | Best for | Cost |
|---|---|---|
| gpt-4o-mini | Most tasks, classification, simple generation | $ |
| gpt-4o | Complex reasoning, coding, analysis | $$ |
| claude-3-5-sonnet | Long documents, nuanced writing | $ |
| gemini-1.5-flash | Fast, cheap, good for simple tasks | $ |
Key Takeaways
- It's just an API call - HTTP request with JSON, nothing magic
- Messages array is key - system sets behavior, user provides input
- Temperature 0 for factual - use low temperature for deterministic outputs
- Always handle errors - rate limits and timeouts will happen
Next up: Prompt Engineering - how to get better outputs from your LLM calls.