from fastapi import FastAPI, HTTPException, UploadFile, File from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import FileResponse, JSONResponse from pydantic import BaseModel from typing import List, Optional import os from dotenv import load_dotenv import logging from emotion_detector import EmotionDetector from ai_insights import AIInsightGenerator from art_generator import MoodArtGenerator from visualizations import VisualizationGenerator from pdf_generator import PDFReportGenerator # Load environment variables load_dotenv() # Configure logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) # Initialize FastAPI app app = FastAPI( title="AI Mirror API", description="The Data-Driven Mood & Personality Visualizer", version="1.0.0" ) # Configure CORS origins = [ "https://aimirror15.netlify.app", # your frontend "http://localhost:5173", # for local testing "https://huggingface.co", # Hugging Face itself ] app.add_middleware( CORSMiddleware, allow_origins=origins, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Initialize components emotion_detector = EmotionDetector() ai_insights = AIInsightGenerator() art_generator = MoodArtGenerator() viz_generator = VisualizationGenerator() pdf_generator = PDFReportGenerator() # Pydantic models class TextInput(BaseModel): text: str user_name: Optional[str] = "User" class MultipleTexts(BaseModel): texts: List[str] user_name: Optional[str] = "User" class EmotionResponse(BaseModel): emotions: dict dominant_emotion: str sentiment_score: float sentiment_label: str @app.get("/") async def root(): """Root endpoint with API information""" return { "message": "Welcome to AI Mirror API", "tagline": "Your words reflect more than you think", "version": "1.0.0", "developer": { "name": "Sayed Mohd Zayeem Khateeb", "email": "zayeem.s.khateeb@gmail.com", "linkedin": "https://www.linkedin.com/in/zayeemkhateeb" } } @app.get("/health") async def health_check(): """Health check endpoint""" return {"status": "healthy", "service": "AI Mirror API"} @app.post("/api/analyze-emotion", response_model=EmotionResponse) async def analyze_emotion(input_data: TextInput): """ Analyze emotion from a single text input """ try: logger.info(f"Analyzing emotion for text: {input_data.text[:50]}...") result = emotion_detector.detect_emotion(input_data.text) return result except Exception as e: logger.error(f"Error analyzing emotion: {str(e)}") raise HTTPException(status_code=500, detail=str(e)) @app.post("/api/analyze-batch") async def analyze_batch(input_data: MultipleTexts): """ Analyze emotions from multiple text inputs """ try: logger.info(f"Analyzing batch of {len(input_data.texts)} texts") results = [] for text in input_data.texts: result = emotion_detector.detect_emotion(text) results.append(result) # Aggregate results aggregated = emotion_detector.aggregate_emotions(results) return aggregated except Exception as e: logger.error(f"Error analyzing batch: {str(e)}") raise HTTPException(status_code=500, detail=str(e)) @app.post("/api/generate-insights") async def generate_insights(input_data: TextInput): """ Generate AI-powered insights from text """ try: logger.info("Generating AI insights...") # First detect emotions emotion_result = emotion_detector.detect_emotion(input_data.text) # Generate insights using LLM insights = await ai_insights.generate_insights( text=input_data.text, emotions=emotion_result['emotions'], user_name=input_data.user_name ) return { "emotions": emotion_result, "insights": insights } except Exception as e: logger.error(f"Error generating insights: {str(e)}") raise HTTPException(status_code=500, detail=str(e)) @app.post("/api/generate-art") async def generate_art(input_data: TextInput): """ Generate AI artwork based on detected emotions """ try: logger.info("Generating mood art...") # Detect emotions emotion_result = emotion_detector.detect_emotion(input_data.text) # Generate art art_result = await art_generator.generate_mood_art( emotions=emotion_result['emotions'], dominant_emotion=emotion_result['dominant_emotion'] ) return { "emotions": emotion_result, "artwork": art_result } except Exception as e: logger.error(f"Error generating art: {str(e)}") raise HTTPException(status_code=500, detail=str(e)) @app.post("/api/visualize") async def create_visualizations(input_data: MultipleTexts): """ Create visualization charts from multiple texts """ try: logger.info("Creating visualizations...") # Analyze all texts results = [] for text in input_data.texts: result = emotion_detector.detect_emotion(text) results.append(result) # Generate visualizations viz_data = viz_generator.create_visualizations(results) return viz_data except Exception as e: logger.error(f"Error creating visualizations: {str(e)}") raise HTTPException(status_code=500, detail=str(e)) @app.post("/api/generate-report") async def generate_report(input_data: MultipleTexts): """ Generate a comprehensive PDF report """ try: logger.info("Generating PDF report...") # Analyze all texts results = [] for text in input_data.texts: result = emotion_detector.detect_emotion(text) results.append(result) # Aggregate emotions aggregated = emotion_detector.aggregate_emotions(results) # Generate insights combined_text = " ".join(input_data.texts) insights = await ai_insights.generate_insights( text=combined_text, emotions=aggregated['emotions'], user_name=input_data.user_name ) # Create visualizations viz_data = viz_generator.create_visualizations(results) # Generate PDF pdf_path = pdf_generator.generate_report( user_name=input_data.user_name, emotions=aggregated, insights=insights, visualizations=viz_data ) return FileResponse( pdf_path, media_type="application/pdf", filename=f"ai_mirror_report_{input_data.user_name}.pdf" ) except Exception as e: logger.error(f"Error generating report: {str(e)}") raise HTTPException(status_code=500, detail=str(e)) @app.post("/api/full-analysis") async def full_analysis(input_data: MultipleTexts): """ Perform complete analysis including emotions, insights, art, and visualizations """ try: logger.info("Performing full analysis...") # Analyze all texts results = [] for text in input_data.texts: result = emotion_detector.detect_emotion(text) results.append(result) # Aggregate emotions aggregated = emotion_detector.aggregate_emotions(results) # Generate insights combined_text = " ".join(input_data.texts) insights = await ai_insights.generate_insights( text=combined_text, emotions=aggregated['emotions'], user_name=input_data.user_name ) # Generate art art_result = await art_generator.generate_mood_art( emotions=aggregated['emotions'], dominant_emotion=aggregated['dominant_emotion'] ) # Create visualizations viz_data = viz_generator.create_visualizations(results) return { "emotions": aggregated, "insights": insights, "artwork": art_result, "visualizations": viz_data, "text_count": len(input_data.texts) } except Exception as e: logger.error(f"Error in full analysis: {str(e)}") raise HTTPException(status_code=500, detail=str(e)) if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000)