AI Integration Troubleshooting Guide
AI Integration Troubleshooting Guide
Section titled “AI Integration Troubleshooting Guide”This guide provides solutions for common issues encountered when integrating AI workflows in browser environments, covering everything from API connectivity problems to performance issues and security constraints.
Common Issues and Solutions
Section titled “Common Issues and Solutions”API Connectivity Issues
Section titled “API Connectivity Issues”Issue: CORS (Cross-Origin Resource Sharing) Errors
Section titled “Issue: CORS (Cross-Origin Resource Sharing) Errors”Symptoms:
Access to fetch at 'https://api.openai.com' from origin 'https://example.com' has been blocked by CORS policy- Network requests failing with CORS-related error messages
- AI API calls returning 0 status codes
Diagnosis:
// CORS issue detectorasync function diagnoseCORSIssue(apiEndpoint) { try { // Test with a simple HEAD request const response = await fetch(apiEndpoint, { method: 'HEAD', mode: 'cors' });
return { hasCORSIssue: false, status: response.status }; } catch (error) { if (error.message.includes('CORS')) { return { hasCORSIssue: true, error: error.message, suggestedSolutions: [ 'Use browser extension background script', 'Implement server-side proxy', 'Use JSONP if supported by API' ] }; }
return { hasCORSIssue: false, networkIssue: true, error: error.message }; }}Solutions:
- Browser Extension Background Script (Recommended)
// Background script (background.js)chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { if (request.type === 'AI_API_REQUEST') { fetch(request.url, { method: request.method, headers: request.headers, body: request.body }) .then(response => response.json()) .then(data => sendResponse({ success: true, data })) .catch(error => sendResponse({ success: false, error: error.message }));
return true; // Keep message channel open for async response }});
// Content script usagefunction makeAIRequest(url, options) { return new Promise((resolve, reject) => { chrome.runtime.sendMessage({ type: 'AI_API_REQUEST', url: url, method: options.method || 'POST', headers: options.headers, body: options.body }, (response) => { if (response.success) { resolve(response.data); } else { reject(new Error(response.error)); } }); });}- Server-Side Proxy
// Proxy implementationclass AIProxyClient { constructor(proxyUrl) { this.proxyUrl = proxyUrl; }
async makeRequest(endpoint, data, options = {}) { const proxyRequest = { target: endpoint, method: options.method || 'POST', headers: options.headers || {}, body: data };
const response = await fetch(`${this.proxyUrl}/ai-proxy`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(proxyRequest) });
if (!response.ok) { throw new Error(`Proxy request failed: ${response.statusText}`); }
return await response.json(); }}Issue: API Rate Limiting
Section titled “Issue: API Rate Limiting”Symptoms:
- HTTP 429 (Too Many Requests) responses
- Temporary API access suspension
- Degraded response times
Diagnosis:
// Rate limit detector and handlerclass RateLimitHandler { constructor() { this.requestHistory = []; this.rateLimits = new Map(); }
async detectRateLimit(response, endpoint) { if (response.status === 429) { const retryAfter = response.headers.get('Retry-After'); const resetTime = response.headers.get('X-RateLimit-Reset');
return { isRateLimited: true, retryAfter: retryAfter ? parseInt(retryAfter) : 60, resetTime: resetTime ? new Date(resetTime * 1000) : null, endpoint: endpoint }; }
// Check for approaching rate limits const remaining = response.headers.get('X-RateLimit-Remaining'); if (remaining && parseInt(remaining) < 5) { return { isRateLimited: false, approachingLimit: true, remaining: parseInt(remaining), endpoint: endpoint }; }
return { isRateLimited: false }; }
async handleRateLimit(rateLimitInfo) { if (rateLimitInfo.isRateLimited) { console.log(`Rate limited. Waiting ${rateLimitInfo.retryAfter} seconds`); await this.wait(rateLimitInfo.retryAfter * 1000); } else if (rateLimitInfo.approachingLimit) { // Implement exponential backoff await this.wait(1000 * Math.pow(2, 5 - rateLimitInfo.remaining)); } }
wait(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }}Solutions:
- Exponential Backoff with Jitter
class ExponentialBackoff { constructor(maxRetries = 5, baseDelay = 1000) { this.maxRetries = maxRetries; this.baseDelay = baseDelay; }
async executeWithBackoff(operation, context = {}) { let attempt = 0;
while (attempt < this.maxRetries) { try { return await operation(); } catch (error) { if (this.isRetryableError(error) && attempt < this.maxRetries - 1) { const delay = this.calculateDelay(attempt); console.log(`Attempt ${attempt + 1} failed, retrying in ${delay}ms`); await this.wait(delay); attempt++; } else { throw error; } } } }
calculateDelay(attempt) { // Exponential backoff with jitter const exponentialDelay = this.baseDelay * Math.pow(2, attempt); const jitter = Math.random() * 0.1 * exponentialDelay; return Math.min(exponentialDelay + jitter, 30000); // Max 30 seconds }
isRetryableError(error) { return error.status === 429 || error.status === 502 || error.status === 503 || error.status === 504; }}- Request Queue with Rate Limiting
class RateLimitedQueue { constructor(requestsPerMinute = 60) { this.requestsPerMinute = requestsPerMinute; this.queue = []; this.processing = false; this.requestTimes = []; }
async enqueue(request) { return new Promise((resolve, reject) => { this.queue.push({ request, resolve, reject }); this.processQueue(); }); }
async processQueue() { if (this.processing || this.queue.length === 0) { return; }
this.processing = true;
while (this.queue.length > 0) { // Check if we can make a request if (await this.canMakeRequest()) { const { request, resolve, reject } = this.queue.shift();
try { const result = await request(); this.recordRequest(); resolve(result); } catch (error) { reject(error); } } else { // Wait before checking again await this.wait(1000); } }
this.processing = false; }
async canMakeRequest() { const now = Date.now(); const oneMinuteAgo = now - 60000;
// Remove old request times this.requestTimes = this.requestTimes.filter(time => time > oneMinuteAgo);
return this.requestTimes.length < this.requestsPerMinute; }
recordRequest() { this.requestTimes.push(Date.now()); }}Memory and Performance Issues
Section titled “Memory and Performance Issues”Issue: Memory Leaks in AI Workflows
Section titled “Issue: Memory Leaks in AI Workflows”Symptoms:
- Gradually increasing memory usage
- Browser becoming unresponsive
- “Out of memory” errors
Diagnosis:
// Memory leak detectorclass MemoryLeakDetector { constructor() { this.memorySnapshots = []; this.monitoringInterval = null; }
startMonitoring() { this.monitoringInterval = setInterval(() => { this.takeMemorySnapshot(); }, 5000); // Every 5 seconds }
takeMemorySnapshot() { if (performance.memory) { const snapshot = { timestamp: Date.now(), used: performance.memory.usedJSHeapSize, total: performance.memory.totalJSHeapSize, limit: performance.memory.jsHeapSizeLimit };
this.memorySnapshots.push(snapshot);
// Keep only recent snapshots if (this.memorySnapshots.length > 100) { this.memorySnapshots.shift(); }
this.analyzeMemoryTrend(); } }
analyzeMemoryTrend() { if (this.memorySnapshots.length < 10) return;
const recent = this.memorySnapshots.slice(-10); const trend = this.calculateTrend(recent.map(s => s.used));
if (trend > 1024 * 1024) { // 1MB increase per snapshot console.warn('Potential memory leak detected'); this.triggerMemoryCleanup(); } }
calculateTrend(values) { // Simple linear regression to detect trend const n = values.length; const sumX = n * (n - 1) / 2; const sumY = values.reduce((a, b) => a + b, 0); const sumXY = values.reduce((sum, y, x) => sum + x * y, 0); const sumXX = n * (n - 1) * (2 * n - 1) / 6;
return (n * sumXY - sumX * sumY) / (n * sumXX - sumX * sumX); }}Solutions:
- Automatic Memory Management
class AIMemoryManager { constructor() { this.memoryThreshold = 100 * 1024 * 1024; // 100MB this.cleanupStrategies = [ this.clearConversationHistory.bind(this), this.clearEmbeddingCache.bind(this), this.clearResponseCache.bind(this), this.forceGarbageCollection.bind(this) ]; }
async manageMemory() { const currentUsage = await this.getCurrentMemoryUsage();
if (currentUsage > this.memoryThreshold) { for (const strategy of this.cleanupStrategies) { await strategy();
const newUsage = await this.getCurrentMemoryUsage(); if (newUsage < this.memoryThreshold * 0.8) { break; // Sufficient memory freed } } } }
async clearConversationHistory() { // Keep only recent conversation history if (this.conversationHistory && this.conversationHistory.length > 10) { this.conversationHistory = this.conversationHistory.slice(-10); console.log('Cleared old conversation history'); } }
async clearEmbeddingCache() { // Clear old embeddings const maxAge = 30 * 60 * 1000; // 30 minutes const now = Date.now();
if (this.embeddingCache) { for (const [key, value] of this.embeddingCache.entries()) { if (now - value.timestamp > maxAge) { this.embeddingCache.delete(key); } } } }
async forceGarbageCollection() { // Force garbage collection if available if (window.gc) { window.gc(); console.log('Forced garbage collection'); } }}Issue: Slow AI Response Times
Section titled “Issue: Slow AI Response Times”Symptoms:
- Long delays before receiving AI responses
- Timeouts on AI requests
- Poor user experience
Diagnosis:
// Performance analyzerclass AIPerformanceAnalyzer { constructor() { this.performanceMetrics = []; }
async analyzePerformance(operation) { const startTime = performance.now(); const startMemory = performance.memory?.usedJSHeapSize || 0;
try { const result = await operation();
const endTime = performance.now(); const endMemory = performance.memory?.usedJSHeapSize || 0;
const metrics = { duration: endTime - startTime, memoryDelta: endMemory - startMemory, success: true, timestamp: Date.now() };
this.performanceMetrics.push(metrics); this.analyzeBottlenecks(metrics);
return result; } catch (error) { const endTime = performance.now();
this.performanceMetrics.push({ duration: endTime - startTime, success: false, error: error.message, timestamp: Date.now() });
throw error; } }
analyzeBottlenecks(metrics) { if (metrics.duration > 5000) { console.warn('Slow AI operation detected:', { duration: metrics.duration, suggestions: [ 'Enable streaming responses', 'Reduce input size', 'Use caching', 'Optimize model parameters' ] }); } }}Solutions:
- Response Streaming Implementation
class StreamingOptimizer { async optimizeWithStreaming(request) { if (this.supportsStreaming(request)) { return await this.processWithStreaming(request); } else { return await this.processWithChunking(request); } }
async processWithStreaming(request) { const response = await fetch(request.url, { ...request.options, headers: { ...request.options.headers, 'Accept': 'text/event-stream' } });
const reader = response.body.getReader(); const decoder = new TextDecoder(); let result = '';
try { while (true) { const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value, { stream: true }); result += chunk;
// Process chunk immediately for better UX if (request.onChunk) { await request.onChunk(chunk, result); }
// Yield control to prevent blocking await new Promise(resolve => setTimeout(resolve, 0)); }
return result; } finally { reader.releaseLock(); } }}Security and Privacy Issues
Section titled “Security and Privacy Issues”Issue: API Key Exposure
Section titled “Issue: API Key Exposure”Symptoms:
- API keys visible in browser developer tools
- Security warnings about exposed credentials
- Unauthorized API usage
Solutions:
- Secure API Key Management
class SecureAPIKeyManager { constructor() { this.encryptionKey = null; this.initializeEncryption(); }
async initializeEncryption() { // Generate or retrieve encryption key this.encryptionKey = await this.getOrGenerateKey(); }
async storeAPIKey(service, apiKey) { const encrypted = await this.encrypt(apiKey);
// Store in browser extension storage (more secure than localStorage) if (chrome && chrome.storage) { await chrome.storage.local.set({ [`api_key_${service}`]: encrypted }); } else { // Fallback to sessionStorage (less persistent) sessionStorage.setItem(`api_key_${service}`, encrypted); } }
async getAPIKey(service) { let encrypted;
if (chrome && chrome.storage) { const result = await chrome.storage.local.get([`api_key_${service}`]); encrypted = result[`api_key_${service}`]; } else { encrypted = sessionStorage.getItem(`api_key_${service}`); }
if (encrypted) { return await this.decrypt(encrypted); }
return null; }
async encrypt(data) { const encoder = new TextEncoder(); const dataBuffer = encoder.encode(data);
const encrypted = await crypto.subtle.encrypt( { name: 'AES-GCM', iv: crypto.getRandomValues(new Uint8Array(12)) }, this.encryptionKey, dataBuffer );
return btoa(String.fromCharCode(...new Uint8Array(encrypted))); }
async decrypt(encryptedData) { const dataBuffer = new Uint8Array( atob(encryptedData).split('').map(char => char.charCodeAt(0)) );
const decrypted = await crypto.subtle.decrypt( { name: 'AES-GCM', iv: dataBuffer.slice(0, 12) }, this.encryptionKey, dataBuffer.slice(12) );
return new TextDecoder().decode(decrypted); }}Issue: Content Security Policy Violations
Section titled “Issue: Content Security Policy Violations”Symptoms:
- CSP violation errors in console
- Blocked script execution
- Failed API requests due to CSP
Solutions:
- CSP-Compliant Implementation
class CSPCompliantAI { constructor() { this.cspPolicy = this.detectCSPPolicy(); this.fallbackStrategies = new Map(); }
detectCSPPolicy() { const metaCSP = document.querySelector('meta[http-equiv="Content-Security-Policy"]'); if (metaCSP) { return this.parseCSP(metaCSP.content); } return null; }
async makeCompliantRequest(url, options) { if (this.isAllowedByCSP(url)) { return await fetch(url, options); } else { return await this.useFallbackStrategy(url, options); } }
async useFallbackStrategy(url, options) { // Use postMessage to communicate with parent frame if (window.parent !== window) { return await this.usePostMessage(url, options); }
// Use web worker if allowed if (this.cspPolicy.allowsWorkers) { return await this.useWebWorker(url, options); }
throw new Error('No CSP-compliant method available for this request'); }}Integration and Compatibility Issues
Section titled “Integration and Compatibility Issues”Issue: LangChain Compatibility Problems
Section titled “Issue: LangChain Compatibility Problems”Symptoms:
- Import errors with LangChain modules
- Runtime errors in browser environment
- Missing dependencies
Solutions:
- Browser-Compatible LangChain Setup
// Browser-compatible LangChain initializationclass BrowserLangChain { constructor() { this.isInitialized = false; this.compatibilityLayer = new CompatibilityLayer(); }
async initialize() { try { // Check for browser compatibility await this.checkCompatibility();
// Initialize browser-compatible components await this.initializeComponents();
this.isInitialized = true; } catch (error) { console.error('LangChain initialization failed:', error); await this.initializeFallback(); } }
async checkCompatibility() { const requirements = { fetch: typeof fetch !== 'undefined', crypto: typeof crypto !== 'undefined', textEncoder: typeof TextEncoder !== 'undefined', webStreams: typeof ReadableStream !== 'undefined' };
const missing = Object.entries(requirements) .filter(([key, available]) => !available) .map(([key]) => key);
if (missing.length > 0) { throw new Error(`Missing browser features: ${missing.join(', ')}`); } }
async initializeComponents() { // Initialize only browser-compatible LangChain components this.llm = await this.createBrowserLLM(); this.memory = await this.createBrowserMemory(); this.tools = await this.createBrowserTools(); }
async createBrowserLLM() { // Use fetch-based LLM implementation return new (await import('./browser-llm.js')).BrowserLLM({ apiKey: await this.getSecureAPIKey(), streaming: true, maxRetries: 3 }); }}Diagnostic Tools
Section titled “Diagnostic Tools”Comprehensive Diagnostic Suite
Section titled “Comprehensive Diagnostic Suite”// AI Integration Diagnostic Toolclass AIDiagnosticTool { constructor() { this.diagnostics = new Map(); this.solutions = new Map(); }
async runFullDiagnostic() { const results = { connectivity: await this.testConnectivity(), performance: await this.testPerformance(), memory: await this.testMemory(), security: await this.testSecurity(), compatibility: await this.testCompatibility() };
const issues = this.identifyIssues(results); const recommendations = this.generateRecommendations(issues);
return { results, issues, recommendations, overallHealth: this.calculateOverallHealth(results) }; }
async testConnectivity() { const tests = [ this.testAPIEndpoints(), this.testCORSPolicy(), this.testNetworkLatency(), this.testRateLimits() ];
const results = await Promise.allSettled(tests);
return { apiEndpoints: results[0].status === 'fulfilled' ? results[0].value : results[0].reason, corsPolicy: results[1].status === 'fulfilled' ? results[1].value : results[1].reason, networkLatency: results[2].status === 'fulfilled' ? results[2].value : results[2].reason, rateLimits: results[3].status === 'fulfilled' ? results[3].value : results[3].reason }; }
generateRecommendations(issues) { const recommendations = [];
for (const issue of issues) { switch (issue.type) { case 'cors_error': recommendations.push({ priority: 'high', action: 'Implement browser extension background script for API calls', implementation: 'Use chrome.runtime.sendMessage for cross-origin requests' }); break;
case 'memory_leak': recommendations.push({ priority: 'high', action: 'Implement automatic memory management', implementation: 'Clear caches periodically and limit conversation history' }); break;
case 'slow_performance': recommendations.push({ priority: 'medium', action: 'Enable response streaming and caching', implementation: 'Use streaming APIs and implement intelligent caching' }); break;
case 'rate_limiting': recommendations.push({ priority: 'medium', action: 'Implement exponential backoff and request queuing', implementation: 'Use rate-limited queue with exponential backoff strategy' }); break; } }
return recommendations; }}This troubleshooting guide provides comprehensive solutions for the most common AI integration issues in browser environments, helping developers quickly identify and resolve problems to maintain optimal AI workflow performance.