Что получится в результате
Соберем ИИ-агента, который принимает изображения, проверяет их, извлекает текст, готовит теги и создает безопасные производные версии: превью, web-формат, обложку или задачу дизайнеру.
Первая рабочая версия будет делать так:
- исходные изображения попадают в папку `incoming_images`;
- n8n забирает новые файлы;
- агент сохраняет оригинал и не перезаписывает его;
- Vision API извлекает OCR, labels и safe search;
- workflow проверяет размер, формат, дубли и риск-категории;
- Cloudinary или другой image API создает превью и web-версию;
- спорные изображения попадают в `review_queue`;
- approved-изображения получают ссылки на derivative-файлы;
- результат записывается в `image_queue`;
- ошибки и ручные решения пишутся в `image_log`.
В первой версии агент не удаляет оригиналы, не публикует изображения без проверки, не меняет лица/людей генеративно и не обрабатывает персональные документы без отдельного approval.
Что понадобится
- n8n Cloud или self-hosted n8n.
- Google Drive или S3-совместимое хранилище.
- Google Sheets для очередей и журнала.
- Cloudinary или другой сервис трансформации изображений.
- Google Cloud Vision API или аналог для OCR/labels/safe search.
- API-ключ LLM-провайдера для описаний и alt-текста.
- 10-20 тестовых изображений.
- Человек, который подтверждает спорные результаты.
Шаг 1. Выберите один сценарий
Не начинайте с “обрабатывать любые картинки”.
Для первого прототипа выберите сценарий:
подготовка изображений для статей: проверка, OCR, alt-текст, теги, resize, web-версия и превью
Что входит:
- JPG/PNG/WebP;
- изображения до 10 MB;
- resize для карточек и статьи;
- alt-текст;
- теги;
- OCR, если на изображении есть текст.
Что не входит:
- документы с паспортами;
- медицинские изображения;
- лица и биометрия;
- генеративное изменение людей;
- массовое удаление файлов.
Проверка: вы можете назвать один вход и один результат обработки.
Шаг 2. Создайте структуру папок
В Google Drive или S3 создайте:
Image AI agent
incoming_images
originals
derivatives
needs_review
rejected
archive
Правило:
оригинал всегда копируется в originals
производные файлы пишутся в derivatives
Проверка: workflow не работает напрямую с единственной копией файла.
Шаг 3. Создайте таблицу проекта
Создайте Google Sheet:
Image processing AI agent
Добавьте листы:
image_queue
processing_rules
review_queue
derivatives
image_log
error_log
settings
test_cases
Проверка: у n8n есть доступ на чтение и запись.
Шаг 4. Создайте image_queue
В листе `image_queue` сделайте колонки:
image_id
file_id
file_name
source_url
original_url
mime_type
width
height
file_size_mb
detected_text
labels
safe_search_json
alt_text
status
risk_level
review_status
created_at
processed_at
error
Статусы:
- `new`;
- `processing`;
- `processed`;
- `needs_review`;
- `approved`;
- `rejected`;
- `error`.
Проверка: каждое изображение будет иметь одну строку состояния.
Шаг 5. Создайте правила обработки
В листе `processing_rules` сделайте колонки:
rule_id
rule_type
condition
action
severity
enabled
Добавьте:
R-001 | format | mime_type not in image/jpeg,image/png,image/webp | reject | high | yes
R-002 | size | file_size_mb > 10 | needs_review | medium | yes
R-003 | dimensions | width < 600 or height < 400 | needs_review | low | yes
R-004 | safe_search | adult likely or violence likely | needs_review | high | yes
R-005 | text | detected_text contains password, token, api_key | reject | critical | yes
R-006 | derivative | create article_card 1200x675 | transform | low | yes
R-007 | derivative | create thumbnail 600x338 | transform | low | yes
Проверка: правила можно менять без редактирования workflow.
Шаг 6. Создайте derivatives
В листе `derivatives` сделайте колонки:
derivative_id
image_id
type
url
width
height
format
transformation
created_at
Типы:
- `article_card`;
- `thumbnail`;
- `web`;
- `social_preview`;
- `ocr_preview`.
Проверка: производные изображения хранятся отдельно от оригинала.
Шаг 7. Создайте review_queue
В листе `review_queue` сделайте колонки:
review_id
image_id
file_name
preview_url
risk_level
reason
review_decision
review_comment
reviewer
created_at
reviewed_at
Решения:
- `approve`;
- `reject`;
- `edit`;
- `request_new_image`;
Проверка: спорные изображения не публикуются автоматически.
Шаг 8. Создайте settings
В листе `settings` добавьте:
key
value
comment
Заполните:
max_file_size_mb | 10 | лимит первой версии
allowed_formats | image/jpeg,image/png,image/webp | разрешенные форматы
article_card_width | 1200 | ширина обложки
article_card_height | 675 | высота обложки
thumbnail_width | 600 | ширина превью
thumbnail_height | 338 | высота превью
auto_publish_allowed | no | в первой версии всегда no
Проверка: размеры и лимиты управляются настройками.
Шаг 9. Подготовьте тестовые изображения
Положите в `incoming_images`:
- нормальное фото;
- PNG-скриншот с текстом;
- картинку маленького размера;
- файл больше лимита;
- WebP;
- изображение с текстом `api_key`;
- изображение с потенциально спорным содержимым;
- дубль нормального фото.
Проверка: тестовый набор проверяет не только идеальные изображения.
Шаг 10. Создайте workflow обработки
Назовите workflow:
Image processing pipeline
Добавьте узлы:
- `Schedule Trigger`;
- `Google Drive` или S3 - список файлов из `incoming_images`;
- `Split In Batches`;
- `Google Drive` - скачать файл;
- `Code` - метаданные файла;
- `Cloudinary Upload` или `HTTP Request` - загрузка оригинала;
- `Google Vision` или `HTTP Request` - OCR/labels/safe search;
- `Code` - проверка правил;
- `LLM` - alt-текст и краткое описание;
- `Cloudinary Transform` - derivative-файлы;
- `Google Sheets` - запись `image_queue`;
- `Google Sheets` - запись `derivatives`;
- `Google Sheets` - запись `review_queue`;
- `Google Sheets` - запись `image_log`;
- `Google Drive` - перенос файла в нужную папку.
Проверка: workflow создан и запускается вручную.
Шаг 11. Получите метаданные файла
В узле `Code` зафиксируйте:
file_name
mime_type
file_size_mb
width
height
hash
Если n8n не видит width/height без библиотеки, получите их через Cloudinary после upload или через выбранный image API.
Проверка: у изображения есть формат, размер и уникальный hash.
Шаг 12. Загрузите оригинал
Загрузите файл в Cloudinary или другое хранилище как оригинал.
Пример Cloudinary upload через HTTP Request:
curl https://api.cloudinary.com/v1_1/CLOUD_NAME/image/upload \
-X POST \
-F "file=@image.jpg" \
-F "folder=ezgpt/originals" \
-F "timestamp=TIMESTAMP" \
-F "api_key=API_KEY" \
-F "signature=SIGNATURE"
В n8n секреты храните в credentials или переменных, а не в таблице.
Проверка: Cloudinary вернул `secure_url`, `public_id`, width, height и format.
Шаг 13. Проверьте дубли
Перед обработкой проверьте hash.
Правило:
если hash уже есть в image_queue со статусом processed/approved, новый файл отправить в needs_review как duplicate
Проверка: одно и то же изображение не обрабатывается повторно без причины.
Шаг 14. Запустите OCR и labels
Отправьте изображение в Vision API.
Нужные результаты:
- `detected_text`;
- `labels`;
- `safe_search`;
- confidence, если API возвращает.
Минимальный объект:
{
"detected_text": "AI agents workflow",
"labels": ["diagram", "text", "software"],
"safe_search": {
"adult": "VERY_UNLIKELY",
"violence": "UNLIKELY",
"racy": "UNLIKELY"
}
}
Проверка: скриншот с текстом дает OCR, а фото получает labels.
Шаг 15. Проверьте sensitive text
В узле `Code` проверьте OCR-текст.
const text = String($json.detected_text || '').toLowerCase();
const forbidden = [
'api_key',
'password',
'secret',
'token',
'bearer ',
'sk-'
];
const hits = forbidden.filter(x => text.includes(x));
if (hits.length > 0) {
return [{
...$json,
status: 'rejected',
risk_level: 'critical',
reason: `Sensitive text detected: ${hits.join(', ')}`
}];
}
return [$json];
Проверка: изображение с ключом не уходит в публикацию.
Шаг 16. Проверьте safe search
Правила первой версии:
adult likely или very_likely -> needs_review
violence likely или very_likely -> needs_review
racy very_likely -> needs_review
medical/legal/personal document -> needs_review
Не удаляйте файл автоматически. Перенесите его в `needs_review` и создайте строку в `review_queue`.
Проверка: спорное изображение не получает `approved`.
Шаг 17. Сгенерируйте alt-текст
LLM получает только безопасные данные:
file_name
labels
detected_text
контекст страницы или статьи, если есть
System prompt:
Ты пишешь alt-текст для изображения.
Пиши кратко и по фактам.
Не придумывай людей, бренды, места и события.
Не описывай скрытые или чувствительные данные.
Верни только JSON.
User prompt:
Labels:
{{labels}}
OCR:
{{detected_text}}
Контекст:
{{page_context}}
Верни JSON:
{
"alt_text": "краткое описание до 160 символов",
"caption": "подпись, если нужна",
"tags": ["tag1", "tag2"],
"confidence": 0.0
}
Проверка: alt-текст не длинный и не выдумывает детали.
Шаг 18. Создайте derivative-версии
Для статьи:
article_card: 1200x675, crop/fill
thumbnail: 600x338, crop/fill
web: ширина до 1600, quality auto, format auto
Пример Cloudinary transformation URL:
https://res.cloudinary.com/CLOUD_NAME/image/upload/c_fill,w_1200,h_675,q_auto,f_auto/PUBLIC_ID
Проверка: derivative открывается по URL и имеет нужный размер.
Шаг 19. Запишите image_queue
Добавьте строку:
image_id
file_id
file_name
source_url
original_url
mime_type
width
height
file_size_mb
detected_text
labels
safe_search_json
alt_text
status
risk_level
review_status
created_at
processed_at
Если все хорошо:
status: processed
review_status: draft
Если нужен человек:
status: needs_review
review_status: draft
Проверка: результат виден в таблице.
Шаг 20. Запишите derivatives
Для каждой производной версии добавьте строку:
derivative_id
image_id
type
url
width
height
format
transformation
created_at
Проверка: можно взять URL обложки, thumbnail и web-версии отдельно.
Шаг 21. Отправьте спорные в review_queue
Если `risk_level = high` или `critical`, создайте review.
Причины:
- sensitive text;
- safe search risk;
- низкое качество;
- слишком маленький размер;
- дубль;
- неясные права на изображение;
- лицо или персональный документ.
Проверка: человек получает понятную причину, а не просто “проверь картинку”.
Шаг 22. Проверьте изображение человеком
Редактор открывает `review_queue`.
Проверяет:
- можно ли использовать изображение;
- нет ли секретов в тексте;
- есть ли права;
- не содержит ли изображение персональные данные;
- подходит ли alt-текст;
- не обрезана ли важная часть на превью;
- нет ли дубликата.
Решение:
approve
reject
edit
request_new_image
Проверка: без решения редактора спорное изображение не попадает в публикацию.
Шаг 23. Создайте workflow применения review
Назовите workflow:
Image review apply
Он делает:
- читает `review_queue`;
- берет строки с `review_decision`;
- обновляет `image_queue`;
- при `approve` ставит `approved`;
- при `reject` переносит файл в `rejected`;
- пишет событие в `image_log`.
Проверка: ручное решение меняет статус изображения.
Шаг 24. Подключите к публикации
Когда изображение `approved`, можно передать URL в CMS.
Минимальный payload:
{
"image_id": "IMG-1001",
"article_card_url": "https://...",
"thumbnail_url": "https://...",
"web_url": "https://...",
"alt_text": "Схема AI-агента для обработки изображений",
"tags": ["AI", "workflow", "image"]
}
Проверка: CMS получает derivative URL, а не исходный файл.
Шаг 25. Добавьте error_log
В листе `error_log` сделайте колонки:
error_id
image_id
file_name
step
error_type
error_text
payload_preview
created_at
resolved_at
Ошибки:
- upload failed;
- OCR failed;
- transformation failed;
- invalid format;
- file too large;
- LLM JSON invalid;
- derivative URL not available.
Проверка: сбой обработки не исчезает в истории n8n.
Шаг 26. Сделайте regression test
В листе `test_cases` сделайте колонки:
case_id
file_name
expected_status
expected_review_required
expected_derivatives_count
expected_has_alt
enabled
Добавьте тесты:
- нормальный JPG;
- нормальный PNG;
- WebP;
- слишком маленькое изображение;
- слишком большой файл;
- скриншот с текстом;
- изображение с `api_key`;
- дубль;
- спорное safe search;
- плохой OCR.
Создайте workflow:
Image processing regression test
Он прогоняет тестовые файлы и сравнивает ожидаемые статусы с фактическими.
Проверка: изменение правил или prompt не ломает базовую обработку.
Минимальная проверка результата
Прототип работает, если выполняются все пункты:
- файл из `incoming_images` попадает в workflow;
- оригинал сохраняется отдельно;
- OCR и labels записываются;
- sensitive text блокируется;
- safe search риски идут в review;
- alt-текст создается по фактам;
- derivative-файлы создаются и доступны по URL;
- спорные изображения попадают в `review_queue`;
- решение редактора меняет статус;
- ошибки пишутся в `error_log`;
- regression test проверяет основные сценарии.
Что нельзя автоматизировать в первой версии
- удаление оригиналов;
- публикацию спорных изображений без review;
- обработку паспортов и документов без отдельного процесса;
- распознавание личности людей;
- генеративное изменение лиц;
- массовую замену изображений на сайте;
- использование картинок без прав;
- скрытие sensitive text вместо блокировки;
- отправку изображений с персональными данными в сторонние API без согласования.
Частые вопросы
Можно ли использовать только LLM без Vision API?
Для первого прототипа лучше разделить задачи. Vision API извлекает OCR, labels и safe search, а LLM пишет alt-текст и объяснение по уже извлеченным данным.
Нужно ли сохранять оригинал?
Да. Оригинал нужен для аудита, повторной обработки и исправления ошибок. Производные версии можно пересоздать, а потерянный оригинал восстановить сложно.
Можно ли автоматически публиковать approved-изображения?
Можно после тестов, но в первой версии лучше передавать approved URL в CMS как черновик. Спорные изображения должны проходить review.
Что делать с изображением, где найден API key?
Ставить `rejected` или `needs_review` с критичным риском. Не публиковать и не пытаться “замазать” секрет автоматически без процедуры безопасности.
Какой минимум нужен для запуска?
Папки `incoming_images`, `originals`, `derivatives`, таблицы `image_queue`, `processing_rules`, `review_queue`, `derivatives`, n8n workflow, OCR/labels API, image transformation API, LLM alt-текст и ручной review.