Skip to main content

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

  1. Observation: The AI observes the current state or receives a query
  2. Thought: The AI reasons about what needs to be done
  3. Action: The AI takes an action (e.g., API call, tool usage)
  4. Observation: The AI observes the result of the action
  5. 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

  1. Initial Response: Generate an initial response to a query
  2. Self-Critique: Analyze the response for potential issues
  3. Revision: Generate an improved version based on the critique
  4. 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

  1. Task Description: Provide a clear description of the task
  2. Examples: Include 1-5 examples of the desired input-output pairs
  3. Query: Present the actual query to be solved
  4. 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:

  1. Data Collection: Gather domain-specific data
  2. Preprocessing: Clean and format the data
  3. Training: Fine-tune with appropriate hyperparameters
  4. 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

  1. Start Simple: Begin with basic patterns before adding complexity
  2. Test Thoroughly: Implement comprehensive testing for all patterns
  3. Monitor Performance: Track metrics and performance over time
  4. Document Everything: Maintain clear documentation of pattern usage
  5. 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.