from fastapi import FastAPI, Request from fastapi.templating import Jinja2Templates from fastapi.staticfiles import StaticFiles from fastapi.responses import HTMLResponse, JSONResponse import pandas as pd from pathlib import Path import asyncio import time from app.backend.constant import Navigation, ModelProvider, EvaluationMetric, EmbdDtype, EmbdDim, Similarity from app.backend.data_engine import DataEngine # 创建 FastAPI 应用 app = FastAPI() # 获取项目根目录 BASE_DIR = Path(__file__).resolve().parent # 挂载静态文件 app.mount("/static", StaticFiles(directory=str(BASE_DIR / "app" / "static")), name="static") # 设置模板 templates = Jinja2Templates(directory=str(BASE_DIR / "app" / "templates")) # 初始化数据引擎 data_engine = None initialization_start_time = None async def initialize_data_engine(): global data_engine, initialization_start_time if data_engine is None and initialization_start_time is None: initialization_start_time = time.time() try: data_engine = DataEngine() print("Successfully initialized DataEngine") except Exception as e: print(f"Error initializing DataEngine: {str(e)}") finally: initialization_start_time = None @app.on_event("startup") async def startup_event(): asyncio.create_task(initialize_data_engine()) @app.get("/health") async def health(): if data_engine is not None: return {"status": "healthy", "initialized": True} elif initialization_start_time is not None: return {"status": "initializing", "initialized": False, "elapsed_time": time.time() - initialization_start_time} else: return {"status": "not_initialized", "initialized": False} @app.get("/", response_class=HTMLResponse) async def home(request: Request, tab: str = "text"): if data_engine is None: return templates.TemplateResponse("loading.html", {"request": request}) try: # Get initial data based on tab if tab == "multimodal": data = data_engine.get_filtered_data(navigation="multimodal") else: data = data_engine.get_data() # Convert data to list for template rendering data_list = data.values.tolist() columns = data.columns.tolist() return templates.TemplateResponse("index.html", { "request": request, "active_tab": tab, "data": data_list, "columns": columns, "navigations": [e.value for e in Navigation], "embd_types": [e.value for e in EmbdDtype], "embd_dims": [e.value for e in EmbdDim], "similarities": [e.value for e in Similarity] }) except Exception as e: print(f"Error in home route: {str(e)}") return templates.TemplateResponse("error.html", { "request": request, "error": str(e) }) @app.post("/api/filter") async def filter_data(filters: dict): if data_engine is None: return JSONResponse( status_code=503, content={"error": "Service is still initializing"} ) try: # Apply filters to data data = data_engine.get_filtered_data( navigation=filters.get('navigation'), embd_type=filters.get('embd_type'), embd_dims=filters.get('embd_dims'), similarity=filters.get('similarity') ) # Convert to list for JSON response return data.values.tolist() except Exception as e: print(f"Error in filter route: {str(e)}") return JSONResponse( status_code=500, content={"error": str(e)} )