kyeongmin ffad1ba82a Phase I 실행 완료 + 프로세스 재설계 (Stage 2.5 → Stage 5)
Phase I: 전수 정합성 복구 + 넘침 처리 패러다임 전환 (14개 항목)
- I-14: SSE 유틸 공통 추출 (src/sse_utils.py 신규, 3개 파일 중복 제거)
- I-13: dead code 3건 삭제 (_call_anthropic_direct, _extract_sse_text x2) + import anthropic 제거
- I-1: STEP_B_PROMPT purpose 가이드 미존재 블록 3개 → 실존 블록 교체
- I-2: catalog.yaml not_for 13건 미존재 블록 참조 교체/제거
- I-12: BLOCK_SLOTS 주석 개수 수정 (cards 9, visuals 6, emphasis 10)
- I-10: INDEX.md 38개 동기화 (삭제된 8개 블록 행 제거)
- I-11: README.md 38개 동기화 (_legacy 제거, 트리/개수 정리)
- I-3: PURPOSE_FALLBACK 상수 + purpose 기반 미등록 블록 교체
- I-7: compare-pill-pair 단독 사용 금지 검증
- I-4: 38개 블록 전체에 slot_desc 추가
- I-5: 편집자 프롬프트에 slot_desc 전달 로직
- I-6: 제목 유사도 70% 초과 시 자동 교정
- I-9: 넘침 판단 Kei API 호출 (KEI_OVERFLOW_PROMPT, call_kei_overflow_judgment)
- I-8: 대형 콘텐츠 정보 Kei overflow 프롬프트에 포함

프로세스 재설계:
- Stage 2.5 제거 → Stage 5에서 Sonnet 감지 + Kei 판단 통합
- _review_balance() 확장: zone 예산 + overflow_detected action 추가
- Stage 5 루프에 Kei 넘침 판단 호출 통합
- _apply_adjustments()에 kei_trim/kei_restructure action 추가
- _build_overflow_context(), _convert_kei_judgment() 헬퍼 함수 추가
- DOWNGRADE_MAP은 Kei API 실패 시 비상용으로만 잔존

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 13:06:21 +09:00
2026-03-24 17:25:47 +09:00
2026-03-24 17:25:47 +09:00
2026-03-24 17:25:47 +09:00

Kei Design Agent

콘텐츠를 시각적으로 구조화된 슬라이드 HTML로 변환하는 독립 에이전트.

개요

텍스트/MDX 콘텐츠를 입력하면, AI가 정보 구조를 파악하고 적합한 레이아웃과 블록을 선택하여 깔끔한 1페이지(또는 다중 페이지) 슬라이드를 생성합니다.

아키텍처 (5단계 파이프라인)

