test/moxie/main.py
2026-03-24 04:04:58 +00:00

114 lines
2.9 KiB
Python
Executable File

"""
MOXIE - Fake Local LLM Orchestrator
Main FastAPI Application Entry Point
"""
import sys
from pathlib import Path
# Add project root to path
sys.path.insert(0, str(Path(__file__).parent))
from contextlib import asynccontextmanager
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse, FileResponse
from fastapi.staticfiles import StaticFiles
from fastapi.middleware.cors import CORSMiddleware
from loguru import logger
from config import settings, get_data_dir, get_workflows_dir
from api.routes import router as api_router
from api.admin import router as admin_router
from core.orchestrator import Orchestrator
from rag.store import RAGStore
# Configure logging
logger.remove()
logger.add(
sys.stderr,
format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>",
level="DEBUG" if settings.debug else "INFO"
)
@asynccontextmanager
async def lifespan(app: FastAPI):
"""Application lifespan manager."""
logger.info("Starting MOXIE Orchestrator...")
# Initialize data directories
get_data_dir()
get_workflows_dir()
# Initialize RAG store
app.state.rag_store = RAGStore()
logger.info("RAG Store initialized")
# Initialize orchestrator
app.state.orchestrator = Orchestrator(app.state.rag_store)
logger.info("Orchestrator initialized")
logger.success(f"MOXIE ready on http://{settings.host}:{settings.port}")
logger.info(f"Admin UI: http://{settings.host}:{settings.port}/{settings.admin_path}")
yield
# Cleanup
logger.info("Shutting down MOXIE...")
# Create FastAPI app
app = FastAPI(
title="MOXIE",
description="OpenAI-compatible API that orchestrates multiple AI services",
version="1.0.0",
lifespan=lifespan,
docs_url=None, # Hide docs
redoc_url=None, # Hide redoc
)
# CORS middleware for open-webui
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Static files for admin UI
admin_static_path = Path(__file__).parent / "admin" / "static"
if admin_static_path.exists():
app.mount(
f"/{settings.admin_path}/static",
StaticFiles(directory=str(admin_static_path)),
name="admin-static"
)
# Include routers
app.include_router(api_router, prefix="/v1")
app.include_router(admin_router, prefix=f"/{settings.admin_path}", tags=["admin"])
@app.get("/health")
async def health_check():
"""Health check endpoint."""
return {"status": "healthy", "service": "moxie"}
# Serve favicon to avoid 404s
@app.get("/favicon.ico")
async def favicon():
return {"status": "not found"}
if __name__ == "__main__":
import uvicorn
uvicorn.run(
"main:app",
host=settings.host,
port=settings.port,
reload=settings.debug,
)