sangsangfinder / api /main.py
cksleigen's picture
Initial clean deploy
54656fc
Raw
History Blame Contribute Delete
3.13 kB
from contextlib import asynccontextmanager
from fastapi import FastAPI, HTTPException
from .core.models import get_vector_collection, load_notices_cache
from .schemas import (
HealthResponse,
NoticeItem,
RecommendRequest,
RecommendResponse,
SearchRequest,
SearchResponse,
)
from .services.recommend_service import recommend_notices, summarize_notice
from .services.search_service import (
generate_llm_reply,
hybrid_search,
)
@asynccontextmanager
async def lifespan(app: FastAPI):
yield
app = FastAPI(
title="์ƒ์ƒํŒŒ์ธ๋” API",
description="ํ•œ์„ฑ๋Œ€ํ•™๊ต ๊ณต์ง€์‚ฌํ•ญ ๊ฒ€์ƒ‰ ๋ฐ ์ถ”์ฒœ API",
version="1.0.0",
lifespan=lifespan,
)
@app.get("/api/v1/health", response_model=HealthResponse, tags=["System"])
def health_check():
notices = load_notices_cache()
try:
indexed = get_vector_collection().count()
except Exception:
indexed = 0
return HealthResponse(
status="ok",
notices_count=len(notices),
indexed_count=indexed,
)
@app.post("/api/v1/search", response_model=SearchResponse, tags=["Search"])
def search(req: SearchRequest):
try:
raw_results = hybrid_search(
query=req.query,
top_k=req.top_k,
alpha=req.alpha,
category_filter=req.category,
candidate_k=50 if req.feature_rerank else None,
feature_rerank=req.feature_rerank,
profile=req.profile,
)
except Exception as e:
raise HTTPException(status_code=500, detail=f"๊ฒ€์ƒ‰ ์˜ค๋ฅ˜: {e}")
# SearchRequest์— profile์ด ์—†์œผ๋ฏ€๋กœ ๋นˆ dict ์ „๋‹ฌ (์ด๋ฆ„ ์ธ์‚ฌ๋ง ์ƒ๋žต)
reply = generate_llm_reply(
user_query=req.query,
results=raw_results,
profile=req.profile,
is_first=req.is_first,
)
items = [
NoticeItem(
title=r["title"],
url=r["url"],
date=r["date"],
category=r.get("category", "๊ธฐํƒ€"),
score=r["score"],
)
for r in raw_results
]
return SearchResponse(reply=reply, results=items)
@app.post("/api/v1/recommend", response_model=RecommendResponse, tags=["Recommend"])
def recommend(req: RecommendRequest):
profile = {
"college": req.college,
"track": req.track,
"grade": req.grade,
"interests": req.interests,
}
try:
raw_results = recommend_notices(profile, top_k=req.top_k)
except Exception as e:
raise HTTPException(status_code=500, detail=f"์ถ”์ฒœ ์˜ค๋ฅ˜: {e}")
notices = load_notices_cache()
body_map = {n["url"]: n.get("body", "") for n in notices}
items = []
for r in raw_results:
body = body_map.get(r["url"], "")
summary = summarize_notice(r["title"], body) if body else None
items.append(NoticeItem(
title=r["title"],
url=r["url"],
date=r["date"],
category=r.get("category", "๊ธฐํƒ€"),
score=r["score"],
summary=summary,
))
return RecommendResponse(results=items)