텍스트 입력 (+ 이미지 폴더 경로)
    ↓
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[1단계] Kei 실장 — 콘텐츠 분석 + 스토리라인 설계
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
│  사용 AI: Kei API (Opus)
│  fallback: manual_classify() (최소 구조 생성)
│
│  1-A: 정보 구조 파악 + 꼭지 추출
│    - 핵심 메시지(core_message) 도출
│    - 본문 흐름(flow) vs 참조 정보(reference) 분리
│    - 각 꼭지의 레이어/강조/배치 방향 판단
│    - 이미지 판단 (개수/소속/핵심·보조/텍스트 포함 여부)
│    - 표 판단 (행/열 규모, 1페이지 표시 가능 여부)
│    - purpose 부여 (문제제기/근거사례/핵심전달/용어정의/결론강조/구조시각화)
│
│  1-B: 각 꼭지 컨셉 구체화
│    - relation_type (비교/포함/계층/인과 등)
│    - expression_hint (표현 방향)
│    - source_data (원본에서 추출할 데이터)
│
│  제목 중복 검증 (I-6)
│    - 슬라이드 제목 ↔ 첫 꼭지 제목 유사도 70% 초과 시 자동 교정
│
│  이미지 크기 측정 (Pillow)
│    - base_path 있으면 이미지 파일 크기 측정 → analysis에 포함
│
    ↓
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[2단계] 디자인 팀장 — 레이아웃 설계 + 블록 매핑
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
│  Step A-1: 레이아웃 프리셋 자동 선택 (규칙 기반, LLM 불필요)
│    - sidebar-right / two-column / hero-detail / single-column
│    - grid는 코드가 프리셋에서 강제 (AI가 변경 불가)
│
│  Step A-2: Opus(Kei API) 블록 추천 (FAISS 검색 결과 기반)
│    사용 AI: Kei API (Opus)
│    - 도메인 지식 + 콘텐츠 성격 기반 블록 추천
│    - fallback: 추천 없이 Step B로
│
│  Step B: 블록 매핑 + 글자 수 가이드 (Sonnet)
│    사용 AI: Anthropic API (Sonnet)
│    - Opus 추천 참고하되 최종 선택은 팀장 판단
│    - 컨테이너 예산(zone별 높이 px) 기반 블록 선택
│    - purpose 기반 블록 선택 가이드 참고
│    - 각 블록에 char_guide(글자 수 가이드) 부여
│
│  블록 검증 (코드):
│    - 미등록 블록 → purpose 기반 fallback (PURPOSE_FALLBACK)
│    - 잘못된 zone → 기본 zone 자동 매핑
│    - conclusion 꼭지 → footer zone 강제
│    - compare-pill-pair 단독 사용 → comparison-2col 교체 (I-7)
│    - 금지 블록(section-title-with-bg) → body/sidebar에서 교체
│
│  높이 예산 검증 (I-9):
│    - zone별 블록 높이 합산 vs budget_px 비교
│    - 초과 시 → overflow 정보 수집 (블록 자동 교체 안 함)
│
    ↓ (overflow 있으면)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[2.5단계] Kei 실장 — 넘침 판단 (I-9)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
│  사용 AI: Kei API (Opus)
│  조건: 2단계에서 overflow 발생 시에만 실행
│
│  Kei에게 전달: 어떤 zone이 얼마나 초과, 블록/콘텐츠 요약, 대형 테이블/이미지 정보 (I-8)
│
│  Kei가 판단:
│    Option 1 "trim" → 텍스트 분량 제약 (char_guide 축소) → 3단계에서 반영
│    Option 2 "restructure" → 핵심 재구성 + 상세는 팝업(detail page) 분리
│                              → detail_target 설정 후 2단계 재실행
│
│  Kei API 실패 시: DOWNGRADE_MAP 비상 작동 (기계적 블록 교체)
│
    ↓
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[3단계] Kei 텍스트 편집자 — 도메인 전문가로서 텍스트 정리
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
│  사용 AI: Kei API (Opus + RAG + 도메인 지식)
│  Sonnet fallback 없음 (Kei API만 사용)
│
│  - 각 블록의 슬롯에 맞게 텍스트 정리
│  - 슬롯 의미 설명(slot_desc) 참고하여 정확한 데이터 배치 (I-4, I-5)
│  - 글자 수 가이드 참고, 내용 의미 우선
│  - 2.5단계에서 trim 제약이 있으면 반영
│  - 원본 텍스트 최대 보존, 출처 보존, 개조식, 날조 금지
│  - detail_target 꼭지: summary + detail 두 버전 작성
│
    ↓
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[4단계] 디자인 실무자 — 디자인 조정 + HTML 조립
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
│  사용 AI: Anthropic API (Sonnet) — CSS 변수 override 결정
│  렌더링: Jinja2 + CSS Grid
│
│  - Sonnet이 텍스트 양에 맞게 CSS 변수 override 결정
│    (--font-body, --font-subtitle, --spacing-inner, --spacing-block 등)
│  - Jinja2로 블록 템플릿 렌더링
│  - CSS 변수 cascade로 area별 자동 적용
│  - SVG 시각화 블록: 좌표 사전 계산 (svg_calculator.py)
│  - 이미지 base64 인라인 삽입 (다운로드 HTML에서도 표시)
│
    ↓
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[5단계] 디자인 팀장 — 전체 재검토 (최대 2회 루프)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
│  사용 AI: Anthropic API (Sonnet) — HTML 기반 균형 점검
│
│  점검 항목:
│    - 빈 블록 감지
│    - 채움 불균형 (한 블록은 빽빽, 다른 블록은 비어있음)
│    - 이미지/표 크기 적절성
│    - 전체 정보량 (페이지당 너무 많거나 적은지)
│
│  조정 필요 시:
│    - expand: 텍스트 늘림 (target_ratio, 예: 1.3 = 30% 증가)
│    - shrink: 텍스트 줄임 (target_ratio, 예: 0.7 = 30% 감소)
│    - rewrite: 텍스트 재작성 (방향 명시)
│    → 3단계(Kei 편집자) 재호출 → 4단계 재렌더링 → 재검토
│
│  조정 불필요 또는 2회 완료 시 확정
│
    ↓
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
미리보기 + HTML 다운로드
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

