97 lines
2.9 KiB
Python
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()
|