Files
C.E.L_Slide_test2/README.md
kyeongmin b0bcffc0f6 Phase N+O: 컨테이너 기반 레이아웃 + Step B 제거 + 전면 정리
- Phase N: catalog 개선, fallback 전면 제거, Kei API 무한 재시도, topic_id 버그 수정
- Phase O: 컨테이너 스펙 계산(비중→px), 블록 스펙 확정, 렌더러 container div
- Step B(Sonnet) 제거: Kei(A-2)+코드로 대체. STEP_B_PROMPT/fallback/DOWNGRADE_MAP 삭제
- Selenium: container div 감지 추가
- catalog.yaml: ref_chars 구조 변환 + FAISS 재빌드
- 문서 전면 갱신: README, PROGRESS, IMPROVEMENT, Phase I~O md

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

252 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Kei Design Agent
콘텐츠를 시각적으로 구조화된 슬라이드 HTML(1280×720px, 16:9)로 변환하는 AI 파이프라인.
## 개요
텍스트/MDX 콘텐츠를 입력하면 Kei 실장(Opus)이 정보 구조와 비중을 판단하고, 그 비중대로 컨테이너를 확정하고, 블록을 선택하고, 텍스트를 편집하여 슬라이드를 생성한다.
**핵심 특징:**
- 콘텐츠마다 비중이 동적으로 변한다 (본심 60% / 배경 20% 등 — Kei가 매번 판단)
- 비중이 컨테이너 px를 확정 → 블록과 텍스트가 컨테이너에 맞춰진다
- Kei API 필수. fallback 없음. 성공할 때까지 무한 재시도.
---
## 파이프라인 (6단계)
```
텍스트 입력
[1단계] Kei 실장 — 꼭지 추출 + 비중 판단 (Kei API / Opus)
[1.5단계] Kei 실장 — 컨셉 구체화 (Kei API / Opus)
[컨테이너 계산] 비중 → px 확정 (코드, 결정론적)
[2단계] 블록 확정 + 배치 (Kei API + Sonnet)
[블록 스펙 확정] 항목수/글자수/폰트 (코드, 결정론적)
[3단계] Kei 편집자 — 텍스트 정리 (Kei API / Opus)
[4단계] 디자인 실무자 — CSS 조정 + HTML 조립 (Sonnet + Jinja2)
[Phase L] Selenium 렌더링 측정 → 피드백 루프
[5단계] Kei 실장 — 최종 검수 (스크린샷) (Opus 멀티모달)
완성 슬라이드 HTML
```
### 단계별 상세
| 단계 | 담당 | AI | 역할 |
|------|------|-----|------|
| **1A** | Kei 실장 | Kei API (Opus) | 핵심 메시지, 꼭지 추출, page_structure(비중), purpose 부여 |
| **1B** | Kei 실장 | Kei API (Opus) | relation_type, expression_hint, source_data |
| **컨테이너** | 코드 | — | Kei 비중 → 역할별 컨테이너 px 확정, height_cost 제약, 블록 스펙 |
| **2 A-2** | Kei 실장 | Kei API (Opus) | 컨테이너 제약 보고 블록 확정 (FAISS 후보 기반) |
| **2 B** | 디자인 팀장 | Sonnet | zone 배치 + char_guide만 (블록 타입 변경 불가) |
| **블록 스펙** | 코드 | — | 컨테이너 크기 → 항목수/글자수/폰트/패딩 확정 |
| **3** | Kei 편집자 | Kei API (Opus) | 텍스트 편집 (컨테이너 제약 준수, 원본 보존) |
| **4** | 디자인 실무자 | Sonnet | CSS 변수 override + Jinja2 렌더링 |
| **Phase L** | 코드 | Selenium | 렌더링 측정 → overflow 감지 → 편집자 재호출 |
| **5** | Kei 실장 | Opus | 스크린샷 보고 최종 검수 (멀티모달) |
### 핵심 원칙
- **비중 → 컨테이너 → 블록 → 콘텐츠** 순서. 비중이 모든 것을 결정
- **Kei API 필수.** fallback 없음. 기본값 없음. 성공할 때까지 무한 재시도
- **Sonnet은 zone 배치 + CSS 조정만.** 블록 선택/콘텐츠 판단 금지
- **블록 선택은 Kei가 확정 → 코드가 강제.** Sonnet이 변경 불가
- **텍스트가 기준.** 디자인이 텍스트에 맞춤. CSS로 사후 자르기 금지
---
## 컨테이너 시스템 (Phase O)
Kei가 판단한 비중이 시각적 레이아웃에 정확히 반영되는 구조.
```
슬라이드 1280×720px
├── header: 제목 (~60px 고정)
├── body (65%): 490px
│ ├── 배경 컨테이너: 490 × 20% = 98px ← Kei 비중으로 확정
│ │ └── 문제제기 + 근거사례 (compact 블록만)
│ └── 본심 컨테이너: 490 × 60% = 294px ← Kei 비중으로 확정
│ └── 핵심전달 (large/xlarge 블록 가능)
├── sidebar (35%): 490px
│ └── 첨부 컨테이너: 490px 전체
│ └── 용어 정의 (여유 있게)
└── footer: 결론 (~60px 고정)
└── banner-gradient (핵심 메시지 한 줄)
```
- 컨테이너 높이(px)가 블록의 height_cost를 제약
- 컨테이너 크기에서 항목수/글자수/폰트/패딩이 자동 계산
- 편집자에게 컨테이너 제약이 전달되어 텍스트 분량이 맞춰짐
---
## 개선 이력
| Phase | 내용 | 상태 |
|-------|------|------|
| **A~D** | 슬라이드 품질 핵심 (디자인 조정, overflow 방지, 이미지 처리) | 완료 |
| **G** | Kei API 통신 정상화 (SSE 스트리밍, Sonnet fallback 제거, GPU 분리) | 완료 |
| **H** | 스토리라인 설계 기반 전환 (core_message, purpose, source_hint) | 완료 |
| **I** | 전수 정합성 복구 + 넘침 처리 패러다임 전환 (14건) | 완료 |
| **J** | 블록 선택 권한 구조 재정의 + 최종 검토 Kei 전환 | 완료 |
| **K** | communicative role 기반 시각적 위계 + purpose별 분량 제약 | 완료 |
| **K-1** | 파이프라인 스텝별 중간 산출물 로컬 저장 (`data/runs/`) | 완료 |
| **L** | 렌더링 측정 에이전트 (Selenium headless) + 피드백 루프 | 완료 |
| **M** | Kei 비중 시스템 (page_structure weight) + 원본 보존 강화 | 완료 |
| **N** | 4대 핵심 문제 해결 — catalog 개선, fallback 전면 제거, topic_id 버그 수정, 무한 재시도 | 완료 |
| **O** | 컨테이너 기반 레이아웃 시스템 — 비중→px→블록제약→콘텐츠제약 | **진행 중** |
---
## 중간 산출물
파이프라인 실행마다 `data/runs/{timestamp}/`에 단계별 결과가 저장된다.
| 파일 | 단계 | 내용 |
|------|------|------|
| `step1_analysis.json` | 1A | 꼭지 추출, page_structure(비중), core_message |
| `step1b_concepts.json` | 1B | relation_type, expression_hint, source_data |
| `step1c_containers.json` | O-1 | 역할별 컨테이너 스펙 (height_px, width_px, max_height_cost) |
| `step2_layout.json` | 2 | 블록 배치 (area, type, purpose, reason) |
| `step2c_block_specs.json` | O-3 | 블록별 스펙 (_max_items, _max_chars, _font_size_px) |
| `step3_filled_blocks.json` | 3 | 텍스트 편집 결과 (data, char_count) |
| `step4_css_adjustment.json` | 4 | CSS 변수 override |
| `step4_rendered.html` | 4 | 렌더링된 HTML |
| `step4_measurement_round*.json` | Phase L | Selenium 측정 (scrollHeight, overflow) |
| `step5_review_round*.json` | 5 | Kei 검수 결과 |
| `final.html` | 최종 | 완성 슬라이드 |
| `report.html` | 리포트 | 전 단계 시각화 리포트 |
리포트 생성: `python scripts/generate_run_report.py`
---
## 블록 라이브러리 (38개)
6개 카테고리, 38개 블록. 각 블록은 `catalog.yaml`에 용도(when), 금지(not_for), purpose_fit이 정의됨.
| 카테고리 | 개수 | 용도 |
|---------|------|------|
| **headers** | 5 | 타이틀, 꼭지 헤더 |
| **cards** | 9 | 항목 나열, 카드 그리드 |
| **tables** | 3 | 비교표, 데이터 테이블 |
| **visuals** | 6 | SVG 다이어그램, 관계도 |
| **emphasis** | 10 | 강조, 인용, 결론, 불릿 |
| **media** | 5 | 이미지/사진 |
FAISS 블록 검색: bge-m3 1024차원 임베딩 → 꼭지별 관련 블록 후보 추출
---
## 기술 스택
| 역할 | 도구 |
|------|------|
| 서버 | FastAPI + uvicorn (포트 8001) |
| AI (Kei 실장/편집자) | Kei API → Opus (localhost:8000) |
| AI (디자인 팀장/실무자) | Anthropic API → Sonnet |
| AI (최종 검수) | Anthropic API → Opus (멀티모달) |
| 블록 검색 | FAISS + bge-m3 |
| 템플릿 | Jinja2 |
| 렌더링 | CSS Grid + 디자인 토큰 (1280×720) |
| 렌더링 측정 | Selenium headless Chrome |
| SVG 시각화 | svg_calculator.py (N개 동적 배치) |
| 이미지 | Pillow (크기 측정) + base64 인라인 |
| 폰트 | Pretendard Variable |
| 공간 계산 | space_allocator.py (결정론적) |
---
## 설치 및 실행
```bash
# 설치
cd design_agent
pip install -e .
# FAISS 인덱스 빌드 (블록 추가/수정 시)
python scripts/build_block_index.py
# .env 설정
ANTHROPIC_API_KEY=sk-ant-...
KEI_API_URL=http://localhost:8000
LOG_LEVEL=DEBUG
```
```bash
# 터미널 1: Kei API (필수)
cd D:\ad-hoc\kei\persona_agent
python -m uvicorn backend.main:app --host 127.0.0.1 --port 8000
# 터미널 2: Design Agent
cd D:\ad-hoc\kei\design_agent
python -m uvicorn src.main:app --host 127.0.0.1 --port 8001 --reload
```
접속: http://localhost:8001
---
## 프로젝트 구조
```
design_agent/
├── src/
│ ├── main.py FastAPI 서버 (포트 8001)
│ ├── config.py 설정 (pydantic-settings)
│ ├── pipeline.py 파이프라인 오케스트레이션 (6단계)
│ ├── kei_client.py Kei API 클라이언트 (1A, 1B, 검수, 넘침 판단)
│ ├── design_director.py 2단계: 프리셋 + Kei 블록 확정 + Sonnet zone 배치
│ ├── content_editor.py 3단계: Kei API 텍스트 편집
│ ├── renderer.py 4단계: HTML 조립 (컨테이너 grid + Jinja2)
│ ├── space_allocator.py 컨테이너 스펙 계산 + 블록 스펙 확정 (Phase O)
│ ├── slide_measurer.py Selenium 렌더링 측정 + 스크린샷 (Phase L/N)
│ ├── block_search.py FAISS 블록 검색
│ ├── svg_calculator.py SVG 좌표 계산 (N개 동적 배치)
│ ├── image_utils.py 이미지 크기 측정 + base64 삽입
│ └── sse_utils.py SSE 스트리밍 유틸
├── templates/
│ ├── slide-base.html 슬라이드 베이스
│ ├── catalog.yaml 블록 카탈로그 (38개, when/not_for/purpose_fit)
│ └── blocks/ 블록 라이브러리 (6 카테고리)
├── scripts/
│ ├── build_block_index.py FAISS 인덱스 빌드
│ └── generate_run_report.py 실행 리포트 생성
├── static/ 프론트엔드 (index.html, CSS)
├── data/ 로컬 데이터 (runs/, FAISS 인덱스)
├── docs/ 기술 조사, Figma 분석
├── IMPROVEMENT.md 개선 계획 총괄 (Phase A~O)
├── IMPROVEMENT-PHASE-*.md 각 Phase 상세
└── PROGRESS.md 진행 상황 추적
```
---
## Kei Persona와의 관계
```
Kei Persona Agent (localhost:8000)
├── Opus + RAG + 세션 컨텍스트
├── 도메인 지식 (건설/DX/BIM)
└── 대화/생성/피드백/실행 모드
Design Agent (localhost:8001, 이 프로젝트)
├── 슬라이드 생성 전용
├── Kei API로 실장(1단계) + 편집자(3단계) + 블록 확정(2단계) 호출
├── 최종 검수(5단계)는 Opus 직접 호출 (멀티모달 스크린샷)
└── 두 프로젝트는 독립. 코드 공유 없음. API 연동만.
```