각 단계별 AI 담당

단계 담당 AI session_id
1-A Kei 실장 Kei API (Opus) design-agent
1-B Kei 실장 Kei API (Opus) design-agent-refine
2 A-2 Kei 실장 Kei API (Opus) design-agent-opus
2 B 디자인 팀장 Anthropic (Sonnet)
2.5 Kei 실장 Kei API (Opus) design-agent-overflow
3 Kei 편집자 Kei API (Opus) design-agent-editor
4 디자인 실무자 Anthropic (Sonnet)
5 디자인 팀장 Anthropic (Sonnet)

블록 라이브러리 (38개)

templates/blocks/
├── INDEX.md                                전체 인덱스
├── headers/ (5개)                          타이틀, 꼭지 헤더
│   ├── section-title-with-bg.html            배경 이미지 + 영문/한글
│   ├── section-header-bar.html               파란 배경 바 + 제목
│   ├── topic-left-right.html                 좌:제목 + 우:설명
│   ├── topic-center.html                     중앙 정렬 제목
│   └── topic-numbered.html                   번호 + 제목 + 설명
├── cards/ (9개)                            카드 계열
│   ├── card-image-3col.html                  이미지 카드 3열
│   ├── card-dark-overlay.html                다크 오버레이 카드
│   ├── card-tag-image.html                   태그 + 이미지 카드
│   ├── card-icon-desc.html                   아이콘 + 설명 카드
│   ├── card-compare-3col.html                비교 카드 3열
│   ├── card-step-vertical.html               세로 단계 카드
│   ├── card-image-round.html                 원형 이미지 카드
│   ├── card-stat-number.html                 큰 숫자 KPI 카드
│   └── card-numbered.html                    번호 리스트 카드
├── tables/ (3개)                           비교 테이블
│   ├── compare-3col-badge.html               A|VS배지|B 3단 비교
│   ├── compare-2col-split.html               좌우 분할 비교
│   └── table-simple-striped.html             줄무늬 일반 테이블
├── visuals/ (6개)                          다이어그램, 관계도 (SVG)
│   ├── venn-diagram.html                     벤 다이어그램 (N개 동적)
│   ├── circle-gradient.html                  그라데이션 원 + 텍스트
│   ├── compare-pill-pair.html                둥근 박스 2개 + VS
│   ├── process-horizontal.html               가로 단계 흐름
│   ├── flow-arrow-horizontal.html            가로 화살표 흐름
│   └── keyword-circle-row.html               키워드 원형 나열
├── emphasis/ (10개)                        강조, 인용, 결론
│   ├── quote-big-mark.html                   큰 따옴표 인용
│   ├── quote-question.html                   질문형 강조
│   ├── comparison-2col.html                  2단 비교
│   ├── banner-gradient.html                  그라데이션 배너
│   ├── dark-bullet-list.html                 다크 배경 불릿 리스트
│   ├── highlight-strip.html                  하이라이트 스트립
│   ├── callout-solution.html                 솔루션 콜아웃
│   ├── callout-warning.html                  경고 콜아웃
│   ├── tab-label-row.html                    탭 라벨 행
│   └── divider-text.html                     텍스트 구분선
└── media/ (5개)                            이미지/미디어
    ├── image-row-2col.html                   이미지 2장 나란히
    ├── image-grid-2x2.html                   이미지 2x2 그리드
    ├── image-side-text.html                  이미지 + 텍스트
    ├── image-full-caption.html               전체 너비 이미지 + 캡션
    └── image-before-after.html               Before/After 비교

