File size: 2,202 Bytes
c87117f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import logging
import sys
from contextlib import asynccontextmanager
from pathlib import Path

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel

sys.path.insert(0, str(Path(__file__).resolve().parent))

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

PROJECT_ROOT  = Path(__file__).resolve().parent.parent
GRAPHRAG_ROOT = PROJECT_ROOT / "graphrag_input"


@asynccontextmanager
async def lifespan(app: FastAPI):
    logger.info(f"Loading GraphRAG engine from {GRAPHRAG_ROOT} ...")
    try:
        from query_engine import init_engine
        init_engine(str(GRAPHRAG_ROOT))
        logger.info("GraphRAG engine ready ✅")
    except Exception as e:
        logger.error(f"Engine load failed (queries will return 503): {e}")
    yield
    logger.info("Shutdown")


app = FastAPI(
    title="K-Drama GraphRAG API",
    description="Persistent in-memory GraphRAG over 1637 K-dramas",
    version="2.0.0",
    lifespan=lifespan,
)


class QueryRequest(BaseModel):
    question: str
    method: str = "global"


class QueryResponse(BaseModel):
    question: str
    method: str
    answer: str


@app.get("/")
def root():
    try:
        from query_engine import get_engine
        loaded = get_engine()._loaded
    except Exception:
        loaded = False
    return {"status": "running", "engine_loaded": loaded}


@app.get("/health")
def health():
    return {"status": "ok"}


@app.post("/query", response_model=QueryResponse)
def query(request: QueryRequest):
    if request.method not in ["global", "local"]:
        raise HTTPException(400, "method must be 'global' or 'local'")
    if not request.question.strip():
        raise HTTPException(400, "question cannot be empty")
    try:
        from query_engine import get_engine
        answer = get_engine().query_sync(request.question, request.method)
        return QueryResponse(
            question=request.question,
            method=request.method,
            answer=answer,
        )
    except RuntimeError as e:
        raise HTTPException(503, f"Engine not ready: {e}")
    except Exception as e:
        logger.exception("Query failed")
        raise HTTPException(500, str(e))