330 lines
15 KiB
Markdown
330 lines
15 KiB
Markdown
# DEV TASK: Скилл `image-gen` — генерация изображений
|
||
|
||
**Статус:** Ready for dev
|
||
**Проект:** image-gen
|
||
**BRD:** `tasks/image-gen/BRD.md`
|
||
|
||
---
|
||
|
||
## Цель
|
||
|
||
Создать AgentSkill `image-gen` в `~/.openclaw/skills/image-gen/` — скилл генерации изображений через Recraft (OpenRouter) и A2E.ai, доступный всем агентам OpenClaw.
|
||
|
||
## Архитектура
|
||
|
||
Агент читает шаблоны из `params/`, составляет английский промпт, вызывает `scripts/generate.py`. Скрипт делает API-запрос, сохраняет картинку на диск, отправляет в Telegram через OpenClaw CLI. Агент тратит токены только на трансформацию запроса → промпт.
|
||
|
||
## Стек / Зависимости
|
||
|
||
- Python 3.x (доступен в контейнере)
|
||
- `requests` (pip install requests)
|
||
- `python-dotenv` (pip install python-dotenv)
|
||
- OpenRouter API (image generation endpoint)
|
||
- A2E.ai API (text-to-image endpoint)
|
||
- OpenClaw CLI (`openclaw message send`)
|
||
|
||
---
|
||
|
||
## Инфраструктура
|
||
|
||
| Параметр | Значение |
|
||
|----------|----------|
|
||
| Расположение скилла | `~/.openclaw/skills/image-gen/` |
|
||
| Env-файл | `~/.openclaw/.env` |
|
||
| Папка для картинок | `~/images/image-gen/YYYY-MM-DD/` |
|
||
| Упаковка скилла | `/app/skills/skill-creator/scripts/package_skill.py` |
|
||
|
||
---
|
||
|
||
## Файловая карта
|
||
|
||
| Действие | Файл | Ответственность |
|
||
|----------|------|-----------------|
|
||
| Создать | `~/.openclaw/skills/image-gen/SKILL.md` | Метаданные + инструкции для агента |
|
||
| Создать | `~/.openclaw/skills/image-gen/params/models.md` | Модели, дефолты, negative prompt |
|
||
| Создать | `~/.openclaw/skills/image-gen/params/templates.md` | Шаблоны объектов |
|
||
| Создать | `~/.openclaw/skills/image-gen/params/styles.md` | Фотостили |
|
||
| Создать | `~/.openclaw/skills/image-gen/params/favorites.md` | Избранные промпты (пустой) |
|
||
| Создать | `~/.openclaw/skills/image-gen/scripts/generate.py` | Скрипт генерации |
|
||
| Создать | `~/.openclaw/skills/image-gen/references/recraft_api.md` | OpenRouter image gen API |
|
||
| Создать | `~/.openclaw/skills/image-gen/references/recraft_prompting.md` | Промптинг для Recraft |
|
||
| Создать | `~/.openclaw/skills/image-gen/references/a2e_api.md` | A2E.ai API (text-to-image) |
|
||
| Создать | `~/.openclaw/skills/image-gen/references/a2e_prompting.md` | Промптинг для A2E |
|
||
|
||
---
|
||
|
||
## Задачи
|
||
|
||
### Task 1: Изучить API и написать references
|
||
|
||
**Шаги:**
|
||
|
||
- [ ] **1.1** Изучить OpenRouter image generation API:
|
||
- Доку: `https://openrouter.ai/docs/guides/overview/multimodal/image-generation.md`
|
||
- Модели Recraft: `https://openrouter.ai/recraft/recraft-v4.1-pro` и соседние
|
||
- Написать `references/recraft_api.md` — endpoint, параметры запроса, формат ответа (base64), `image_config` (aspect_ratio, image_size), negative prompt
|
||
|
||
- [ ] **1.2** Изучить A2E.ai text-to-image API:
|
||
- Сайт: `https://video.a2e.ai/dev` (может требовать браузер — попробовать `curl -L`)
|
||
- Поискать OpenAPI spec или Swagger: `https://video.a2e.ai/api/schema/` или `/openapi.json`
|
||
- Ключ: `A2E_API_TOKEN` в `~/.openclaw/.env`
|
||
- Написать `references/a2e_api.md` — endpoint, параметры, формат ответа
|
||
|
||
- [ ] **1.3** Написать `references/recraft_prompting.md`:
|
||
- Структура промпта для recraft (subject, style, lighting, camera, quality)
|
||
- Примеры хороших промптов
|
||
- Что работает хорошо / плохо
|
||
- Источник: `https://www.recraft.ai/docs/api-reference/getting-started` + практические примеры
|
||
|
||
- [ ] **1.4** Написать `references/a2e_prompting.md`:
|
||
- Аналогично для A2E моделей
|
||
|
||
**Критерий готовности:** 4 reference файла созданы, содержат рабочие примеры запросов.
|
||
|
||
---
|
||
|
||
### Task 2: Создать `params/` файлы
|
||
|
||
**Шаги:**
|
||
|
||
- [ ] **2.1** Создать `params/models.md`:
|
||
|
||
```md
|
||
## Recraft (OpenRouter)
|
||
|
||
default_model: recraft/recraft-v4.1-pro
|
||
default_aspect_ratio: 9:16
|
||
default_count: 1
|
||
default_image_size: 2K
|
||
negative_prompt: deformed limbs, distorted hands, extra fingers, bad anatomy, blurry, low quality, watermark, signature, text overlay
|
||
|
||
### Доступные модели
|
||
- recraft/recraft-v4.1-pro ← дефолт
|
||
- recraft/recraft-v4.1-utility-pro
|
||
- recraft/recraft-v4.1-utility
|
||
- recraft/recraft-v4.1
|
||
- recraft/recraft-v4-pro
|
||
- recraft/recraft-v4
|
||
- recraft/recraft-v3
|
||
|
||
### Группы (для мульти-генерации)
|
||
- group:all_v4.1 = recraft/recraft-v4.1-pro, recraft/recraft-v4.1-utility-pro, recraft/recraft-v4.1-utility, recraft/recraft-v4.1
|
||
- group:all_v4 = recraft/recraft-v4.1-pro, recraft/recraft-v4.1-utility-pro, recraft/recraft-v4.1-utility, recraft/recraft-v4.1, recraft/recraft-v4-pro, recraft/recraft-v4
|
||
- group:all = все выше + recraft/recraft-v3
|
||
|
||
## A2E.ai
|
||
default_model: (заполнить из API доки)
|
||
api_url: https://video.a2e.ai/api/
|
||
```
|
||
|
||
- [ ] **2.2** Создать `params/templates.md` со стартовыми шаблонами:
|
||
|
||
```md
|
||
# Шаблоны объектов для image-gen
|
||
# Формат: triggers (слова для матчинга, через запятую) + base (описание на английском)
|
||
# Quality enhancers включены прямо в base каждого шаблона
|
||
|
||
## blonde_woman
|
||
Triggers: блондинка, blonde, блондинки
|
||
Base: A beautiful blonde woman, 25 years old, long wavy golden hair, blue eyes, natural makeup, slim athletic figure, photorealistic, sharp focus, 8K resolution, masterpiece quality, professional photography
|
||
|
||
## brunette_woman
|
||
Triggers: брюнетка, brunette, брюнетки
|
||
Base: A beautiful brunette woman, 25 years old, long dark wavy hair, green eyes, natural makeup, slim figure, photorealistic, sharp focus, 8K resolution, masterpiece quality, professional photography
|
||
|
||
## park
|
||
Triggers: парк, park, садик
|
||
Base: lush green urban park, sunny afternoon, tall trees, soft bokeh background, natural daylight, fresh grass
|
||
|
||
## forest
|
||
Triggers: лес, forest, лесу
|
||
Base: dense green forest, dappled sunlight through trees, misty atmosphere, natural lighting, photorealistic environment
|
||
|
||
## beach
|
||
Triggers: пляж, beach, море, sea
|
||
Base: sunny tropical beach, clear turquoise water, white sand, palm trees, golden hour lighting
|
||
|
||
## city
|
||
Triggers: город, city, улица, street
|
||
Base: modern city street, urban environment, evening golden hour, bokeh city lights background
|
||
|
||
## cafe
|
||
Triggers: кафе, cafe, кофейня, coffee shop
|
||
Base: cozy modern cafe interior, warm lighting, wooden tables, coffee cups, soft bokeh background
|
||
```
|
||
|
||
- [ ] **2.3** Создать `params/styles.md`:
|
||
|
||
```md
|
||
# Фотографические стили для image-gen
|
||
|
||
## portrait
|
||
Triggers: портрет, portrait
|
||
Style: 85mm lens portrait photography, shallow depth of field f/1.8, studio lighting, sharp focus on face, professional headshot quality
|
||
|
||
## cinematic
|
||
Triggers: кинематограф, cinematic, кино, film
|
||
Style: cinematic shot, movie still, dramatic lighting, widescreen 2.35:1 composition, film grain, color grading
|
||
|
||
## street
|
||
Triggers: стрит, уличное, street photography, репортаж
|
||
Style: candid street photography, natural available light, urban setting, Leica style, documentary feel
|
||
|
||
## fashion
|
||
Triggers: фэшн, fashion, модный, editorial
|
||
Style: high fashion editorial photography, Vogue style, dramatic studio lighting, fashion magazine composition
|
||
|
||
## artistic
|
||
Triggers: арт, художественное, artistic, art photo
|
||
Style: fine art photography, creative composition, dramatic shadows, high contrast, artistic vision
|
||
```
|
||
|
||
- [ ] **2.4** Создать пустой `params/favorites.md`:
|
||
|
||
```md
|
||
# Избранные промпты image-gen
|
||
# Формат: дата — описание | Model | Prompt | Negative
|
||
|
||
```
|
||
|
||
**Критерий готовности:** 4 params файла созданы, templates содержат минимум 5 объектов.
|
||
|
||
---
|
||
|
||
### Task 3: Написать `scripts/generate.py`
|
||
|
||
**Шаги:**
|
||
|
||
- [ ] **3.1** Реализовать скрипт со следующим CLI-интерфейсом:
|
||
|
||
```
|
||
python generate.py \
|
||
--prompt "A beautiful blonde woman in a park..." \
|
||
--negative "deformed limbs, bad anatomy..." \
|
||
--model "recraft/recraft-v4.1-pro" \
|
||
--ratio "9:16" \
|
||
--count 1 \
|
||
--provider "openrouter" \
|
||
--save-dir "/root/images/image-gen/2026-05-24/" \
|
||
--tg-chat-id "126472752"
|
||
```
|
||
|
||
- [ ] **3.2** Логика скрипта:
|
||
1. Загрузить `.env` из `~/.openclaw/.env`
|
||
2. Если `--model` начинается с `group:` — развернуть в список моделей из `params/models.md` (парсить файл)
|
||
3. Для каждой модели × count итераций:
|
||
- Сделать API запрос (OpenRouter или A2E в зависимости от `--provider`)
|
||
- Сохранить как `YYYY-MM-DD_HH-MM-SS_<model_short>.jpg`
|
||
4. Каждую картинку отправить в TG:
|
||
```bash
|
||
openclaw message send --channel telegram --target <tg-chat-id> \
|
||
--media <path> \
|
||
--message "🎨 Model: <model>\n📝 <caption>"
|
||
```
|
||
|
||
- [ ] **3.3** OpenRouter API вызов:
|
||
```python
|
||
POST https://openrouter.ai/api/v1/chat/completions
|
||
Authorization: Bearer $OPENROUTER_API_KEY
|
||
{
|
||
"model": "recraft/recraft-v4.1-pro",
|
||
"messages": [{"role": "user", "content": prompt}],
|
||
"modalities": ["image"],
|
||
"image_config": {
|
||
"aspect_ratio": ratio,
|
||
"image_size": "2K"
|
||
}
|
||
}
|
||
# Ответ: choices[0].message.images[0].image_url.url → base64
|
||
# Декодировать base64 и сохранить как .jpg
|
||
```
|
||
|
||
- [ ] **3.4** A2E API вызов — реализовать согласно `references/a2e_api.md` (изучить в Task 1)
|
||
|
||
- [ ] **3.5** Протестировать:
|
||
```bash
|
||
cd ~/.openclaw/skills/image-gen/
|
||
python scripts/generate.py \
|
||
--prompt "A beautiful blonde woman in a sunny park, portrait, 8K, photorealistic" \
|
||
--negative "deformed limbs, distorted hands" \
|
||
--model "recraft/recraft-v4.1-pro" \
|
||
--ratio "9:16" \
|
||
--count 1 \
|
||
--provider "openrouter" \
|
||
--save-dir "/tmp/test-images/" \
|
||
--tg-chat-id "126472752"
|
||
```
|
||
Ожидаемый результат: картинка сохранена в `/tmp/test-images/`, пришла в Telegram с подписью.
|
||
|
||
**Критерий готовности:** тест успешен, картинка в Telegram.
|
||
|
||
---
|
||
|
||
### Task 4: Написать `SKILL.md`
|
||
|
||
- [ ] **4.1** Создать `SKILL.md` с фронтматтером и инструкциями:
|
||
|
||
```yaml
|
||
---
|
||
name: image-gen
|
||
description: Generate images via Recraft (OpenRouter) and A2E.ai models.
|
||
Use when user asks to generate, draw, or create an image/photo.
|
||
Triggers: "сгенерируй фото", "нарисуй изображение", "generate image",
|
||
"сгенерируй картинку", "create a photo", "draw me".
|
||
---
|
||
```
|
||
|
||
Тело SKILL.md должно содержать:
|
||
- Как читать `params/templates.md` и матчить объекты из запроса
|
||
- Как читать `params/styles.md` и применять стиль
|
||
- Формула промпта: `base_template + location/context + style + user_unique_details`
|
||
- Как вызывать `scripts/generate.py`
|
||
- Как обрабатывать мульти-модель запросы (`group:all_v4`)
|
||
- После генерации: спросить "Сохранить в избранное?" → если да, добавить в `params/favorites.md`
|
||
- Ссылки на references: читать перед работой с новой моделью или если нужны детали API
|
||
|
||
- [ ] **4.2** Убедиться что SKILL.md ≤ 500 строк (детали → в references)
|
||
|
||
**Критерий готовности:** SKILL.md проходит валидацию `package_skill.py`.
|
||
|
||
---
|
||
|
||
### Task 5: Упаковать скилл
|
||
|
||
- [ ] **5.1** Запустить упаковку:
|
||
```bash
|
||
python /app/skills/skill-creator/scripts/package_skill.py \
|
||
~/.openclaw/skills/image-gen/ \
|
||
~/.openclaw/skills/
|
||
```
|
||
Ожидаемый результат: `~/.openclaw/skills/image-gen.skill` создан без ошибок.
|
||
|
||
**Критерий готовности:** файл `image-gen.skill` создан, валидация прошла без ошибок.
|
||
|
||
---
|
||
|
||
## Проверка (Acceptance)
|
||
|
||
| # | Проверка | Команда | Ожидаемый результат |
|
||
|---|----------|---------|---------------------|
|
||
| 1 | Структура скилла | `ls ~/.openclaw/skills/image-gen/` | Все папки и файлы созданы |
|
||
| 2 | Тест генерации Recraft | `python generate.py --prompt "test girl in park" --model recraft/recraft-v4.1-pro ...` | Картинка в TG |
|
||
| 3 | Тест группы моделей | `--model group:all_v4.1 --count 1` | 4 картинки в TG |
|
||
| 4 | Упаковка | `package_skill.py ~/.openclaw/skills/image-gen/` | Нет ошибок валидации |
|
||
|
||
---
|
||
|
||
## Ограничения и контекст
|
||
|
||
- ⚠️ API ключи **только из `~/.openclaw/.env`** — не хардкодить в скрипт
|
||
- ⚠️ A2E API может требовать браузерного рендеринга для доки — попробовать `curl -H "Authorization: Bearer $A2E_API_TOKEN" https://video.a2e.ai/api/` для autodiscovery
|
||
- ⚠️ OpenRouter возвращает изображение как base64 data URL в `choices[0].message.images[0].image_url.url` — нужно декодировать и сохранить
|
||
- ⚠️ `openclaw message send --media` — таймаут 30+ секунд
|
||
- ⚠️ `params/models.md` — парсить нужно только секцию `groups:` для разворачивания групп; простой text parsing достаточен
|
||
- 🚫 Не использовать `MEDIA:` директиву в ответах агента — только `openclaw message send`
|
||
- ℹ️ Скилл устанавливается в `~/.openclaw/skills/` — общая папка для всех агентов
|
||
|
||
---
|
||
|
||
*Создано: 2026-05-24 | Автор ТЗ: Стрим | Исполнитель: Dev-агент*
|