File size: 2,761 Bytes
5b7955a
 
 
 
b9ba43b
aa76de3
 
 
 
 
 
 
 
5b7955a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b9ba43b
 
 
 
 
 
5b7955a
 
 
 
 
14d08f0
5b7955a
 
14d08f0
5b7955a
 
aa76de3
 
5b7955a
 
 
 
 
 
 
 
 
 
 
 
aa76de3
b9ba43b
5b7955a
 
b9ba43b
5b7955a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b9ba43b
 
 
 
 
 
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
"""PolicyDecoder RAG API — FastAPI application entry point."""

import sys
import io
import os

# Force UTF-8 encoding for stdout and stderr on Windows to prevent logging crashes
if sys.platform == "win32":
    try:
        sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
        sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8')
    except Exception:
        pass # Fallback if buffer is not available

from contextlib import asynccontextmanager
import logging

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
import uvicorn

from api.routes.query import router as query_router
from api.routes.ingest import router as ingest_router
from api.routes.health import router as health_router

logger = logging.getLogger(__name__)


def _get_cors_origins() -> list[str]:
    raw_origins = os.getenv("CORS_ORIGINS", "*")
    origins = [origin.strip() for origin in raw_origins.split(",") if origin.strip()]
    return origins or ["*"]


# ------------------------------------------------------------------ #
#  Lifespan — pre-load heavy components once at startup
# ------------------------------------------------------------------ #
@asynccontextmanager
async def lifespan(app: FastAPI):
    logger.info("Lifespan: Loading heavy components...")
    from rag_engine.services.query_service import QueryService

    logger.info("Initializing QueryService...")
    app.state.query_service = QueryService()
    logger.info("QueryService loaded and ready")
    yield  # app is running
    # shutdown cleanup (nothing required for now)


# ------------------------------------------------------------------ #
#  App
# ------------------------------------------------------------------ #
app = FastAPI(
    title="PolicyDecoder RAG API",
    description="AI-powered insurance policy Q&A engine",
    version="1.0.0",
    lifespan=lifespan,
)

# CORS — wide open for development; backend team will restrict in prod
cors_origins = _get_cors_origins()
app.add_middleware(
    CORSMiddleware,
    allow_origins=cors_origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# ------------------------------------------------------------------ #
#  Routers
# ------------------------------------------------------------------ #
app.include_router(query_router)
app.include_router(ingest_router)
app.include_router(health_router)

# ------------------------------------------------------------------ #
#  Dev entry point
# ------------------------------------------------------------------ #
if __name__ == "__main__":
    uvicorn.run(
        "api.main:app",
        host=os.getenv("HOST", "0.0.0.0"),
        port=int(os.getenv("PORT", "8000")),
        reload=True,
    )