DroneAgent / app.py
zok213
🚀 DRONEAGENT v3.0 - HuggingFace Spaces Optimization
c528c82
#!/usr/bin/env python3
"""
🚁 DroneAgent - HF Spaces Application
FastAPI application for HuggingFace Spaces deployment
"""
import os
import asyncio
import uvicorn
from pathlib import Path
from fastapi import FastAPI, HTTPException, Request
from fastapi.responses import HTMLResponse, FileResponse
from fastapi.staticfiles import StaticFiles
from fastapi.middleware.cors import CORSMiddleware
from contextlib import asynccontextmanager
# Import our DroneAgent modules
from src.services.drone_agent import DroneAgent
from src.core.websocket_server import start_websocket_server
# Global drone agent instance
drone_agent = None
@asynccontextmanager
async def lifespan(app: FastAPI):
"""Application lifespan manager."""
global drone_agent
print("🚁 Starting DroneAgent v3.0 for HF Spaces")
print("📍 Initializing GPS coordinate systems...")
print("🧠 Loading AI knowledge base...")
# Initialize DroneAgent first
try:
drone_agent = DroneAgent()
print("✅ DroneAgent v3.0 initialized successfully")
print("🧠 Gemini 2.0 Flash AI Integration Ready")
print("📡 Real-Time Flight Management Ready")
print("🗺️ 6-Decimal GPS Precision Ready")
except Exception as e:
print(f"⚠️ DroneAgent initialization warning: {e}")
drone_agent = None
# Start WebSocket server for real-time notifications
print("📡 Starting WebSocket notification server...")
try:
# Start WebSocket server in background
asyncio.create_task(start_websocket_server())
print("✅ WebSocket server started successfully on port 8001")
except Exception as e:
print(f"⚠️ WebSocket server warning: {e}")
# Create necessary directories
Path("downloads").mkdir(exist_ok=True)
Path("chat_testing").mkdir(exist_ok=True)
print("🚀 DroneAgent v3.0 fully operational!")
print("🌐 Ready to accept chat requests and mission planning")
yield
print("🛑 Shutting down DroneAgent v3.0")
# Initialize FastAPI with lifespan
app = FastAPI(
title="🚁 DroneAgent",
description="Professional AI-Powered Drone Mission Planner with Real-Time Flight Management",
version="3.0.0",
lifespan=lifespan
)
# Add CORS middleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/", response_class=HTMLResponse)
async def root():
"""Serve the main DroneAgent interface."""
return """
<html>
<head>
<title>🚁 DroneAgent</title>
<style>
body { font-family: Arial, sans-serif; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white; text-align: center; padding: 50px; margin: 0; height: 100vh; display: flex;
flex-direction: column; justify-content: center; }
.container { max-width: 800px; margin: 0 auto; }
h1 { font-size: 3em; margin-bottom: 20px; }
p { font-size: 1.2em; margin-bottom: 30px; }
.features { text-align: left; display: inline-block; background: rgba(255,255,255,0.1);
padding: 20px; border-radius: 10px; margin: 20px 0; }
.status { background: rgba(0,255,0,0.2); padding: 10px; border-radius: 5px; margin: 10px 0; }
a { color: #4CAF50; text-decoration: none; }
a:hover { text-decoration: underline; }
</style>
</head>
<body>
<div class="container">
<h1>🚁 DroneAgent v3.0</h1>
<p>Professional AI-Powered Drone Mission Planner</p>
<div class="features">
<h3>✨ Key Features:</h3>
<ul>
<li>🧠 Gemini 2.0 Flash AI Integration</li>
<li>📡 Real-Time Flight Management</li>
<li>🗺️ 6-Decimal GPS Precision</li>
<li>🌐 Vietnamese Geocoding Support</li>
<li>📱 WebSocket Notifications</li>
<li>⏸️ Dynamic Mission Control</li>
</ul>
</div>
<div class="status">
<h3>🌐 API Status:
<span id="status">
<script>
fetch('/api/status')
.then(r => r.json())
.then(d => {
document.getElementById('status').innerHTML =
d.status === 'operational' ? '✅ Operational' : '⚠️ Initializing';
})
.catch(() => {
document.getElementById('status').innerHTML = '⚠️ Initializing';
});
</script>
</span>
</h3>
</div>
<p><strong>🌐 Access Points:</strong></p>
<ul style="list-style: none;">
<li>🌐 Web Interface: <a href="/chat">/chat</a></li>
<li>📚 API Documentation: <a href="/docs">/docs</a></li>
<li>🔧 API Status: <a href="/api/status">/api/status</a></li>
</ul>
</div>
</body>
</html>
"""
@app.get("/api/status")
async def api_status():
"""Get API status information."""
return {
"name": "DroneAgent",
"version": "3.0.0",
"status": "operational" if drone_agent else "initializing",
"drone_agent_loaded": drone_agent is not None,
"websocket_enabled": True,
"features": [
"🧠 Gemini 2.0 Flash AI Integration",
"📡 Real-Time Flight Management",
"🗺️ 6-Decimal GPS Precision",
"🌐 Vietnamese Geocoding Support",
"📱 WebSocket Notifications",
"⏸️ Dynamic Mission Control"
]
}
@app.get("/chat", response_class=HTMLResponse)
async def chat_interface():
"""Serve the chat interface."""
try:
if os.path.exists("chatbot_enhanced.html"):
return FileResponse("chatbot_enhanced.html", media_type="text/html")
elif os.path.exists("chatbot.html"):
return FileResponse("chatbot.html", media_type="text/html")
except:
pass
return """
<html>
<head><title>🚁 DroneAgent Chat</title></head>
<body style="font-family: Arial; padding: 20px; background: #f5f5f5;">
<div style="max-width: 800px; margin: 0 auto; background: white; padding: 30px; border-radius: 10px;">
<h1>🚁 DroneAgent Chat Interface</h1>
<p>Use the API endpoints directly:</p>
<ul>
<li><strong>POST /chat</strong> - Send chat messages</li>
<li><a href="/docs">📚 API Documentation</a></li>
</ul>
</div>
</body>
</html>
"""
# Include our DroneAgent API routes
try:
from src.api.routes import router as api_router
app.include_router(api_router)
print("✅ API routes loaded successfully")
except Exception as e:
print(f"⚠️ Could not load API routes: {e}")
# Add basic chat endpoint if routes fail to load
from src.api.models import ChatMessage
@app.post("/chat")
async def fallback_chat(message: ChatMessage):
"""Fallback chat endpoint when main routes fail."""
if drone_agent:
try:
response = await drone_agent.process_message(message.message)
return response
except Exception as e:
return {
"response": f"Error processing message: {str(e)}",
"error": True,
"is_guidance": True
}
else:
return {
"response": "DroneAgent is initializing. Please try again in a moment.",
"error": True,
"is_guidance": True
}
if __name__ == "__main__":
port = int(os.environ.get('PORT', 7860)) # HF Spaces default port
print(f"🚁 Starting DroneAgent on port {port}")
uvicorn.run(app, host="0.0.0.0", port=port, log_level="info")