""" AI Service Manager - Manages multiple AI services with OpenAI as primary. """ import logging from typing import Dict, List, Optional, Any from config import settings from services.openai_service import OpenAIService # Optional import for Hugging Face service try: from services.huggingface_service import HuggingFaceService HUGGINGFACE_AVAILABLE = True except ImportError: HUGGINGFACE_AVAILABLE = False HuggingFaceService = None logger = logging.getLogger(__name__) class AIServiceManager: """Manages multiple AI services with OpenAI as the primary service.""" def __init__(self): self.openai_service = None self.huggingface_service = None self.primary_service = settings.primary_ai_service.lower() # Initialize OpenAI service (primary) if settings.openai_api_key: try: self.openai_service = OpenAIService() logger.info("OpenAI service initialized successfully") except Exception as e: logger.error(f"Failed to initialize OpenAI service: {e}") else: logger.warning("OpenAI API key not configured") # Initialize Hugging Face service (optional) if HUGGINGFACE_AVAILABLE and settings.hf_api_token: try: self.huggingface_service = HuggingFaceService() logger.info("Hugging Face service initialized successfully") except Exception as e: logger.error(f"Failed to initialize Hugging Face service: {e}") elif not HUGGINGFACE_AVAILABLE: logger.warning("Hugging Face service not available - dependencies not installed") logger.info(f"AI Service Manager initialized with primary service: {self.primary_service}") async def generate_content( self, prompt: str, context: str = "", temperature: float = 0.7, max_tokens: int = 2000, service: str = "auto" ) -> str: """Generate content using the appropriate AI service.""" try: # Determine which service to use if service == "auto": service = self.primary_service elif service == "openai" and self.openai_service: service = "openai" elif service == "huggingface" and self.huggingface_service: service = "huggingface" else: # Fallback to available service if self.openai_service: service = "openai" elif self.huggingface_service: service = "huggingface" else: raise Exception("No AI service available") # Generate content using selected service if service == "openai" and self.openai_service: return await self.openai_service.generate_content( prompt=prompt, context=context, temperature=temperature, max_tokens=max_tokens ) elif service == "huggingface" and self.huggingface_service: return await self.huggingface_service.generate_text( prompt=prompt, max_length=max_tokens, temperature=temperature ) else: raise Exception(f"Service '{service}' not available") except Exception as e: logger.error(f"Content generation error: {e}") raise Exception(f"Failed to generate content: {str(e)}") async def generate_text( self, prompt: str, max_tokens: int = 2000, temperature: float = 0.7, service: str = "auto" ) -> Dict[str, str]: """Generate text using the appropriate AI service. Alias for generate_content.""" try: content = await self.generate_content( prompt=prompt, temperature=temperature, max_tokens=max_tokens, service=service ) return {"text": content} except Exception as e: logger.error(f"Text generation error: {e}") return {"text": "I apologize, but I'm having trouble generating a response right now. Please try again."} async def create_embedding( self, text: str, service: str = "auto" ) -> List[float]: """Create embedding using the appropriate AI service.""" try: # Determine which service to use if service == "auto": # Prefer OpenAI for embeddings if self.openai_service: service = "openai" elif self.huggingface_service: service = "huggingface" else: raise Exception("No AI service available") # Create embedding using selected service if service == "openai" and self.openai_service: return await self.openai_service.create_embedding(text) elif service == "huggingface" and self.huggingface_service: return await self.huggingface_service.create_embedding(text) else: raise Exception(f"Service '{service}' not available") except Exception as e: logger.error(f"Embedding creation error: {e}") raise Exception(f"Failed to create embedding: {str(e)}") async def analyze_content_structure( self, content: str, service: str = "auto" ) -> dict: """Analyze content structure using the appropriate AI service.""" try: # OpenAI has better structure analysis, prefer it if service == "auto" and self.openai_service: service = "openai" elif service == "auto" and self.huggingface_service: service = "huggingface" if service == "openai" and self.openai_service: return await self.openai_service.analyze_content_structure(content) elif service == "huggingface" and self.huggingface_service: # Basic analysis for Hugging Face return { "key_points": [], "topics": [], "complexity_level": "medium", "word_count": len(content.split()), "summary": "Analysis via Hugging Face" } else: raise Exception(f"Service '{service}' not available") except Exception as e: logger.error(f"Content analysis error: {e}") return { "key_points": [], "topics": [], "complexity_level": "medium", "word_count": len(content.split()), "summary": "Analysis failed" } def get_service_status(self) -> Dict[str, Any]: """Get status of all AI services.""" return { "primary_service": self.primary_service, "openai": { "available": self.openai_service is not None, "configured": bool(settings.openai_api_key), "model": settings.openai_model if self.openai_service else None }, "huggingface": { "available": self.huggingface_service is not None, "configured": bool(settings.hf_api_token or settings.hf_model_name), "model": settings.hf_model_name if self.huggingface_service else None, "dependencies_available": HUGGINGFACE_AVAILABLE } } def get_available_services(self) -> List[str]: """Get list of available AI services.""" services = [] if self.openai_service: services.append("openai") if self.huggingface_service: services.append("huggingface") return services # Global instance ai_service_manager = AIServiceManager()