FAISS 블록 검색

38개 블록 전체를 프롬프트에 넣는 대신, FAISS로 꼭지별 관련 블록만 검색하여 전달합니다.

꼭지 "A vs B 비교" → FAISS 검색 → comparison-2col, compare-pill-pair, compare-2col-split
꼭지 "연도별 로드맵" → FAISS 검색 → process-horizontal, flow-arrow-horizontal, card-step-vertical
  • 임베딩 모델: BAAI/bge-m3 (1024차원, 한국어 최적화)
  • 인덱스 빌드: python scripts/build_block_index.py
  • fallback: 인덱스 없으면 catalog.yaml 전문 전달 (기존 방식)

레이아웃 프리셋

프리셋 조건 CSS Grid zone 예산
sidebar-right reference 꼭지 있음 65:35 좌우 분할 body 490px, sidebar 490px
two-column 대등한 비교 50:50 균등 left 490px, right 490px
hero-detail 고강조 1개 + 보조 hero 영역 + detail hero 310px, detail 155px
single-column 순차적 flow만 1열 body 490px

grid는 코드(Step A)가 결정. Sonnet은 blocks만 출력. grid 변경 불가.

기술 스택

역할 도구
서버 FastAPI + uvicorn (포트 8001)
AI (1단계 실장) Kei API (Opus) → fallback: Sonnet
AI (2단계 A-2) Kei API (Opus) — 블록 추천
AI (2단계 B) Anthropic API (Sonnet) — 블록 매핑
AI (3단계 편집자) Kei API → fallback: Sonnet
AI (4단계 실무자) Anthropic API (Sonnet) — CSS 조정
AI (5단계 재검토) Anthropic API (Sonnet) — 균형 점검
블록 검색 FAISS + bge-m3 (38개 블록 인덱스)
템플릿 Jinja2 (카테고리별 블록 조합)
렌더링 CSS Grid + 디자인 토큰 (16:9, 1280×720)
SVG 시각화 svg_calculator.py (cos/sin 좌표 계산, N개 동적)
이미지 처리 Pillow (크기 측정) + base64 인라인
폰트 Pretendard Variable (한국어)

설치 및 실행

설치

cd design_agent
python -m venv .venv
.venv/Scripts/activate    # Windows
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

실행

# 터미널 1: Kei 백엔드 (Opus 실장 + 편집자 역할)
cd D:\ad-hoc\kei\persona_agent
uvicorn backend.main:app --reload --host 127.0.0.1 --port 8000

# 터미널 2: Design Agent
cd D:\ad-hoc\kei\design_agent
uvicorn src.main:app --reload --host 127.0.0.1 --port 8001

접속: http://localhost:8001

프로젝트 구조

