| from contextlib import asynccontextmanager |
| from pathlib import Path |
|
|
| from fastapi import FastAPI |
| from fastapi.middleware.cors import CORSMiddleware |
| from fastapi.responses import FileResponse |
| from fastapi.staticfiles import StaticFiles |
|
|
| from app.config import get_settings |
| from app.routers import docs, ingest, query |
| from app.state import AppState |
|
|
|
|
| @asynccontextmanager |
| async def lifespan(app: FastAPI): |
| settings = get_settings() |
| state = AppState.from_settings(settings) |
| state.vector_store.load_existing() |
| app.state.rag = state |
| yield |
|
|
|
|
| app = FastAPI( |
| title="RAG Document Q&A API", |
| description="A low-level RAG pipeline for document ingestion and grounded Q&A.", |
| version="0.1.0", |
| lifespan=lifespan, |
| ) |
|
|
| app.add_middleware( |
| CORSMiddleware, |
| allow_origins=["*"], |
| allow_credentials=False, |
| allow_methods=["*"], |
| allow_headers=["*"], |
| ) |
|
|
| app.include_router(ingest.router) |
| app.include_router(query.router) |
| app.include_router(docs.router) |
|
|
| frontend_dir = Path(__file__).resolve().parent.parent / "frontend" |
| if frontend_dir.exists(): |
| app.mount("/static", StaticFiles(directory=frontend_dir), name="static") |
|
|
|
|
| @app.get("/", include_in_schema=False) |
| def frontend() -> FileResponse: |
| return FileResponse(frontend_dir / "index.html") |
|
|
|
|
| @app.get("/health", tags=["health"]) |
| def health() -> dict[str, str]: |
| return {"status": "ok"} |
|
|