Initial commit: Kei Design Agent
콘텐츠를 시각적으로 구조화된 슬라이드 HTML로 변환하는 독립 에이전트. 아키텍처 (4단계 파이프라인): 1. Kei 실장 (Opus) — 콘텐츠 유형 분류 + 블록 배치 2. 디자인 팀장 (Sonnet) — 레이아웃 컨셉 (블록 배치 + 페이지 수) 3. 텍스트 편집자 (Sonnet) — 슬롯 텍스트 정리 (핵심 유지) 4. CSS Grid 렌더러 — HTML 조립 블록 템플릿 7종: comparison, card-grid, relationship, process, quote-block, conclusion-bar, comparison-table 기술 스택: FastAPI + Anthropic API + Jinja2 + CSS Grid Pretendard Variable 한국어 폰트 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
60
src/main.py
Normal file
60
src/main.py
Normal file
@@ -0,0 +1,60 @@
|
||||
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.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
|
||||
|
||||
|
||||
@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):
|
||||
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")
|
||||
Reference in New Issue
Block a user