Files
chunking_strategies_evaluation/src/main.py
Mahdi Bazrafshan a309e64841 feat(admin): add admin backend endpoints and service layer
Why:
- Dashboard needs system health, Qdrant management, chunk preview, questions, and cost estimation endpoints

Changes:
- Add admin router with 11 endpoints (health, Qdrant CRUD, chunk preview, questions management, cost estimation)
- Add delete_experiment to SQLite storage
- Mount admin router and dashboard static files at /app

Impact:
- New /admin/* API routes available
- Dashboard served at /app/ via StaticFiles
2026-07-29 17:53:43 +03:30

106 lines
3.2 KiB
Python

"""FastAPI app factory. Composes all domain routers and middleware."""
import logging
import os
import time
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.requests import Request
from starlette.responses import Response
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from src.core.exceptions import (
ChunkingError,
BenchmarkError,
QueryError,
chunking_exception_handler,
benchmark_exception_handler,
)
from src.documents.routes import router as documents_router
from src.benchmarking.routes import router as benchmarking_router
from src.admin.routes import router as admin_router
from src.storage.sqlite import init_db
# Configure logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
)
logger = logging.getLogger(__name__)
# ── Request Logging Middleware ─────────────────────────────────────
class RequestLoggingMiddleware(BaseHTTPMiddleware):
"""Log request method, path, status code, and duration."""
async def dispatch(self, request: Request, call_next) -> Response:
start = time.time()
method = request.method
path = request.url.path
response = await call_next(request)
duration = (time.time() - start) * 1000 # ms
status = response.status_code
# Log at appropriate level
if status >= 500:
logger.error("%s %s -> %d (%.1fms)", method, path, status, duration)
elif status >= 400:
logger.warning("%s %s -> %d (%.1fms)", method, path, status, duration)
else:
logger.info("%s %s -> %d (%.1fms)", method, path, status, duration)
return response
def create_app() -> FastAPI:
"""Create and configure the FastAPI application.
Mounts domain routers and registers exception handlers.
"""
# Ensure SQLite tables exist at startup
init_db()
app = FastAPI(
title="RAG Chunking Benchmarker",
description="Benchmark five chunking strategies on regulatory documents. "
"Compare retrieval quality, answer faithfulness, and cost.",
version="0.1.0",
)
# CORS — allow all origins for development
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Request logging
app.add_middleware(RequestLoggingMiddleware)
# Register exception handlers
app.add_exception_handler(ChunkingError, chunking_exception_handler)
app.add_exception_handler(BenchmarkError, benchmark_exception_handler)
app.add_exception_handler(QueryError, benchmark_exception_handler)
# Mount domain routers
app.include_router(documents_router)
app.include_router(benchmarking_router)
app.include_router(admin_router)
# Mount dashboard at /app
static_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "static")
app.mount("/app", StaticFiles(directory=static_dir, html=True), name="dashboard")
return app
app = create_app()