UNPKG

azureai-optimizer

Version:

AI-Powered Azure Infrastructure Optimization via Model Context Protocol

416 lines (407 loc) 17.5 kB
/** * AI Analyzer * Multi-LLM analysis engine for Azure optimization insights */ import OpenAI from 'openai'; import Anthropic from '@anthropic-ai/sdk'; import { Logger } from '../utils/logger.js'; export class AIAnalyzer { openai; anthropic; openrouter; // OpenRouter uses OpenAI-compatible API logger; providers; constructor(providers = {}) { this.providers = providers; this.logger = new Logger('AIAnalyzer'); this.initializeProviders(); } initializeProviders() { // Initialize OpenRouter client (preferred) if (this.providers.openrouter?.apiKey) { this.openrouter = new OpenAI({ apiKey: this.providers.openrouter.apiKey, baseURL: this.providers.openrouter.baseUrl || 'https://openrouter.ai/api/v1' }); this.logger.info('✅ OpenRouter client initialized'); } // Initialize OpenAI client (fallback) if (this.providers.openai?.apiKey) { this.openai = new OpenAI({ apiKey: this.providers.openai.apiKey }); this.logger.info('✅ OpenAI client initialized'); } // Initialize Anthropic client (fallback) if (this.providers.anthropic?.apiKey) { this.anthropic = new Anthropic({ apiKey: this.providers.anthropic.apiKey }); this.logger.info('✅ Anthropic client initialized'); } // Log available providers const availableProviders = []; if (this.openrouter) availableProviders.push('OpenRouter'); if (this.openai) availableProviders.push('OpenAI'); if (this.anthropic) availableProviders.push('Anthropic'); this.logger.info(`🤖 Available AI providers: ${availableProviders.join(', ')}`); } async analyzeCostData(data) { try { this.logger.info('🧠 Starting AI-powered cost analysis...'); // Use OpenRouter with GPT-4.1 for cost analysis (preferred) let costInsights; if (this.openrouter) { costInsights = await this.analyzeCostWithOpenRouter(data); } else if (this.openai) { // Fallback to direct OpenAI costInsights = await this.analyzeCostWithOpenAI(data); } else { throw new Error('No AI provider available for cost analysis'); } // Combine insights const insights = { top_optimization_opportunities: costInsights.opportunities, cost_drivers: costInsights.drivers, recommendations_summary: costInsights.summary }; this.logger.info(`✅ AI analysis completed with ${insights.top_optimization_opportunities.length} opportunities`); return insights; } catch (error) { this.logger.error('❌ AI analysis failed:', error); // Fallback to rule-based analysis if AI fails this.logger.warn('🔄 Falling back to rule-based analysis...'); return this.fallbackAnalysis(data); } } async analyzeCostWithOpenRouter(data) { if (!this.openrouter) { throw new Error('OpenRouter client not available'); } const prompt = this.buildCostAnalysisPrompt(data); const model = this.providers.openrouter?.models?.cost_analysis || 'openai/gpt-4.1-preview'; try { this.logger.info(`🤖 Using OpenRouter model: ${model} for cost analysis`); const response = await this.openrouter.chat.completions.create({ model: model, messages: [ { role: 'system', content: `You are an Azure cost optimization expert with deep knowledge of Azure pricing models, reserved instances, and cost management best practices. Analyze the provided cost data and generate actionable recommendations in JSON format.` }, { role: 'user', content: prompt } ], temperature: 0.3, max_tokens: 2000, response_format: { type: 'json_object' } }); const content = response.choices[0]?.message?.content; if (!content) { throw new Error('No response from OpenRouter'); } return JSON.parse(content); } catch (error) { this.logger.error('OpenRouter API error:', error); throw error; } } async analyzeCostWithOpenAI(data) { if (!this.openai) { throw new Error('OpenAI client not available'); } const prompt = this.buildCostAnalysisPrompt(data); try { const response = await this.openai.chat.completions.create({ model: this.providers.openai?.model || 'gpt-4-turbo-preview', messages: [ { role: 'system', content: `You are an Azure cost optimization expert with deep knowledge of Azure pricing models, reserved instances, and cost management best practices. Analyze the provided cost data and generate actionable recommendations in JSON format.` }, { role: 'user', content: prompt } ], temperature: 0.3, max_tokens: 2000, response_format: { type: 'json_object' } }); const content = response.choices[0]?.message?.content; if (!content) { throw new Error('No response from OpenAI'); } return JSON.parse(content); } catch (error) { this.logger.error('OpenAI API error:', error); throw error; } } buildCostAnalysisPrompt(data) { const { costData, advisorRecommendations, subscriptionId, analysisContext } = data; return ` Analyze the following Azure cost data and provide optimization recommendations: **Subscription:** ${subscriptionId} **Analysis Period:** ${analysisContext.daysBack} days **Total Cost:** $${costData.summary.total_cost.toFixed(2)} ${costData.summary.currency} **Cost Trend:** ${costData.trends.cost_trend} **Top Services by Cost:** ${costData.breakdown.by_service.slice(0, 5).map((service) => `- ${service.service}: $${service.cost.toFixed(2)} (${service.percentage.toFixed(1)}%)`).join('\n')} **Cost Anomalies:** ${costData.trends.anomalies.length > 0 ? costData.trends.anomalies.map((anomaly) => `- ${anomaly.date}: $${anomaly.cost.toFixed(2)} (${anomaly.deviation.toFixed(1)}% deviation)`).join('\n') : 'No significant anomalies detected'} **Azure Advisor Recommendations:** ${advisorRecommendations.length > 0 ? advisorRecommendations.slice(0, 3).map((rec) => `- ${rec.title}: ${rec.description} (Potential savings: $${rec.potential_savings || 0})`).join('\n') : 'No Advisor recommendations available'} Please provide a JSON response with the following structure: { "opportunities": [ { "title": "Optimization opportunity title", "description": "Detailed description of the opportunity", "potential_savings": 1000, "savings_percentage": 15, "complexity": "Low|Medium|High", "risk_level": "Low|Medium|High", "implementation_steps": ["Step 1", "Step 2", "Step 3"] } ], "drivers": ["Primary cost driver 1", "Primary cost driver 2"], "summary": "Executive summary of findings and recommendations" } Focus on: 1. Top 3-5 optimization opportunities with highest impact 2. Specific, actionable implementation steps 3. Realistic savings estimates based on the data 4. Risk assessment for each recommendation 5. Implementation complexity (time/effort required) `; } async analyzeSecurityCompliance(data) { try { this.logger.info('🔒 Starting AI-powered security analysis...'); // Use OpenRouter with Claude Sonnet 4 for security analysis (preferred) if (this.openrouter) { return await this.analyzeSecurityWithOpenRouter(data); } else if (this.anthropic) { // Fallback to direct Anthropic return await this.analyzeSecurityWithAnthropic(data); } else if (this.openai) { // Last resort fallback to OpenAI return await this.analyzeSecurityWithOpenAI(data); } else { throw new Error('No AI providers available for security analysis'); } } catch (error) { this.logger.error('❌ Security analysis failed:', error); return this.fallbackSecurityAnalysis(data); } } async analyzeSecurityWithOpenRouter(data) { if (!this.openrouter) { throw new Error('OpenRouter client not available'); } const prompt = this.buildSecurityAnalysisPrompt(data); const model = this.providers.openrouter?.models?.security_analysis || 'anthropic/claude-3.5-sonnet:beta'; try { this.logger.info(`🤖 Using OpenRouter model: ${model} for security analysis`); const response = await this.openrouter.chat.completions.create({ model: model, messages: [ { role: 'system', content: 'You are an Azure security expert specializing in compliance frameworks and security best practices. Provide detailed security analysis in JSON format.' }, { role: 'user', content: prompt } ], temperature: 0.3, max_tokens: 2000, response_format: { type: 'json_object' } }); const content = response.choices[0]?.message?.content; if (!content) { throw new Error('No response from OpenRouter'); } return JSON.parse(content); } catch (error) { this.logger.error('OpenRouter security analysis error:', error); throw error; } } async analyzeSecurityWithAnthropic(data) { if (!this.anthropic) { throw new Error('Anthropic client not available'); } const prompt = this.buildSecurityAnalysisPrompt(data); try { const response = await this.anthropic.messages.create({ model: this.providers.anthropic?.model || 'claude-3-5-sonnet-20241022', max_tokens: 2000, temperature: 0.3, messages: [ { role: 'user', content: prompt } ] }); const content = response.content[0]; if (content.type === 'text') { return JSON.parse(content.text); } throw new Error('Unexpected response format from Anthropic'); } catch (error) { this.logger.error('Anthropic API error:', error); throw error; } } async analyzeSecurityWithOpenAI(data) { if (!this.openai) { throw new Error('OpenAI client not available'); } const prompt = this.buildSecurityAnalysisPrompt(data); try { const response = await this.openai.chat.completions.create({ model: this.providers.openai?.model || 'gpt-4-turbo-preview', messages: [ { role: 'system', content: 'You are an Azure security expert specializing in compliance frameworks and security best practices.' }, { role: 'user', content: prompt } ], temperature: 0.3, max_tokens: 2000, response_format: { type: 'json_object' } }); const content = response.choices[0]?.message?.content; if (!content) { throw new Error('No response from OpenAI'); } return JSON.parse(content); } catch (error) { this.logger.error('OpenAI API error:', error); throw error; } } buildSecurityAnalysisPrompt(data) { return ` Analyze the following Azure security configuration and provide compliance assessment: **Subscription:** ${data.subscriptionId} **Compliance Framework:** ${data.framework} **Resources Analyzed:** ${data.resourceCount} **Security Findings:** ${data.findings.map((finding) => `- ${finding.title}: ${finding.severity}`).join('\n')} Provide JSON response with compliance assessment and remediation steps. `; } fallbackAnalysis(data) { this.logger.info('🔄 Using rule-based fallback analysis...'); const opportunities = []; const drivers = []; // Rule-based analysis of top cost services const topServices = data.costData.breakdown.by_service.slice(0, 3); topServices.forEach((service) => { if (service.service.includes('Virtual Machines') && service.percentage > 30) { opportunities.push({ title: 'Virtual Machine Right-Sizing', description: `Virtual Machines account for ${service.percentage.toFixed(1)}% of costs. Consider right-sizing underutilized VMs.`, potential_savings: service.cost * 0.25, savings_percentage: 25, complexity: 'Medium', risk_level: 'Low', implementation_steps: [ 'Analyze VM utilization metrics', 'Identify underutilized VMs', 'Test smaller VM sizes in development', 'Implement changes during maintenance windows' ] }); drivers.push('High Virtual Machine costs'); } if (service.service.includes('Storage') && service.percentage > 20) { opportunities.push({ title: 'Storage Tier Optimization', description: `Storage costs are ${service.percentage.toFixed(1)}% of total. Optimize storage tiers based on access patterns.`, potential_savings: service.cost * 0.15, savings_percentage: 15, complexity: 'Low', risk_level: 'Low', implementation_steps: [ 'Analyze storage access patterns', 'Move infrequently accessed data to cool/archive tiers', 'Implement lifecycle management policies', 'Monitor access patterns regularly' ] }); drivers.push('Suboptimal storage tier usage'); } }); // Check for cost anomalies if (data.costData.trends.anomalies.length > 0) { opportunities.push({ title: 'Cost Anomaly Investigation', description: `${data.costData.trends.anomalies.length} cost anomalies detected. Investigate unusual spending patterns.`, potential_savings: data.costData.trends.anomalies.reduce((sum, anomaly) => sum + Math.max(0, anomaly.cost - anomaly.expected_cost), 0), savings_percentage: 10, complexity: 'High', risk_level: 'Medium', implementation_steps: [ 'Review anomalous spending dates', 'Identify root causes of cost spikes', 'Implement monitoring and alerting', 'Establish cost governance policies' ] }); drivers.push('Unexpected cost spikes'); } return { top_optimization_opportunities: opportunities, cost_drivers: drivers, recommendations_summary: `Based on rule-based analysis, identified ${opportunities.length} optimization opportunities with potential savings of $${opportunities.reduce((sum, opp) => sum + opp.potential_savings, 0).toFixed(2)}.` }; } fallbackSecurityAnalysis(_data) { return { compliance_score: 75, findings: [ { title: 'Security assessment requires AI provider configuration', severity: 'Info', description: 'Configure OpenAI or Anthropic API keys for detailed security analysis' } ], recommendations: [ 'Configure AI providers for enhanced security analysis', 'Review security center recommendations manually' ] }; } } //# sourceMappingURL=analyzer.js.map