AI Design Patterns
Introduction
AI design patterns are reusable solutions to common problems encountered when building AI applications. These patterns provide structured approaches to implementing various AI capabilities, from reasoning and learning to security and evaluation.
ReAct Pattern (Reasoning + Acting)
What is ReAct?
ReAct is a pattern that combines reasoning with action-taking capabilities, enabling AI systems to use external tools and APIs to accomplish tasks that require real-world interaction.
How ReAct Works
- Observation: The AI observes the current state or receives a query
- Thought: The AI reasons about what needs to be done
- Action: The AI takes an action (e.g., API call, tool usage)
- Observation: The AI observes the result of the action
- Repeat: The cycle continues until the task is complete
Example Implementation
# ReAct Pattern Example
def react_agent(query):
while not task_complete:
# Step 1: Think
thought = llm.generate_thought(query, context)
# Step 2: Act
action = llm.decide_action(thought)
result = execute_action(action)
# Step 3: Observe
context.update(result)
# Step 4: Check completion
if is_task_complete(result):
break
Applications
- Web scraping and data collection
- API integration and automation
- Tool usage (calculators, databases, etc.)
- Interactive environments
Constitutional AI Pattern
What is Constitutional AI?
Constitutional AI is a self-improvement pattern where the AI critiques and revises its own outputs to align with human values and reduce harmful content.
How Constitutional AI Works
- Initial Response: Generate an initial response to a query
- Self-Critique: Analyze the response for potential issues
- Revision: Generate an improved version based on the critique
- Iteration: Repeat until the response meets quality standards
Example Implementation
def constitutional_ai(query):
# Generate initial response
response = llm.generate(query)
# Self-critique
critique = llm.critique(response, constitution)
# Revise based on critique
if critique.requires_revision:
response = llm.revise(response, critique)
return response
Benefits
- Improved safety and alignment
- Reduced harmful outputs
- Self-improving capabilities
- Better adherence to guidelines
Few-Shot Learning Pattern
What is Few-Shot Learning?
Few-Shot Learning enables AI models to perform new tasks with minimal examples by leveraging their pre-trained knowledge and adapting to new domains.
How Few-Shot Learning Works
- Task Description: Provide a clear description of the task
- Examples: Include 1-5 examples of the desired input-output pairs
- Query: Present the actual query to be solved
- Generation: The model generates the response based on the pattern
Example
Task: Translate English to French
Examples:
- "Hello" → "Bonjour"
- "Good morning" → "Bonjour"
- "How are you?" → "Comment allez-vous?"
Query: "Thank you"
Response: "Merci"
Applications
- Domain adaptation
- Custom language models
- Specialized tasks
- Rapid prototyping
Prompt Engineering Patterns
System Prompts
System prompts define the AI's role, behavior, and constraints.
system_prompt = """
You are a helpful AI assistant specialized in Python programming.
- Always provide clear, well-documented code
- Include error handling
- Explain your reasoning
- Follow PEP 8 style guidelines
"""
Role-Based Prompting
Assign specific roles to guide AI behavior.
role_prompt = """
You are an expert data scientist with 10 years of experience.
Your task is to analyze this dataset and provide insights.
Consider: statistical significance, practical implications, and limitations.
"""
Chain-of-Thought Prompting
Encourage step-by-step reasoning.
cot_prompt = """
Let's approach this step by step:
1. First, let's understand the problem
2. Then, identify the key components
3. Finally, solve it systematically
Problem: {user_query}
"""
Context Window Management
Strategies for handling long conversations:
- Sliding Window: Keep most recent N tokens
- Summarization: Summarize older parts of conversation
- Hierarchical: Maintain high-level context with detailed recent context
Fine-tuning and LoRA Patterns
Parameter-Efficient Fine-tuning
LoRA (Low-Rank Adaptation) reduces computational costs while maintaining performance.
# LoRA Configuration
lora_config = {
"r": 16, # Rank
"lora_alpha": 32, # Scaling factor
"target_modules": ["q_proj", "v_proj"],
"lora_dropout": 0.1
}
Domain Adaptation
Fine-tune models for specific domains:
- Data Collection: Gather domain-specific data
- Preprocessing: Clean and format the data
- Training: Fine-tune with appropriate hyperparameters
- Evaluation: Test on domain-specific metrics
Best Practices
- Start with small learning rates
- Use validation sets to prevent overfitting
- Monitor training metrics carefully
- Consider using techniques like QLoRA for memory efficiency
Orchestration Patterns
Workflow Management
Manage complex AI workflows with proper error handling and fallbacks.
class AIWorkflow:
def __init__(self):
self.steps = []
self.fallbacks = {}
def add_step(self, step, fallback=None):
self.steps.append(step)
if fallback:
self.fallbacks[step] = fallback
def execute(self, input_data):
for step in self.steps:
try:
result = step.execute(input_data)
input_data = result
except Exception as e:
if step in self.fallbacks:
result = self.fallbacks[step].execute(input_data)
else:
raise e
return input_data
Rate Limiting and Cost Optimization
class RateLimiter:
def __init__(self, max_requests_per_minute):
self.max_requests = max_requests_per_minute
self.requests = []
def can_make_request(self):
now = time.time()
# Remove requests older than 1 minute
self.requests = [req for req in self.requests if now - req < 60]
return len(self.requests) < self.max_requests
def record_request(self):
self.requests.append(time.time())
Caching Strategies
- Response Caching: Cache identical queries
- Embedding Caching: Cache vector embeddings
- Model Caching: Keep models in memory for faster inference
Evaluation and Testing Patterns
A/B Testing Framework
class ABTest:
def __init__(self, variant_a, variant_b):
self.variant_a = variant_a
self.variant_b = variant_b
self.results = {"A": [], "B": []}
def run_test(self, test_data):
for item in test_data:
variant = random.choice(["A", "B"])
if variant == "A":
result = self.variant_a.process(item)
else:
result = self.variant_b.process(item)
self.results[variant].append(result)
def analyze_results(self):
# Statistical analysis of results
pass
Human Evaluation Framework
class HumanEvaluator:
def __init__(self, evaluation_criteria):
self.criteria = evaluation_criteria
def evaluate_response(self, response, ground_truth=None):
scores = {}
for criterion in self.criteria:
score = self.evaluate_criterion(response, criterion, ground_truth)
scores[criterion] = score
return scores
def evaluate_criterion(self, response, criterion, ground_truth):
# Implementation depends on the specific criterion
pass
Automated Metrics
- BLEU Score: For translation tasks
- ROUGE Score: For summarization tasks
- Perplexity: For language modeling
- Accuracy: For classification tasks
Security and Safety Patterns
Prompt Injection Prevention
def sanitize_prompt(user_input):
# Remove potentially harmful patterns
dangerous_patterns = [
r"ignore previous instructions",
r"system prompt",
r"override",
r"ignore above"
]
for pattern in dangerous_patterns:
user_input = re.sub(pattern, "", user_input, flags=re.IGNORECASE)
return user_input
Output Filtering
class ContentFilter:
def __init__(self):
self.harmful_patterns = [
"violence", "hate speech", "personal information"
]
def filter_output(self, text):
for pattern in self.harmful_patterns:
if self.detect_pattern(text, pattern):
return self.sanitize_text(text)
return text
def detect_pattern(self, text, pattern):
# Implementation for pattern detection
pass
def sanitize_text(self, text):
# Implementation for text sanitization
pass
Privacy-Preserving Techniques
- Data Anonymization: Remove personally identifiable information
- Differential Privacy: Add noise to protect individual data points
- Federated Learning: Train models without sharing raw data
- Homomorphic Encryption: Process encrypted data
Best Practices Summary
General Guidelines
- Start Simple: Begin with basic patterns before adding complexity
- Test Thoroughly: Implement comprehensive testing for all patterns
- Monitor Performance: Track metrics and performance over time
- Document Everything: Maintain clear documentation of pattern usage
- Iterate and Improve: Continuously refine patterns based on results
Pattern Selection
- ReAct: Use when external tools or APIs are needed
- Constitutional AI: Use for safety-critical applications
- Few-Shot Learning: Use for rapid domain adaptation
- Prompt Engineering: Use for all LLM interactions
- Fine-tuning: Use when domain-specific performance is crucial
- Orchestration: Use for complex, multi-step workflows
- Evaluation: Use for all production AI systems
- Security: Use for all user-facing AI applications
Conclusion
AI design patterns provide structured approaches to building robust, scalable, and safe AI applications. Understanding and implementing these patterns helps developers create more effective AI systems while avoiding common pitfalls. The key is to choose the right patterns for your specific use case and combine them effectively to achieve your goals.