Phase P~S 전체 작업물: 검증 스크립트, 블록 템플릿, 설계 문서, 코드 수정

포함 내용:
- Phase P/Q/R/S 설계 문서 (IMPROVEMENT-PHASE-*.md)
- 영역별 검증 스크립트 (scripts/verify_*.py, test_*.py)
- 블록 템플릿 추가 (cards, emphasis 변형)
- 코드 수정: block_search, content_editor, design_director, slide_measurer
- catalog.yaml 블록 목록 업데이트
- CLAUDE.md, PROGRESS.md, README.md 업데이트

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-31 08:38:06 +09:00
parent 0e4b8c091c
commit 29f56187c0
44 changed files with 9431 additions and 313 deletions

View File

@@ -1,12 +1,11 @@
# Design Agent — 진행 상황
## 현재 상태 요약 (2026-03-27 기준)
## 현재 상태 요약 (2026-03-28 기준)
| 상태 | 내용 |
|------|------|
| **완료** | Phase 1~5 기반 구축, Phase I~N 개선, Step B 제거 + 죽은 코드 정리 |
| **진행 중** | Phase O 컨테이너 시스템 (코드 작성 완료, 미세 조정 필요) |
| **미해결** | 컨테이너 크기 vs 블록 크기 불일치, Selenium container div 미감지 |
| **완료** | Phase 1~5 기반 구축, Phase I~O 개선, Step B 제거, Phase P 실행 완료 |
| **다음** | Phase Q — 제약 기반 블록 선택 + 글자수 예산 시스템 (설계 확정, 실행 대기) |
---
@@ -43,44 +42,75 @@
- 이미지 크기 측정 + base64 삽입 (image_utils.py)
### 버그 수정 완료
- BF-1: SSE 파싱 실패 → static/index.html 분리 + 정규식
- BF-2: Jinja2 변수 전달 실패 → get_template().render() 방식
- BF-3: 한글 깨짐 → UTF-8 BOM 추가
- BF-4: body 블록 겹침 → _group_blocks_by_area() OrderedDict
- BF-5: 제목 미표시 → 프리셋 area명 header 통일
- BF-7: 블록 텍스트 비어있음 → topic_id 매칭 개선
- BF-8: 컨테이너 예산 기반 배치 → zone별 budget_px
- BF-9: grid와 Sonnet 역할 분리 → 코드가 grid 강제
- BF-10: catalog 캐시 갱신 → mtime 체크
- BF-1~BF-10: 전부 수정 완료 (SSE 파싱, Jinja2 변수, 한글, body 겹침, 제목, topic_id, 예산, grid, catalog 캐시)
---
## 🟡 진행 중
## ✅ Phase P 실행 완료 + 결과 분석 (2026-03-27~28)
### Phase O 컨테이너 시스템
- **코드 작성 완료:** calculate_container_specs(), finalize_block_specs(), 렌더러 컨테이너 div
- **문제 확인됨:** 배경 20%=117px에 topic 2개 → 각 58px. callout-warning(122px)이 안 맞음
- **원인:** height_cost "medium"(80~200px)이 컨테이너 58px보다 큰데 통과됨
- **필요 조치:** 컨테이너 px가 작을 때 topic당 블록 높이를 더 정밀하게 제약
### 실행 결과
- **실행 데이터:** `data/runs/1774599277829/`
- **최종 슬라이드 품질:** 20/100점
### Phase L 피드백 루프
- **동작:** 측정 → overflow 감지 → _max_chars_total 축소 → 편집자 재호출
- **문제:** `_MEASURE_SCRIPT``.area-*`만 검색. Phase O의 `.container-*` div를 못 찾음
- **필요 조치:** slide_measurer.py에 container div 셀렉터 추가
### 발견된 근본 문제 5가지
### BF-6: sidebar 카드 찢어짐
- Phase J에서 column_override + SIDEBAR_FORBIDDEN_BLOCKS 추가
- 완전 해결 여부 테스트 필요
| # | 근본 원인 | 증상 |
|---|----------|------|
| R1 | FAISS 텍스트 임베딩이 시각 블록을 매칭하지 못함 | "hierarchy" 관계인데 venn 대신 comparison-2col 선택 |
| R2 | Opus 추천에 catalog 검증 없음 | 존재하지 않는 블록 5개 환각 (arrow-flow, hierarchy-tree 등) |
| R3 | overflow 해소 실패 시 출력 차단 없음 | 배경 117px에 330px 콘텐츠 → 겹침 상태로 출력 |
| R4 | 블록 중복 사용 제한 없음 | 5개 topic에 3종류 블록만 사용 (38개 중 7.9%) |
| R5 | 공간 배분이 일방향 | 배경 20%에 topic 2개 강제 → card-numbered(205px)가 컨테이너(117px)에 안 맞음 |
### Phase P 접근법의 구조적 한계
- 3후보 × 5topics = **15번 렌더링 + 15번 AI 호출 → ~40분 소요**
- 15개 중 10개 폐기 (작업의 2/3 낭비)
- 업계 조사 결과, **다후보 렌더링 비교 방식은 어떤 상용/오픈소스 도구도 사용하지 않음**
- 블록 유형 선택은 **렌더링 전에 결정할 수 있는 문제** (콘텐츠 relation_type 기반)
### 업계 조사 결과 (2026-03-28)
| 접근법 | 대표 사례 | 핵심 원리 |
|--------|----------|----------|
| 제약 기반 레이아웃 엔진 | Beautiful.ai | AI는 콘텐츠만, 레이아웃은 규칙 엔진이 결정론적으로 |
| 템플릿 검색 + AI 커스터마이징 | Canva | 벡터 검색으로 템플릿 매칭, AI가 텍스트/색상만 교체 |
| NLP 관계 유형 → 시각화 매핑 | Napkin.ai | 계층/비교/프로세스 감지 → 다이어그램 유형 자동 선택 |
| 시각적 자기교정 | VASCAR (2024) | 생성→렌더링→비전 모델 평가→개선, 훈련 불필요 |
| 참조 기반 학습 | PPTAgent (EMNLP 2025) | 기존 프레젠테이션에서 디자인 패턴 귀납적 학습 |
**업계 합의:** AI가 레이아웃을 직접 결정하면 안 된다. AI는 콘텐츠만, 레이아웃은 제약 엔진이 담당.
---
## ❌ 미해결 → ✅ 해결됨 (2026-03-27)
## 📋 Phase Q: 제약 기반 블록 선택 + 글자수 예산 시스템 (설계 확정)
| 항목 | 해결 내용 |
|------|---------|
| 컨테이너 px vs 블록 높이 불일치 | `_max_allowed_height_cost()`를 topic당 높이(per_topic_px)로 판단하도록 수정 |
| Selenium container div 미감지 | `_MEASURE_SCRIPT``.container-*` 셀렉터 추가 + pipeline.py에서 container overflow 체크 |
| catalog.yaml schema 글자수 하드코딩 | 37개 필드를 `ref_chars` + `max_lines` + `font_size` 구조로 변환. FAISS 재빌드 완료 |
**상세:** [IMPROVEMENT-PHASE-Q.md](IMPROVEMENT-PHASE-Q.md)
**핵심 원칙:** "계산 먼저, AI 판단 나중에, 렌더링은 검증만"
### 실행 스텝
| 스텝 | 내용 | 유형 | 파일 | 의존성 | 상태 |
|------|------|------|------|--------|------|
| Q-1 | catalog.yaml 메타데이터 보강 (min_height_px, relation_types, category, min/max_items) | 데이터 | `templates/catalog.yaml` | ✅ 완료 |
| Q-2 | relation_type → 블록 카테고리 결정론적 매핑 엔진 | 신규 | `src/block_selector.py` | ✅ 완료 |
| Q-3 | 글자수 예산 계산 엔진 | 추가 | `src/space_allocator.py` | ✅ 완료 |
| Q-4 | Kei 블록 선택 프롬프트 재설계 (필터링된 2-3개만 제시) | 수정 | `src/kei_client.py` | ✅ 완료 |
| Q-5 | pipeline.py 재구성 (Phase P 15-render → Phase Q 단일 경로) | 수정 | `src/pipeline.py` | ✅ 완료 |
| Q-6 | 비전 모델 품질 게이트 (VASCAR식) | 신규 | `src/kei_client.py` | ✅ 완료 |
| Q-7 | overflow 수학적 조정 (LaTeX 글루 모델) | 추가 | `src/space_allocator.py` | ✅ 완료 |
| Q-8 | 출력 차단 정책 + P0 재시도 제한 (30회/300초) | 추가 | `src/pipeline.py` | ✅ 완료 |
### 기대 효과
| 지표 | Phase P | Phase Q 목표 |
|------|---------|-------------|
| 슬라이드 품질 | 20/100 | 70-80/100 |
| 처리 시간 | ~40분 | ~8-12분 |
| API 호출 | ~25회 | ~8회 |
| 유령 블록 | 5건 발생 | 불가능 |
| overflow 출력 | 허용 | 차단 |
---
@@ -98,11 +128,86 @@
| J | 블록 선택 권한 재정의 | 완료 | Step B 제거로 일부 무력화 |
| K | purpose 기반 시각적 위계 | 완료 | |
| K-1 | 중간 산출물 저장 | 완료 | |
| L | Selenium 렌더링 측정 | 완료 | container div 감지 미완 |
| L | Selenium 렌더링 측정 | 완료 | |
| M | Kei 비중 시스템 | 완료 | Phase O로 교체 |
| N | 4대 핵심 문제 해결 | 완료 | catalog, fallback, topic_id, 무한재시도 |
| **O** | **컨테이너 기반 레이아웃** | **진행 중** | 코드 완료, 미세 조정 필요 |
| — | Step B 제거 + 죽은 코드 정리 | 완료 | Phase O 후속 |
| N | 4대 핵심 문제 해결 | 완료 | |
| **O** | **컨테이너 기반 레이아웃** | **완료** | 코드 + 미해결 3건 해결 + Step B 제거 |
| **P** | **다후보 렌더링 비교 선택** | **완료** | 실행됨. 결과 20/100점 → Phase Q로 방향 전환 |
| **Q** | **제약 기반 블록 선택 + 글자수 예산** | **코드 완료** | Q-1~Q-8 구현 + fill_candidates 복원. 블록 선택 개선 확인 |
| **R** | **하이브리드 블록 시스템 (variant 추가)** | **실패** | 기존 블록 선택 구조 위에 패치만 추가. P=Q=R 동일 구조. |
| **R'** | **접근 C: 블록 CSS 참고 + AI 구조 결정** | **설계** | 방향만 확정. Kei API HTML 생성 실패 확인. |
| **S** | **검증 기반 확정 — Claude HTML 생성 + 검증된 프롬프트 규칙** | **설계 확정** | 영역별 검증 합격. Claude Sonnet 확정. 실행 대기. |
---
## ❌ Phase R 실패 기록
Phase R은 접근 C로 가기로 합의했으나, 구현에서 기존 블록 선택 시스템 위에 variant 패치만 추가.
**P = Q = R: 세 개 다 "블록 선택 → 슬롯 채우기" 근본 구조가 동일.**
결과물 34점. C_reference.png(70점) 수준에 전혀 도달 못함.
근본 원인: 기존 코드(block_selector, catalog, fill_candidates)를 유지하면서 최소 변경으로 해결하려는 관성.
---
## 📋 Phase R': 접근 C — 블록 CSS 참고 + AI 구조 결정 (설계 확정)
**상세:** [IMPROVEMENT-PHASE-R-PRIME.md](IMPROVEMENT-PHASE-R-PRIME.md)
### 핵심 전환
```
P=Q=R (실패): 블록이 구조를 결정 → 콘텐츠를 슬롯에 채움
R' (접근 C): 콘텐츠가 구조를 결정 → 블록 CSS를 참고하여 HTML 생성
```
### 프로세스 변경
| 단계 | 현재 (P=Q=R) | R' (접근 C) |
|------|-------------|------------|
| 1단계 Kei 분석 | 유지 | 유지 |
| 1.5단계 컨셉 구체화 | 유지 | 유지 |
| 컨테이너 계산 | 유지 | 유지 |
| 프리셋 선택 | 유지 | 유지 |
| **2단계** | block_selector → 블록 선택 | **제거** → html_generator가 AI HTML 생성 |
| **3단계** | fill_candidates → 슬롯 채우기 | **제거** → html_generator에 통합 |
| 4단계 렌더링 | render_slide (블록 템플릿) | render_slide_from_html (AI HTML 삽입) |
| 검증 | Selenium + 비전 모델 | 유지 |
### 실행 스텝
| 스텝 | 내용 | 파일 | 상태 |
|------|------|------|------|
| R'-1 | 디자인 토큰 + 블록 CSS 패턴을 프롬프트용 텍스트로 추출 | 신규 `src/design_tokens.py` | 대기 |
| R'-2 | few-shot 예시 슬라이드 정리 | `data/examples/` | 대기 |
| R'-3 | AI HTML 생성 함수 구현 | 신규 `src/html_generator.py` | 대기 |
| R'-4 | pipeline.py 2-3단계 교체 (블록 선택+채우기 → html_generator) | `src/pipeline.py` | 대기 |
| R'-5 | 렌더러에 AI HTML 삽입 함수 추가 | `src/renderer.py` | 대기 |
| R'-6 | HTML 정화 + 토큰 위반 검증 | 신규 `src/html_validator.py` | 대기 |
| R'-7 | 테스트 (2개 콘텐츠) | `scripts/test_phase_r_prime.py` | 대기 |
### 회귀 방지 — 호출하면 안 되는 함수
- `select_block_candidates()` — 블록 선택 회귀
- `fill_candidates()` / `fill_content()` — 슬롯 채우기 회귀
- `select_block_for_topics()` — 블록 선택 AI 회귀
- `finalize_block_specs()` — 블록 스펙 회귀
### 합격 기준
C_reference.png와 동일 수준의 결과를 **자동으로** 생성:
- topic 합침 가능
- 포함 관계 시각화 가능
- 핵심 메시지 별도 강조 가능
- 원본 텍스트 보존 (자유도 15-20)
- 720px overflow 없음
---
## Phase R' 이후 방향
- 디자인 참조 DB 구축 → 성공한 슬라이드를 few-shot으로 축적
- Playwright 마이그레이션 → 더 빠른 측정 + PDF 내보내기
---
@@ -110,9 +215,11 @@
| 항목 | 파일 | 상태 |
|------|------|------|
| 프로젝트 규칙 | CLAUDE.md | 완료 |
| 개선 계획 | IMPROVEMENT.md | Phase O까지 반영 |
| 진행 추적 | PROGRESS.md | 이 파일 (2026-03-27 갱신) |
| 프로젝트 규칙 | CLAUDE.md | Phase R' 반영 |
| 개선 계획 | IMPROVEMENT.md | Phase R' 반영 |
| 진행 추적 | PROGRESS.md | 이 파일 (2026-03-30 갱신) |
| 전체 감사 | CLEANUP-AUDIT.md | 유효/무력화 분류 완료 |
| Phase별 상세 | IMPROVEMENT-PHASE-{A~O}.md | 각 Phase 기록 |
| README | README.md | Phase O + Step B 제거 반영 |
| Phase별 상세 | IMPROVEMENT-PHASE-{A~R'}.md | 각 Phase 기록 |
| Phase R 실패 기록 | IMPROVEMENT-PHASE-R.md | 블록 선택 위에 variant 패치 — 실패 |
| Phase R' 설계 | IMPROVEMENT-PHASE-R-PRIME.md | 접근 C 기반 재설계 |
| README | README.md | Phase R' 반영 |