AumCore-AI / app.py
AumCoreAI's picture
Update app.py
b274ba8 verified
raw
history blame
34.7 kB
# app.py - HUGGING FACE SPACES COMPATIBLE
import os
import sys
import uvicorn
import asyncio
import json
import markdown
from pathlib import Path
from fastapi import FastAPI, Form, HTTPException
from fastapi.responses import HTMLResponse, JSONResponse, PlainTextResponse
from groq import Groq
# ============================================
# 1. CONFIGURATION FOR SPACES
# ============================================
class Config:
VERSION = "3.0.5-Spaces"
USERNAME = "AumCore AI"
PORT = 7860
HOST = "0.0.0.0"
# Hugging Face Spaces specific
IS_SPACES = os.environ.get('SPACE_ID') is not None
BASE_DIR = Path(__file__).parent
# ============================================
# 2. GROQ CLIENT WITH ERROR HANDLING
# ============================================
def init_groq_client():
"""Initialize Groq client with proper error handling"""
try:
# Check for API key in multiple locations
api_key = os.environ.get("GROQ_API_KEY")
if not api_key or api_key.strip() == "":
print("⚠️ GROQ_API_KEY not found in environment variables")
return None, False
client = Groq(api_key=api_key)
# Test the client with a simple call
test_response = client.chat.completions.create(
model="llama-3.3-70b-versatile",
messages=[{"role": "user", "content": "Hello"}],
max_tokens=10
)
print(f"βœ… Groq client initialized successfully")
print(f" Model: {test_response.model}")
return client, True
except Exception as e:
print(f"❌ Failed to initialize Groq client: {str(e)}")
print(f" API Key present: {'Yes' if 'GROQ_API_KEY' in os.environ else 'No'}")
return None, False
# Initialize Groq
client, GROQ_AVAILABLE = init_groq_client()
# ============================================
# 3. FASTAPI APP
# ============================================
app = FastAPI(
title="AumCore AI",
description="Advanced AI Assistant for Hugging Face Spaces",
version=Config.VERSION,
docs_url="/docs" if not Config.IS_SPACES else None,
redoc_url="/redoc" if not Config.IS_SPACES else None
)
# Add CORS if needed
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# ============================================
# 4. ENHANCED UI WITH ERROR DISPLAY
# ============================================
HTML_UI = '''
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AumCore AI - Spaces Edition</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
:root {
--primary: #3b82f6;
--secondary: #1e293b;
--accent: #10b981;
--danger: #ef4444;
--bg-dark: #0f172a;
--bg-light: #1e293b;
--text: #e2e8f0;
--text-light: #94a3b8;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: var(--bg-dark);
color: var(--text);
font-family: 'Segoe UI', system-ui, sans-serif;
min-height: 100vh;
line-height: 1.6;
}
.container {
max-width: 1000px;
margin: 0 auto;
padding: 20px;
}
.header {
text-align: center;
padding: 30px 0;
border-bottom: 1px solid var(--bg-light);
margin-bottom: 30px;
}
.logo {
font-size: 2.8rem;
font-weight: 800;
background: linear-gradient(135deg, var(--primary), var(--accent));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
margin-bottom: 10px;
}
.tagline {
color: var(--text-light);
font-size: 1.1rem;
margin-bottom: 15px;
}
.status-badge {
display: inline-block;
padding: 6px 12px;
background: var(--GROQ_STATUS_COLOR);
color: white;
border-radius: 20px;
font-size: 0.9rem;
font-weight: 600;
}
.controls {
display: flex;
gap: 10px;
flex-wrap: wrap;
margin-bottom: 25px;
justify-content: center;
}
.btn {
padding: 10px 20px;
background: var(--bg-light);
border: 1px solid #334155;
color: var(--text);
border-radius: 8px;
cursor: pointer;
transition: all 0.2s ease;
display: flex;
align-items: center;
gap: 8px;
font-weight: 500;
}
.btn:hover {
background: #334155;
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0,0,0,0.2);
}
.btn-primary {
background: var(--primary);
border-color: var(--primary);
}
.btn-primary:hover {
background: #2563eb;
}
.btn-danger {
background: var(--danger);
border-color: var(--danger);
}
.btn-danger:hover {
background: #dc2626;
}
.btn-success {
background: var(--accent);
border-color: var(--accent);
}
.chat-container {
background: var(--bg-light);
border-radius: 12px;
padding: 25px;
margin-bottom: 25px;
min-height: 500px;
max-height: 600px;
overflow-y: auto;
box-shadow: 0 8px 32px rgba(0,0,0,0.3);
}
.message {
margin-bottom: 25px;
animation: fadeIn 0.3s ease;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.user-message {
background: rgba(59, 130, 246, 0.15);
border-left: 4px solid var(--primary);
padding: 15px 20px;
border-radius: 10px;
margin-left: 10%;
}
.ai-message {
background: rgba(30, 41, 59, 0.8);
border-left: 4px solid var(--accent);
padding: 15px 20px;
border-radius: 10px;
margin-right: 10%;
}
.message-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
}
.message-sender {
font-weight: 700;
color: var(--primary);
display: flex;
align-items: center;
gap: 8px;
}
.message-time {
color: var(--text-light);
font-size: 0.85rem;
}
.message-content {
font-size: 1.05rem;
line-height: 1.7;
}
.message-content code {
background: rgba(0,0,0,0.3);
padding: 2px 6px;
border-radius: 4px;
font-family: 'Courier New', monospace;
font-size: 0.95em;
}
.message-content pre {
background: rgba(0,0,0,0.4);
padding: 15px;
border-radius: 8px;
overflow-x: auto;
margin: 10px 0;
}
.message-content pre code {
background: none;
padding: 0;
}
.typing-indicator {
display: flex;
gap: 6px;
padding: 20px;
}
.typing-dot {
width: 10px;
height: 10px;
background: var(--primary);
border-radius: 50%;
animation: bounce 1.4s infinite;
}
.typing-dot:nth-child(2) { animation-delay: 0.2s; }
.typing-dot:nth-child(3) { animation-delay: 0.4s; }
@keyframes bounce {
0%, 60%, 100% { transform: translateY(0); opacity: 0.7; }
30% { transform: translateY(-12px); opacity: 1; }
}
.input-area {
background: var(--bg-light);
border-radius: 12px;
padding: 20px;
box-shadow: 0 8px 32px rgba(0,0,0,0.3);
}
.input-container {
display: flex;
gap: 12px;
}
#userInput {
flex: 1;
padding: 16px;
background: var(--bg-dark);
border: 2px solid #334155;
border-radius: 8px;
color: var(--text);
font-size: 1.05rem;
resize: none;
min-height: 60px;
transition: border 0.2s;
}
#userInput:focus {
outline: none;
border-color: var(--primary);
}
#sendBtn {
padding: 0 30px;
background: var(--primary);
color: white;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 1.1rem;
transition: all 0.2s;
display: flex;
align-items: center;
justify-content: center;
}
#sendBtn:hover {
background: #2563eb;
transform: translateY(-2px);
}
#sendBtn:disabled {
background: #475569;
cursor: not-allowed;
transform: none;
}
.footer {
text-align: center;
margin-top: 30px;
padding-top: 20px;
border-top: 1px solid var(--bg-light);
color: var(--text-light);
font-size: 0.95rem;
}
.alert {
position: fixed;
top: 20px;
right: 20px;
padding: 15px 20px;
background: var(--bg-light);
border-left: 4px solid var(--primary);
border-radius: 8px;
box-shadow: 0 8px 32px rgba(0,0,0,0.4);
z-index: 1000;
display: none;
max-width: 400px;
}
.alert.show {
display: block;
animation: slideIn 0.3s ease;
}
@keyframes slideIn {
from { transform: translateX(100%); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
.alert-error {
border-left-color: var(--danger);
}
.alert-success {
border-left-color: var(--accent);
}
@media (max-width: 768px) {
.container { padding: 15px; }
.logo { font-size: 2.2rem; }
.chat-container { max-height: 500px; }
.user-message, .ai-message { margin-left: 0; margin-right: 0; }
}
</style>
</head>
<body>
<div class="container">
<!-- Header -->
<div class="header">
<div class="logo">AUMCORE AI</div>
<div class="tagline">Advanced AI Assistant on Hugging Face Spaces</div>
<div class="status-badge" id="statusBadge">
<i class="fas fa-circle"></i> Initializing...
</div>
</div>
<!-- Controls -->
<div class="controls">
<button class="btn btn-primary" onclick="newChat()">
<i class="fas fa-plus"></i> New Chat
</button>
<button class="btn" onclick="checkSystemHealth()">
<i class="fas fa-heartbeat"></i> System Health
</button>
<button class="btn" onclick="runDiagnostics()">
<i class="fas fa-stethoscope"></i> Diagnostics
</button>
<button class="btn" onclick="runTests()">
<i class="fas fa-vial"></i> Run Tests
</button>
<button class="btn btn-danger" onclick="resetMemory()">
<i class="fas fa-trash-alt"></i> Reset Memory
</button>
</div>
<!-- Chat Container -->
<div class="chat-container" id="chatContainer">
<div class="message ai-message">
<div class="message-header">
<div class="message-sender">
<i class="fas fa-robot"></i> AumCore AI
</div>
<div class="message-time" id="currentTime"></div>
</div>
<div class="message-content">
<strong>Namaste! πŸ™</strong> Welcome to AumCore AI on Hugging Face Spaces.<br><br>
I'm your advanced AI assistant capable of:
<ul style="margin: 10px 0 10px 20px;">
<li>Hindi & English conversations</li>
<li>Code generation and debugging</li>
<li>Technical explanations</li>
<li>Creative writing</li>
<li>Problem solving</li>
</ul>
Just type your message below and let's get started!
</div>
</div>
</div>
<!-- Input Area -->
<div class="input-area">
<div class="input-container">
<textarea
id="userInput"
placeholder="Type your message here... (Press Shift+Enter for new line, Enter to send)"
onkeydown="handleKeyPress(event)"
oninput="autoResize(this)"
rows="1"
></textarea>
<button id="sendBtn" onclick="sendMessage()">
<i class="fas fa-paper-plane"></i>
</button>
</div>
<div style="margin-top: 10px; color: var(--text-light); font-size: 0.9rem; text-align: center;">
<i class="fas fa-info-circle"></i> Powered by Groq's Llama 3.3 70B β€’ FastAPI β€’ Hugging Face Spaces
</div>
</div>
<!-- Footer -->
<div class="footer">
<div>Version: 3.0.5-Spaces | Built with ❀️ by Sanjay</div>
<div>Β© 2024 AumCore AI | All responses are generated by AI</div>
</div>
</div>
<!-- Alert Box -->
<div class="alert" id="alert">
<div id="alertMessage"></div>
</div>
<script>
// Global Variables
let chatHistory = [];
let isProcessing = false;
// Initialize
function init() {
updateTime();
setInterval(updateTime, 60000);
checkSystemStatus();
document.getElementById('userInput').focus();
}
function updateTime() {
const now = new Date();
const timeStr = now.toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'});
document.getElementById('currentTime').textContent = timeStr;
}
// Status Check
async function checkSystemStatus() {
try {
const response = await fetch('/system/health');
const data = await response.json();
const badge = document.getElementById('statusBadge');
if (data.groq_available) {
badge.innerHTML = '<i class="fas fa-circle" style="color:#10b981"></i> System Online';
badge.style.backgroundColor = '#10b981';
} else {
badge.innerHTML = '<i class="fas fa-circle" style="color:#f59e0b"></i> Groq API Not Configured';
badge.style.backgroundColor = '#f59e0b';
}
} catch (error) {
console.error('Status check failed:', error);
}
}
// Alert System
function showAlert(message, type = 'info', duration = 3000) {
const alert = document.getElementById('alert');
const alertMsg = document.getElementById('alertMessage');
alertMsg.textContent = message;
alert.className = 'alert show';
if (type === 'error') alert.classList.add('alert-error');
if (type === 'success') alert.classList.add('alert-success');
setTimeout(() => {
alert.className = 'alert';
}, duration);
}
// Input Handling
function autoResize(textarea) {
textarea.style.height = 'auto';
textarea.style.height = Math.min(textarea.scrollHeight, 200) + 'px';
}
function handleKeyPress(event) {
if (event.key === 'Enter' && !event.shiftKey) {
event.preventDefault();
if (!isProcessing) sendMessage();
}
}
// Format Messages
function formatMessage(text) {
// Convert markdown to HTML
let formatted = text
.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
.replace(/\*\*\*(.*?)\*\*\*/g, '<strong><em>$1</em></strong>')
.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
.replace(/\*(.*?)\*/g, '<em>$1</em>')
.replace(/`(.*?)`/g, '<code>$1</code>')
.replace(/```(\w+)?\n([\s\S]*?)```/g,
'<pre><code class="language-$1">$2</code></pre>')
.replace(/\n/g, '<br>');
return formatted;
}
// Chat Functions
async function sendMessage() {
const input = document.getElementById('userInput');
const message = input.value.trim();
if (!message) return;
if (isProcessing) {
showAlert('Please wait for the current response...', 'error');
return;
}
// Clear input
input.value = '';
input.style.height = 'auto';
// Add user message
const chatContainer = document.getElementById('chatContainer');
const userMsgId = 'user-' + Date.now();
chatContainer.innerHTML += `
<div class="message user-message" id="${userMsgId}">
<div class="message-header">
<div class="message-sender">
<i class="fas fa-user"></i> You
</div>
<div class="message-time">${new Date().toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'})}</div>
</div>
<div class="message-content">${formatMessage(message)}</div>
</div>
`;
// Add typing indicator
const typingId = 'typing-' + Date.now();
chatContainer.innerHTML += `
<div class="message ai-message" id="${typingId}">
<div class="typing-indicator">
<div class="typing-dot"></div>
<div class="typing-dot"></div>
<div class="typing-dot"></div>
</div>
</div>
`;
// Scroll to bottom
chatContainer.scrollTop = chatContainer.scrollHeight;
// Set processing flag
isProcessing = true;
document.getElementById('sendBtn').disabled = true;
try {
// Send to backend
const response = await fetch('/chat', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: 'message=' + encodeURIComponent(message)
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const data = await response.json();
// Remove typing indicator
document.getElementById(typingId)?.remove();
// Add AI response
const aiMsgId = 'ai-' + Date.now();
chatContainer.innerHTML += `
<div class="message ai-message" id="${aiMsgId}">
<div class="message-header">
<div class="message-sender">
<i class="fas fa-robot"></i> AumCore AI
</div>
<div class="message-time">${new Date().toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'})}</div>
</div>
<div class="message-content">${data.response}</div>
</div>
`;
// Add to history
chatHistory.push({
user: message,
ai: data.response,
timestamp: new Date().toISOString()
});
showAlert('Response received successfully', 'success', 2000);
} catch (error) {
console.error('Error:', error);
// Remove typing indicator
document.getElementById(typingId)?.remove();
// Show error message
chatContainer.innerHTML += `
<div class="message ai-message">
<div class="message-header">
<div class="message-sender" style="color:#ef4444">
<i class="fas fa-exclamation-triangle"></i> System Error
</div>
</div>
<div class="message-content" style="color:#f87171">
Sorry, I encountered an error processing your request.<br>
Please check if the Groq API key is properly configured.
</div>
</div>
`;
showAlert('Connection error. Please try again.', 'error');
} finally {
// Reset processing flag
isProcessing = false;
document.getElementById('sendBtn').disabled = false;
// Scroll to bottom
chatContainer.scrollTop = chatContainer.scrollHeight;
// Focus input
input.focus();
}
}
// Control Functions
function newChat() {
if (chatHistory.length > 0) {
if (confirm('Start a new chat? Current conversation will be cleared.')) {
document.getElementById('chatContainer').innerHTML = `
<div class="message ai-message">
<div class="message-header">
<div class="message-sender">
<i class="fas fa-robot"></i> AumCore AI
</div>
<div class="message-time">${new Date().toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'})}</div>
</div>
<div class="message-content">
<strong>New chat started! ✨</strong><br>
How can I assist you today?
</div>
</div>
`;
chatHistory = [];
showAlert('New chat started', 'success');
}
}
}
async function checkSystemHealth() {
try {
const response = await fetch('/system/health');
const data = await response.json();
let message = `πŸ₯ System Health Report\n`;
message += `═══════════════════════════\n`;
message += `Health Score: ${data.health_score}/100\n`;
message += `Status: ${data.status}\n`;
message += `Groq API: ${data.groq_available ? 'βœ… Available' : '❌ Not Available'}\n`;
message += `Version: ${data.version}\n`;
message += `Uptime: ${Math.floor(data.timestamp)} seconds`;
alert(message);
} catch (error) {
showAlert('Health check failed', 'error');
}
}
async function runDiagnostics() {
showAlert('Running diagnostics...', 'info');
try {
const response = await fetch('/system/diagnostics');
const data = await response.json();
if (data.success) {
showAlert(`Diagnostics passed! Score: ${data.health_score}/100`, 'success');
} else {
showAlert('Diagnostics failed', 'error');
}
} catch (error) {
showAlert('Diagnostics error', 'error');
}
}
async function runTests() {
showAlert('Running system tests...', 'info');
try {
const response = await fetch('/system/tests');
const data = await response.json();
if (data.success) {
showAlert(`Tests completed! Score: ${data.score}/100`, 'success');
}
} catch (error) {
showAlert('Tests failed', 'error');
}
}
async function resetMemory() {
if (confirm('Are you sure you want to reset the conversation memory?')) {
try {
const response = await fetch('/reset', { method: 'POST' });
const data = await response.json();
if (data.success) {
showAlert('Memory reset successfully', 'success');
chatHistory = [];
}
} catch (error) {
showAlert('Reset failed', 'error');
}
}
}
// Initialize on load
window.onload = init;
</script>
</body>
</html>
'''
# ============================================
# 5. ENDPOINTS
# ============================================
@app.get("/", response_class=HTMLResponse)
async def get_ui():
"""Serve the main UI"""
return HTML_UI
@app.get("/health")
async def health_check():
"""Simple health check for Spaces"""
return {"status": "healthy", "service": "AumCore AI"}
@app.post("/reset")
async def reset_memory():
"""Reset conversation memory"""
return {
"success": True,
"message": "Memory reset successfully",
"timestamp": asyncio.get_event_loop().time()
}
@app.post("/chat")
async def chat_endpoint(message: str = Form(...)):
"""Main chat endpoint"""
print(f"πŸ’¬ Chat request: {message[:100]}...")
if not GROQ_AVAILABLE:
error_html = '''
<div style="color:#ef4444; padding: 15px; background: rgba(239, 68, 68, 0.1); border-radius: 8px; border-left: 4px solid #ef4444;">
<strong><i class="fas fa-exclamation-triangle"></i> Groq API Not Configured</strong><br>
Please set the GROQ_API_KEY environment variable in your Hugging Face Spaces settings.<br><br>
Steps to fix:
<ol style="margin-left: 20px; margin-top: 10px;">
<li>Go to your Space Settings</li>
<li>Navigate to "Repository secrets"</li>
<li>Add a secret named "GROQ_API_KEY" with your Groq API key</li>
<li>Restart the Space</li>
</ol>
</div>
'''
return {"response": error_html}
try:
# Create system prompt
system_prompt = f"""You are AumCore AI, an advanced AI assistant created by Sanjay.
You are running on Hugging Face Spaces.
Key Information:
- User: {Config.USERNAME}
- Version: {Config.VERSION}
- Platform: Hugging Face Spaces
Instructions:
1. Be helpful, friendly, and professional
2. You can speak in both Hindi and English
3. Format responses with proper markdown
4. For code, use code blocks with language specification
5. Keep responses concise but thorough
6. If you don't know something, admit it honestly
Current time: {asyncio.get_event_loop().time()}
"""
# Prepare messages for Groq
messages = [
{"role": "system", "content": system_prompt},
{"role": "user", "content": message}
]
# Call Groq API
completion = client.chat.completions.create(
model="llama-3.3-70b-versatile",
messages=messages,
temperature=0.7,
max_tokens=1500,
top_p=0.9
)
response_text = completion.choices[0].message.content
# Convert markdown to HTML
try:
html_response = markdown.markdown(
response_text,
extensions=['fenced_code', 'tables', 'nl2br']
)
except:
# Fallback if markdown conversion fails
html_response = response_text.replace('\n', '<br>')
print(f"βœ… Response generated ({len(response_text)} chars)")
return {"response": html_response}
except Exception as e:
error_msg = str(e)
print(f"❌ Chat error: {error_msg}")
error_html = f'''
<div style="color:#ef4444; padding: 15px; background: rgba(239, 68, 68, 0.1); border-radius: 8px; border-left: 4px solid #ef4444;">
<strong><i class="fas fa-exclamation-circle"></i> System Error</strong><br>
{error_msg}<br><br>
Please try again or check the Groq API configuration.
</div>
'''
return {"response": error_html}
@app.get("/system/health")
async def system_health():
"""System health endpoint"""
return {
"success": True,
"health_score": 95 if GROQ_AVAILABLE else 60,
"status": "OPERATIONAL" if GROQ_AVAILABLE else "DEGRADED",
"groq_available": GROQ_AVAILABLE,
"version": Config.VERSION,
"timestamp": asyncio.get_event_loop().time(),
"platform": "Hugging Face Spaces" if Config.IS_SPACES else "Local",
"message": "System is running normally" if GROQ_AVAILABLE else "Groq API not configured"
}
@app.get("/system/diagnostics")
async def diagnostics():
"""System diagnostics"""
return {
"success": True,
"health_score": 90 if GROQ_AVAILABLE else 50,
"checks": {
"fastapi": "PASS",
"groq_connection": "PASS" if GROQ_AVAILABLE else "FAIL",
"memory": "PASS",
"disk_space": "PASS"
},
"recommendations": ["Configure GROQ_API_KEY"] if not GROQ_AVAILABLE else ["All systems operational"]
}
@app.get("/system/tests")
async def system_tests():
"""System tests"""
return {
"success": True,
"score": 85 if GROQ_AVAILABLE else 40,
"tests_passed": 4 if GROQ_AVAILABLE else 2,
"total_tests": 5,
"details": {
"api_connectivity": "PASS" if GROQ_AVAILABLE else "FAIL",
"response_time": "PASS",
"ui_rendering": "PASS",
"error_handling": "PASS",
"memory_management": "PASS"
}
}
# ============================================
# 6. STARTUP AND ERROR HANDLING
# ============================================
@app.on_event("startup")
async def startup_event():
"""Initialize on startup"""
print("=" * 60)
print("πŸš€ AUMCORE AI - HUGGING FACE SPACES EDITION")
print("=" * 60)
print(f"πŸ“ Version: {Config.VERSION}")
print(f"πŸ‘€ User: {Config.USERNAME}")
print(f"🌐 Platform: {'Hugging Face Spaces' if Config.IS_SPACES else 'Local'}")
print(f"πŸ”— Endpoint: /")
print(f"πŸ€– AI Model: llama-3.3-70b-versatile")
print(f"πŸ”‘ Groq API: {'βœ… AVAILABLE' if GROQ_AVAILABLE else '❌ NOT CONFIGURED'}")
if not GROQ_AVAILABLE:
print("\n⚠️ IMPORTANT: GROQ_API_KEY not configured!")
print(" To fix: Set GROQ_API_KEY in Environment Variables")
print(" Without it, AI responses will not work")
print("=" * 60)
print("βœ… System initialized successfully!")
print("=" * 60)
@app.exception_handler(404)
async def not_found(request, exc):
"""Handle 404 errors"""
return JSONResponse(
status_code=404,
content={"error": "Endpoint not found", "available_endpoints": ["/", "/chat", "/system/health"]}
)
@app.exception_handler(500)
async def server_error(request, exc):
"""Handle 500 errors"""
return JSONResponse(
status_code=500,
content={"error": "Internal server error", "message": str(exc)}
)
# ============================================
# 7. MAIN ENTRY POINT
# ============================================
if __name__ == "__main__":
# Get port from environment (Spaces uses 7860)
port = int(os.environ.get("PORT", Config.PORT))
print(f"\nπŸ“‘ Starting server on port {port}...")
uvicorn.run(
app,
host=Config.HOST,
port=port,
log_level="info",
access_log=True
)