Fernandosr85's picture
Update app.py
812895b verified
# ============================================================================
# 📦 INCLUSIVEEDU - FULL VERSION WITH GRADIO + INTEGRATED API
# Compatible with Hugging Face Spaces + External API Access
# ============================================================================
import os
import re
import time
import random
from datetime import datetime
from typing import List, Optional, Dict, Any
from dataclasses import dataclass
from pydantic import BaseModel
# FastAPI imports
try:
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
FASTAPI_AVAILABLE = True
except ImportError:
print("⚠️ FastAPI not available - API mode disabled")
FASTAPI_AVAILABLE = False
# Gradio imports
try:
import gradio as gr
GRADIO_AVAILABLE = True
except ImportError:
print("⚠️ Gradio not available - Interface mode disabled")
GRADIO_AVAILABLE = False
# PyTorch imports (optional)
try:
import torch
TORCH_AVAILABLE = True
except ImportError:
print("⚠️ PyTorch not available - using CPU simulation")
TORCH_AVAILABLE = False
# ============================================================================
# 1. DATA MODELS
# ============================================================================
@dataclass
class ProfileInfo:
"""Profile information structure"""
name: str
description: str
characteristics: List[str]
best_for: List[str]
# Pydantic models for API
if FASTAPI_AVAILABLE:
class ContentRequest(BaseModel):
content: str
profile: str = "visual_structure"
interests: List[str] = []
complexity: str = "intermediate"
format: str = "html"
class ContentResponse(BaseModel):
adapted_content: str
gamification: Dict[str, Any]
processing_time: float
profile_used: str
interests: List[str]
complexity: str
success: bool
format: str
timestamp: str
raw_html: Optional[str] = None
class HealthResponse(BaseModel):
status: str
ai_mode: str
profiles_available: int
timestamp: str
version: str
# ============================================================================
# 2. AI CONFIGURATION
# ============================================================================
class AIConfig:
"""AI configuration and model management"""
def __init__(self, safe_mode=True):
self.simulation_mode = True # Always use simulation for safety
self.safe_mode = safe_mode
self.gemma3_model = None
self.gemma3_tokenizer = None
print("🎭 AI Config initialized in simulation mode")
def generate_with_gemma3(self, prompt, max_length=400):
"""Generate content using simulation"""
# Simulate AI processing time
time.sleep(random.uniform(0.1, 0.3))
# Generate realistic adaptive content based on prompt
if "visual structure" in prompt.lower():
return self._generate_visual_content(prompt)
elif "hyperfocus" in prompt.lower() or "technical" in prompt.lower():
return self._generate_technical_content(prompt)
elif "sensory" in prompt.lower() or "calm" in prompt.lower():
return self._generate_sensory_content(prompt)
elif "interests" in prompt.lower() or "gamif" in prompt.lower():
return self._generate_interest_content(prompt)
else:
return self._generate_default_content(prompt)
def _generate_visual_content(self, prompt):
return """
## 📚 Structured Learning Overview
**Key Concepts** organized for clarity:
### 🎯 Main Topic
Clear presentation of core information with visual hierarchy and organized structure.
### 📊 Important Details
- **Primary points** highlighted for easy scanning
- **Secondary information** properly categorized
- **Visual elements** integrated for better comprehension
### ✅ Summary Points
Essential takeaways presented in an accessible, scannable format with consistent organization.
"""
def _generate_technical_content(self, prompt):
return """
## 🔬 Technical Deep Dive
**Comprehensive Analysis** with detailed specifications:
### 🔧 Technical Specifications
Advanced implementation details with precise terminology and comprehensive coverage of all relevant aspects.
### 📈 Performance Metrics
- **Efficiency ratings**: 94.7% optimization achieved
- **Processing speed**: 2.3ms average response time
- **Accuracy measures**: 99.2% precision in target scenarios
- **Resource utilization**: Optimal memory allocation patterns
### 🎛️ Advanced Configuration
Detailed parameter settings and fine-tuning options for specialized use cases and expert-level customization.
"""
def _generate_sensory_content(self, prompt):
return """
## 🌸 Gentle Learning Space
**Comfortable Environment** designed for ease:
### 🕊️ Peaceful Introduction
A calm and welcoming approach to the topic, presented at a comfortable pace.
### 💫 Gentle Progression
Learning unfolds naturally:
• Soft transitions between concepts
• Comfortable information density
• Regular pause points for reflection
### 🌱 Supportive Summary
Key insights presented gently, with encouragement and positive reinforcement for continued learning.
"""
def _generate_interest_content(self, prompt):
return """
## 🎮 Interactive Learning Adventure
**Engaging Experience** tailored to your interests:
### 🏆 Achievement Unlocked
You've started an exciting learning journey! Connect this topic to your favorite interests for maximum engagement.
### 🎯 Challenge Mode
- **Discovery Quest**: Explore core concepts
- **Knowledge Builder**: Stack new information
- **Mastery Challenge**: Apply what you've learned
- **Bonus Round**: Find real-world connections
### ⭐ Power-Up Summary
Level up your understanding with these key insights, designed to fuel your curiosity and passion for learning!
"""
def _generate_default_content(self, prompt):
return """
## 📖 Adaptive Learning Content
**Personalized Approach** for your learning style:
### 🎓 Core Concepts
Essential information presented clearly and effectively for optimal understanding.
### 🔍 Key Details
Important points highlighted with appropriate depth and clarity for your learning needs.
### 📝 Learning Summary
Comprehensive overview designed to reinforce understanding and support continued learning progress.
"""
# ============================================================================
# 3. PROFILE SYSTEM
# ============================================================================
class NeuroProfileSystem:
"""Neurodiverse learning profile system"""
def __init__(self):
self.profiles = {
"visual_structure": {
"name": "🎯 Visual Structure",
"description": "Clear organization, visual hierarchy, and structured elements",
"colors": ["#2E86AB", "#A23B72", "#F18F01", "#C73E1D"],
"characteristics": [
"Clear hierarchical organization with consistent structure",
"Strategic use of visual elements and color coding",
"Predictable navigation patterns and layout design",
"Visual learning aids and interactive elements"
],
"best_for": [
"Visual learners who need structure",
"People who benefit from clear organization",
"Those who prefer predictable layouts"
]
},
"hyperfocus_directed": {
"name": "🔬 Directed Hyperfocus",
"description": "Deep technical focus, detailed information, and comprehensive analysis",
"colors": ["#1B4332", "#2D6A4F", "#40916C", "#52B788"],
"characteristics": [
"Detailed technical content with comprehensive data",
"In-depth analysis and specialized terminology",
"Extended exploration opportunities and resources",
"Advanced tools and expert-level information"
],
"best_for": [
"Deep technical learning",
"Specialized interest areas",
"Comprehensive analysis needs"
]
},
"sensory_adaptation": {
"name": "🌸 Sensory Adaptation",
"description": "Calm environment, sensory awareness, and accessible design",
"colors": ["#F7F3E9", "#E8DDBF", "#D4C5A9", "#C4A77D"],
"characteristics": [
"Gentle presentation with calming visual design",
"Reduced sensory load and minimal distractions",
"Comfortable pacing with built-in break suggestions",
"Accessibility features and customization options"
],
"best_for": [
"Sensory-sensitive learners",
"Those needing calm environments",
"People requiring accessibility features"
]
},
"special_interests": {
"name": "🎮 Special Interests",
"description": "Interest-based connections, gamification, and motivational design",
"colors": ["#FF6B6B", "#4ECDC4", "#45B7D1", "#96CEB4"],
"characteristics": [
"Gamification elements with achievement systems",
"Personal interest integration and connections",
"Motivational design with clear goal progression",
"Community features and collaborative opportunities"
],
"best_for": [
"Interest-driven learning",
"Motivation through gamification",
"Achievement-focused students"
]
}
}
def get_profile(self, profile_key):
return self.profiles.get(profile_key, self.profiles["visual_structure"])
def get_profile_names(self):
return [(profile["name"], key) for key, profile in self.profiles.items()]
def get_all_profiles_info(self):
"""Get detailed info for all profiles"""
profiles_info = {}
for key, profile in self.profiles.items():
profiles_info[key] = ProfileInfo(
name=profile["name"],
description=profile["description"],
characteristics=profile["characteristics"],
best_for=profile.get("best_for", [])
)
return profiles_info
# ============================================================================
# 4. CONTENT ADAPTATION PIPELINE
# ============================================================================
class ContentAdaptationPipeline:
"""Main content adaptation pipeline"""
def __init__(self, ai_config):
self.ai_config = ai_config
self.profile_system = NeuroProfileSystem()
self.adaptation_count = 0
self.session_start = datetime.now()
def adapt_content(self, content, profile_key, interests, complexity="intermediate"):
"""Main content adaptation function"""
start_time = time.time()
try:
# Validate inputs
if not content or not content.strip():
raise ValueError("Content cannot be empty")
# Get profile information
profile = self.profile_system.get_profile(profile_key)
# Create adaptation prompt
prompt = self._create_adaptation_prompt(content, profile_key, interests, complexity)
# Generate adapted content
adapted_text = self.ai_config.generate_with_gemma3(prompt, max_length=400)
# Create enhanced HTML output
html_content = self._create_enhanced_html(adapted_text, profile, interests, complexity)
# Generate gamification elements
gamification = self._create_gamification_system(interests, profile_key)
# Calculate metrics
processing_time = time.time() - start_time
self.adaptation_count += 1
return {
"adapted_content": html_content,
"gamification": gamification,
"processing_time": processing_time,
"profile_used": profile_key,
"interests": interests,
"complexity": complexity,
"gemma3_used": not self.ai_config.simulation_mode,
"adaptation_count": self.adaptation_count,
"success": True,
"timestamp": datetime.now().isoformat()
}
except Exception as e:
print(f"❌ Adaptation error: {e}")
return self._create_fallback_result(content, profile_key, str(e))
def _create_adaptation_prompt(self, content, profile_key, interests, complexity):
"""Create targeted adaptation prompt based on profile"""
interest_text = ", ".join(interests) if interests else "general learning"
prompts = {
"visual_structure": f"""
Adapt this educational content for VISUAL STRUCTURE learning:
- Use clear headings and organization
- Add visual elements and structured layout
- Create scannable, hierarchical content
- Include visual learning aids
Content: {content}
Interests: {interest_text}
Complexity: {complexity}
Visual structure adaptation:
""",
"hyperfocus_directed": f"""
Adapt this educational content for DIRECTED HYPERFOCUS:
- Add technical details and specifications
- Include comprehensive analysis
- Provide in-depth information
- Use specialized terminology appropriately
Content: {content}
Interests: {interest_text}
Complexity: {complexity}
Technical deep-dive adaptation:
""",
"sensory_adaptation": f"""
Adapt this educational content for SENSORY ADAPTATION:
- Use gentle, calming language
- Break into manageable sections
- Reduce cognitive load
- Create comfortable learning environment
Content: {content}
Interests: {interest_text}
Complexity: {complexity}
Sensory-friendly adaptation:
""",
"special_interests": f"""
Adapt this educational content for SPECIAL INTERESTS:
- Connect to personal interests: {interest_text}
- Add gamification elements
- Create motivational connections
- Include achievement opportunities
Content: {content}
Interests: {interest_text}
Complexity: {complexity}
Interest-based gamified adaptation:
"""
}
return prompts.get(profile_key, f"Adapt this content for {profile_key}: {content}")
def _create_enhanced_html(self, content, profile, interests, complexity):
"""Create enhanced HTML with full styling and interactivity"""
colors = profile["colors"]
profile_name = profile["name"]
# Complexity indicators
complexity_colors = {
"beginner": "#28a745",
"intermediate": "#ffc107",
"advanced": "#dc3545"
}
complexity_color = complexity_colors.get(complexity, "#6c757d")
html = f"""
<div style="font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, {colors[0]}08, {colors[1]}08);
border-radius: 20px; padding: 30px; margin: 15px 0;
box-shadow: 0 8px 32px rgba(0,0,0,0.1); border: 1px solid {colors[0]}20;">
<!-- Header Section -->
<div style="text-align: center; margin-bottom: 25px; padding-bottom: 20px;
border-bottom: 2px solid {colors[1]}40;">
<div style="display: inline-block; background: {colors[0]}; color: white;
padding: 8px 20px; border-radius: 25px; font-size: 0.9em;
margin-bottom: 10px; font-weight: bold;">
{profile_name}
</div>
<h2 style="color: {colors[0]}; margin: 10px 0 5px 0; font-size: 1.8em;">
Adaptive Learning Content
</h2>
<p style="color: {colors[1]}; margin: 0; font-size: 1.1em;">
{profile['description']}
</p>
</div>
<!-- Content Section -->
<div style="background: white; padding: 25px; border-radius: 15px;
box-shadow: 0 4px 16px rgba(0,0,0,0.08); margin: 20px 0;">
{self._format_content_advanced(content)}
</div>
<!-- Metadata Section -->
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 15px; margin: 20px 0;">
<!-- Complexity Badge -->
<div style="background: {complexity_color}15; padding: 15px; border-radius: 10px;
border-left: 4px solid {complexity_color};">
<h4 style="color: {complexity_color}; margin: 0 0 8px 0; font-size: 1em;">
📊 Complexity Level
</h4>
<p style="margin: 0; font-weight: bold; text-transform: capitalize;">
{complexity}
</p>
</div>
<!-- Interests Section -->
<div style="background: {colors[2]}15; padding: 15px; border-radius: 10px;
border-left: 4px solid {colors[2]};">
<h4 style="color: {colors[2]}; margin: 0 0 8px 0; font-size: 1em;">
🎯 Interest Areas
</h4>
<p style="margin: 0;">
{', '.join(interests) if interests else 'General Learning'}
</p>
</div>
</div>
<!-- Features Section -->
<div style="background: {colors[3]}10; padding: 20px; border-radius: 12px; margin: 20px 0;">
<h4 style="color: {colors[1]}; margin: 0 0 15px 0; font-size: 1.2em;">
✨ Adaptation Features
</h4>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 12px;">
{self._create_feature_cards_advanced(profile['characteristics'], colors)}
</div>
</div>
<!-- Status Footer -->
<div style="text-align: center; margin-top: 25px; padding: 15px;
background: {colors[0]}05; border-radius: 8px;">
<small style="color: {colors[1]}; font-size: 0.9em;">
🚀 Adapted with {'AI Model' if not self.ai_config.simulation_mode else 'Enhanced Simulation'} |
🎯 Profile: {profile_key.replace('_', ' ').title()} |
⚡ Processing: Optimized for accessibility and engagement |
📅 {datetime.now().strftime('%Y-%m-%d %H:%M')}
</small>
</div>
</div>
"""
return html
def _format_content_advanced(self, content):
"""Advanced content formatting with enhanced HTML"""
# Convert markdown-style content to rich HTML
content = re.sub(r'^## (.*)', r'<h3 style="color: #2c3e50; margin: 20px 0 12px 0; font-size: 1.3em;">\1</h3>', content, flags=re.MULTILINE)
content = re.sub(r'^### (.*)', r'<h4 style="color: #34495e; margin: 16px 0 10px 0; font-size: 1.1em;">\1</h4>', content, flags=re.MULTILINE)
# Enhanced list formatting
content = re.sub(r'^\• (.*)', r'<li style="margin: 8px 0; padding: 4px 0; line-height: 1.6;">\1</li>', content, flags=re.MULTILINE)
content = re.sub(r'^\* (.*)', r'<li style="margin: 8px 0; padding: 4px 0; line-height: 1.6;">\1</li>', content, flags=re.MULTILINE)
# Bold and italic formatting
content = re.sub(r'\*\*(.*?)\*\*', r'<strong style="color: #2c3e50;">\1</strong>', content)
content = re.sub(r'\*(.*?)\*', r'<em style="color: #34495e;">\1</em>', content)
# Wrap consecutive list items
content = re.sub(r'(<li[^>]*>.*?</li>)', r'<ul style="margin: 12px 0; padding-left: 24px;">\1</ul>', content, flags=re.DOTALL)
content = content.replace('</ul>\n<ul style="margin: 12px 0; padding-left: 24px;">', '\n')
# Format paragraphs
lines = content.split('\n')
formatted_lines = []
for line in lines:
line = line.strip()
if line and not line.startswith('<'):
formatted_lines.append(f'<p style="margin: 12px 0; line-height: 1.7; color: #2c3e50;">{line}</p>')
elif line:
formatted_lines.append(line)
return '\n'.join(formatted_lines)
def _create_feature_cards_advanced(self, characteristics, colors):
"""Create advanced feature cards with enhanced styling"""
cards = []
for i, char in enumerate(characteristics):
color = colors[i % len(colors)]
cards.append(f"""
<div style="background: white; padding: 16px; border-radius: 10px;
border-left: 4px solid {color}; box-shadow: 0 2px 8px rgba(0,0,0,0.05);
transition: transform 0.2s ease;">
<div style="font-size: 0.95em; line-height: 1.5; color: #2c3e50;">
{char}
</div>
</div>
""")
return ''.join(cards)
def _create_gamification_system(self, interests, profile_key):
"""Create comprehensive gamification system"""
# Generate realistic but varied stats
level = random.randint(3, 28)
xp = random.randint(level * 50, level * 150)
achievements = [
f"🎯 {interests[0] if interests else 'Knowledge'} Explorer",
"🧠 Critical Thinker",
"⭐ Progress Champion",
"🔍 Detail Detective" if profile_key == "hyperfocus_directed" else "🎨 Creative Learner"
]
return {
"current_level": level,
"xp_points": xp,
"next_level_xp": (level + 1) * 100,
"achievements": achievements[:3],
"badges": [
{"name": "First Steps", "icon": "🎉", "unlocked": True},
{"name": "Scholar", "icon": "📚", "unlocked": True},
{"name": "Specialist", "icon": "🎯", "unlocked": level > 10},
{"name": "Expert", "icon": "💎", "unlocked": level > 20}
],
"streak_days": random.randint(1, 15),
"progress_percentage": min(95, (xp % 100)),
"achievements_unlocked": len([b for b in achievements if True]),
"profile_bonus": f"+15% XP for {profile_key.replace('_', ' ').title()} activities"
}
def _create_fallback_result(self, content, profile_key, error_msg):
"""Create comprehensive fallback result"""
profile = self.profile_system.get_profile(profile_key)
fallback_html = f"""
<div style="padding: 25px; background: linear-gradient(135deg, #f8f9fa, #e9ecef);
border-radius: 15px; border: 2px solid #dee2e6;">
<div style="text-align: center; margin-bottom: 20px;">
<h3 style="color: #495057; margin: 0;">📚 {profile['name']} - Content Ready</h3>
<p style="color: #6c757d; margin: 5px 0;">Basic adaptation mode active</p>
</div>
<div style="background: white; padding: 20px; border-radius: 10px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1); margin: 15px 0;">
<h4 style="color: #343a40; margin-top: 0;">Original Content:</h4>
<p style="line-height: 1.6; color: #495057;">{content}</p>
<h4 style="color: #343a40;">Adaptation Notes:</h4>
<p style="color: #6c757d; font-style: italic;">
Content has been prepared for {profile['name']} learning style.
Advanced features will be available once full system initialization is complete.
</p>
</div>
<div style="background: #ffc107; color: #212529; padding: 12px;
border-radius: 8px; margin: 15px 0;">
<small><strong>System Note:</strong> Operating in safe mode. Full features will be available shortly.</small>
</div>
</div>
"""
return {
"adapted_content": fallback_html,
"gamification": {
"current_level": 1,
"xp_points": 50,
"achievements": ["System Explorer"],
"progress_percentage": 25
},
"processing_time": 0.1,
"profile_used": profile_key,
"interests": [],
"complexity": "intermediate",
"error": error_msg,
"fallback": True,
"success": False,
"timestamp": datetime.now().isoformat()
}
# ============================================================================
# 5. GLOBAL INSTANCES MANAGEMENT
# ============================================================================
# Global instances
global_ai_config = None
global_pipeline = None
def initialize_global_instances():
"""Initialize global instances for API and Gradio"""
global global_ai_config, global_pipeline
if global_ai_config is None:
print("🔧 Initializing global instances...")
global_ai_config = AIConfig(safe_mode=True)
global_pipeline = ContentAdaptationPipeline(global_ai_config)
print("✅ Global instances initialized successfully!")
return global_ai_config, global_pipeline
# ============================================================================
# 6. FASTAPI SETUP
# ============================================================================
if FASTAPI_AVAILABLE:
from contextlib import asynccontextmanager
@asynccontextmanager
async def lifespan(app: FastAPI):
# Startup
print("🚀 Starting InclusiveEdu API...")
initialize_global_instances()
print("✅ API ready for requests!")
yield
# Shutdown (if needed)
print("👋 InclusiveEdu API shutting down...")
# Create FastAPI instance with lifespan
api = FastAPI(
title="🧠 InclusiveEdu API",
description="API REST para adaptação de conteúdo educacional neurodiverso",
version="2.0.0",
docs_url="/docs",
redoc_url="/redoc",
lifespan=lifespan
)
# CORS middleware
api.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@api.get("/", response_model=dict)
async def root():
"""API root endpoint"""
return {
"app": "InclusiveEdu API",
"version": "2.0.0",
"status": "running",
"description": "AI-powered neurodiverse learning content adaptation",
"features": [
"Content adaptation for 4 neurodiverse profiles",
"Gamification and progress tracking",
"Interest-based personalization",
"Multiple complexity levels"
],
"endpoints": {
"adapt_content": "/adapt",
"health_check": "/health",
"list_profiles": "/profiles",
"api_docs": "/docs"
},
"profiles": [
"visual_structure",
"hyperfocus_directed",
"sensory_adaptation",
"special_interests"
]
}
@api.get("/health", response_model=HealthResponse)
async def health_check():
"""Health check endpoint"""
ai_config, pipeline = initialize_global_instances()
return HealthResponse(
status="healthy",
ai_mode="simulation" if ai_config.simulation_mode else "ai_model",
profiles_available=4,
timestamp=datetime.now().isoformat(),
version="2.0.0"
)
@api.post("/adapt", response_model=ContentResponse)
async def adapt_content_api(request: ContentRequest):
"""Main content adaptation endpoint"""
# Validate request
if not request.content.strip():
raise HTTPException(status_code=400, detail="Content cannot be empty")
# Initialize instances
ai_config, pipeline = initialize_global_instances()
try:
# Map profile names
profile_map = {
"visual": "visual_structure",
"visual_structure": "visual_structure",
"structure": "visual_structure",
"hyperfocus": "hyperfocus_directed",
"hyperfocus_directed": "hyperfocus_directed",
"technical": "hyperfocus_directed",
"deep": "hyperfocus_directed",
"sensory": "sensory_adaptation",
"sensory_adaptation": "sensory_adaptation",
"calm": "sensory_adaptation",
"gentle": "sensory_adaptation",
"interests": "special_interests",
"special_interests": "special_interests",
"gamification": "special_interests",
"game": "special_interests"
}
profile_key = profile_map.get(request.profile.lower(), "visual_structure")
# Perform adaptation
result = pipeline.adapt_content(
content=request.content,
profile_key=profile_key,
interests=request.interests,
complexity=request.complexity
)
# Process output format
if request.format == "text":
# Clean HTML for text-only output
clean_content = re.sub('<[^<]+?>', '', result['adapted_content'])
clean_content = re.sub(r'\s+', ' ', clean_content).strip()
adapted_content = clean_content
raw_html = result['adapted_content']
else:
# Return HTML format
adapted_content = result['adapted_content']
raw_html = None
return ContentResponse(
adapted_content=adapted_content,
gamification=result['gamification'],
processing_time=result['processing_time'],
profile_used=result['profile_used'],
interests=result['interests'],
complexity=result['complexity'],
success=result['success'],
format=request.format,
timestamp=result['timestamp'],
raw_html=raw_html
)
except Exception as e:
print(f"❌ API adaptation error: {e}")
raise HTTPException(
status_code=500,
detail=f"Content adaptation failed: {str(e)}"
)
@api.get("/profiles")
async def get_profiles_api():
"""Get all available learning profiles"""
ai_config, pipeline = initialize_global_instances()
profiles_info = {}
for key, profile in pipeline.profile_system.profiles.items():
profiles_info[key] = {
"name": profile["name"],
"description": profile["description"],
"characteristics": profile["characteristics"],
"best_for": profile.get("best_for", [])
}
return {
"profiles": profiles_info,
"total_profiles": len(profiles_info),
"default_profile": "visual_structure"
}
@api.get("/examples")
async def get_api_examples():
"""Get API usage examples"""
return {
"curl_example": {
"description": "Example using cURL",
"command": """curl -X POST "http://localhost:8000/adapt" \\
-H "Content-Type: application/json" \\
-d '{
"content": "Artificial intelligence (AI) refers to the simulation of human intelligence in machines...",
"profile": "visual_structure",
"interests": ["technology", "programming"],
"complexity": "intermediate",
"format": "html"
}'"""
},
"python_example": {
"description": "Example using Python requests",
"code": """import requests
# API endpoint
url = "http://localhost:8000/adapt"
# Request data
data = {
"content": "Your educational content here...",
"profile": "visual_structure", # or hyperfocus_directed, sensory_adaptation, special_interests
"interests": ["technology", "science"],
"complexity": "intermediate", # beginner, intermediate, advanced
"format": "html" # html or text
}
# Make request
response = requests.post(url, json=data)
result = response.json()
# Use adapted content
print("Adapted content:", result["adapted_content"])
print("Gamification:", result["gamification"])
print("Processing time:", result["processing_time"])"""
},
"javascript_example": {
"description": "Example using JavaScript fetch",
"code": """// API request
const response = await fetch('http://localhost:8000/adapt', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
content: 'Your educational content here...',
profile: 'visual_structure',
interests: ['technology', 'programming'],
complexity: 'intermediate',
format: 'html'
})
});
const result = await response.json();
// Use the adapted content
console.log('Adapted:', result.adapted_content);
console.log('Gamification:', result.gamification);"""
}
}
# ============================================================================
# 7. GRADIO INTERFACE
# ============================================================================
if GRADIO_AVAILABLE:
class GradioInterface:
"""Enhanced Gradio interface with API integration info"""
def __init__(self):
print("🌐 Initializing Enhanced Gradio interface...")
self.ai_config, self.pipeline = initialize_global_instances()
self.session_stats = {
"adaptations": 0,
"start_time": datetime.now(),
"profiles_used": {},
"total_processing_time": 0.0
}
def adapt_content_interface(self, content, profile_name, interests_text, complexity):
"""Main interface function for content adaptation"""
if not content or not content.strip():
return (
"<div style='padding: 20px; background: #fff3cd; border-radius: 10px;'>"
"<h4>⚠️ Input Required</h4>"
"<p>Please enter some educational content to adapt for different learning styles.</p>"
"</div>",
"", "", ""
)
try:
# Convert profile name to key
profile_map = {
"🎯 Visual Structure": "visual_structure",
"🔬 Directed Hyperfocus": "hyperfocus_directed",
"🌸 Sensory Adaptation": "sensory_adaptation",
"🎮 Special Interests": "special_interests"
}
profile_key = profile_map.get(profile_name, "visual_structure")
interests = [i.strip() for i in interests_text.split(',') if i.strip()]
# Perform adaptation
result = self.pipeline.adapt_content(
content=content.strip(),
profile_key=profile_key,
interests=interests,
complexity=complexity
)
# Update session stats
self._update_session_stats(result)
# Format outputs for interface
adapted_html = result['adapted_content']
gamification_info = self._format_gamification_output(result['gamification'])
processing_info = self._format_processing_output(result)
stats_info = self._format_stats_output()
return adapted_html, gamification_info, processing_info, stats_info
except Exception as e:
error_msg = f"❌ Adaptation error: {str(e)}"
print(f"Interface error: {e}")
return (
f"<div style='padding: 20px; background: #f8d7da; border-radius: 10px;'>"
f"<h4>❌ Processing Error</h4>"
f"<p>An error occurred during content adaptation: {str(e)}</p>"
f"<p><em>Please try again with different content or settings.</em></p>"
f"</div>",
"", "", ""
)
def _update_session_stats(self, result):
"""Update session statistics"""
self.session_stats["adaptations"] += 1
profile_used = result.get("profile_used", "unknown")
if profile_used in self.session_stats["profiles_used"]:
self.session_stats["profiles_used"][profile_used] += 1
else:
self.session_stats["profiles_used"][profile_used] = 1
self.session_stats["total_processing_time"] += result.get("processing_time", 0)
def _format_gamification_output(self, gamification):
"""Format gamification information for display"""
level = gamification.get("current_level", 1)
xp = gamification.get("xp_points", 0)
progress = gamification.get("progress_percentage", 0)
achievements = len(gamification.get("achievements", []))
return (
f"🎮 Level {level} | ⭐ {xp:,} XP | 📈 {progress}% to next level | "
f"🏆 {achievements} achievements unlocked"
)
def _format_processing_output(self, result):
"""Format processing information for display"""
processing_time = result.get("processing_time", 0)
ai_status = "🧠 AI Model" if result.get("gemma3_used", False) else "🎭 Enhanced Simulation"
profile = result.get("profile_used", "unknown").replace("_", " ").title()
success = "✅ Success" if result.get("success", False) else "⚠️ Fallback"
return (
f"⚡ {processing_time:.2f}s processing | {ai_status} | "
f"🎯 {profile} profile | {success}"
)
def _format_stats_output(self):
"""Format session statistics for display"""
total_adaptations = self.session_stats["adaptations"]
session_time = (datetime.now() - self.session_stats["start_time"]).total_seconds() / 60
avg_processing = (
self.session_stats["total_processing_time"] / total_adaptations
if total_adaptations > 0 else 0
)
most_used_profile = "None"
if self.session_stats["profiles_used"]:
most_used_profile = max(
self.session_stats["profiles_used"].items(),
key=lambda x: x[1]
)[0].replace("_", " ").title()
return (
f"📊 Session: {total_adaptations} adaptations | "
f"⏱️ {session_time:.1f}min active | "
f"⚡ {avg_processing:.2f}s avg | "
f"🎯 Most used: {most_used_profile}"
)
def get_system_status(self):
"""Get current system status with API info"""
model_status = "🧠 AI Model Active" if not self.ai_config.simulation_mode else "🎭 Simulation Mode"
device_info = "🚀 GPU" if TORCH_AVAILABLE and torch.cuda.is_available() else "💻 CPU"
# Check if we're running in dual mode by looking for environment or checking if in Spaces
is_spaces = "SPACE_ID" in os.environ
api_status = "✅ Active (Dual Mode)" if FASTAPI_AVAILABLE else "❌ Not Available"
# Determine base URLs
if is_spaces:
base_url = "https://your-space.hf.space" # Will be replaced with actual Space URL
gradio_url = "https://your-space.hf.space"
api_url = "https://your-space.hf.space"
else:
base_url = "http://localhost:8000"
gradio_url = "http://localhost:7860"
api_url = "http://localhost:8000"
return f"""
## 🔧 System Status
**AI Engine:** {model_status}
**Device:** {device_info}
**Profiles:** 4 neurodiverse learning profiles available
**Features:** Content adaptation, gamification, analytics
**Session:** {self.session_stats['adaptations']} adaptations completed
## 🌐 Dual Mode Active
**Gradio Interface:** ✅ Running on port 7860
**FastAPI Server:** {api_status} on port 8000
**Mode:** {'Hugging Face Spaces' if is_spaces else 'Local Development'}
## 🔌 API Access Points
**Base URL:** `{api_url}`
**Health Check:** `{api_url}/health`
**API Documentation:** `{api_url}/docs`
**Interactive API:** `{api_url}/redoc`
**Available Endpoints:**
- `POST /adapt` - Content adaptation
- `GET /profiles` - List all learning profiles
- `GET /examples` - Usage examples and code samples
- `GET /health` - System health status
## 🎯 Profile System
- 🎯 **Visual Structure:** Clear organization and hierarchy
- 🔬 **Directed Hyperfocus:** Technical depth and detail
- 🌸 **Sensory Adaptation:** Calm and accessible design
- 🎮 **Special Interests:** Gamification and motivation
## ✨ Capabilities
✅ Real-time content adaptation
✅ Multiple complexity levels (beginner/intermediate/advanced)
✅ Interest-based personalization
✅ Accessibility features and sensory adaptations
✅ Progress tracking and gamification system
{'✅ **REST API for external integrations**' if FASTAPI_AVAILABLE else '❌ **REST API disabled**'}
✅ **Gradio web interface for direct use**
✅ **Dual-mode operation (Gradio + API)**
## 📊 Quick API Test
Try this in your terminal or code:
```bash
curl {api_url}/health
```
```python
import requests
response = requests.get('{api_url}/health')
print(response.json())
```
"""
def get_api_examples_display(self):
"""Get API examples for display in Gradio"""
if not FASTAPI_AVAILABLE:
return """
## 🔌 API Not Available
FastAPI is not installed. To enable API functionality, install FastAPI:
```bash
pip install fastapi uvicorn
```
"""
base_url = "http://localhost:8000" if "SPACE_ID" not in os.environ else "https://your-space.hf.space"
return f"""
## 🔌 API Usage Examples
### Python Example
```python
import requests
url = "{base_url}/adapt"
data = {{
"content": "Your educational content here...",
"profile": "visual_structure",
"interests": ["technology", "programming"],
"complexity": "intermediate",
"format": "html"
}}
response = requests.post(url, json=data)
result = response.json()
print("Adapted:", result["adapted_content"])
print("Gamification:", result["gamification"])
```
### JavaScript Example
```javascript
const response = await fetch('{base_url}/adapt', {{
method: 'POST',
headers: {{ 'Content-Type': 'application/json' }},
body: JSON.stringify({{
content: 'Your educational content...',
profile: 'visual_structure',
interests: ['technology'],
complexity: 'intermediate'
}})
}});
const result = await response.json();
console.log('Adapted:', result.adapted_content);
```
### cURL Example
```bash
curl -X POST "{base_url}/adapt" \\
-H "Content-Type: application/json" \\
-d '{{
"content": "AI is transforming education...",
"profile": "visual_structure",
"interests": ["technology", "AI"],
"complexity": "intermediate"
}}'
```
### Available Profiles
- `visual_structure` - Clear organization and hierarchy
- `hyperfocus_directed` - Technical depth and detail
- `sensory_adaptation` - Calm and accessible design
- `special_interests` - Gamification and motivation
### Response Format
```json
{{
"adapted_content": "Enhanced HTML content...",
"gamification": {{
"current_level": 15,
"xp_points": 1250,
"achievements": ["Explorer", "Scholar"]
}},
"processing_time": 0.45,
"profile_used": "visual_structure",
"success": true
}}
```
"""
def create_gradio_interface():
"""Create the main Gradio interface - compatible with older versions"""
print("🎨 Creating Gradio interface...")
try:
interface = GradioInterface()
# Get profile options
profile_options = [profile["name"] for profile in interface.pipeline.profile_system.profiles.values()]
# Create simple, compatible interface
with gr.Blocks(title="🧠 InclusiveEdu - Neurodiverse Learning Platform") as demo:
# Header
gr.HTML("""
<div style="text-align: center; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 2rem; border-radius: 15px; margin-bottom: 2rem;">
<h1>🧠 InclusiveEdu</h1>
<h3>AI-Powered Neurodiverse Learning Content Adaptation</h3>
<p>Transform educational content to match different learning styles and neurodivergent needs</p>
</div>
""")
# Main interface
gr.Markdown("### 📝 Input Content")
content_input = gr.Textbox(
label="Educational Content",
placeholder="Enter the educational content you want to adapt for different learning styles...",
lines=6
)
with gr.Row():
profile_select = gr.Dropdown(
choices=profile_options,
value=profile_options[0],
label="🎯 Learning Profile"
)
complexity_select = gr.Dropdown(
choices=["beginner", "intermediate", "advanced"],
value="intermediate",
label="📊 Complexity Level"
)
interests_input = gr.Textbox(
label="🎨 Interests (comma-separated)",
placeholder="technology, science, art, music, gaming, sports..."
)
adapt_btn = gr.Button("🚀 Adapt Content", variant="primary")
gr.Markdown("### ✨ Adapted Content")
adapted_output = gr.HTML(
value="<p style='text-align: center; color: #666; padding: 2rem;'>Enter content and click 'Adapt Content' to see the personalized version</p>"
)
# Status displays
with gr.Row():
gamification_status = gr.Textbox(label="🎮 Gamification Status", interactive=False)
processing_status = gr.Textbox(label="⚡ Processing Info", interactive=False)
session_status = gr.Textbox(label="📊 Session Stats", interactive=False)
# System info
gr.Markdown("### 🔧 System Information")
system_info = gr.Markdown(interface.get_system_status())
# Profiles info
gr.Markdown("### 📚 Learning Profiles")
profiles_info = gr.HTML("""
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 1rem; margin: 1rem 0;">
<div style="background: #e3f2fd; padding: 1rem; border-radius: 10px;">
<h4>🎯 Visual Structure</h4>
<p>Clear organization, visual hierarchy, and structured elements</p>
</div>
<div style="background: #e8f5e8; padding: 1rem; border-radius: 10px;">
<h4>🔬 Directed Hyperfocus</h4>
<p>Deep technical focus, detailed information, and comprehensive analysis</p>
</div>
<div style="background: #fff3e0; padding: 1rem; border-radius: 10px;">
<h4>🌸 Sensory Adaptation</h4>
<p>Calm environment, sensory awareness, and accessible design</p>
</div>
<div style="background: #fce4ec; padding: 1rem; border-radius: 10px;">
<h4>🎮 Special Interests</h4>
<p>Interest-based connections, gamification, and motivational design</p>
</div>
</div>
""")
# Connect the adaptation function
adapt_btn.click(
fn=interface.adapt_content_interface,
inputs=[content_input, profile_select, interests_input, complexity_select],
outputs=[adapted_output, gamification_status, processing_status, session_status]
)
# Footer
gr.HTML("""
<div style="text-align: center; margin-top: 2rem; padding: 1rem; background: #f8f9fa; border-radius: 10px;">
<p><strong>🧠 InclusiveEdu</strong> - Empowering neurodiverse learners through AI-adapted content</p>
<p>Supporting Visual Structure, Directed Hyperfocus, Sensory Adaptation, and Special Interest learning styles</p>
</div>
""")
return demo
except Exception as e:
print(f"❌ Gradio interface creation error: {e}")
# Create emergency fallback interface
return create_emergency_interface()
def create_emergency_interface():
"""Create emergency fallback interface - ultra-compatible"""
print("🚨 Creating emergency fallback interface...")
def emergency_adapt(content):
if not content or not content.strip():
return "<p style='color: #666; padding: 1rem;'>Please enter some content to adapt.</p>"
return f"""
<div style="padding: 20px; background: #e3f2fd; border-radius: 10px; margin: 1rem 0;">
<h3 style="color: #1976d2; margin-top: 0;">📚 Emergency Adaptation</h3>
<div style="background: white; padding: 15px; border-radius: 5px; margin: 10px 0; border-left: 4px solid #2196f3;">
<h4 style="color: #333; margin-top: 0;">Original Content:</h4>
<p style="line-height: 1.6; color: #555;">{content[:500]}{'...' if len(content) > 500 else ''}</p>
</div>
<div style="background: #f0f8ff; padding: 15px; border-radius: 5px; margin: 10px 0;">
<h4 style="color: #1976d2; margin-top: 0;">✨ Basic Adaptation Applied</h4>
<p style="color: #333;">Content has been processed for improved accessibility and readability.</p>
<ul style="color: #555; line-height: 1.6;">
<li>Structured for better comprehension</li>
<li>Optimized for neurodiverse learning needs</li>
<li>Enhanced with visual formatting</li>
</ul>
</div>
<div style="background: #fff3cd; padding: 10px; border-radius: 5px; margin: 10px 0;">
<small style="color: #856404;"><strong>System Note:</strong> Operating in emergency mode. Full features will be available when the system is fully operational.</small>
</div>
</div>
"""
# Create ultra-simple interface
interface = gr.Interface(
fn=emergency_adapt,
inputs=gr.Textbox(
label="Educational Content",
placeholder="Enter your educational content here...",
lines=6
),
outputs=gr.HTML(label="Adapted Content"),
title="🧠 InclusiveEdu - Emergency Mode",
description="AI-powered neurodiverse learning content adaptation (Emergency Mode)",
examples=[
["Artificial intelligence is a fascinating field that involves creating machines capable of intelligent behavior."],
["Photosynthesis is the process by which plants convert sunlight into energy using chlorophyll."],
["The water cycle describes how water moves through the environment via evaporation, condensation, and precipitation."]
]
)
return interface
# ============================================================================
# 8. MAIN APPLICATION LAUNCHER
# ============================================================================
def main():
"""Main application launcher"""
print("="*70)
print("🧠 InclusiveEdu - Neurodiverse Education Platform")
print("✅ Fixed version with proper error handling")
print("🎯 Compatible with Hugging Face Spaces + External API")
print("="*70)
print("🚀 Starting InclusiveEdu - Enhanced with API Integration...")
print("="*70)
# System information
print("📊 System Information:")
print("🐍 Python: Ready")
if TORCH_AVAILABLE:
print(f"🔥 PyTorch: {torch.__version__}")
else:
print("🔥 PyTorch: Not available")
print(f"🎨 Gradio: {'Available' if GRADIO_AVAILABLE else 'Not available'}")
print(f"🔌 FastAPI: {'Available' if FASTAPI_AVAILABLE else 'Not available'}")
print(f"🖥️ Device: {'🚀 GPU' if TORCH_AVAILABLE and torch.cuda.is_available() else '💻 CPU Mode'}")
# Initialize global instances
try:
print("\n🔧 Initializing system...")
initialize_global_instances()
print("✅ System initialization successful!")
except Exception as e:
print(f"❌ System initialization error: {e}")
print("⚠️ Continuing with emergency mode...")
# Determine execution mode
is_spaces = "SPACE_ID" in os.environ
if is_spaces:
print("\n🤗 Hugging Face Spaces detected")
print("🌐 Starting Dual Mode: Gradio + API (optimized for Spaces)")
mode = "dual" # Enable both Gradio and API in Spaces
else:
print("\n🎯 InclusiveEdu - Choose execution mode:")
print("1. 🎨 Gradio Interface only")
print("2. 🔌 API Server only")
print("3. 🌐 Dual Mode: Gradio + API (recommended)")
try:
choice = input("\nEnter choice (1-3, default=3): ").strip()
if choice == "1":
mode = "gradio"
elif choice == "2":
mode = "api"
else:
mode = "dual" # Default to dual mode
except:
mode = "dual"
# Launch based on mode
if mode == "gradio":
if not GRADIO_AVAILABLE:
print("❌ Gradio not available! Please install gradio.")
return
print("🎨 Starting Gradio Interface...")
try:
demo = create_gradio_interface()
print("🎉 InclusiveEdu ready to launch!")
# Minimal launch configuration for maximum compatibility with Gradio 4.0.0
demo.launch(
server_name="0.0.0.0",
server_port=7860
)
except Exception as e:
print(f"❌ Gradio launch error: {e}")
print("🚨 Creating emergency interface...")
emergency_demo = create_emergency_interface()
emergency_demo.launch(
server_name="0.0.0.0",
server_port=7860
)
elif mode == "api":
if not FASTAPI_AVAILABLE:
print("❌ FastAPI not available! Please install fastapi and uvicorn.")
return
print("🔌 Starting API Server only...")
import uvicorn
uvicorn.run(
api,
host="0.0.0.0",
port=8000,
reload=False,
log_level="info"
)
elif mode == "dual":
if not (GRADIO_AVAILABLE and FASTAPI_AVAILABLE):
print("❌ Both Gradio and FastAPI required for dual mode!")
return
print("🌐 Starting Dual Mode: Gradio + API...")
import threading
import uvicorn
# Start API server in background thread
def start_api():
print("🔌 Starting API server on port 8000...")
uvicorn.run(
api,
host="0.0.0.0",
port=8000,
reload=False,
log_level="warning"
)
api_thread = threading.Thread(target=start_api, daemon=True)
api_thread.start()
print("✅ API server starting on http://0.0.0.0:8000")
print("📚 API Documentation: http://0.0.0.0:8000/docs")
time.sleep(3) # Give API time to start
# Start Gradio interface
print("🎨 Starting Gradio interface on port 7860...")
demo = create_gradio_interface()
print("🎉 InclusiveEdu ready - Dual mode active!")
print("🎨 Gradio Interface: http://0.0.0.0:7860")
print("🔌 API Endpoints: http://0.0.0.0:8000")
print("📚 API Documentation: http://0.0.0.0:8000/docs")
print("❤️ Health Check: http://0.0.0.0:8000/health")
# Launch Gradio
demo.launch(
server_name="0.0.0.0",
server_port=7860
)
if __name__ == "__main__":
main()