Illustration
AI 시각 자산 (SVG) — prompt builder + SVG 보안 정화 (script/iframe/external image 차단)
상태
| 항목 | 값 |
|---|---|
| Layer | domain |
| Tier | L1 |
| Status | wip |
| Version | 0.9.0 |
| 가격 | Free (free) |
| **카� | |
| �고리** | Content |
개요
개요
Illustration 은 multi-saas-kit 의 Layer 3 Domain Plugin � 니다. 학습 콘� �츠에 임베드할 SVG 일러스트를 LLM 으로 생성하기 위한 표준 prompt builder + 안전성 검증 sanitizer 를 제공합니다.
LLM 호출 부분은 AiRelay plugin 에 위임 — 본 plugin 은 prompt 구성과 결과 검증 의 Pure 부분만 담당.
핵심 컴포넌트 (3 + 2 enums)
Enums (2�
)
| Enum | Cases | 메서드 |
|---|---|---|
IllustrationKind | CARTOON / PHOTO / DIAGRAM / ICON | visualHint() |
StylePreset | FLAT / CARTOON / LINE / HAND_DRAWN | styleHint() |
Kind/Style 별 시각 묘사 hint 자동 생성 — prompt 에 자동 삽� .
PromptBuilder (Pure)
academy.how IllustrationGenerator::buildPrompt 추출.
�
력: caption + kind + style + locale
출력: LLM 에 전달할 SVG 생성 prompt 문자열.
Prompt 에 자동 포함:
- Kind / Style 시각 hint
- viewBox (config 으로 변경 가능, default
0 0 480 320) - Locale →
<title>screen-reader 언어 매핑 (en/ja/zh/zh-TW/ko) - 보안 제약 (script/event handler/external image 금지)
- 크기 제약 (60 lines / 8KB)
SvgSanitizer (Pure)
LLM 이 생성한 SVG 의 안전성 + 형식 검증.
자동 처리:
- Markdown code fence 자동 제거 (
```svg ... ```,```xml ... ```,``` ... ```) <svg>시작 +</svg>끝 검증
보안 차단:
- 위험 태그:
script,foreignObject,iframe,object,embed - 이벤트 핸들러:
onclick,onload,onmouseover,onerror등 - External image (
<image href="https://...">)
크기 제약:
- max_size_bytes: 8192 (default)
- max_lines: 60 (default)
결과 shape:
{
ok: bool,
svg: ?string, // ok=true 시에만 sanitized SVG
issues: ['forbidden_tag_script', 'size_exceeds_8192', ...],
size_bytes: int,
line_count: int,
}
Issue code 는 i18n 가능 — 호출자가 사용자에게 구체적 거부 사유 표시.
설정 (config/illustration.php)
return [
'enabled' => env('PLG_ILLUSTRATION_ENABLED', true),
'svg' => [
'max_size_bytes' => 8192,
'max_lines' => 60,
'view_box' => '0 0 480 320',
],
'forbidden' => [
'tags' => ['script', 'foreignObject', 'iframe', 'object', 'embed'],
'event_handlers' => ['onclick', 'onload', 'onmouseover', 'onerror', 'onfocus', 'onblur'],
'block_external_images' => true,
],
'locale_to_title_lang' => [
'en' => 'English', 'ja' => 'Japanese',
'zh' => 'Chinese (Simplified)', 'zh-CN' => 'Chinese (Simplified)', 'zh-TW' => 'Chinese (Traditional)',
'ko' => 'Korean',
],
'default_title_lang' => 'Korean',
];
사용 예시
use App\Plugins\Illustration\Enums\{IllustrationKind, StylePreset};
use App\Plugins\Illustration\Services\{PromptBuilder, SvgSanitizer};
use App\Plugins\AiRelay\Services\LlmRelayClient;
// 1) Prompt 구성
$builder = PromptBuilder::fromConfig(config('illustration'));
$prompt = $builder->build(
caption: '햇살 아래 사과 한 개',
kind: IllustrationKind::CARTOON,
style: StylePreset::FLAT,
locale: app()->getLocale(),
);
// 2) AiRelay 로 LLM 호출
$llm = LlmRelayClient::fromConfig(config('ai-relay'));
$result = $llm->complete([
'model' => 'gpt-4o-mini',
'messages' => [['role' => 'user', 'content' => $prompt]],
]);
if ($result['status'] !== 'success') {
throw new \RuntimeException('LLM call failed');
}
// 3) SVG 검증
$sanitizer = SvgSanitizer::fromConfig(config('illustration'));
$sanitized = $sanitizer->sanitize($result['data']['text']);
if (! $sanitized['ok']) {
Log::warning('illustration_sanitize_failed', ['issues' => $sanitized['issues']]);
return null;
}
// 4) DB 저장 / 콘�
�츠에 임베드
$documentIllustration->svg_content = $sanitized['svg'];
$documentIllustration->save();
출처
academy.how 의 App\Modules\Content\Services\IllustrationGenerator (320줄) 에서 추출.
buildPrompt(50줄) →PromptBuilder::build()kind분기 →IllustrationKindenum +visualHint()stylePreset분기 →StylePresetenum +styleHint()- locale → titleLang 매핑 → config 기반
resolveTitleLang() - SVG 보안 검증 (academy 에 분산되어 있던 부분) →
SvgSanitizer표준화
LLM 호출 / DocumentIllustration Eloquent 저장 / AiRun 추적 부분은 프로젝트 � 임으로 분리.
의존성
- DocumentProcessor — 생성된 SVG 를 Document 본문에 임베드
- AiRelay (선택) — LLM 호출 표준 어댑터
- AiTracking (Phase 2) — 생성 이력 / 재시도 / 실패 로그
다음 단계 (Phase 3+)
- 표준
IllustrationModel + Migration (선택 활성) - Filament Resource (운영자가 일러스트 검수)
- Refine prompt builder (사용자 지시 + 첨부 이미지 기반 재생성)
- 다중 provider 지원 (OpenAI / Claude / Gemini)
- Caption → SVG 캐싱 (동일 caption 재사용)
라이선스
MIT
의존성
데모
- Platform 관리자 패널에서 메타 확인 🔒 로그인 필요
- 사용 예시 (PHP)
🛒 Plugin Store에서 보기: store.codebase.how/plugins/illustration