Overview
Large Language Models (LLMs)
Large Language Models are transformer-based neural networks trained on extensive text corpora using self-supervised learning. These models employ attention mechanisms to capture long-range dependencies and contextual relationships within sequences.
Key capabilities:
- Natural language understanding and generation
- Context-aware reasoning (up to 1M tokens)
- Multi-turn conversation with memory retention
- Function calling and tool integration
- Structured output generation (JSON, XML, code)
- Multimodal processing (text, images, audio)
Transformer Architecture Fundamentals
Modern LLMs utilize the transformer architecture introduced in "Attention Is All You Need" (Vaswani et al., 2017). Key components:
- Self-Attention Mechanism: Enables parallel processing of sequence elements with O(n²) complexity
- Multi-Head Attention: Captures different representation subspaces simultaneously
- Feed-Forward Networks: Position-wise fully connected layers with GELU/SwiGLU activation
- Positional Encoding: RoPE (Rotary Position Embedding) or ALiBi for sequence position awareness
- Layer Normalization: RMSNorm or Pre-LN for training stability
Market-Leading Models (2024-2025)
| Model | Organization | Context | Modality | Best For |
|---|---|---|---|---|
| GPT-5.6 | OpenAI | 128K | Text, Vision | General purpose, complex reasoning |
| Claude Sonnet 5 | Anthropic | 1M | Text, Vision | Long-context analysis, code generation |
| Gemini 3.1 Pro | 2M | Text, Vision, Audio | Ultra-long context, multimodal tasks | |
| Grok 4.5 | xAI | 32K | Text, Vision | Real-time data, X integration |
| DeepSeek V4 | DeepSeek | 128K | Text | Cost-efficient, high performance |
Architecture
Decoder-Only Transformer Architecture
Most modern LLMs (GPT series, Claude, LLaMA) use decoder-only architectures optimized for autoregressive generation:
Input Tokens → Embedding Layer → Positional Encoding
↓
Transformer Decoder Blocks (×N layers):
├─ Multi-Head Self-Attention (causal masking)
├─ Layer Normalization
├─ Feed-Forward Network (4× hidden dim)
└─ Residual Connections
↓
Final Layer Norm → Output Projection → Logits → Softmax
Key architectural innovations:
- Grouped-Query Attention (GQA): Reduces KV cache memory by sharing key/value heads
- FlashAttention: IO-aware attention computation for 2-4× speed improvement
- Mixture of Experts (MoE): Sparse activation of expert networks (GPT-5.6, Mixtral)
- SwiGLU Activation: Gated Linear Unit variant outperforming ReLU/GELU
- RMSNorm: Computationally efficient alternative to LayerNorm
Training Pipeline
Modern LLMs undergo multi-stage training:
1. Pre-training
Next-token prediction on trillion-token datasets. Objectives: minimize cross-entropy loss, learn language patterns and world knowledge.
2. Supervised Fine-Tuning (SFT)
Training on curated instruction-response pairs to align model behavior with desired task formats.
3. RLHF
Reinforcement Learning from Human Feedback using PPO algorithm to optimize for human preferences.
4. Constitutional AI
Self-supervised alignment using AI-generated critiques and revisions (Anthropic's approach).
Context Window Management
Context window determines the maximum sequence length the model can process:
| Context Size | Use Case | KV Cache Memory |
|---|---|---|
| 4K-8K tokens | Short conversations, simple queries | ~100MB |
| 32K-128K tokens | Document analysis, extended dialogues | ~1-4GB |
| 1M-2M tokens | Entire codebases, books, long-form content | ~10-100GB |
Prompt Engineering
Systematic Prompting Techniques
Prompt engineering is the practice of designing inputs to elicit optimal model behavior. Advanced techniques:
1. Zero-Shot Prompting
Direct instruction without examples. Effective for well-defined tasks and capable models.
Classify the sentiment of this text as positive, negative, or neutral:
"The product exceeded my expectations and arrived early."
Expected output: positive
2. Few-Shot Prompting
Provide examples to establish pattern. Crucial for complex or ambiguous tasks.
Extract structured data from product descriptions.
Example 1:
Input: "Samsung 65-inch QLED 4K TV, $1,299"
Output: {"brand": "Samsung", "size": "65-inch", "type": "QLED 4K TV", "price": 1299}
Example 2:
Input: "Apple MacBook Pro M3, 16GB RAM, $2,499"
Output: {"brand": "Apple", "model": "MacBook Pro M3", "ram": "16GB", "price": 2499}
Now extract from: "Sony WH-1000XM5 Noise-Cancelling Headphones, $399"
3. Chain-of-Thought (CoT)
Elicit step-by-step reasoning to improve accuracy on complex problems.
Solve this problem step by step:
A company's revenue increased by 15% in Q1, then decreased by 10% in Q2.
If the initial revenue was $1,000,000, what is the final revenue?
Let's break this down:
Step 1: Calculate Q1 revenue after 15% increase
$1,000,000 × 1.15 = $1,150,000
Step 2: Calculate Q2 revenue after 10% decrease
$1,150,000 × 0.90 = $1,035,000
Final answer: $1,035,000
4. Structured Output with Schema
Define exact output format using JSON schema or TypeScript interfaces.
Extract information in this exact JSON format:
{
"name": string,
"email": string,
"skills": string[],
"experience_years": number,
"remote_willing": boolean
}
Resume text: "John Doe (john@example.com) is a senior developer
with 8 years of experience in Python, TypeScript, and React.
Open to remote opportunities."
Output: {
"name": "John Doe",
"email": "john@example.com",
"skills": ["Python", "TypeScript", "React"],
"experience_years": 8,
"remote_willing": true
}
5. ReAct Pattern (Reasoning + Acting)
Combine reasoning traces with action execution for agentic behavior.
Task: Find the current stock price of Apple and calculate portfolio value
Thought: I need to get the current AAPL stock price first
Action: search("Apple Inc stock price AAPL current")
Observation: $178.45 per share
Thought: Now I need to know how many shares the user owns
Action: check_portfolio("AAPL")
Observation: 150 shares
Thought: I can now calculate the total value
Action: calculate(150 * 178.45)
Observation: $26,767.50
Answer: Your Apple portfolio is currently worth $26,767.50
(150 shares × $178.45/share)
API Integration
OpenAI API Integration
Standard interface for GPT models with streaming, function calling, and vision capabilities.
import openai
from openai import OpenAI
client = OpenAI(api_key="sk-...")
# Basic chat completion
response = client.chat.completions.create(
model="gpt-4-turbo",
messages=[
{"role": "system", "content": "You are a technical assistant."},
{"role": "user", "content": "Explain async/await in JavaScript"}
],
temperature=0.7,
max_tokens=500,
top_p=0.95,
frequency_penalty=0.0,
presence_penalty=0.0
)
print(response.choices[0].message.content)
# Streaming response
stream = client.chat.completions.create(
model="gpt-4-turbo",
messages=[{"role": "user", "content": "Write a Python function"}],
stream=True
)
for chunk in stream:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="")
Function Calling / Tool Use
Enable models to interact with external systems through structured function calls.
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather for a location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name, e.g. San Francisco"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"]
}
},
"required": ["location"]
}
}
}
]
response = client.chat.completions.create(
model="gpt-4-turbo",
messages=[{"role": "user", "content": "What's the weather in Paris?"}],
tools=tools,
tool_choice="auto"
)
# Handle function call
if response.choices[0].message.tool_calls:
tool_call = response.choices[0].message.tool_calls[0]
function_name = tool_call.function.name
arguments = json.loads(tool_call.function.arguments)
# Execute function
result = get_weather(**arguments)
# Send result back to model
messages.append(response.choices[0].message)
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(result)
})
Anthropic Claude API
Claude API with extended context windows and multimodal capabilities.
import anthropic
client = anthropic.Anthropic(api_key="sk-ant-...")
message = client.messages.create(
model="claude-sonnet-5",
max_tokens=4096,
temperature=0,
system="You are a code review assistant. Analyze code for bugs and improvements.",
messages=[
{
"role": "user",
"content": [
{
"type": "text",
"text": "Review this Python function:\n\ndef process_data(items):\n result = []\n for i in range(len(items)):\n if items[i] > 0:\n result.append(items[i] * 2)\n return result"
}
]
}
]
)
print(message.content[0].text)
# Vision example
with open("diagram.png", "rb") as f:
image_data = base64.standard_b64encode(f.read()).decode("utf-8")
message = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
messages=[{
"role": "user",
"content": [
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/png",
"data": image_data
}
},
{
"type": "text",
"text": "Explain this architecture diagram"
}
]
}]
)
Critical Parameters
| Parameter | Range | Effect | Recommended |
|---|---|---|---|
| temperature | 0.0 - 2.0 | Higher = more random/creative | 0.0-0.3 (code), 0.7-1.0 (creative) |
| top_p | 0.0 - 1.0 | Nucleus sampling threshold | 0.9-0.95 (balanced diversity) |
| max_tokens | 1 - context_limit | Maximum output length | 500-2000 (typical), 4096+ (long-form) |
| frequency_penalty | -2.0 - 2.0 | Reduce token repetition | 0.0-0.5 (avoid redundancy) |
| presence_penalty | -2.0 - 2.0 | Encourage topic diversity | 0.0-0.6 (varied content) |
RAG Systems
Retrieval-Augmented Generation (RAG)
RAG combines retrieval systems with LLMs to provide grounded, factual responses using external knowledge bases. Essential for production applications requiring up-to-date or domain-specific information.
RAG Pipeline:
┌─────────────┐
│ Query │
└──────┬──────┘
│
v
┌─────────────────────┐
│ Embed Query │ ← Embedding Model (e.g., text-embedding-3-large)
└──────┬──────────────┘
│
v
┌─────────────────────┐
│ Vector Search │ ← Vector DB (Pinecone, Weaviate, ChromaDB)
│ Top-K Documents │
└──────┬──────────────┘
│
v
┌─────────────────────┐
│ Rerank Results │ ← Reranking Model (Cohere, cross-encoder)
└──────┬──────────────┘
│
v
┌─────────────────────┐
│ Augment Prompt │ ← Inject retrieved context
└──────┬──────────────┘
│
v
┌─────────────────────┐
│ LLM Generation │ ← GPT-5.6, Claude, etc.
└─────────────────────┘
Vector Database Implementation
Store and retrieve document embeddings using vector similarity search.
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings
from langchain.document_loaders import DirectoryLoader
# Load documents
loader = DirectoryLoader('./docs', glob="**/*.md")
documents = loader.load()
# Split into chunks (critical for quality)
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200,
length_function=len,
separators=["\n\n", "\n", " ", ""]
)
chunks = text_splitter.split_documents(documents)
# Create embeddings and store in vector DB
embeddings = OpenAIEmbeddings(model="text-embedding-3-large")
vectorstore = Chroma.from_documents(
documents=chunks,
embedding=embeddings,
persist_directory="./chroma_db"
)
# Retrieve relevant documents
query = "How do I configure authentication?"
relevant_docs = vectorstore.similarity_search(
query,
k=4, # Top 4 results
fetch_k=20 # Fetch 20, rerank to 4
)
# Build context for LLM
context = "\n\n".join([doc.page_content for doc in relevant_docs])
prompt = f"""Answer the question based on this context:
Context:
{context}
Question: {query}
Answer:"""
Advanced RAG Techniques
Hybrid Search
Combine vector similarity (semantic) with keyword search (BM25) for better recall. Weight: 0.7 vector + 0.3 keyword.
Hypothetical Document Embeddings (HyDE)
Generate hypothetical answer first, embed it, then retrieve similar real documents.
Parent-Child Chunking
Store small chunks for retrieval, but provide larger parent chunks to LLM for better context.
Reranking
Use cross-encoder models to rerank retrieved results. Cohere Rerank improves relevance by 20-30%.
Production RAG Stack
from langchain.chat_models import ChatOpenAI
from langchain.chains import RetrievalQA
from langchain.prompts import PromptTemplate
# Define custom prompt
template = """Use the following context to answer the question.
If you don't know the answer, say so - don't make up information.
Context: {context}
Question: {question}
Provide a detailed answer with sources:"""
prompt = PromptTemplate(
template=template,
input_variables=["context", "question"]
)
# Create retrieval chain
llm = ChatOpenAI(model="gpt-4-turbo", temperature=0)
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff", # Options: stuff, map_reduce, refine
retriever=vectorstore.as_retriever(
search_type="mmr", # Maximum Marginal Relevance
search_kwargs={
"k": 4,
"fetch_k": 20,
"lambda_mult": 0.5 # Diversity vs relevance
}
),
return_source_documents=True,
chain_type_kwargs={"prompt": prompt}
)
# Query
result = qa_chain({"query": "How do I implement OAuth2?"})
print(result["result"])
print(f"\nSources: {[doc.metadata for doc in result['source_documents']]}")
Agentic Workflows
AI Agents: Autonomous Task Execution
AI agents are LLM-powered systems that can plan, execute actions, use tools, and iterate towards goals autonomously. They extend LLM capabilities beyond single-turn generation.
Core agent components:
- Reasoning Engine: LLM for decision-making and planning
- Memory: Short-term (conversation) and long-term (vector DB)
- Tools: External functions (APIs, databases, calculators)
- Planning: Task decomposition and execution strategies
- Reflection: Self-critique and iterative improvement
ReAct Agent Implementation
ReAct (Reasoning + Acting) pattern enables agents to interleave thought and action.
from langchain.agents import initialize_agent, Tool, AgentType
from langchain.chat_models import ChatOpenAI
from langchain.utilities import SerpAPIWrapper, PythonREPL
# Define tools
search = SerpAPIWrapper()
python_repl = PythonREPL()
tools = [
Tool(
name="Search",
func=search.run,
description="Search the internet for current information"
),
Tool(
name="Python",
func=python_repl.run,
description="Execute Python code. Input should be valid Python code."
),
Tool(
name="Calculator",
func=lambda x: eval(x),
description="Perform mathematical calculations"
)
]
# Initialize agent
llm = ChatOpenAI(model="gpt-4-turbo", temperature=0)
agent = initialize_agent(
tools=tools,
llm=llm,
agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
verbose=True,
max_iterations=5,
early_stopping_method="generate"
)
# Execute complex task
result = agent.run("""
Find the current stock price of NVIDIA, then calculate how many shares
I could buy with $10,000 and what the total value would be if the price
increases by 15%.
""")
# Agent output (example):
# Thought: I need to search for NVIDIA's current stock price
# Action: Search
# Action Input: "NVIDIA stock price today"
# Observation: $495.22 per share
#
# Thought: Now I'll calculate how many shares $10,000 can buy
# Action: Calculator
# Action Input: 10000 / 495.22
# Observation: 20.19 shares
#
# Thought: Calculate value with 15% increase
# Action: Python
# Action Input: shares = 20.19; price = 495.22; new_price = price * 1.15; ...
# Observation: $11,500.00
#
# Final Answer: With $10,000, you can buy approximately 20 shares of NVIDIA...
Multi-Agent Systems
Coordinate multiple specialized agents for complex workflows.
from langchain.agents import AgentExecutor
from langchain.chat_models import ChatAnthropic
from langgraph.prebuilt import create_react_agent
# Define specialized agents
researcher = create_react_agent(
ChatAnthropic(model="claude-sonnet-5"),
tools=[search_tool, arxiv_tool],
prompt="You are a research assistant. Find accurate technical information."
)
coder = create_react_agent(
ChatOpenAI(model="gpt-4-turbo"),
tools=[python_repl, file_read_tool, file_write_tool],
prompt="You are a coding assistant. Write clean, efficient code."
)
critic = create_react_agent(
ChatAnthropic(model="claude-sonnet-5"),
tools=[],
prompt="You are a code reviewer. Critique for bugs, efficiency, and best practices."
)
# Orchestration workflow
def multi_agent_workflow(task):
# 1. Research phase
research_result = researcher.invoke({"messages": [("user", f"Research: {task}")]})
# 2. Implementation phase
code_result = coder.invoke({
"messages": [("user", f"Implement based on: {research_result}")]
})
# 3. Review phase
critique = critic.invoke({
"messages": [("user", f"Review this code:\n{code_result}")]
})
# 4. Refinement (if needed)
if "issues found" in critique.lower():
final_code = coder.invoke({
"messages": [("user", f"Fix these issues:\n{critique}")]
})
else:
final_code = code_result
return final_code
result = multi_agent_workflow("Create a REST API for user authentication")
Agent Frameworks Comparison
| Framework | Best For | Key Features |
|---|---|---|
| LangGraph | Complex stateful workflows | Graph-based execution, checkpointing, human-in-loop |
| AutoGPT | Autonomous goal pursuit | Self-prompting, memory management, web browsing |
| CrewAI | Multi-agent collaboration | Role-based agents, task delegation, shared memory |
| LangChain Agents | Tool-using agents | ReAct, OpenAI Functions, extensive tool integrations |
Fine-Tuning
When to Fine-Tune vs Prompt Engineering
Fine-tuning adapts pre-trained models to specific domains or tasks through additional training. Consider fine-tuning when:
- Domain-specific terminology and patterns (legal, medical, finance)
- Consistent output formatting that's hard to achieve with prompts
- Need to reduce latency by embedding instructions in model weights
- Cost optimization for high-volume production use
- Have 500+ high-quality training examples
Stick with prompt engineering if:
- Few examples available (<500)
- Requirements change frequently
- Task is well-handled by base model with good prompts
- Need model flexibility across various tasks
Supervised Fine-Tuning (SFT)
Train on input-output pairs to specialize model behavior.
# Prepare training data (JSONL format)
# Each line: {"messages": [{"role": "system", ...}, {"role": "user", ...}, {"role": "assistant", ...}]}
training_data = [
{
"messages": [
{"role": "system", "content": "You are a legal contract analyzer."},
{"role": "user", "content": "Analyze this NDA clause: ..."},
{"role": "assistant", "content": "This is a mutual NDA with standard provisions..."}
]
},
# ... 500+ more examples
]
# OpenAI Fine-Tuning
from openai import OpenAI
client = OpenAI()
# Upload training file
file = client.files.create(
file=open("training_data.jsonl", "rb"),
purpose="fine-tune"
)
# Create fine-tuning job
job = client.fine_tuning.jobs.create(
training_file=file.id,
model="gpt-3.5-turbo",
hyperparameters={
"n_epochs": 3,
"batch_size": 4,
"learning_rate_multiplier": 0.1
}
)
# Monitor training
while True:
job_status = client.fine_tuning.jobs.retrieve(job.id)
print(f"Status: {job_status.status}")
if job_status.status in ["succeeded", "failed", "cancelled"]:
break
time.sleep(60)
# Use fine-tuned model
response = client.chat.completions.create(
model=job_status.fine_tuned_model,
messages=[{"role": "user", "content": "Analyze this contract..."}]
)
Parameter-Efficient Fine-Tuning (PEFT)
Efficient alternatives to full fine-tuning for large models.
LoRA (Low-Rank Adaptation)
Train small adapter matrices instead of full model. 0.1% parameters, 90% performance. Ideal for resource-constrained environments.
QLoRA
LoRA + 4-bit quantization. Fine-tune 65B models on single GPU. Memory efficient while maintaining quality.
Prefix Tuning
Optimize continuous prompt vectors. Fast adaptation, easy multi-task switching by swapping prefixes.
Adapter Layers
Insert small trainable layers between frozen transformer blocks. Modular and composable.
LoRA Fine-Tuning with Hugging Face
from transformers import AutoModelForCausalLM, AutoTokenizer, TrainingArguments
from peft import LoraConfig, get_peft_model, TaskType
from trl import SFTTrainer
# Load base model
model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-2-7b-hf",
load_in_8bit=True,
device_map="auto"
)
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-hf")
# Configure LoRA
lora_config = LoraConfig(
r=16, # Rank of adaptation matrices
lora_alpha=32, # Scaling factor
target_modules=["q_proj", "v_proj"], # Which layers to adapt
lora_dropout=0.05,
bias="none",
task_type=TaskType.CAUSAL_LM
)
model = get_peft_model(model, lora_config)
model.print_trainable_parameters() # Shows only 0.8% params trainable
# Training arguments
training_args = TrainingArguments(
output_dir="./lora-output",
per_device_train_batch_size=4,
gradient_accumulation_steps=4,
num_train_epochs=3,
learning_rate=2e-4,
fp16=True,
logging_steps=10,
save_strategy="epoch"
)
# Train
trainer = SFTTrainer(
model=model,
train_dataset=dataset,
peft_config=lora_config,
args=training_args,
tokenizer=tokenizer
)
trainer.train()
# Save adapter weights only (few MB vs GB)
model.save_pretrained("./lora-adapter")
Production Deployment
Production-Ready Architecture
Deploy LLM applications with reliability, scalability, and cost efficiency.
┌──────────────┐
│ Client │
└──────┬───────┘
│
v
┌──────────────────────┐
│ Load Balancer │ ← Rate limiting, request routing
└──────┬───────────────┘
│
v
┌──────────────────────┐
│ API Gateway │ ← Authentication, logging, caching
└──────┬───────────────┘
│
v
┌──────────────────────┐
│ Application │ ← FastAPI / Flask / Express
│ - Prompt templates │
│ - Response parsing │
│ - Error handling │
└──────┬───────────────┘
│
├─────────────────┐
v v
┌──────────────┐ ┌──────────────┐
│ LLM API │ │ Vector DB │ ← RAG knowledge base
│ (OpenAI, │ │ (Pinecone, │
│ Claude) │ │ Weaviate) │
└──────────────┘ └──────────────┘
│
v
┌──────────────────────┐
│ Monitoring │ ← Logs, metrics, tracing
│ - Latency tracking │
│ - Token usage │
│ - Error rates │
└──────────────────────┘
Caching Strategy
Reduce latency and costs with intelligent caching.
import redis
import hashlib
import json
redis_client = redis.Redis(host='localhost', port=6379, db=0)
def cached_llm_call(prompt, model="gpt-4-turbo", ttl=3600):
# Create cache key from prompt + model
cache_key = hashlib.sha256(
f"{model}:{prompt}".encode()
).hexdigest()
# Check cache
cached = redis_client.get(cache_key)
if cached:
print("Cache hit!")
return json.loads(cached)
# Call LLM
response = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": prompt}]
)
result = response.choices[0].message.content
# Store in cache
redis_client.setex(
cache_key,
ttl,
json.dumps(result)
)
return result
# Semantic caching with embeddings
def semantic_cache_lookup(query, threshold=0.95):
# Embed query
query_embedding = get_embedding(query)
# Search similar cached queries
similar = vector_store.similarity_search_with_score(
query_embedding,
k=1
)
if similar and similar[0][1] > threshold:
return similar[0][0].metadata["response"]
return None
Error Handling & Retry Logic
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type
import openai
@retry(
retry=retry_if_exception_type((
openai.RateLimitError,
openai.APIConnectionError,
openai.APITimeoutError
)),
wait=wait_exponential(multiplier=1, min=4, max=60),
stop=stop_after_attempt(5)
)
def call_llm_with_retry(prompt):
try:
response = client.chat.completions.create(
model="gpt-4-turbo",
messages=[{"role": "user", "content": prompt}],
timeout=30
)
return response.choices[0].message.content
except openai.RateLimitError as e:
print(f"Rate limited. Retrying... {e}")
raise
except openai.InvalidRequestError as e:
# Don't retry invalid requests
print(f"Invalid request: {e}")
return None
except Exception as e:
print(f"Unexpected error: {e}")
# Log to monitoring system
sentry.capture_exception(e)
raise
# Fallback to cheaper model on failure
def call_with_fallback(prompt):
try:
return call_llm_with_retry(prompt)
except Exception:
print("GPT-5.6 failed, falling back to GPT-5.6 Luna")
return client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": prompt}]
).choices[0].message.content
Cost Optimization
| Strategy | Impact | Implementation |
|---|---|---|
| Caching | 60-90% cost reduction | Redis + semantic similarity |
| Model Selection | 10-50× cost difference | GPT-5.6 Luna for simple, GPT-5.6 for complex |
| Prompt Compression | 30-70% token reduction | Remove redundancy, use abbreviations |
| Response Streaming | Better UX, same cost | stream=True in API calls |
| Batch Processing | 50% cost reduction | OpenAI Batch API (24h latency) |
Monitoring & Observability
from prometheus_client import Counter, Histogram, Gauge
import time
# Define metrics
llm_requests = Counter(
'llm_requests_total',
'Total LLM API requests',
['model', 'status']
)
llm_latency = Histogram(
'llm_latency_seconds',
'LLM API latency',
['model']
)
llm_tokens = Counter(
'llm_tokens_total',
'Total tokens consumed',
['model', 'type'] # type: prompt or completion
)
llm_cost = Counter(
'llm_cost_usd',
'Total LLM cost in USD',
['model']
)
def monitored_llm_call(prompt, model="gpt-4-turbo"):
start = time.time()
try:
response = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": prompt}]
)
# Track metrics
latency = time.time() - start
llm_latency.labels(model=model).observe(latency)
llm_requests.labels(model=model, status="success").inc()
# Track tokens
prompt_tokens = response.usage.prompt_tokens
completion_tokens = response.usage.completion_tokens
llm_tokens.labels(model=model, type="prompt").inc(prompt_tokens)
llm_tokens.labels(model=model, type="completion").inc(completion_tokens)
# Track cost (GPT-5.6 pricing: $10/1M prompt, $30/1M completion)
cost = (prompt_tokens * 0.00001) + (completion_tokens * 0.00003)
llm_cost.labels(model=model).inc(cost)
return response.choices[0].message.content
except Exception as e:
llm_requests.labels(model=model, status="error").inc()
raise
Deployment Checklist
- Rate limiting configured (per user, per endpoint)
- Error handling with retries and fallbacks
- Caching layer implemented (Redis/Memcached)
- Monitoring and alerting (Prometheus/Datadog)
- Cost tracking per request
- Input validation and sanitization
- Timeout configuration (30-60s)
- Load testing completed (concurrent requests)
- API keys secured (env variables, secrets manager)
- Logging (structured, with request IDs)
- Circuit breakers for downstream dependencies
- Health check endpoints configured