Полезная миграция на Seedream 5.5 — это не просто замена названия модели, а рабочий процесс с файлами: сгенерировать изображение, проверить полученную задачу, сохранить изображение, а затем отправить сохранённые данные как референс для редактирования.
Seedream 5.5 на AIHubMix сейчас использует doubao-seedream-5-5 и POST /ai/v1/images/generations. В этом руководстве создаётся изображение керамической кружки для товара, а затем запрашивается изменение только её цвета.
Область проверки: документация проверена 12 ноября 2026 года. Код прошёл только локальную проверку синтаксиса и вспомогательных функций в офлайн-режиме; запрос на генерацию не выполнялся. Это не подтверждает качество результата, точность редактирования, задержку или фактическую стоимость.
1. Подготовьте один простой и конкретный запрос
Используйте Python 3.10+ с requests. В Bash установите зависимость и введите ключ так, чтобы его значение не попало в историю командной оболочки:
python3 -m pip install requests
read -r -s -p 'AIHubMix API key: ' AIHUBMIX_API_KEY
printf '\n'
export AIHUBMIX_API_KEY
Для развёрнутого кода передавайте переменную окружения через менеджер секретов. Не помещайте ключ в исходные файлы, примеры запросов, журналы, ноутбуки и код на стороне браузера. Перед любым из двух POST-запросов включите функцию задач в аккаунте, как указано в руководстве по асинхронным задачам. Это требование относится к нативным эндпоинтам медиа-задач /ai/v1, включая синхронное ожидание; оно не связано с выбором фонового выполнения.
Изучите текущую схему эндпоинта модели, выбрав запись по path, а не по позиции в массиве. Ограничения конкретной модели имеют приоритет над общим списком параметров.
| Параметр | Используемое здесь значение |
|---|---|
| Модель | doubao-seedream-5-5 |
| Маршрут | POST /ai/v1/images/generations |
| Тело запроса | Плоский JSON |
| Размер | 2048x2048 |
| Количество изображений | n = 1 |
| Формат файла | png |
| Формат ответа | url |
Согласно схеме, обязательны model и непустой prompt, параметр n может быть только равен 1, а для результата указаны форматы png и jpeg. Принимается URL в image, входные данные в Base64 или объект {url}; параметр images принимает массив, для которого опубликован максимум в 14 референсов. Это ограничение здесь не проверялось во время выполнения. В примере используется один референс и явно задаётся размер по умолчанию; внешний объект input и расширения extra не используются.
2. Сгенерируйте изображение, проверьте задачу и сохраните PNG
Документация по унифицированному API изображений описывает ответ с полями задачи id, object: image, model, status, output и error. Не считайте, что ответ имеет устаревшую структуру data[0].url.
Сначала ознакомьтесь с кратким описанием процесса; полная настройка и вспомогательная функция скачивания приведены в свёрнутом ниже Приложении. Перед выполнением этих примеров один раз загрузите блок из приложения в ту же сессию Python. В нём определены settings, api_json и collect, но запрос на генерацию изображения не отправляется. Затем запускайте короткие блоки по порядку. Каждый POST — отдельное платное действие; не запускайте его повторно из-за отсутствующего ответа или сбоя скачивания.
Отправьте запрос на изображение один раз
generation = {
**settings,
"prompt": "Product photograph of one matte blue ceramic mug on a cream tabletop, "
"soft side lighting, plain warm-gray background, no text or logos.",
}
task = api_json("POST", IMAGES + "/generations", generation)
Проверьте задачу, затем сохраните PNG
Если не указывать async, выполняется синхронное ожидание. В HTTP 200 всё равно может содержаться status: failed. Вспомогательная функция сохраняет ID задачи до проверки статуса: к скачиванию переходит только при completed; при failed, cancelled и неизвестных состояниях она останавливается. Для pending и in_progress нужно проверить существующую задачу, а не запускать генерацию заново.
collect(task, "mug-blue")
Этот единственный вызов использует ключ, создавший задачу, чтобы получить готовый результат, проверяет, что данные являются PNG, и сохраняет файл как mug-blue.png. Он не выполняет автоматическую повторную отправку запроса на создание и перед передачей ключа отклоняет неожиданные хосты скачивания и перенаправления. Полная реализация приведена в приложении; описанное поведение основано на документации, а не на проверенном результате генерации.
Руководство по модели указывает, что URL результатов доступны примерно 30 минут. Скачайте файл без задержки с тем же заголовком Bearer и сохраните данные у себя. Значение expires_at: null не означает, что файл будет храниться постоянно. Если заполнено поле b64_json, декодируйте его вместо скачивания по URL.
3. Отредактируйте локальный файл, а не защищённый URL для скачивания
Перед платным редактированием самостоятельно проверьте сохранённое изображение. Доступный вашему авторизованному клиенту content_url не обязательно является общедоступным URL, по которому провайдер изображений сможет получить файл. Повторно загрузите локальный PNG в виде Data URI:
reference = Path("mug-blue.png").read_bytes()
if not reference.startswith(b"\x89PNG\r\n\x1a\n"):
raise SystemExit("The editing reference must be the saved PNG.")
edit = {
**settings,
"prompt": "Change only the mug color from blue to forest green. Preserve the mug shape, "
"camera angle, tabletop, background, lighting, and shadows.",
"image": "data:image/png;base64," + base64.b64encode(reference).decode("ascii"),
}
task = api_json("POST", IMAGES + "/generations", edit)
collect(task, "mug-green")
Такой запрос просит сохранить изображение, но не доказывает, что оно действительно было сохранено без изменений. Перед следующим платным этапом проверьте результат. Весь JSON-запрос, включая встроированные данные, должен укладываться в 32 MiB; действуют также ограничения модели на медиафайлы. Другой допустимый вариант входных данных — общедоступный URL изображения, доступный провайдеру.
4. Необязательно: асинхронное ожидание и восстановление после прерывания
Требование к аккаунту из раздела 1 не зависит от режима выполнения. Ошибка 403 async_not_enabled означает, что функцию задач нужно включить в консоли. Необязателен только фоновый режим выполнения.
Если вы предпочитаете фоновую генерацию, сформируйте такой же словарь generation, а затем используйте две приведённые ниже строки вместо строки синхронного выполнения task = api_json(...) и отдельного вызова collect(...). Выберите режим до отправки запроса; не запускайте обе версии:
task = api_json("POST", IMAGES + "/generations", {**generation, "async": True})
collect(task, "mug-blue", poll=True)
Вспомогательная функция примерно каждые 15 секунд отправляет запрос GET /ai/v1/images/{id}, пока задача не перейдёт в конечное состояние. Это рекомендуемый в документации интервал опроса, а не ограничение на стороне сервера. Для вебхуков требуется async: true; настройка получателя вебхуков выходит за рамки этого руководства.
Если получение результата прервалось, при необходимости заново загрузите в новой сессии только общий блок настройки и вспомогательных функций из приложения, но не блок создания. Если ID сохранён, продолжите без POST-запроса:
task_id = Path("mug-blue.task-id").read_text(encoding="utf-8").strip()
task = api_json("GET", IMAGES + "/" + quote(task_id, safe=""))
collect(task, "mug-blue", poll=True)
Для восстановления редактирования используйте соответствующую основу имени mug-green. Если ответ с генерацией пропал до сохранения ID, вместо этого проверьте список недавних задач:
recent = api_json("GET", IMAGES + "?limit=20&order=desc")
for row in recent.get("data", []):
print(row.get("id"), row.get("model"), row.get("status"), row.get("created_at"))
Сопоставьте модель и время создания; не выбирайте наугад самую новую задачу. При необходимости используйте next_after как курсор after для следующего запроса. Если однозначно определить задачу не удаётся, обратитесь в поддержку, а не отправляйте запрос повторно. Список представляет собой снимок состояния; для опроса используйте сведения о задаче. Значение output_error в строке означает, что результат не удалось прочитать, а не то, что генерация ничего не создала или стоимость изменилась.
Продолжайте использовать ключ, которым была создана задача. В частности, доступ к списку унифицированных задач, сведениям о них и их содержимому изолирован по токену: другой ключ того же аккаунта не сможет прочитать эти задачи. Локальное прерывание не доказывает ни сбой, ни отсутствие списания.
5. Ошибки миграции и актуальные ошибки
Документация по устаревшему адаптеру Doubao перечисляет старые ID с маршрутом /v1/models/doubao/<id>/predictions и оболочкой input. В этом перечне версии 5.5 нет. Используйте доступный для обнаружения маршрут 5.5 и плоское тело запроса, приведённые здесь; сбой генерации через устаревший маршрут не проверялся. Точно скопируйте текущий ID с дефисами, не предполагая, что вариант с точкой является его псевдонимом.
Не переносите параметры верхнего уровня quality, background, aspect_ratio или seed: в текущей схеме этой модели их нет. В анонсе ByteDance о запуске описывается нативный вывод с прозрачностью в RGBA, однако схема шлюза не содержит ни background, ни layer_decomposition. Одного выбора PNG недостаточно, чтобы гарантировать прозрачность.
Это ошибки унифицированного API изображений, описанные в документации, а не фактически полученные ответы версии 5.5. Проверяйте HTTP-статус отдельно от статуса задачи и выбирайте действие по полю code, а не по полному тексту сообщения.
| Где | Код | Следующее действие |
|---|---|---|
| HTTP 400 | schema_violation | Исправьте поля схемы |
| HTTP 400 | capability_not_supported | Удалите неподдерживаемые параметры |
| HTTP 504 | sync_timeout | Восстановите задачу; обратитесь в поддержку |
| HTTP 502 | task_status_unavailable | Не отправляйте запрос повторно |
| HTTP 422 | output_blocked | Измените содержимое |
| HTTP 403 | async_not_enabled | Включите функцию задач |
| Ошибка задачи | result_delivery_failed | Проверьте существующий результат |
Для HTTP 502 task_status_unavailable в руководстве сказано:
Не удалось подтвердить состояние задачи у провайдера модели. Не отправляйте запрос повторно. Обратитесь в поддержку, указав ID задачи или ID запроса.
Для ошибки задачи result_delivery_failed указано:
Не удалось доставить сгенерированный результат. Не отправляйте запрос повторно автоматически. Обратитесь в поддержку, указав ID задачи.
Ошибка sync_timeout не означает, что выполнение не состоялось. Сохраните error.tid; используйте ID задачи, только если он действительно был возвращён, и попросите поддержку разобраться в неопределённом исходе. Если сбой скачивания можно устранить, повторите получение результата, а не генерацию. Ситуация с 410 artifact_expired другая: этот артефакт уже нельзя получить. Сначала проверьте сохранённые файлы; если замена всё ещё нужна, осознанно разрешите новую платную генерацию. При 429 too_many_downloads проверьте сохранённые копии или обратитесь в поддержку; ожидание само по себе не гарантирует, что доступ восстановится.
В руководстве прямо указано, что плата за генерацию не взимается при output_blocked, в том числе если ошибка указана в задаче со статусом failed. Не распространяйте это исключение на все неудачные запросы или запросы, прошедшие модерацию: к output_policy_violation применяются действующие правила оплаты с учётом модерации.
6. Планируйте бюджет на весь процесс, а не только на один результат
В отчёте Sina Technology о запуске указана стоимость около CNY 0.28 за одно редактирование изображения в квадратном разрешении 2K с учётом входного и выходного изображений; токены текста бесплатны. Это сведения из прессы, а не подтверждённый официальный тариф или предложение AIHubMix.
Например: два платных этапа редактирования существующего изображения, каждый соответствующий этому округлённому сценарию, обойдутся примерно в 2 × CNY 0.28 = CNY 0.56. Сюда не входят первоначальная генерация изображения по тексту, дополнительные референсы, дополнительные варианты и повторные попытки. Это не фактически измеренный счёт.
Для примера с генерацией и последующим редактированием используйте формулу итоговая стоимость = стоимость первоначальной генерации + стоимость редактирования с референсом. На просмотренных страницах не удалось подтвердить полный официальный тариф версии 5.5, поэтому в этом руководстве не приводятся ни фиксированная итоговая сумма, ни точное соотношение экономии по сравнению со старой версией.
Перед отправкой запроса:
- Проверьте актуальный ID, маршрут, плоское тело запроса и схему модели.
- Храните ключ в переменной окружения, а ID задач сохраняйте для восстановления.
- Считайте каждый POST отдельным платным действием, а не повторной попыткой скачивания.
- Перед редактированием проверьте статус задачи и сохранённое изображение.
- Загрузите локальные байты повторно, указав правильный MIME-тип.
- Сначала проверьте статус неопределённых задач, и только потом запускайте генерацию заново.
Начните с одного изображения и одного продуманного изменения; добавляйте новые этапы, только проверив файлы.
Приложение: общие настройки и вспомогательная функция загрузки
При чтении описания рабочего процесса это приложение можно пропустить. Перед запуском коротких примеров разверните этот блок и один раз выполните его в той же сессии Python. Он настраивает сессию и определяет функции, не генерируя изображение. Чтобы восстановить прерванную задачу в новой сессии, загрузите только этот блок — не блок создания или редактирования.
Разверните полный вспомогательный блок — загрузите его один раз перед короткими примерами; запрос изображения не выполняется
import base64
import os
import time
from pathlib import Path
from urllib.parse import quote, urlsplit
import requests
BASE = "https://aihubmix.com"
IMAGES = "/ai/v1/images"
settings = {
"model": "doubao-seedream-5-5",
"size": "2048x2048",
"n": 1,
"output_format": "png",
"response_format": "url",
}
client = requests.Session()
client.headers["Authorization"] = "Bearer " + os.environ["AIHUBMIX_API_KEY"]
def api_json(method, path, body=None):
try:
response = client.request(
method, BASE + path, json=body,
timeout=(15, 600), allow_redirects=False,
)
except requests.RequestException:
raise SystemExit(
"Connection interrupted. Recover the existing task before another POST."
) from None
try:
data = response.json()
except ValueError:
raise SystemExit(
f"HTTP {response.status_code}: non-JSON response; recover before another POST."
) from None
if not isinstance(data, dict):
raise SystemExit("Unexpected response; recover before another POST.")
if not 200 <= response.status_code < 300:
error = data.get("error") or {}
raise SystemExit(
f"HTTP {response.status_code}: code={error.get('code')}, "
f"tid={error.get('tid')}. No automatic generation retry."
)
return data
def collect(task, stem, poll=False):
task_id = task.get("id")
if not isinstance(task_id, str) or not task_id:
raise SystemExit("No task ID returned. Recover from the task list; do not resubmit.")
Path(stem + ".task-id").write_text(task_id + "\n", encoding="utf-8")
while True:
status = task.get("status")
print("Task:", task_id, "status:", status)
if status == "completed":
break
if status not in {"pending", "in_progress"}:
error = task.get("error") or {}
raise SystemExit(
f"Stopped: status={status}, code={error.get('code')}; task={task_id}."
)
if not poll:
raise SystemExit("Task still active. Query the saved ID; do not recreate it.")
time.sleep(15)
task = api_json("GET", IMAGES + "/" + quote(task_id, safe=""))
output = task.get("output") or []
if not output:
raise SystemExit("Completed without readable output; investigate the saved task.")
item = output[0]
if item.get("b64_json"):
image_bytes = base64.b64decode(item["b64_json"], validate=True)
else:
url = item.get("content_url")
if not isinstance(url, str):
raise SystemExit("Missing content_url; investigate the saved task.")
parsed = urlsplit(url)
if (parsed.scheme, parsed.netloc) != ("https", "aihubmix.com"):
raise SystemExit("Unexpected download origin; key was not forwarded.")
try:
response = client.get(url, timeout=(15, 120), allow_redirects=False)
except requests.RequestException:
raise SystemExit("Download interrupted; recover this task, not a new generation.") from None
if not 200 <= response.status_code < 300:
try:
detail = response.json()
except ValueError:
detail = {}
error = detail.get("error", {}) if isinstance(detail, dict) else {}
code = error.get("code") if isinstance(error, dict) else None
if response.status_code == 410 or code == "artifact_expired":
raise SystemExit("Artifact expired; retrieval cannot recover it. Check saved files first.")
if code == "too_many_downloads":
raise SystemExit("Download allowance exhausted; check saved files or contact support.")
raise SystemExit(
f"Download HTTP {response.status_code}, code={code}; "
"inspect the saved task. Retry retrieval only if recoverable."
)
image_bytes = response.content
if not image_bytes.startswith(b"\x89PNG\r\n\x1a\n"):
raise SystemExit("Expected PNG bytes; stopped before saving or reusing the result.")
destination = Path(stem + ".png")
destination.write_bytes(image_bytes)
print("Saved:", destination)
return destination
Тайм-аут чтения в 600 секунд — это настройка клиента, а не обещание такой задержки со стороны сервиса. Проверка PNG соответствует явно указанному в этом руководстве формату вывода; если выберете JPEG, адаптируйте её.
Часто задаваемые вопросы
Какой ID модели и эндпоинт использовать для Seedream 5.5?
Используйте doubao-seedream-5-5 с POST /ai/v1/images/generations и плоским JSON. Не считайте, что другое написание или устаревший адаптер равнозначны.
В этом руководстве есть проверенные результаты генерации?
Нет. Код основан на документации; проверялись только локальный синтаксис и вспомогательные функции в автономном режиме. Запросы инференса, оценка качества изображений, измерение задержки и проверка тарификации не выполнялись.
Асинхронный режим обязателен?
Нет, по умолчанию используется синхронное ожидание. Фоновое выполнение задаётся булевым параметром async: true. Для нативных эндпоинтов задач обработки медиа требуется предварительно включить эту функцию на уровне аккаунта, даже если ожидание выполняется синхронно.
Означает ли HTTP 200, что изображение создано успешно?
Нет. Проверьте статус задачи и текст ошибки. Задача может завершиться с ошибкой, даже если HTTP-запрос выполнен успешно; скачивайте результат только после завершения.
Можно ли использовать URL для скачивания результата как референс для следующего редактирования?
Не рассчитывайте на это. Скачайте изображение с помощью ключа, использованного при создании, а затем закодируйте локальный файл как Data URI или укажите общедоступный URL изображения.
Что делать после тайм-аута или потери ответа?
Не запускайте генерацию повторно автоматически. Проверьте сохранённый ID задачи или найдите её в списке изображений с помощью ключа, использованного при создании. Сохраняйте ID запросов и обращайтесь в поддержку, если результат неясен.
Гарантирует ли выбор PNG прозрачный фон или счёт на CNY 0.28?
Ни то ни другое. В схеме нет проверенного параметра управления прозрачностью. CNY 0.28 — приблизительная стоимость редактирования изображения 2K, о которой сообщалось в прессе, а не тариф AIHubMix и не фиксированная цена генерации изображения по тексту с последующим редактированием.
Читайте дальше: серия Seedream 5.5
- Прежде чем менять существующий рабочий процесс на 5.0 Pro, взвесьте преимущества обновления: Seedream 5.5 и 5.0 Pro: стоит ли обновляться?
- Если для того же рабочего процесса подойдёт другая модель изображений, сравните компромиссы: Seedream 5.5 и GPT Image 2.6 Sunburst: что выбрать?
Источники
- Анонс запуска Seedream 5.5 — ByteDance Seed; заявления поставщика о возможностях.
- Актуальная схема эндпоинта Seedream 5.5 — AIHubMix; поля запроса и ограничения конкретной модели.
- Унифицированный API генерации изображений — AIHubMix; задачи, скачивание и актуальные ошибки.
- Руководство по модели Seedream 5.5 — AIHubMix; ID модели и кратковременные ссылки на скачивание с аутентификацией; сведения об ошибках конкретных маршрутов см. в документе по унифицированному API.
- Освещение запуска Seedream 5.5 в прессе — Sina Technology; пример приблизительной стоимости редактирования, а не официальный тариф.



