Phase W + V' 완료: before→filled→after 파이프라인 + 조립 로직 수정
Phase W: - weight 비율 초기 배정 (space_allocator header 높이 반영) - block_assembler 공통 조립 함수 (filled/assembled 통합) - filled → Selenium 측정 → context 저장 - sidebar overflow 확장 + body 재배분 - sub_layouts 사전 계산 (이미지 누락 해결) Phase V': - 팝업 링크 우측상단 배치 (인라인 → position:absolute) - 표 내용 Kei 판단 (공란 크기 계산 → 행/열 산출 → Kei 요약) - 출처 라벨 삭제 + 이미지 아래 캡션 배치 - after 공란 제거 (결론 바로 위까지 body/sidebar 채움) 추가: - V-10 bold 키워드: 기계적 추출 → Kei 문맥 판단 - ** 마크다운 → <strong> 변환 - [이미지:] 마커 제거 (bold 변환 전 처리) - grid-template-rows AFTER 크기 반영 (Sonnet final) - assemble_stage2 CSS font-size override, white-space fix - 하드코딩 전수 검토 완료 - 본심 여러 topic 텍스트 합침 Phase X 계획 문서 작성 (동적 역할 구조) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
344
README.md
344
README.md
@@ -4,112 +4,153 @@
|
||||
|
||||
## 개요
|
||||
|
||||
텍스트/MDX 콘텐츠를 입력하면 Kei 실장(Opus)이 정보 구조와 비중을 판단하고, 그 비중대로 컨테이너를 확정하고, 블록을 선택하고, 텍스트를 편집하여 슬라이드를 생성한다.
|
||||
|
||||
**핵심 특징:**
|
||||
- 콘텐츠마다 비중이 동적으로 변한다 (본심 60% / 배경 20% 등 — Kei가 매번 판단)
|
||||
- 비중이 컨테이너 px를 확정 → 블록과 텍스트가 컨테이너에 맞춰진다
|
||||
- Kei API 필수. fallback 없음. 성공할 때까지 무한 재시도.
|
||||
텍스트/MDX 콘텐츠를 입력하면:
|
||||
1. Kei 실장(Opus)이 정보 구조와 비중을 판단하고
|
||||
2. 코드가 컨테이너 크기를 계산하고
|
||||
3. 블록을 선택하고
|
||||
4. 콘텐츠-컨테이너 적합성을 검증하고
|
||||
5. AI(Sonnet)가 블록 디자인을 참고하여 HTML을 생성하고
|
||||
6. 코드가 슬라이드 프레임에 조립하고
|
||||
7. 측정+비전 모델로 검증합니다
|
||||
|
||||
---
|
||||
|
||||
## 파이프라인 (6단계)
|
||||
## 파이프라인 (10단계)
|
||||
|
||||
```
|
||||
텍스트 입력
|
||||
↓
|
||||
[1단계] Kei 실장 — 꼭지 추출 + 비중 판단 (Kei API / Opus)
|
||||
↓
|
||||
[1.5단계] Kei 실장 — 컨셉 구체화 (Kei API / Opus)
|
||||
↓
|
||||
[컨테이너 계산] 비중 → px 확정 (코드, 결정론적)
|
||||
↓
|
||||
[2단계] 블록 선택 (Phase Q) (코드: 결정론적 + Kei 1회)
|
||||
│ relation_type → 카테고리 매핑 (코드)
|
||||
│ → 컨테이너 제약 필터링 (코드)
|
||||
│ → 글자수 예산 계산 (코드)
|
||||
│ → Kei에게 2-3개 후보 제시 → 1개 선택 (AI)
|
||||
↓
|
||||
[3단계] Kei 편집자 — 텍스트 정리 (예산 포함) (Kei API / Opus)
|
||||
↓
|
||||
[4단계] 디자인 실무자 — CSS 조정 + HTML 조립 (Sonnet + Jinja2)
|
||||
↓
|
||||
[검증] Selenium 렌더링 1회 → 수학적 조정 (코드, AI 없음)
|
||||
↓
|
||||
[품질 게이트] 비전 모델 평가 → 미달 시 교정/차단 (Opus 멀티모달)
|
||||
↓
|
||||
완성 슬라이드 HTML
|
||||
MDX 원본
|
||||
↓
|
||||
[Stage 0] MDX 정규화 (코드)
|
||||
↓
|
||||
[Stage 1A] 꼭지 추출 + 영역 배정 (Kei API / Opus)
|
||||
↓
|
||||
[Stage 1B] 컨셉 구체화 (Kei API / Opus)
|
||||
↓
|
||||
[Stage 1.5a] 컨테이너 초기 계산 (코드)
|
||||
↓
|
||||
[Stage 1.7] 블록 선택 (코드)
|
||||
↓
|
||||
[Stage 1.8] 적합성 검증 + 재배분 + 보강 (코드 + Kei 에스컬레이션)
|
||||
↓
|
||||
[Stage 1.5b] 디자인 예산 재계산 (코드)
|
||||
↓
|
||||
[Stage 2] HTML 생성 (영역별 개별 호출) (Claude Sonnet)
|
||||
↓
|
||||
[Stage 3] 렌더링 조립 + 후처리 (코드)
|
||||
↓
|
||||
[Stage 4] 측정 + 품질 검증 (Selenium + Opus Vision)
|
||||
↓
|
||||
검증 통과 시 → final.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 제약 |
|
||||
| **블록 선택** | 코드 + Kei | 결정론적 + AI 1회 | relation_type → 카테고리 매핑 → 컨테이너 제약 필터 → Kei 최종 선택 (Phase Q) |
|
||||
| **예산 계산** | 코드 | 결정론적 | 컨테이너 px → 글자수 예산 사전 계산 → AI 편집 시 하드 제약 (Phase Q) |
|
||||
| **3** | Kei 편집자 | Kei API (Opus) | 텍스트 편집 (글자수 예산 준수, 원본 보존) |
|
||||
| **4** | 디자인 실무자 | Sonnet + Jinja2 | CSS 변수 override + HTML 조립 |
|
||||
| **검증** | 코드 | Selenium 1회 | 검증 렌더링 — overflow 확인 (예산으로 사전 방지됨) |
|
||||
| **품질 게이트** | 비전 모델 | Opus 멀티모달 | 스크린샷 기반 시각 품질 평가 (VASCAR식) — 미달 시 출력 차단 (Phase Q) |
|
||||
|
||||
### 핵심 원칙
|
||||
|
||||
- **비중 → 컨테이너 → 블록 → 콘텐츠** 순서. 비중이 모든 것을 결정
|
||||
- **Kei API 필수.** fallback 없음. 기본값 없음. 성공할 때까지 무한 재시도
|
||||
- **계산 먼저, AI 판단 나중에, 렌더링은 검증만** (Phase Q 핵심 원칙)
|
||||
- **블록 선택은 결정론적 필터링 → Kei 최종 선택.** AI에게 불가능한 선택지를 주지 않는다
|
||||
- **콘텐츠가 구조를 결정, 블록 CSS는 참고만** (Phase R'). AI가 HTML 구조 직접 생성
|
||||
- **글자수 예산은 하드 제약.** 컨테이너 px에서 수학적으로 도출, AI 편집 전에 전달
|
||||
- **overflow 상태에서 출력 금지.** 비전 모델 품질 게이트 통과 필수
|
||||
- **블록 = 시각 패턴(구조), 크기가 아님.** 같은 블록이 컨테이너에 따라 항목수/폰트/패딩 변동
|
||||
- **텍스트가 기준.** 디자인이 텍스트에 맞춤. CSS로 사후 자르기 금지
|
||||
※ Stage 4 이후의 파일 저장은 별도 Stage가 아닌 후처리입니다.
|
||||
|
||||
---
|
||||
|
||||
## 컨테이너 시스템 (Phase O)
|
||||
## 단계별 상세
|
||||
|
||||
Kei가 판단한 비중이 시각적 레이아웃에 정확히 반영되는 구조.
|
||||
### Stage 0: MDX 정규화
|
||||
|
||||
```
|
||||
슬라이드 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 (핵심 메시지 한 줄)
|
||||
```
|
||||
| 항목 | 내용 |
|
||||
|------|------|
|
||||
| **목적** | 원본 MDX에서 JSX/frontmatter를 제거하고, 섹션/팝업/이미지/테이블로 분리 |
|
||||
| **적용기술** | 코드 (`normalize_mdx_content()`) |
|
||||
| **인풋** | 원본 MDX 문자열 |
|
||||
| **아웃풋** | `normalized` — clean_text, title, sections[], popups[], images[], tables[] |
|
||||
| **연계** | → Stage 1A가 clean_text를 Kei에게 전달 |
|
||||
|
||||
- 컨테이너 높이(px)가 블록의 height_cost를 제약
|
||||
- 컨테이너 크기에서 항목수/글자수/폰트/패딩이 자동 계산
|
||||
- 편집자에게 컨테이너 제약이 전달되어 텍스트 분량이 맞춰짐
|
||||
### Stage 1A: 꼭지 추출 + 영역 배정
|
||||
|
||||
---
|
||||
| 항목 | 내용 |
|
||||
|------|------|
|
||||
| **목적** | 콘텐츠에서 핵심 파트(꼭지)를 식별하고, 슬라이드의 어떤 영역(배경/본심/첨부/결론)에 배치할지 결정 |
|
||||
| **적용기술** | Kei API (`classify_content()`) |
|
||||
| **인풋** | normalized.clean_text |
|
||||
| **아웃풋** | `topics[]` (id, title, purpose, layer, relation_type, expression_hint), `page_structure` (role별 topic_ids, weight) |
|
||||
| **연계** | → Stage 1B가 각 꼭지를 구체화 |
|
||||
|
||||
## 개선 이력
|
||||
### Stage 1B: 컨셉 구체화
|
||||
|
||||
| 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→블록제약→콘텐츠제약 | 완료 |
|
||||
| **P** | 블록 재구성 + 실제 렌더링 비교 선택 — 후보 3개 렌더링→Kei 스크린샷 판단 | **계획 확정** |
|
||||
| 항목 | 내용 |
|
||||
|------|------|
|
||||
| **목적** | 각 꼭지에 실제 원본 텍스트(source_data)와 요약(summary)을 매핑 |
|
||||
| **적용기술** | Kei API (`refine_concepts()`) |
|
||||
| **인풋** | topics + clean_text |
|
||||
| **아웃풋** | `topics` 업데이트 — source_data, summary 추가 |
|
||||
| **연계** | → Stage 1.5a가 텍스트 양을 기반으로 컨테이너 비율 계산 |
|
||||
|
||||
### Stage 1.5a: 컨테이너 초기 계산
|
||||
|
||||
| 항목 | 내용 |
|
||||
|------|------|
|
||||
| **목적** | 폰트 위계 확정 + 슬라이드 내 영역별 컨테이너 크기(px) 계산 + 프리셋 선택 |
|
||||
| **적용기술** | 코드 (`calculate_font_hierarchy()`, `calculate_dynamic_ratio()`, `calculate_container_specs()`) |
|
||||
| **인풋** | topics, page_structure (weight), preset |
|
||||
| **아웃풋** | `font_hierarchy` (key_msg/core/bg/sidebar px), `container_ratio` (71:29 등), `containers` (role별 width_px, height_px), `preset` |
|
||||
| **연계** | → Stage 1.7이 컨테이너 크기를 보고 블록 선택 |
|
||||
|
||||
### Stage 1.7: 블록 선택
|
||||
|
||||
| 항목 | 내용 |
|
||||
|------|------|
|
||||
| **목적** | 각 꼭지의 relation_type + expression_hint + 컨테이너 크기로 적합한 블록 결정. 같은 영역 꼭지들의 layer가 다르면 주종관계 판단 (블록 1개로 합침) |
|
||||
| **적용기술** | 코드 (`select_and_generate_references()`) — catalog.yaml 기반 결정론적 매칭 |
|
||||
| **인풋** | topics, containers, page_structure |
|
||||
| **아웃풋** | `references` — role별 block_id, variant, design_reference_html, topic_id, is_hierarchical, supporting_topic_ids |
|
||||
| **연계** | → Stage 1.8이 선택된 블록+콘텐츠가 컨테이너에 맞는지 검증 |
|
||||
|
||||
### Stage 1.8: 적합성 검증 + 재배분 + 보강 + 서브 컨테이너
|
||||
|
||||
| 항목 | 내용 |
|
||||
|------|------|
|
||||
| **목적** | 콘텐츠가 컨테이너에 들어가는지 검증 → 안 맞으면 재배분 → 여전히 안 되면 Kei 에스컬레이션 → 여유 공간에 보충 콘텐츠 → 서브 컨테이너 배치 계산 |
|
||||
| **적용기술** | 코드 (`calculate_fit()`, `redistribute()`, `analyze_enhancements()`, `apply_enhancements()`, `calculate_sub_layout()`) + Kei API (에스컬레이션 시 `call_kei_fit_escalation()`) |
|
||||
| **인풋** | topics, containers, references, font_hierarchy, normalized, core_message |
|
||||
| **아웃풋** | `containers` (재배분된 height_px), `fit_result` (role별 fit_status, redistribution), `enhancement_result` (V-7 subordinate_treatments, V-8 supplement_blocks, V-9 emphasis_blocks, V-10 bold_keywords, V-4 kei_decisions), `sub_layouts` (role별 서브 컨테이너 name/width/height, table_rows) |
|
||||
| **내부 흐름** | Step 1: 필요 높이 계산 → Step 2: 재배분 → Step 3: Kei 에스컬레이션 → Step 4-5: 보강 분석+적용 → Step 6: fit 재검증 → Step 7: 서브 컨테이너 배치 → Step 8: 확정 |
|
||||
| **연계** | → Stage 1.5b가 재배분된 크기로 디자인 예산 재계산, → Stage 2가 sub_layouts + enhancements를 프롬프트에 반영 |
|
||||
|
||||
### Stage 1.5b: 디자인 예산 재계산
|
||||
|
||||
| 항목 | 내용 |
|
||||
|------|------|
|
||||
| **목적** | 재배분된 컨테이너 크기 + 선택된 블록 schema 기준으로 영역별 가용 공간 계산 |
|
||||
| **적용기술** | 코드 (`calculate_design_budget()`) |
|
||||
| **인풋** | containers (재배분 후), references (블록 schema) |
|
||||
| **아웃풋** | `containers` 업데이트 — design_budget (available_height_px, available_width_px, fits) |
|
||||
| **연계** | → Stage 2가 design_budgets를 프롬프트에 포함 |
|
||||
|
||||
### Stage 2: HTML 생성 (영역별 개별 호출)
|
||||
|
||||
| 항목 | 내용 |
|
||||
|------|------|
|
||||
| **목적** | page_structure에 존재하는 각 역할(배경/본심/첨부/결론)의 HTML을 **영역별 개별 Sonnet 호출**로 생성. 블록 디자인을 참고하되 콘텐츠가 구조를 결정 (Phase R' 방식) |
|
||||
| **적용기술** | Claude Sonnet API — 영역당 1회 호출 (`build_area_prompt()` → `_call_claude()`) |
|
||||
| **인풋** | raw_content, topics, containers, font_hierarchy, references (design_reference_html), sub_layouts (서브 컨테이너 치수), enhancements (V-4~V-10 지시), design_budgets |
|
||||
| **호출 흐름** | Sonnet(배경) → bg_html, Sonnet(본심) → core_html, Sonnet(첨부) → sidebar_html, Sonnet(결론) → footer_html. 해당 역할에 꼭지가 없으면 스킵. body_html = bg_html + spacer + core_html |
|
||||
| **아웃풋** | `generated_html` — body_html, sidebar_html, footer_html |
|
||||
| **프롬프트에 포함되는 것** | 서브 컨테이너 레이아웃 제약, 디자인 레퍼런스 HTML (블록 CSS 참고), Kei 에스컬레이션 결정, 종속 꼭지 처리 지시, 보충 블록 지시, 강조 문장, bold 키워드, 폰트/컨테이너 크기 제약 |
|
||||
| **연계** | → Stage 3이 영역별 HTML을 슬라이드 프레임에 배치 |
|
||||
|
||||
### Stage 3: 렌더링 조립 + 후처리
|
||||
|
||||
| 항목 | 내용 |
|
||||
|------|------|
|
||||
| **목적** | 생성된 HTML 조각을 CSS Grid 슬라이드 프레임에 삽입 + 후처리 (폰트 캡핑, overflow 제거, sidebar width 조정, bold 변환) |
|
||||
| **적용기술** | 코드 (`render_slide_from_html()`) |
|
||||
| **인풋** | generated_html, preset (grid_areas, grid_columns), font_hierarchy, container_ratio |
|
||||
| **아웃풋** | `rendered_html` → `final.html` 파일 저장 |
|
||||
| **연계** | → Stage 4가 렌더링 결과를 측정+검증 |
|
||||
|
||||
### Stage 4: 품질 검증
|
||||
|
||||
| 항목 | 내용 |
|
||||
|------|------|
|
||||
| **목적** | Selenium으로 실제 브라우저 렌더링 후 overflow 측정 + Opus Vision으로 시각적 품질 평가 |
|
||||
| **적용기술** | Selenium (`measure_rendered_heights()`) + Claude Opus Vision (`vision_quality_gate()`) |
|
||||
| **인풋** | rendered_html |
|
||||
| **아웃풋** | `measurement` (zone별 clientHeight, scrollHeight, overflow, excess_px), `quality_score` |
|
||||
| **연계** | 파이프라인 완료. overflow 시 경고 포함하여 진행 |
|
||||
|
||||
---
|
||||
|
||||
@@ -117,28 +158,55 @@ Kei가 판단한 비중이 시각적 레이아웃에 정확히 반영되는 구
|
||||
|
||||
파이프라인 실행마다 `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` | 리포트 | 전 단계 시각화 리포트 |
|
||||
### JSON Context (Stage별 누적 상태)
|
||||
| 파일 | Stage | 내용 |
|
||||
|------|-------|------|
|
||||
| `stage_0_context.json` | 0 | normalized (섹션, 팝업, 이미지) |
|
||||
| `stage_1a_context.json` | 1A | topics, page_structure |
|
||||
| `stage_1b_context.json` | 1B | topics (source_data 추가) |
|
||||
| `stage_1_5a_context.json` | 1.5a | font_hierarchy, containers, ratio |
|
||||
| `stage_1_7_context.json` | 1.7 | references (블록 선택 결과) |
|
||||
| `stage_1_8_context.json` | 1.8 | fit_result, enhancements, sub_layouts |
|
||||
| `stage_1_5b_context.json` | 1.5b | containers (design_budget 추가) |
|
||||
| `stage_2_context.json` | 2 | generated_html |
|
||||
| `stage_3_context.json` | 3 | (rendered_html은 final.html로 별도 저장) |
|
||||
| `stage_4_context.json` | 4 | measurement, quality_score |
|
||||
| `final_context.json` | 최종 | 전체 context |
|
||||
|
||||
리포트 생성: `python scripts/generate_run_report.py`
|
||||
### HTML 시각화 (`steps/` 폴더)
|
||||
| 파일 | Stage | 내용 |
|
||||
|------|-------|------|
|
||||
| `stage_0.html` | 0 | 섹션/팝업/이미지 목록 |
|
||||
| `stage_1a.html` | 1A | 꼭지 테이블 (purpose, layer, 영역) |
|
||||
| `stage_1b.html` | 1B | 꼭지 + source_data + summary |
|
||||
| `stage_1_5a.html` | 1.5a | 빈 컨테이너 (1280×720) |
|
||||
| `stage_1_5a_content.html` | 1.5a | 컨테이너에 콘텐츠 배치 |
|
||||
| `stage_1_5b.html` | 1.5b | 디자인 예산 (available height/width) |
|
||||
| `stage_1_7.html` | 1.7 | 블록 선택 표시 |
|
||||
| `stage_1_8_fit_before.html` | 1.8 | 적합성 (재배분 전) |
|
||||
| `stage_1_8_fit_after.html` | 1.8 | 재배분 후 + 보강 |
|
||||
| `stage_1_8_blocks.html` | 1.8 | SLOT 구조 + 블록 디자인 + 주종관계 (1280×720) |
|
||||
| `stage_2.html` | 2 | 영역별 Sonnet 출력을 실제 렌더링 (역할별 개별 확인) |
|
||||
| `stage_3.html` | 3 | 영역을 합쳐 슬라이드 프레임에 배치한 결과 (1280×720 실제 렌더링) |
|
||||
| `stage_4.html` | 4 | 측정 결과 + 품질 점수 |
|
||||
|
||||
---
|
||||
|
||||
## 핵심 원칙
|
||||
|
||||
1. **콘텐츠가 구조를 결정** — 블록 CSS는 참고만. AI가 콘텐츠 전달 의도를 보고 HTML 구조 결정 (Phase R')
|
||||
2. **하드코딩 금지** — font-size 외 모든 수치는 동적 계산. 어떤 MDX가 들어와도 동일하게 동작
|
||||
3. **스크롤 절대 금지** — overflow:auto/scroll 어떤 영역에서도 불허
|
||||
4. **Kei API 필수** — fallback 없음. 성공할 때까지 무한 재시도
|
||||
5. **AI가 옵션 생성, Kei가 결정** — 공간 부족 시 하드코딩 대응이 아니라 Kei 판단 요청
|
||||
6. **계산 먼저, AI 판단 나중에, 렌더링은 검증만**
|
||||
7. **overflow 상태에서 출력 금지** — Vision 모델 품질 게이트 통과 필수
|
||||
|
||||
---
|
||||
|
||||
## 블록 라이브러리 (38개)
|
||||
|
||||
6개 카테고리, 38개 블록. 각 블록은 `catalog.yaml`에 용도(when), 금지(not_for), purpose_fit이 정의됨.
|
||||
6개 카테고리, 38개 블록. 각 블록은 `catalog.yaml`에 용도(when), 금지(not_for), purpose_fit, schema(슬롯 정의)가 있음.
|
||||
|
||||
| 카테고리 | 개수 | 용도 |
|
||||
|---------|------|------|
|
||||
@@ -149,8 +217,6 @@ Kei가 판단한 비중이 시각적 레이아웃에 정확히 반영되는 구
|
||||
| **emphasis** | 10 | 강조, 인용, 결론, 불릿 |
|
||||
| **media** | 5 | 이미지/사진 |
|
||||
|
||||
FAISS 블록 검색: bge-m3 1024차원 임베딩 → 꼭지별 관련 블록 후보 추출
|
||||
|
||||
---
|
||||
|
||||
## 기술 스택
|
||||
@@ -159,16 +225,16 @@ FAISS 블록 검색: bge-m3 1024차원 임베딩 → 꼭지별 관련 블록 후
|
||||
|------|------|
|
||||
| 서버 | FastAPI + uvicorn (포트 8001) |
|
||||
| AI (Kei 실장/편집자) | Kei API → Opus (localhost:8000) |
|
||||
| AI (디자인 팀장/실무자) | Anthropic API → Sonnet |
|
||||
| AI (최종 검수) | Anthropic API → Opus (멀티모달) |
|
||||
| AI (HTML 생성) | Anthropic API → Claude Sonnet |
|
||||
| AI (품질 검증) | Anthropic API → Claude Opus Vision |
|
||||
| 블록 검색 | FAISS + bge-m3 |
|
||||
| 템플릿 | Jinja2 |
|
||||
| 템플릿 | Jinja2 (블록 디자인 레퍼런스용) |
|
||||
| 렌더링 | CSS Grid + 디자인 토큰 (1280×720) |
|
||||
| 렌더링 측정 | Selenium headless Chrome |
|
||||
| SVG 시각화 | svg_calculator.py (N개 동적 배치) |
|
||||
| 이미지 | Pillow (크기 측정) + base64 인라인 |
|
||||
| 폰트 | Pretendard Variable |
|
||||
| 공간 계산 | space_allocator.py (결정론적) |
|
||||
| 공간 계산 | space_allocator.py + fit_verifier.py (결정론적) |
|
||||
|
||||
---
|
||||
|
||||
@@ -202,42 +268,21 @@ python -m uvicorn src.main:app --host 127.0.0.1 --port 8001 --reload
|
||||
|
||||
---
|
||||
|
||||
## 프로젝트 구조
|
||||
## 개선 이력
|
||||
|
||||
```
|
||||
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 진행 상황 추적
|
||||
```
|
||||
| Phase | 내용 | 상태 |
|
||||
|-------|------|------|
|
||||
| A~D | 슬라이드 품질 핵심 | 완료 |
|
||||
| G~N | Kei API, 스토리라인, 정합성, 블록 선택, 비중, 측정 | 완료 |
|
||||
| O | 컨테이너 기반 레이아웃 | 완료 |
|
||||
| P | 다후보 렌더링 비교 | 완료 (20/100점 → 방향 전환) |
|
||||
| Q | 제약 기반 블록 선택 | 완료 |
|
||||
| R | 하이브리드 블록 (실패 — P=Q=R 동일 구조) | 실패 |
|
||||
| R' | 블록 CSS 참고 + AI 구조 결정 | 설계 확정 |
|
||||
| S | 검증 합격 프롬프트 + Claude HTML 생성 | 설계 확정 |
|
||||
| T | 11-Stage 파이프라인 + 디자인 레퍼런스 | 완료 (31/31 통과) |
|
||||
| V | 적합성 검증 + Kei 에스컬레이션 + 서브 컨테이너 | 완료 |
|
||||
| W | Stage 2 출력 품질 수정 (6건) | 진행 중 |
|
||||
|
||||
---
|
||||
|
||||
@@ -251,7 +296,8 @@ Kei Persona Agent (localhost:8000)
|
||||
|
||||
Design Agent (localhost:8001, 이 프로젝트)
|
||||
├── 슬라이드 생성 전용
|
||||
├── Kei API로 실장(1단계) + 편집자(3단계) + 블록 확정(2단계) 호출
|
||||
├── 최종 검수(5단계)는 Opus 직접 호출 (멀티모달 스크린샷)
|
||||
├── Kei API로 꼭지 추출(1A) + 컨셉 구체화(1B) + 에스컬레이션(1.8) 호출
|
||||
├── Sonnet으로 HTML 생성(Stage 2)
|
||||
├── Opus Vision으로 품질 검증(Stage 4)
|
||||
└── 두 프로젝트는 독립. 코드 공유 없음. API 연동만.
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user