design_agent/
├── CLAUDE.md                     프로젝트 규칙 + 5단계 프로세스
├── PLAN.md                       태스크 계획
├── PROGRESS.md                   진행 상황
├── IMPROVEMENT.md                개선 계획 (Phase A~F)
├── IMPROVEMENT-PHASE-{A~D}.md    각 Phase 실행 상세
├── README.md                     이 파일
├── pyproject.toml
├── .env                          API 키
│
├── src/                          파이프라인 코드
│   ├── main.py                     FastAPI 서버 (포트 8001)
│   ├── config.py                   설정 (pydantic-settings)
│   ├── kei_client.py               1단계: Kei API → 꼭지 추출
│   ├── design_director.py          2단계: 프리셋 선택 + Opus 추천 + 블록 매핑
│   ├── content_editor.py           3단계: Kei API → 텍스트 정리
│   ├── pipeline.py                 5단계 파이프라인 (디자인 조정 + 재검토 루프)
│   ├── renderer.py                 4단계: HTML 조립 (SVG 전처리 + CSS 변수 override)
│   ├── block_search.py             FAISS 블록 검색 모듈
│   ├── svg_calculator.py           SVG 좌표 계산 (cos/sin N개 배치)
│   └── image_utils.py              이미지 크기 측정 + base64 삽입
│
├── scripts/
│   └── build_block_index.py        FAISS 인덱스 빌드 스크립트
│
├── templates/
│   ├── slide-base.html             슬라이드 베이스 (다중 페이지 + 인쇄 JS)
│   ├── catalog.yaml                블록 카탈로그 (38개, height_cost 포함)
│   └── blocks/                     블록 라이브러리 (6 카테고리, 38개)
│       ├── INDEX.md                  전체 인덱스
│       ├── headers/ (5)              타이틀, 꼭지 헤더
│       ├── cards/ (10)               카드 계열
│       ├── tables/ (3)               비교 테이블
│       ├── visuals/ (10)             다이어그램, 관계도 (SVG)
│       ├── emphasis/ (13)            강조, 인용, 결론, 자세히보기
│       ├── media/ (5)                이미지/미디어
│       └── media/ (5)                이미지/미디어
│
├── static/
│   ├── index.html                  프론트엔드 (이미지 경로 입력 팝업 포함)
│   ├── tokens.css                  디자인 토큰
│   └── base.css                    기본 슬라이드 스타일
│
├── data/                           로컬 데이터 (gitignored)
│   ├── block_index.faiss             FAISS 벡터 인덱스
│   └── block_metadata.json           인덱스 메타데이터
│
├── docs/
│   ├── RESEARCH.md                 기술 조사
│   ├── PHASE2-PLAN.md              Phase 2 계획
│   ├── PHASE2-PROCESS.md           Phase 2 실행 프로세스
│   ├── PHASE2-TECH-REVIEW.md       Phase 2 기술 검토
│   ├── figma-screenshots/          Figma 스크린샷 (16장)
│   ├── figma-assets/               Figma 에셋
│   ├── figma-analysis/             노드 구조 분석
│   └── block-tests/                블록 테스트 HTML
│
└── tests/

핵심 원칙

  • 모든 판단은 AI 사고. 하드코딩 없음
  • 텍스트가 기준. 디자인이 텍스트에 맞춤 (텍스트를 자르지 않음)
  • 이미지 원본 그대로, 크기만 조절 (object-fit: contain)
  • 컨테이너 예산(zone별 높이 px) 안에서 블록 배치
  • grid는 코드가 결정. Sonnet은 blocks만 판단
  • Kei API 1차 → Sonnet fallback (1단계, 3단계)
  • Kei Persona Agent 코드를 수정하지 않음

Kei Persona와의 관계

Kei Persona (본체) — localhost:5173/8000
  ├ 대화/생성/피드백/실행 모드
  ├ Opus + RAG (bge-m3 + FAISS)
  └ 독립적으로 동작

Design Agent (이 프로젝트) — localhost:8001
  ├ 슬라이드 생성 전용
  ├ Kei API로 실장(1단계) + 편집자(3단계) + 블록 추천(2단계 A-2) 호출
  ├ FAISS 블록 검색 (bge-m3, Kei와 동일 모델)
  └ 독립적으로 동작 (Kei 없이도 Sonnet fallback)

두 프로젝트는 완전히 독립. 코드 공유 없음. API 연동만.

Description
No description provided
Readme 214 MiB
Languages
Python 86.6%
HTML 12.7%
CSS 0.7%