o2o-plagiarism-ai/app/main.py

97 lines
2.9 KiB
Python

from __future__ import annotations
import logging
from contextlib import asynccontextmanager
from pathlib import Path
from fastapi import FastAPI
from fastapi.responses import FileResponse
from fastapi.staticfiles import StaticFiles
from app.api.routes import router as api_router
from app.core.config import get_settings
from app.engine.detector import PlagiarismDetector
from app.jobs.store import JobStore
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(name)s: %(message)s")
@asynccontextmanager
async def lifespan(app: FastAPI):
settings = get_settings()
app.state.settings = settings
app.state.detector = PlagiarismDetector(settings=settings)
app.state.job_store = JobStore()
import threading
app.state.detector_lock = threading.Lock()
logging.info(
"Engine ready: version=%s, corpus_size=%d",
settings.engine_version,
app.state.detector.corpus_size,
)
yield
def rebuild_detector(app: FastAPI) -> int:
"""코퍼스 변경 후 인덱스 재빌드. 호출 시점에 lock으로 보호."""
settings = app.state.settings
with app.state.detector_lock:
app.state.detector = PlagiarismDetector(settings=settings)
return app.state.detector.corpus_size
_settings = get_settings()
app = FastAPI(
title="O2O 저작권 침해 여부 탐지 API",
description=(
"오투오 1단계 산출물 - 콘텐츠 표절 여부 AI 탐지 모듈. "
"본 응답 스키마는 커뮤니케이션북스(아카이빙) 및 바이칼AI(분석 보고서) 통합 기준."
),
version="1.0.0",
lifespan=lifespan,
root_path=_settings.root_path,
)
app.include_router(api_router)
_STATIC_DIR = Path(__file__).resolve().parent / "static"
if _STATIC_DIR.exists():
app.mount("/static", StaticFiles(directory=str(_STATIC_DIR)), name="static")
@app.get("/", include_in_schema=False)
async def root() -> FileResponse:
"""검토 콘솔 페이지 — 컴북스 측이 브라우저에서 직접 엔진 성능 확인."""
index = _STATIC_DIR / "index.html"
if index.exists():
return FileResponse(str(index))
from fastapi.responses import JSONResponse
return JSONResponse({"service": "o2o-plagiarism-api", "docs": "/docs"})
def main() -> None:
"""`.env` 의 HOST/PORT/LOG_LEVEL/RELOAD 를 읽어 서버 기동.
사용법:
python -m app.main # .env 따라 실행
PORT=9000 python -m app.main # 환경변수 override
"""
import uvicorn
settings = get_settings()
uvicorn.run(
"app.main:app",
host=settings.host,
port=settings.port,
log_level=settings.log_level,
reload=settings.reload,
root_path=settings.root_path,
forwarded_allow_ips="*", # 리버스 프록시(Apache) 헤더 신뢰
proxy_headers=True,
)
if __name__ == "__main__":
main()