Files
C.E.L_Slide_test2/src/main.py
kyeongmin 7ac9eea21a 런타임 품질 개선: Kei JSON 파싱 + 높이 예산 강제 + conclusion 강제 + FAISS 프리로드
1. kei_client.py: Kei API가 마크다운 리스트(- ) 접두사로 JSON 응답 시 전처리하여 파싱
2. image_utils.py: base_path+상대경로 이중 시 파일명 rglob 재탐색
3. design_director.py:
   - conclusion 꼭지 → footer zone + conclusion-accent-bar 코드 레벨 강제
   - _validate_height_budget(): zone별 height_cost 합산 검증, 초과 시 큰 블록 자동 교체
   - Opus 추천 프롬프트에 zone 배정 규칙 명시 (conclusion→footer 등)
4. main.py: 서버 startup 시 FAISS 인덱스 + bge-m3 모델 미리 로드

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 19:15:28 +09:00

73 lines
2.1 KiB
Python

from __future__ import annotations
import json
import logging
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import FileResponse
from fastapi.staticfiles import StaticFiles
from pathlib import Path
from pydantic import BaseModel
from sse_starlette.sse import EventSourceResponse
from src.config import settings
from src.pipeline import generate_slide
logging.basicConfig(level=getattr(logging, settings.log_level, logging.DEBUG))
logger = logging.getLogger(__name__)
app = FastAPI(title="Design Agent", version="0.1.0")
@app.on_event("startup")
async def startup_preload():
"""서버 시작 시 FAISS 인덱스 + 임베딩 모델 미리 로드."""
try:
from src.block_search import _ensure_loaded
_ensure_loaded()
logger.info("FAISS 인덱스 + bge-m3 모델 미리 로드 완료")
except Exception as e:
logger.warning(f"FAISS 미리 로드 실패 (첫 요청 시 로드): {e}")
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:5174", "http://localhost:5173"],
allow_methods=["*"],
allow_headers=["*"],
)
# 정적 파일 서빙 (CSS, 폰트 등)
static_dir = Path(__file__).parent.parent / "static"
if static_dir.exists():
app.mount("/static", StaticFiles(directory=str(static_dir)), name="static")
class SlideRequest(BaseModel):
content: str
base_path: str = "" # 이미지 기준 폴더 경로 (선택, 로컬 경로)
@app.get("/api/health")
async def health():
return {"status": "ok", "service": "design-agent"}
@app.post("/api/generate")
async def generate(req: SlideRequest):
"""콘텐츠 → 슬라이드 생성 (SSE 스트리밍)."""
async def event_stream():
async for event in generate_slide(req.content, base_path=req.base_path):
yield {
"event": event["event"],
"data": json.dumps(event["data"], ensure_ascii=False),
}
return EventSourceResponse(event_stream())
@app.get("/")
async def frontend():
"""프론트엔드 UI — static/index.html 서빙."""
return FileResponse(str(static_dir / "index.html"), media_type="text/html")