Самый простой способ автоматизировать генерацию изображений в масштабе без управления несколькими разными API — отделить рабочий процесс от поставщика модели. Помещайте каждый запрос на изображение в одну очередь, маршрутизируйте каждую задачу на текущий идентификатор модели и отправляйте совместимые запросы через один ключ CometAPI и OpenAI-совместимый базовый URL https://api.cometapi.com/v1.
Это руководство строит такой конвейер на Python. Оно принимает задания по продуктам, рекламе и контенту из очереди в формате JSON Lines; выбирает модель; ограничивает параллелизм; повторяет попытки при временных сбоях; сохраняет результаты в виде URL или base64; и записывает использование и оценочную стоимость по каждой задаче. В примере эти необходимые для продакшена элементы собраны в одном компактном блоке, чтобы вы могли протестировать рабочий процесс, не превращая статью в справочник по коду.
Как единый API изображений упрощает пакетную генерацию
К концу вы получите такой рабочий процесс:
jobs.jsonl → bounded worker pool → CometAPI /v1/images/generations → object storage → manifest.jsonl
Очередь и слой хранения остаются под вашим контролем. Переключение моделей изображения меняет значение model, а не систему аутентификации или основной маршрут запроса. Это практическое преимущество единого API изображений: выбор модели становится решением маршрутизации внутри одного конвейера, а не интеграцией отдельного провайдера.
Что нужно для автоматизации генерации изображений?
Вам понадобятся Python 3.10 или новее, пакет requests, ключ CometAPI, доступное для записи место вывода и как минимум один текущий идентификатор модели изображений.
Установите единственную зависимость:
pip install requests
Задайте ключ на сервере, никогда не в коде браузера или репозитории:
export COMETAPI_KEY="your-key"
Базовый URL — https://api.cometapi.com/v1, а совместимые текст-в-изображение задачи используют POST /images/generations. Перед развёртыванием проверьте каждую модель в живом каталоге моделей; каталог возвращает текущий идентификатор, поддерживаемый endpoint, возможности и ценовые метаданные без необходимости заголовка авторизации.
По состоянию на 20 августа 2026 года живой каталог перечислял эти два полезных маршрута:
| Нагрузка | Идентификатор модели | Почему подходит |
|---|---|---|
| Продуктовые изображения с контролируемыми настройками вывода | gpt-image-2 | Возвращает данные об использовании и содержимое изображения в base64 на документированном маршруте, совместимом с OpenAI |
| Массовые рекламные и контентные концепции | doubao-seedream-4-5-251128 | Использует тот же маршрут генерации и указан с ценой за запрос |
Эта таблица — отправная точка, а не утверждение, что модели обладают идентичными возможностями. Размер, качество, формат, поддержка референс-изображений и поведение ответа остаются специфичными для модели. Проверьте запись модели и связанную документацию перед передачей необязательных параметров.
Как построить пакетный рабочий процесс генерации изображений на Python
1. Дайте каждой задаче долговечный идентификатор
Используйте по одному объекту JSON на строку, чтобы очередь, экспорт базы данных или задание из таблицы могли питать один и тот же воркер:
{"id":"sku-1001","kind":"product","prompt":"Studio product photo of a ceramic coffee dripper on a warm neutral background"}
{"id":"campaign-204","kind":"ad","prompt":"Editorial summer travel image, vivid natural light, wide composition, no text"}
{"id":"blog-088","kind":"content","prompt":"Minimal illustration of a developer automating a creative workflow, no text"}
Идентификатор становится именем выходного файла и ключом манифеста. В продакшене используйте его как идемпотентный ключ и пропускайте идентификаторы, уже отмеченные как успешные, перед повторной обработкой очереди.
2. Маршрутизируйте по типу задачи, затем валидируйте по живому каталогу
В примере продуктовые задачи сопоставляются с gpt-image-2, а рекламные и контентные — с doubao-seedream-4-5-251128. Задача может переопределить этот выбор своим полем model. При запуске воркер скачивает публичный каталог и отклоняет идентификатор, который больше не числится.
Это безопаснее, чем жёстко прошивать провайдерский SDK по всему приложению. Вы можете изменить маршрут в одном сопоставлении после оценки качества, задержки и цены для ваших подсказок.
3. Ограничьте параллелизм вместо запуска всего батча
Воркер начинает с четырёх параллельных запросов. Это число — консервативная настройка приложения, а не универсальный лимит сервиса. Измеряйте задержку и ответы 429 для своей учётной записи, затем осознанно повышайте или понижайте MAX_WORKERS.
Повторяются только ответы 408, 429 и 5xx с экспоненциальной задержкой и джиттером. Ошибки аутентификации, недействительные идентификаторы моделей и неподдерживаемые параметры завершаются немедленно, поскольку повторение того же некорректного запроса лишь добавляет задержку.
4. Нормализуйте результат перед сохранением
Модели изображений не всегда возвращают один и тот же контейнер. Документированный ответ GPT Image содержит data[0].b64_json; другие совместимые модели могут вернуть data[0].url. Воркер обрабатывает оба варианта, записывает изображение во временный файл и переименовывает его только после успешной загрузки или декодирования.
В продакшене замените локальный каталог output/ на S3, R2, GCS или иное хранилище объектов. Не рассматривайте URL, размещённый провайдером, как постоянное хранилище, если его политика удержания явно этого не предусматривает.
5. Записывайте использование, попытки и оценочную стоимость
Каждый результат становится компактной строкой манифеста с идентификатором задачи, моделью, сохранённым путём, статусом и оценочной стоимостью в долларах США, если живой каталог предоставляет достаточно данных о ценах. Неудачные задачи сохраняют ошибку, а не исчезают из батча.
Полный скрипт Python для пакетной генерации изображений
Сохраните следующее как batch_image_pipeline.py, поместите очередь рядом как jobs.jsonl и выполните python3 batch_image_pipeline.py.
import base64, json, os, random, time
from concurrent.futures import ThreadPoolExecutor
from pathlib import Path
import requests
BASE_URL = "https://api.cometapi.com/v1"
KEY = os.environ["COMETAPI_KEY"]
WORKERS = int(os.getenv("MAX_WORKERS", "4"))
OUT = Path("output")
ROUTES = {
"product": "gpt-image-2",
"ad": "doubao-seedream-4-5-251128",
"content": "doubao-seedream-4-5-251128",
}
catalog = requests.get("https://api.cometapi.com/api/models", timeout=30)
catalog.raise_for_status()
CATALOG = {model["id"]: model for model in catalog.json()["data"]}
def generate(job):
model = job.get("model", ROUTES[job["kind"]])
if model not in CATALOG:
raise ValueError(f"Unknown model: {model}")
payload = {"model": model, "prompt": job["prompt"], "n": 1}
if model == "gpt-image-2":
payload.update(quality="low", size="1024x1024", output_format="jpeg")
for attempt in range(4):
response = requests.post(
f"{BASE_URL}/images/generations",
headers={"Authorization": f"Bearer {KEY}"},
json=payload,
timeout=180,
)
if response.status_code not in {408, 429} and response.status_code < 500:
break
time.sleep(2**attempt + random.random())
response.raise_for_status()
body = response.json()
item = body["data"][0]
if item.get("b64_json"):
data = base64.b64decode(item["b64_json"])
extension = body.get("output_format", "png")
else:
download = requests.get(item["url"], timeout=120)
download.raise_for_status()
data = download.content
extension = {"image/png": "png", "image/webp": "webp"}.get(
download.headers.get("content-type"), "jpg"
)
path = OUT / f"{job['id']}.{extension}"
path.write_bytes(data)
price, usage = CATALOG[model].get("pricing") or {}, body.get("usage", {})
cost = price.get("per_request")
if cost is None and price.get("input") is not None:
cost = (usage.get("input_tokens", 0) * price["input"] +
usage.get("output_tokens", 0) * price["output"]) / 1_000_000
return {"id": job["id"], "model": model, "path": str(path),
"estimated_usd": cost * price.get("ratio", 1) if cost is not None else None}
def safe_generate(job):
try:
return {"status": "success", **generate(job)}
except Exception as error:
return {"id": job["id"], "status": "failed", "error": str(error)}
OUT.mkdir(exist_ok=True)
jobs = [json.loads(line) for line in Path("jobs.jsonl").read_text().splitlines() if line]
with ThreadPoolExecutor(max_workers=WORKERS) as pool:
results = list(pool.map(safe_generate, jobs))
with (OUT / "manifest.jsonl").open("w") as manifest:
manifest.writelines(json.dumps(result) + "\n" for result in results)
Скрипт использует актуальный каталог во время выполнения, а два резервных сопоставления — это примеры, проверенные 20 августа 2026 года. Перепроверьте их перед публикацией или развёртыванием кода в другую дату.
Как протестировать пакетный рабочий процесс генерации изображений
Начните с одной задачи и одного воркера:
MAX_WORKERS=1 python3 batch_image_pipeline.py
Успешный ответ GPT Image имеет такую структуру:
{
"created": 1776841943,
"output_format": "jpeg",
"quality": "low",
"size": "1024x1024",
"usage": {
"input_tokens": 16,
"output_tokens": 208,
"total_tokens": 224
},
"data": [{"b64_json": "<base64-image-data>"}]
}
Воркер декодирует изображение, записывает output/<job-id>.jpeg и добавляет строку об успехе в output/manifest.jsonl. Если модель возвращает URL, воркер скачивает его и сохраняет локальный путь в том же формате манифеста.
Код прошёл проверку синтаксиса локально. Для живого вызова генерации по-прежнему требуется ваш ключ CometAPI, поэтому запустите дымовой тест с одной задачей, прежде чем повышать параллелизм.
Сколько стоит пакетная генерация изображений?
Цены должны иметь отметку времени, поскольку тарифы моделей меняются. По состоянию на 20 августа 2026 года живой каталог моделей CometAPI возвращал следующие базовые ценовые поля и коэффициент биллинга 0.8:
gpt-image-2: $5 за 1M входных токенов и $30 за 1M выходных токенов; применение указанного коэффициента даёт эффективные ставки $4 и $24 за 1M токенов.doubao-seedream-4-5-251128: $0.04 за запрос; применение указанного коэффициента даёт $0.032 за запрос.
Руководство по ценообразованию CometAPI объясняет биллинг по токенам для моделей с официальным прайсингом и биллинг по вызовам для моделей с ценой за запрос. Скрипт читает каталог при запуске и использует то же правило:
token cost = ratio × (input tokens × input rate + output tokens × output rate) / 1,000,000
request cost = ratio × per-request price
Например, задокументированный ответ GPT Image выше сообщает о 16 входных и 208 выходных токенах. Используя значения каталога от 20 августа, этот показательный результат оценивается примерно в $0.005056. Фактическая сумма меняется в зависимости от модели, качества, размера, подсказки, повторных попыток и использования в ответе. Рассматривайте ответ API и панель использования аккаунта как учётную запись биллинга, а не фиксированную стоимость на изображение.
Заложите бюджет и на неуспешные работы. Повтор после неподтверждённого таймаута может привести к второму тарифицируемому результату, а технически успешное изображение, не прошедшее проверку, всё равно расходует бюджет. Отслеживайте как стоимость API, так и долю принятых результатов:
effective cost per accepted image = total batch spend / approved images
Распространённые ошибки API генерации изображений и способы их устранения
| Симптом | Вероятная причина | Решение |
|---|---|---|
| 401 | Отсутствует или недействительный ключ | Проверьте серверный COMETAPI_KEY |
| 400 | Недействительная модель или неподдерживаемая опция | Перепроверьте живой каталог и удалите специфичные для модели поля |
| 429 | Слишком высокий параллелизм | Понизьте MAX_WORKERS и сохраняйте экспоненциальный бэкофф |
| Повторяющиеся 5xx | Временный сбой на стороне upstream | Повторяйте с ограничением, затем отправьте задачу в DLQ |
| Нет сохранённого изображения | Ответ использовал другой контейнер | Проверьте data[0] и поддержите как b64_json, так и url |
| Дублирующиеся затраты | Задача была повторно воспроизведена после частичного сбоя | Используйте долговечные ID и подтверждайте только после успешного сохранения |
Не повторяйте каждый тип ошибки. Постоянный 400 останется недействительным, в то время как неограниченный цикл повторов при 429 может превратить всплеск трафика в бэклог.
Лучшие практики для продакшен-генерации изображений в масштабе
Переходите от JSON Lines к устойчивой очереди при участии нескольких воркеров. Установите время видимости дольше максимального времени генерации, подтверждайте задачу только после сохранения изображения и манифеста, а исчерпанные задачи отправляйте в очередь мёртвых писем для проверки.
Держите необязательные настройки в конфигурации, специфичной для модели. Общий payload должен содержать только общие поля, такие как model, prompt и n: 1; добавляйте quality, size или output_format только после того, как документация выбранной модели подтвердит их. Если вы добавляете запасной маршрут, выбирайте модель, поддерживающую ту же задачу, и перестраивайте payload для этой модели, вместо бездумного повтора провайдер-специфичных опций.
Храните ключ API в менеджере секретов, ограничивайте ввод подсказок, сканируйте сгенерированные ассеты в соответствии с вашей политикой и не сохраняйте URL провайдера в долгосрочных продуктовых записях. Логируйте идентификатор задачи, идентификатор модели, задержку, число попыток, использование, путь хранения, результат проверки и дату снимка каталога. Эти поля позволят сравнивать модели по стоимости принятого изображения, а не по номинальной цене.
Наконец, задайте бюджетные рамки: максимальный размер батча, ограничение повторов на задачу, дневное оповещение о расходах и условие остановки при падении доли одобрения. Масштабирование неудачной подсказки быстрее — не оптимизация.
Частые вопросы об автоматизации генерации изображений в масштабе
Какой самый простой способ автоматизировать генерацию изображений в масштабе без управления несколькими API?
Используйте одну очередь и рабочий процесс хранения, затем отправляйте совместимые запросы на изображения через один ключ CometAPI и https://api.cometapi.com/v1/images/generations. Меняйте идентификатор модели в своём слое маршрутизации вместо поддержки отдельной аутентификации и SDK для каждого провайдера.
Могу ли я отправить один запрос и попросить несколько моделей изображений сгенерировать результат одновременно?
В примере используется одна модель на задачу. Расщепление (fan-out) — это логика приложения: продублируйте задачу с разными идентификаторами и значениями модели, затем сравните сохранённые результаты. Так сохраняется привязка стоимости и статуса проверки к каждой модели.
Какой параллелизм следует использовать?
Единого числа для всех аккаунтов и моделей нет. Начните с небольшой ограниченной пулой, например из четырёх воркеров, мониторьте задержку и ответы 429, и настраивайте на основе данных.
Следует ли хранить возвращённый URL или само изображение?
Храните изображение в собственном объектном хранилище. Возвращённый URL может быть временным, в то время как модели GPT Image могут возвращать содержимое в base64 вместо URL.
Как выбрать самую дешёвую модель?
Рассчитывайте стоимость на принятое изображение, а не только цену за вызов. Учитывайте токенные или запросные списания, повторы, неудачные загрузки, отклонённые ассеты, пост-обработку и ручную проверку. Перепроверяйте живой каталог моделей в день публикации или развёртывания.
Где следует проверять endpoint и формат ответа?
Используйте CometAPI Quick Start, документацию по каталогу моделей, справочник по генерации изображений и руководство по ценообразованию.