kyeongmin 24eb1bc5ad Phase U: 하드코딩 10건 제거 — 범용 프롬프트 시스템
제거:
- _get_popup_data() 함수 삭제 (DX/BIM 비교표 하드코딩)
- "📊 DX와 BIM의 상세 비교" 팝업 링크 → Claude 자율 판단
- "BIM ≠ DX" 예시 → core_message 변수만
- "상위개념/하위기술/포함관계" 금지어 → 범용 "임의 라벨 금지"
- fallback 키워드 ["혼용","사례"], ["관계","핵심기술","DX"] → source_hint 동적 추출
- "사례 카드" → "토픽" 범용화
- "BIM (Building Information Modeling)" 예시 → 제거

추가:
- _extract_keywords_from_hints(): source_hint에서 섹션명 키워드 동적 추출
- 팝업: 원본에 비교 구조 있으면 Claude가 자체 판단, 없으면 팝업 없음
- content_verifier: body_bg overflow 패턴 OR 수정, popup-link 필수 해제

회귀 테스트: 기존 MDX 전체 PASS (1차 시도)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 10:44:45 +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(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단계] 블록 선택 (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

단계별 상세

단계 담당 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로 사후 자르기 금지

컨테이너 시스템 (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→블록제약→콘텐츠제약 완료
P 블록 재구성 + 실제 렌더링 비교 선택 — 후보 3개 렌더링→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 리포트 전 단계 시각화 리포트

리포트 생성: 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 (결정론적)

설치 및 실행

# 설치
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
# 터미널 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 연동만.
Description
No description provided
Readme 214 MiB
Languages
Python 86.6%
HTML 12.7%
CSS 0.7%