Dash Creator
Developer Guide
자연어 한 줄로 Android AI 위젯을 생성하는 플랫폼의 공식 개발자 문서. L1~L5 파이프라인, REST API, DASH.md 스펙, 스킨 시스템을 다룹니다.
01 빠른 시작
서버를 시작하고 첫 Dash를 생성하기까지 60초면 충분합니다.
# 서버 시작 cd skills/dash-creator/src uvicorn api.playground:app --reload --port 8000 # 첫 번째 Dash 생성 curl -X POST http://localhost:8000/api/creator/generate \ -H "Content-Type: application/json" \ -d '{"text": "매일 아침 날씨 알려줘"}'
성공하면 아래 구조의 JSON이 반환됩니다.
{
"ok": true,
"trace_id": "a3f2c91d",
"intent": {
"domain": "WEATHER",
"size": "MEDIUM",
"skin": "dark-ocean",
"confidence": 0.91
},
"files": {
"dash_composable_kt": "WeatherDailyDash.kt (...) ",
"repository_kt": "WeatherDailyRepository.kt (...)",
"dash_md": "DASH.md (...)"
},
"validation": {
"passed": true,
"score": 8.7,
"failed_rules": []
},
"stage": "ok",
"retried": false
}
/api/creator/simulate 엔드포인트를 사용하세요. 결정론적 출력이 반환됩니다.02 아키텍처 개요
자연어 텍스트는 creator_chain.py 오케스트레이터를 거쳐 L1→L5 파이프라인을 통과합니다. 각 레이어는 독립 모듈로 분리돼 있어 단계별 교체·확장이 가능합니다.
creator_intent.py · LLM이 자연어를 분석해 구조화된 인텐트를 추출합니다blueprint_registry.py · 도메인에 맞는 Dash 구조 규칙을 조회합니다style_registry.py · 스킨별 디자인 토큰과 컬러를 해석합니다data_registry.py · 데이터 소스 설정과 샘플 컨텍스트를 구성합니다creator_codegen.py · L1~L3 컨텍스트를 바탕으로 Kotlin + DASH.md 파일을 생성합니다creator_validator.py · 생성 코드 품질을 규칙 기반으로 검증합니다. 실패 시 L4 1회 재시도run_text_to_dash(text) 한 줄로 전체 파이프라인이 실행됩니다.03 API 레퍼런스
모든 엔드포인트는 http://localhost:8000/api/creator/ 아래 위치합니다. 요청/응답 모두 application/json입니다.
자연어 텍스트로 Dash를 생성합니다. L1~L5 파이프라인 전체를 실행하며, LLM API 키가 필요합니다.
| 필드 | 타입 | 필수 | 설명 | 기본값 |
|---|---|---|---|---|
| text | string | REQUIRED | 자연어 요청 텍스트 | — |
| size | string | optional | TINY · SMALL · MEDIUM · LARGE · EXTRALARGE | MEDIUM |
| skin | string | optional | dark-ocean · neon-city · warm-paper · forest-green · pure-light · sunset-warm | 도메인 자동 선택 |
| domain | string | optional | 도메인 힌트 — L1 파싱 우선 적용 | L1 자동 분류 |
| 필드 | 타입 | 설명 |
|---|---|---|
| ok | boolean | 파이프라인 성공 여부 |
| trace_id | string | 8자 요청 추적 ID (디버깅용) |
| intent | DashIntent | L1 파싱 결과 (domain, size, skin, confidence) |
| files | GeneratedFiles | 생성된 파일 내용 (composable_kt, repository_kt, dash_md) |
| validation | ValidationResult | L5 검증 결과 (passed, score, failed_rules) |
| stage | string | 실패 단계 (ok · L1 · L2a · L4 · L5) |
| clarification_needed | boolean | L1 confidence < 0.5 — 추가 질의 필요 |
| retried | boolean | Validator 실패로 L4 재생성 실행 여부 |
| error | string? | 실패 메시지 (ok=true 시 null) |
LLM 키 없이 결정론적 Dash를 생성합니다. CI 테스트 및 개발 환경 검증에 사용합니다. 인터페이스는 /generate와 동일합니다.
텍스트의 인텐트만 파싱합니다 (L1만 실행). 사용자 입력의 즉각적인 분류 피드백에 활용합니다.
{ "text": "삼성전자 주가 5분마다 알려줘" }
{
"domain": "FINANCE",
"size": "SMALL",
"skin": "dark-ocean",
"confidence": 0.88,
"clarification_needed": false
}
시스템 상태, 지원 도메인, 스킨 목록을 반환합니다.
{
"status": "ok",
"version": "1.0.0",
"domains": ["FINANCE", "WEATHER", "HEALTH", "PRODUCTIVITY", "COMMUTE", "MEDIA", "BUSINESS", "LIFESTYLE", "NATURE"],
"skins": ["dark-ocean", "neon-city", "warm-paper", "forest-green", "pure-light", "sunset-warm"],
"llm_available": true
}
04 DASH.md 스펙
각 Dash는 DASH.md 메타파일을 포함합니다. Orchestrator가 이 파일을 파싱해 트리거 조건, 권한, 데이터 소스, 스킨 진입점을 결정합니다.
전체 예시 — 일일 날씨 대시
DASH.md 전체 구조 보기
meta: id: "com.theuniverse.weather-daily" name: "일일 날씨 대시" version: "1.0.0" category: "utility" keywords: ["날씨", "기온", "미세먼지", "forecast"] author: "creator@theuniverse.app" description: "매일 아침 날씨와 미세먼지를 한눈에 확인" trigger: conditions: - type: time start: "07:00" end: "08:30" days: [1, 2, 3, 4, 5, 6, 7] - type: orchestrator_call keywords: ["날씨", "기온", "비 올까", "우산"] confidence: 0.8 skin: sizes: ["mini", "standard", "expanded"] theme_aware: true composable_entry: "WeatherDailyDash" default_size: "standard" dash: entry: "WeatherDailyDash" description: "실시간 날씨 정보. 기온·체감온도·습도·미세먼지 제공." capabilities: [current_weather, air_quality, hourly_forecast] intents: ["날씨 알려줘", "오늘 기온", "미세먼지 어때"] data_sources: - type: web_api name: "kma_weather" update_interval: "1hour" permissions: [network, notifications, location_coarse] local_state: false quota: memory_mb: 24 network_kb_per_min: 256 cpu_percent: 5 protocol: fusible_with: ["travel", "schedule_management", "environmental"]
05 Spec Roles (8개)
Dash의 행동은 8개 Role의 조합으로 정의됩니다. 하나의 Dash는 여러 Role을 가질 수 있으며, display는 항상 필수입니다.
role: display layout: card_metric media_type: text priority: 1
role: source source_type: web_api topic: stock_price location: KR
role: notify channel: push target: user timing: on_threshold
role: trigger event: price_change condition: gt threshold: 0.1
role: schedule cron: "0 7 * * *" timezone: Asia/Seoul
role: generate prompt: "오늘의 격언 생성" media_type: text
role: filter criteria: category_match threshold: 0.7
role: summarize prompt: "핵심 3줄 요약" max_length: 120
06 카테고리 & 도메인
9개 도메인 (L1 자동 분류)
L1 Intent Parse가 자연어를 분석해 자동으로 도메인을 할당합니다.
22개 카테고리
DASH.md의 meta.category에 기록됩니다.
자연어 → 도메인 → 카테고리 매핑 예시
| 자연어 예시 | 도메인 | 카테고리 | 기본 스킨 |
|---|---|---|---|
| "삼성전자 주가 5분마다 알려줘" | FINANCE | finance | dark-ocean |
| "오늘 미세먼지 어때" | WEATHER | environment | forest-green |
| "매일 만보 걷기 기록" | HEALTH | fitness | forest-green |
| "오늘 할일 알려줘" | PRODUCTIVITY | calendar | pure-light |
| "지하철 막차 시간" | COMMUTE | transport | neon-city |
| "요즘 핫한 유튜브 트렌드" | MEDIA | video | neon-city |
| "오늘 점심 뭐 먹을까" | LIFESTYLE | food | sunset-warm |
07 코드 예제
Python — creator_chain.py 직접 호출
from engine.creator_chain import run_text_to_dash, ChainHints # ── 기본 생성 ────────────────────────────────────────────── result = run_text_to_dash("매일 아침 삼성전자 주가 알려줘") if result.ok: print(result.files.dash_composable_kt) print(f"검증 점수: {result.validation.score}/10") elif result.clarification_needed: print("명확히 해주세요:", result.error) else: print(f"실패 단계 {result.stage}:", result.error) # ── 힌트 지정 ─────────────────────────────────────────────── result = run_text_to_dash( "주가 대시", hints=ChainHints( size="LARGE", skin="dark-ocean", domain="FINANCE" ) ) # ── 다중 후보 생성 ────────────────────────────────────────── from engine.creator_chain import run_text_to_dash_variants variants = run_text_to_dash_variants("날씨 대시", n=3) best = max( (v for v in variants if v.ok), key=lambda v: v.validation.score ) print(f"최고 점수: {best.validation.score} / skin: {best.intent.skin}")
cURL
# 생성 (LLM 호출) curl -X POST http://localhost:8000/api/creator/generate \ -H "Content-Type: application/json" \ -d '{"text": "주가 10% 떨어지면 알려줘", "size": "MEDIUM"}' # 시뮬레이션 (LLM 없이) curl -X POST http://localhost:8000/api/creator/simulate \ -H "Content-Type: application/json" \ -d '{"text": "날씨 대시"}' # 인텐트만 확인 curl -X POST http://localhost:8000/api/creator/validate-text \ -H "Content-Type: application/json" \ -d '{"text": "내일 미세먼지 알려줘"}' # 헬스체크 curl http://localhost:8000/api/creator/health
08 스킨 (6종)
스킨은 Dash의 시각적 정체성을 정의합니다. L1이 도메인 기반으로 자동 선택하며, 사용자가 skin 파라미터로 명시 지정할 수 있습니다.
09 인텐트 처리
L1이 자연어에서 추출하는 인텐트 유형과 각 처리 방식입니다.
| 인텐트 | 설명 | 처리 방식 | 상태 |
|---|---|---|---|
| create | 새 Dash 생성 | L1~L5 전체 파이프라인 실행 | ✅ 안정 |
| condition | if-then 조건 설정 | condition_branch 반환 → 런타임 처리 | 🔧 Phase 2 |
| edit | 기존 Dash 수정 | Dash 조회 후 변경 부분 재생성 | 🔧 Phase 2 |
| schedule | 주기 실행 설정 | schedule Role 삽입 후 재생성 | ✅ 안정 |
| notify | 알림 조건 설정 | notify Role 삽입 후 재생성 | ✅ 안정 |
| summarize | 요약 요청 | summarize Role 추가 후 재생성 | ✅ 안정 |
| generate | AI 콘텐츠 생성 요청 | generate Role 추가 후 재생성 | 📋 실험적 |
| filter | 데이터 필터링 | filter Role + 조건 추가 | ✅ 안정 |
| query | 단순 정보 조회 | clarification 없이 L1 결과만 반환 | ✅ 안정 |
| unknown | 분류 불가 | clarification_needed=true 반환 | ✅ 안정 |
10 오류 처리 & 트러블슈팅
ChainResult.stage로 실패 단계를 특정하고 error 필드로 원인을 확인합니다.
| 단계 | 원인 | 해결 방법 |
|---|---|---|
L1 confidence 낮음 |
텍스트가 너무 짧거나 모호합니다 (예: "대시 만들어줘") | clarification_needed=true 확인 후 사용자에게 추가 입력 요청. domain 힌트 명시 |
L2a 도메인 없음 |
BlueprintRegistry에 해당 도메인 항목이 없습니다 | blueprint_registry.py에 도메인 BlueprintRule 추가 |
L2b 스킨 없음 |
요청한 skin 값이 등록되지 않았습니다 |
/api/creator/health의 skins 목록으로 유효값 확인 |
L4 codegen 실패 |
LLM API 오류 또는 키 누락 | ANTHROPIC_API_KEY / GEMINI_API_KEY 환경변수 확인. /simulate로 우선 검증 |
L5 검증 실패 |
생성 코드가 필수 규칙을 위반합니다 (score < 6.0) |
failed_rules 배열로 위반 규칙 확인. retry_on_validator_fail=True로 자동 재생성 활성화 |
자주 겪는 문제
서버 시작 후 422 Unprocessable Entity 반환
text 필드는 필수입니다. Content-Type: application/json 헤더가 포함되어야 합니다.Python 모듈 임포트 오류 (ModuleNotFoundError)
skills/dash-creator/src 디렉토리에서 실행하세요. 또는 PYTHONPATH를 해당 경로로 설정하세요.export PYTHONPATH=skills/dash-creator/src python -m pytest ../tests/ -v
L4 codegen이 항상 실패합니다
/simulate를 사용하세요. 실제 키가 있다면 llm_router.py의 provider 우선순위를 확인하세요 (Gemini → Claude → fallback).11 환경 설정
설치
# 의존성 설치 cd skills/dash-creator/src pip install -r requirements.txt
환경 변수
| 변수 | 설명 | 필수 |
|---|---|---|
| ANTHROPIC_API_KEY | Claude LLM 호출용 키 (sk-ant-...) | L4 필수 |
| GEMINI_API_KEY | Gemini LLM 호출용 키 (AI...) | 선택 |
# 환경변수 설정 export ANTHROPIC_API_KEY=sk-ant-... export GEMINI_API_KEY=AI... # 개발 서버 시작 uvicorn api.playground:app --reload --port 8000 # 전체 테스트 (LLM 없이) python -m pytest ../tests/ -v # creator_chain 테스트만 python -m pytest ../tests/test_creator_chain.py -v # 특정 테스트 함수 python -m pytest ../tests/test_creator_chain.py::test_simulate_weather -v
.env 파일이나 시스템 환경변수를 사용하고, .gitignore에 .env를 반드시 추가하세요.