from fastapi import FastAPI, WebSocket from fastapi.middleware.cors import CORSMiddleware import logging import os from backend.app.api import (auth, domains, knowledge, models, orcid_auth, proposals, questions, succession, system, config, training, enrichment) from backend.app.config import settings # 新しいOAuth & ワークスペースAPIをインポート try: from backend.app.api import oauth, workspaces oauth_available = True except ImportError: oauth_available = False logging.warning("OAuth and Workspaces modules not available") # ロギング設定 logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) # FastAPIアプリケーションの作成 app = FastAPI( title="NullAI API", description="Zero-Hallucination Knowledge Reasoning Engine API with Multi-Tenant Workspaces", version="0.2.0" ) # Check app mode from environment variable and log it APP_MODE = os.getenv("APP_MODE", "FULL").upper() logger.info(f"Application starting in APP_MODE: {APP_MODE}") # CORSミドルウェアの設定 app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Check app mode from environment variable APP_MODE = os.getenv("APP_MODE", "FULL").upper() # ===== Application Lifecycle Events ===== @app.on_event("startup") async def startup_event(): """アプリケーション起動時の処理""" logger.info("Application startup - initializing services...") # 自動学習監視サービスの起動 (FULL modeのみ) settings_dict = settings.model_dump() if hasattr(settings, "model_dump") else settings.dict() auto_training_enabled = settings_dict.get("auto_training", {}).get("enabled", False) if APP_MODE == "FULL" and auto_training_enabled: try: from backend.app.api.training import start_auto_training_monitor start_auto_training_monitor() logger.info("Auto-training monitor started successfully") except Exception as e: logger.error(f"Failed to start auto-training monitor: {e}", exc_info=True) @app.on_event("shutdown") async def shutdown_event(): """アプリケーション終了時の処理""" logger.info("Application shutdown - cleaning up services...") # 自動学習監視サービスの停止 if APP_MODE == "FULL": try: from backend.app.api.training import stop_auto_training_monitor stop_auto_training_monitor() logger.info("Auto-training monitor stopped successfully") except Exception as e: logger.error(f"Failed to stop auto-training monitor: {e}", exc_info=True) # ルーター登録 # Core routers for both modes # app.include_router(auth.router, prefix="/api/auth", tags=["Authentication"]) # DEPRECATED # app.include_router(orcid_auth.router, prefix="/api/auth", tags=["ORCID Authentication"]) # DEPRECATED app.include_router(domains.router, prefix="/api/domains", tags=["Domains"]) app.include_router(proposals.router, prefix="/api/proposals", tags=["Proposals"]) app.include_router(knowledge.router, prefix="/api/knowledge", tags=["Knowledge Base"]) app.include_router(system.router, prefix="/api/system", tags=["System"]) app.include_router(config.router, prefix="/api/config", tags=["Configuration"]) # Routers for FULL mode only if APP_MODE == "FULL": app.include_router(questions.router, prefix="/api/questions", tags=["Questions"]) app.include_router(models.router, prefix="/api/models", tags=["Models"]) app.include_router(succession.router, prefix="/api/succession", tags=["Model Succession"]) app.include_router(training.router, prefix="/api/training", tags=["Fine-tuning"]) app.include_router(enrichment.router, prefix="/api/enrichment", tags=["Enrichment"]) logger.info("Running in FULL mode. All inference APIs enabled.") else: logger.info(f"Running in {APP_MODE} mode. Inference APIs are disabled.") # 新しい認証&ワークスペースルーター if oauth_available: app.include_router(oauth.router, prefix="/api/oauth", tags=["OAuth Authentication"]) app.include_router(workspaces.router, prefix="/api/workspaces", tags=["Workspaces"]) logger.info("OAuth and Workspaces APIs enabled") # ヘルスチェック @app.get("/health") async def health_check(): return {"status": "ok", "service": "ilm-athens-api"} # ルートエンドポイント @app.get("/") async def root(): return { "message": "Ilm-Athens API v0.1 (Backend)", "docs": "/docs", "health": "/health" } # Log all registered routes for debugging from fastapi.routing import APIRoute logger.info("--- Registered Routes ---") for route in app.routes: if isinstance(route, APIRoute): logger.info(f"Path: {route.path}, Methods: {route.methods}") logger.info("-------------------------") if __name__ == "__main__": import uvicorn # `reload=True`は開発時のみ使用 uvicorn.run( "app.main:app", host="0.0.0.0", port=8000, reload=settings.DEBUG, log_level="info" if settings.DEBUG else "warning" )