#!/usr/bin/env python3 """Simplified main application using modular FastAPI backend.""" import logging import gradio as gr import uvicorn from dotenv import load_dotenv from api.core.config import get_settings # Import the modular FastAPI app from api.main import app # Load environment variables load_dotenv() logger = logging.getLogger(__name__) settings = get_settings() def create_simple_gradio_interface() -> gr.Blocks: """Create a simple Gradio interface for testing the new backend.""" with gr.Blocks(title="KGraph-MCP - Modular Backend Test") as interface: gr.Markdown("# 🚀 KGraph-MCP with Modular FastAPI Backend") gr.Markdown("## Testing the new modular architecture") gr.Markdown( """ ### 🎯 New Architecture Features: - ✅ Modular FastAPI application structure - ✅ Separated routes, models, and services - ✅ Dependency injection pattern - ✅ Clean configuration management - ✅ Proper error handling ### 📋 API Endpoints Available: - `GET /health` - Health check - `GET /api/tasks` - List all tasks - `POST /api/tasks` - Create a new task - `GET /api/tasks/{id}` - Get specific task - `POST /api/tools/suggest` - Suggest tools for query - `POST /api/plan/generate` - Generate execution plan """ ) with gr.Row(): with gr.Column(): query_input = gr.Textbox( label="Test Query", placeholder="Enter a test query to analyze...", lines=2, ) test_button = gr.Button("🔍 Test Backend", variant="primary") with gr.Column(): output_display = gr.JSON(label="Backend Response") def test_backend(query: str) -> dict: """Test the backend services.""" from api.core.dependencies import get_planner_agent planner_agent = get_planner_agent() if not planner_agent: return { "status": "error", "message": "Backend services not initialized", } if not query.strip(): return {"status": "error", "message": "Please enter a test query"} try: # Test the planner planned_steps = planner_agent.generate_plan(query, top_k=2) return { "status": "success", "query": query, "backend_initialized": True, "plans_found": len(planned_steps), "first_plan": ( { "tool": ( planned_steps[0].tool.name if planned_steps else None ), "prompt": ( planned_steps[0].prompt.name if planned_steps else None ), "summary": ( planned_steps[0].summary if planned_steps else None ), } if planned_steps else None ), } except Exception as e: return {"status": "error", "message": f"Backend error: {e!s}"} test_button.click( fn=test_backend, inputs=[query_input], outputs=[output_display] ) gr.Markdown( """ --- **🔧 Development Notes:** - The old monolithic `app.py` (1392 lines) has been refactored into a clean modular structure - New structure follows FastAPI best practices with proper separation of concerns - All business logic moved to service layer with dependency injection - Configuration centralized using Pydantic settings - Ready for further development and testing """ ) return interface def main() -> None: """Main application entry point.""" logger.info(f"🚀 Starting {settings.app_title} v{settings.app_version}") logger.info(f"📡 API Server: http://{settings.host}:{settings.port}") logger.info(f"📚 API Documentation: http://{settings.host}:{settings.port}/docs") logger.info(f"🎨 Gradio UI: http://{settings.host}:{settings.port}/ui") try: # Create Gradio interface gradio_app = create_simple_gradio_interface() # Mount Gradio app to FastAPI combined_app = gr.mount_gradio_app(app, gradio_app, path="/ui") # Run the combined application uvicorn.run( combined_app, host=settings.host, port=settings.port, log_level=settings.log_level.lower(), reload=settings.reload, ) except Exception as e: logger.error(f"❌ Failed to start application: {e}") logger.info("🔄 Starting with FastAPI only...") # Fallback to FastAPI only uvicorn.run( app, host=settings.host, port=settings.port, log_level=settings.log_level.lower(), reload=settings.reload, ) if __name__ == "__main__": main()