13 KiB
13 KiB
Design Agent 파이프라인 현황
최종 갱신: 2026-04-13 목적: 새 세션의 AI가 이 문서만 읽으면 파이프라인 전체를 이해하고 작업할 수 있도록 한다.
1. 전체 흐름 요약
MDX 입력
↓
[Stage 0] MDX 정규화 (코드)
↓
[Stage 1A] Kei 실장 — 꼭지 추출 (AI: Opus)
→ layout_template: A 또는 B 선택
↓
[Stage 1B] 컨셉 구체화 (AI: Opus)
→ relation_type, expression_hint, source_data
↓
[Stage 1B-ST] 구조화 텍스트 생성 (AI: Opus)
→ structured_text per topic
↓
[Stage 1.5a] 컨테이너 계산 (코드: 결정론적)
→ FontHierarchy, ContainerSpec, Preset
↓
[Stage 1.7] 블록 레퍼런스 선택 (코드 + AI 1회)
→ relation_type → 카테고리 → 필터 → 블록 결정
↓
[Stage 1.8] 적합성 검증 + 보강 (코드 + Selenium + AI)
→ overflow 감지 → Kei 에스컬레이션 → 재배분
↓
[Stage 1.5b] 디자인 예산 계산 (코드)
↓
[Stage 2] HTML 생성 (Type에 따라 다름)
→ Type B/B'/B'': block_assembler (코드)
→ Type A: Sonnet 재구성 (AI, 미완성)
↓
[Stage 3] 렌더링 조립 (Type A만, Jinja2)
↓
[Stage 4] 검증 (Selenium + Opus Vision)
→ overflow 측정 + 스크린샷 품질 평가
↓
최종 HTML 출력 (data/runs/{id}/final.html)
2. 레이아웃 유형 (Type A / B / B' / B'')
2.1 Kei가 선택하는 유형: A와 B
Kei 프롬프트(src/kei_client.py:34-46)에서 A 또는 B를 선택한다.
| 유형 | 조건 | Zone 구조 |
|---|---|---|
| Type A | 참조자료(용어 정의, 부록 등)가 별도로 존재 | body(배경+본심) + sidebar(첨부) + footer(결론) |
| Type B | 본문 흐름만. 배경/첨부가 없거나 억지로 만들어야 하면 | top + bottom_left + bottom_right + footer |
2.2 Type B 변형: B'과 B''
B'과 B''은 Kei가 선택하지 않는다. 특정 MDX 테스트 과정에서 하드코딩한 변형이다.
| 변형 | 생성 경위 | 차이점 | 코드 위치 |
|---|---|---|---|
| B | 범용 | 상단(전체폭 텍스트+이미지) + 하단 2분할 + 결론 | block_assembler.py:461 _assemble_slide_html_type_b() |
| B' | 03번 MDX 테스트 중 생성 | 상단이 세로 카드 형태 + 하단에 표 렌더링 + 불릿 전용 | block_assembler.py:885 _assemble_slide_html_type_b_prime() |
| B'' | B'에서 스타일 변형 | border/gradient 없음. 색상바+여백으로 구분 | block_assembler_b2.py:9 _assemble_slide_html_type_b_double_prime() |
분기 코드 (block_assembler.py:370-378):
if ctx.analysis.layout_template == "B":
return _assemble_slide_html_type_b(ctx, title_text)
if ctx.analysis.layout_template == "B'":
return _assemble_slide_html_type_b_prime(ctx, title_text)
if ctx.analysis.layout_template == "B''":
return _assemble_slide_html_type_b_double_prime(ctx, title_text)
2.3 향후 방향
B'/B''은 범용화가 필요하다. 현재는 03번 콘텐츠 구조(카드형+표)를 B 조립 함수가 커버하지 못해서 만든 땜질이다. 궁극적으로는 B 하나로 다양한 콘텐츠 구조를 커버하거나, AI가 서브타입을 판단하게 해야 한다.
3. MDX 샘플 ↔ 유형 매핑
| MDX | 파일 | 콘텐츠 성격 | 선택 유형 | 상태 |
|---|---|---|---|---|
| 01번 | samples/mdx/01. 건설산업 DX의 올바른 이해(0127).mdx |
용어 혼용 문제 + 용어 정의(참조) | Type A | ⚠ Stage 2 미완성 (Sonnet 의존) |
| 02번 | samples/mdx/02. DX의 시행 목표 및 기대효과.mdx |
본문 흐름 (3대 목표) | Type B | ✅ 동작 |
| 03번 | samples/mdx/03. DX 시행을 위한 필수 요건 및 혁신 방안.mdx |
카드형 구조 + 표 + 불릿 | Type B' | ✅ 동작 (하드코딩) |
4. 단계별 상세
Stage 0: MDX 정규화
- 파일:
src/mdx_normalizer.py→normalize_mdx_content() - 입력: raw MDX 텍스트
- 출력:
NormalizedContent(sections, images, tables 분리)
Stage 1A: Kei 실장 — 꼭지 추출
- 파일:
src/kei_client.py→classify_content() - AI: Opus (Kei API)
- 입력: 정규화된 텍스트
- 출력:
Analysis(title, core_message, layout_template, total_pages, page_structure, topics) - 핵심 판단:
- 꼭지 5개 이내 추출
- 각 꼭지에 purpose, layer, role, emphasis, direction 부여
- layout_template = "A" 또는 "B" 선택
- page_structure에 역할별 weight(비중) 배정
Stage 1B: 컨셉 구체화
- 파일:
src/kei_client.py→refine_concepts() - AI: Opus
- 출력: topics에 relation_type, expression_hint, source_data 추가
Stage 1B-ST: 구조화 텍스트 생성
- 파일:
src/kei_client.py→generate_structured_text() - AI: Opus
- 출력: topic별 structured_text (마크다운 형태)
Stage 1.5a: 컨테이너 계산 (결정론적)
- 파일:
src/space_allocator.py - 함수:
- Type A →
calculate_container_specs() - Type B/B'/B'' →
build_containers_type_b() - 공통 →
calculate_font_hierarchy(),select_preset()
- Type A →
- 입력: page_structure의 weight, slide 크기(1280×720)
- 출력: 역할별
ContainerSpec(width_px, height_px, zone) - 로직: weight × available_px = 각 zone px 확정
Stage 1.7: 블록 레퍼런스 선택
- 파일:
src/block_reference.py→select_and_generate_references() - 로직 (코드 결정론적 + AI 1회):
- relation_type → 블록 카테고리 매핑
- expression_hint 키워드 매칭
- 컨테이너 크기 적합성 필터
- role/zone 제약 (sidebar → visuals/media 제외)
- catalog.yaml 존재 검증 (유령 블록 차단)
- 후보 2-3개 → Kei 1회 호출로 최종 선택
- 출력: 역할별
BlockReference(block_id, design_reference_html)
Stage 1.8: 적합성 검증 + 보강
- 파일:
src/fit_verifier.py→calculate_fit() - 로직:
- 텍스트 분량 vs 할당 공간 계산
- Selenium으로 실제 높이 측정 (3회 루프)
- overflow 시 → Kei 에스컬레이션 (
call_kei_fit_escalation())- 팝업 분리 판단, zone 간 재배분
- 보강 제안: bold 키워드, 팝업 요약 등
Stage 2: HTML 생성
Type B/B'/B'' (코드 조립):
- 파일:
src/block_assembler.py→assemble_slide_html() - 역할별
assemble_role_html()호출 → 블록 HTML 조립 - structured_text + design_reference_html 결합
- 이미지/팝업 embed
- 즉시 완성 HTML 반환
Type A (AI 재구성, 미완성):
- 파일:
src/content_verifier.py→generate_with_retry() - Sonnet에 phase_t_context 전달 → CSS + 레이아웃 생성
- 현재 검증 불완전
Stage 3: 렌더링 조립 (Type A만)
- 파일:
src/renderer.py→render_slide_from_html() - Type B는 Stage 2에서 완전한 HTML이므로 스킵
Stage 4: 검증
- 파일:
src/slide_measurer.pymeasure_rendered_heights()— Selenium 실측capture_slide_screenshot()— 스크린샷 캡처
- 파일:
src/kei_client.py→vision_quality_gate()- Opus 멀티모달: 스크린샷 보고 시각 품질 평가
5. 핵심 파일 맵
src/
├── main.py ← FastAPI 서버, POST /api/generate
├── pipeline.py ← 파이프라인 오케스트레이터 (generate_slide)
├── pipeline_context.py ← PipelineContext 데이터 클래스
├── config.py ← 설정 (API key, 슬라이드 크기)
│
├── mdx_normalizer.py ← Stage 0: MDX → NormalizedContent
├── kei_client.py ← Stage 1A/1B/1B-ST: Kei API 호출 + 프롬프트
├── space_allocator.py ← Stage 1.5a: 컨테이너 px 계산
├── block_reference.py ← Stage 1.7: 블록 선택 (relation_type 기반)
├── fit_verifier.py ← Stage 1.8: 적합성 검증 + Selenium 루프
├── block_assembler.py ← Stage 2: Type B/B' HTML 조립
├── block_assembler_b2.py ← Stage 2: Type B'' HTML 조립
├── content_verifier.py ← Stage 2: Type A HTML (Sonnet, 미완성)
├── renderer.py ← Stage 3: Jinja2 렌더링 (Type A만)
├── slide_measurer.py ← Stage 4: Selenium 측정 + 스크린샷
├── validators.py ← Kei 응답 검증 (A/B별 구조 확인)
│
├── image_utils.py ← 이미지 크기 측정 + data URI 변환
├── svg_calculator.py ← SVG 다이어그램 좌표 계산
└── sse_utils.py ← SSE 스트리밍 유틸
templates/
├── slide-base.html ← 슬라이드 기본 구조 (Jinja2, CSS Grid)
├── catalog.yaml ← 블록 라이브러리 정의 (50+개)
└── blocks/ ← 블록 HTML 템플릿
├── headers/ (8개)
├── cards/ (17개)
├── emphasis/ (12개)
├── tables/ (8개)
├── visuals/ (6개)
├── media/ (4개)
└── BEPs/ (6개)
6. 데이터 흐름 (PipelineContext)
PipelineContext:
raw_content ← 원본 MDX
normalized ← NormalizedContent (sections, images, tables)
analysis ← Analysis (title, core_message, layout_template, page_structure, topics)
topics ← list[Topic] (relation_type, expression_hint, structured_text 포함)
page_structure ← PageStructure (roles → {topic_ids, weight, zone})
containers ← dict[role → ContainerSpec(width_px, height_px)]
font_hierarchy ← FontHierarchy (key_msg, core, bg, sidebar 폰트 크기)
references ← dict[role → list[BlockReference]]
sub_layouts ← dict[role → SubLayout]
fit_result ← 역할별 fit_status, 재배분값
enhancement_result ← bold_keywords, popup_summaries 등
generated_html ← Stage 2 출력
rendered_html ← Stage 3 출력 (완전 HTML)
measurement ← Selenium 측정값
quality_score ← 0-100
7. 현재 구현 상태 (Phase Y-11~13, 2026-04-15)
Phase Y: slide-base 기반 파이프라인 재설계. 상세:
docs/history/PHASE-Y-PLAN.md
파이프라인 흐름 (현재)
[Stage 0] MDX → normalized.sections (source of truth)
[Stage 1A] Kei 꼭지 추출 (영역/zone 판단 안 함)
[Phase Y] 코드: normalized → 대목차 추출 → group schema 분류 → 블록 매칭 → 영역 확정
[Stage 1.5a] space_allocator: weight → zone px (% 기반)
[Stage 1.7] block_reference: tag_match → schema_match → fallback 순서
[Stage 1.8] assembler(measure_mode) → Selenium 측정 → fit 루프
[Stage 2] assembler(slide-base + 블록) → final HTML
[Stage 4] Selenium overflow + 비전 (-1 미평가)
MDX별 상태
| MDX | 상태 | 비고 |
|---|---|---|
| 03 | ✅ 동작 | prerequisites-3col + pp2. 텍스트 누락 없음. 회귀 기준. |
| 02 | ⚠ schema 1차 | top: parallel_3_with_image. bottom: 분류 정교화 필요. |
| 01 | ⬜ 미착수 | Type A. 별도 작업. |
핵심 원칙 (확립됨)
- source of truth = normalized.sections (Stage 0)
- 영역 = 코드가 결정 (Kei 아님). sub_titles 기반 + group schema.
- 블록 CSS에 최종 고정값. slide_font_css는 공통 레이아웃 계약만.
- zone = % 기반, block = height:100%.
- 글씨 크기 고정. fit은 padding → 내용량 → font 1단계(responsive tier).
- 기존 경로 삭제 금지. 새 schema 점진적 추가. MDX 03 회귀 기준.
- 하드코딩 금지. 프로세스가 결과를 만드는 구조.
- 블록 글씨 크기 하드코딩 (px 고정)
- 블록 CSS에 font-size가 Figma 원본 px로 고정
- 컨테이너 크기에 따라 조정 불가 → overflow 원인
- CSS 변수(
var(--block-font-heading))로 전환 → assembler가 zone 크기에 따라 계산
미해결 프로세스
- overflow 시 font 조정 루프 — 재배분만으로 부족할 때 font/padding 줄이기 (Y-5)
- Sonnet redesign 경로 — tag 매칭 실패 시 블록 단위 redesign → 저장 (Y-6)
8. 검증 계획
업데이트된 템플릿이 파이프라인에서 제대로 동작하는지 확인한다.
| MDX | 유형 | 검증 포인트 |
|---|---|---|
| 01번 | Type A | 업데이트된 블록 + slide-base.html로 조립 정상 동작 |
| 02번 | Type B | 업데이트된 블록 선택 + 조립 + overflow 없음 |
| 03번 | Type B' | 카드/표 구조가 업데이트된 템플릿으로 정상 렌더링 |
검증 방법
- 각 MDX를 파이프라인에 투입
- 중간 산출물(step1_analysis.json 등) 확인 — 블록 선택이 의도대로인지
- 최종 HTML(final.html) 렌더링 — overflow, 시각 품질 확인
- 업데이트 전/후 비교