Async AI: Design Patterns for AI-First Development
Building AI-first applications requires new patterns. Just as we developed design patterns for async programming, we need patterns for AI integration.
The Circuit Breaker Pattern
Protect your app from AI service failures:
class AICircuitBreaker {
private failureCount = 0;
private lastFailure?: Date;
private state: 'closed' | 'open' | 'half-open' = 'closed';
async callAI(prompt: string): Promise<string> {
if (this.state === 'open') {
if (this.shouldAttemptReset()) {
this.state = 'half-open';
} else {
throw new Error('Circuit breaker is open');
}
}
try {
const result = await this.aiService.call(prompt);
this.onSuccess();
return result;
} catch (error) {
this.onFailure();
throw error;
}
}
}
The Prompt Chain Pattern
Break complex tasks into manageable steps:
class PromptChain {
async processDocument(content: string) {
const summary = await this.ai.summarize(content);
const keyPoints = await this.ai.extractKeyPoints(summary);
const categories = await this.ai.categorize(keyPoints);
return {
summary,
keyPoints,
categories
};
}
}
The Response Validation Pattern
Always validate AI outputs:
interface ValidationRule<T> {
validate(response: T): boolean;
errorMessage: string;
}
class AIResponseValidator<T> {
constructor(private rules: ValidationRule<T>[]) {}
validate(response: T): void {
for (const rule of this.rules) {
if (!rule.validate(response)) {
throw new Error(rule.errorMessage);
}
}
}
}
The Fallback Chain Pattern
Progressive degradation for AI failures:
class FallbackChain {
async generateResponse(prompt: string): Promise<string> {
try {
return await this.gpt4.generate(prompt);
} catch {
try {
return await this.gpt3.generate(prompt);
} catch {
return await this.templateResponse(prompt);
}
}
}
}
The Context Window Manager
Handle token limits gracefully:
class ContextManager {
private maxTokens: number;
async optimizeContext(messages: Message[]): Promise<Message[]> {
let tokenCount = this.countTokens(messages);
while (tokenCount > this.maxTokens) {
// Remove oldest non-system messages first
messages = this.removeOldestUserMessage(messages);
tokenCount = this.countTokens(messages);
}
return messages;
}
}
The Async Promise Pattern
Combine multiple AI operations:
class AsyncAIOrchestrator {
async processUserRequest(request: UserRequest) {
const [
sentiment,
intent,
entities
] = await Promise.allSettled([
this.analyzeSentiment(request.text),
this.detectIntent(request.text),
this.extractEntities(request.text)
]);
return this.combineResults({
sentiment: sentiment.status === 'fulfilled' ? sentiment.value : null,
intent: intent.status === 'fulfilled' ? intent.value : null,
entities: entities.status === 'fulfilled' ? entities.value : []
});
}
}
These patterns help build resilient AI applications that handle the async, unpredictable nature of AI services while maintaining good user experience.