File size: 5,210 Bytes
594ed40
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
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"
    )