Руководство
Как использовать recraft/creative-upscale через HiAPI API: руководство по запросам curl и Python
Роль recraft/creative-upscale в рабочем процессе разработчика
recraft/creative-upscale — это эндпоинт «изображение в изображение»: вы отправляете существующее изображение, а модель возвращает увеличенную версию, реконструированную моделью. Ключевое слово здесь — креативный (creative). Классический шаг апскейлинга (билинейный, Lanczos или универсальные модели суперразрешения) сохраняет входные данные максимально точно. Креативный апскейлинг позволяет заново генерировать детали, которых никогда не было в исходных пикселях: края синтезируются заново, текстуры выводятся, а небольшие размытые области могут быть заточены в правдоподобное содержимое, а не просто интерполированы.
Это отличает его от простых инструментов масштабирования и определяет его особое место в конвейере.
Когда его использовать
- Обновление материалов. Миниатюра или устаревшее изображение продукта должно отображаться в большем размере, а обычное масштабирование по сравнению с соседями в нативном разрешении будет выглядеть размытым.
- Работа с референсами и эскизами. Концепт-арт, раскадровка или изображение-заполнитель должны демонстрироваться в большом размере, не выдавая своё низкое разрешение.
- Апскейлинг внутри цикла генерации. Вы сгенерировали изображение в небольшом рабочем размере и хотите получить финальный материал без повторного запуска всего процесса генерации на большем холсте.
Когда его не использовать
Если требуется побайтовая точность — архивные сканы, документы, текстурные атласы, где значения пикселей и есть данные — не используйте креативную модель. Перегенерированные детали — это разумное предположение, а не реконструкция; для целей измерений или архивирования это предположение является дефектом. В таких случаях используйте детерминированный ресемплер, а креативную модель оставьте для перцептивного вывода.
Форма вызова
Эндпоинт следует той же схеме запроса, что и другие эндпоинты изображений HiAPI: аутентифицированный JSON POST-запрос к пути модели с входным изображением и объектом параметров. Если вы уже интегрировали любую другую модель изображений на платформе, эта ментальная модель переносится напрямую — в этом и смысл маршрутизации таких вызовов через единый интерфейс. Работающий вызов curl становится шаблоном для каждого эндпоинта изображений, к которому вы обратитесь впоследствии.
Полезный способ понять этот шаг: он потребляет изображение, которому вы уже доверяете (композиция, содержимое, цвета определены), и возвращает более крупный, более детальный вариант. Решения о содержимом принимаются выше по потоку; recraft/creative-upscale — это завершающий этап.
Предварительные требования и настройка эндпоинта
Перед написанием первого запроса соберите четыре вещи. Ни одна из них не требует специального SDK — вся интеграция представляет собой чистую HTTPS-коммуникацию с JSON-телом запроса.
1. API-ключ
Вам нужен ключ HiAPI API с доступом к моделям изображений. Относитесь к нему как к секрету: загружайте из переменной окружения, а не вставляйте в скрипт и никогда не коммитьте в репозиторий.
export HIAPI_API_KEY="your-key-here"
Ключ передаётся через заголовок, не в URL и не в JSON-теле. Исключив его из строки запроса, вы также исключаете его из истории shell и логов прокси.
2. Базовый URL
Базовый URL — это хост вашего HiAPI API. Все вызовы моделей являются относительными путями под ним, поэтому вы можете задать его как переменную и повторно использовать в каждом скрипте:
export HIAPI_BASE_URL="https://api.hiapi.ai"
Обратитесь к справочной документации API платформы, чтобы получить канонический базовый URL и префикс пути для вашего аккаунта, и сохраните их в этой единственной переменной. Так изменение хоста или версии — это правка одной строки.
3. Идентификатор модели
ID модели — это сегмент пути, который должен быть указан строго так, как опубликован: recraft/creative-upscale. Он содержит косую черту, что важно в некоторых инструментах — в разделе отладки это подробно описано. Регистр и дефисы имеют значение. Один неверный символ приведёт к ошибке «модель не найдена», которая, если вы лишь бегло просмотрите сообщение, будет выглядеть как проблема аутентификации.
4. Тестовое изображение
Подготовьте изображение на диске и знайте его точный путь и MIME-тип. Для первого запуска используйте небольшой файл, чтобы сбой однозначно был проблемой запроса, а не размером нагрузки или тайм-аутом. Вы позже будете повторно использовать то же изображение для сравнительных запусков, поэтому выбирайте что-то с видимыми деталями (ткань, растительность, вывеска без текста), а не плоский градиент.
Контрольный список заголовков
Каждый запрос отсюда и далее несёт одни и те же заголовки:
Authorization: Bearer $HIAPI_API_KEYContent-Type: application/json
Если вы отправляете изображение в JSON-теле в виде base64 или data URI, этих двух заголовков достаточно. Если вместо этого вы сначала загружаете файл для получения URL, выполните эту загрузку как отдельный вызов и сохраните полученный URL отдельно от запроса к модели.
Имея ключ, базовый URL, ID модели и тестовое изображение, вы можете выполнить реальный вызов менее чем за минуту.
Рабочий запрос с curl
Ниже приведён вызов, готовый к запуску. Замените значение изображения своим входным — это может быть публично доступный URL или base64-кодированный data URI, в зависимости от того, что принимает режим ввода модели.
curl -sS -X POST "$HIAPI_BASE_URL/v1/models/recraft/creative-upscale" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"input": {
"image": "https://example.com/test-input.png"
},
"parameters": {
"upscale": 2
}
}' \
-o response.json
Запись ответа в файл с помощью -o вместо потокового вывода в терминал сохраняет JSON целым для парсинга и делает вызов скриптуемым.
Что делает каждая часть
-X POST— эндпоинт принимает POST; GET вернёт ошибку метода, которую легко принять за проблему с правами.- URL — базовый URL, затем путь модели с полным ID модели. Поскольку ID сам содержит косую черту, путь после коллекции моделей имеет два сегмента; держите его одной строкой и не позволяйте клиентской библиотеке перекодировать его в
recraft%2Fcreative-upscale, если документация не указывает это как ожидаемое поведение. Authorization— bearer-токен. Если вы видите 401 на этой точной команде, ключ или формат заголовка неверны; больше ничего в теле запроса ещё не проверялось.Content-Type: application/json— обязателен. Без него некоторые шлюзы рассматривают тело запроса как form data, и запрос никогда не достигает модели.input.image— исходное изображение. При итерациях предпочитайте URL: он держит команду короткой, а диффы — чистыми.parameters.upscale— управление апскейлингом. Начните с умеренного множителя, подтвердите ответ, затем увеличивайте.
Два практичных варианта
Чтобы отправить локальный файл в виде base64 вместо URL:
B64=$(base64 -w0 ./test-input.png)
curl -sS -X POST "$HIAPI_BASE_URL/v1/models/recraft/creative-upscale" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d "{
\"input\": { \"image\": \"data:image/png;base64,${B64}\" },
\"parameters\": { \"upscale\": 2 }
}" \
-o response.json
Чтобы при отладке видеть одновременно HTTP-статус и тело ответа, добавьте -w '\nHTTP %{http_code}\n' и уберите -o.
Рассматривайте эту одну команду как свой шаблон. Как только она возвращает изображение, каждое последующее изменение — другой множитель, другое исходное изображение — это правка двух полей, а не новая интеграция.
Тот же запрос на Python
Версия на Python не должна быть копипастой тела curl-запроса; это должна быть небольшая переиспользуемая функция, чтобы последующие сравнительные запуски требовали одного вызова каждая. Используйте только стандартную библиотеку — SDK не нужен.
import base64
import json
import os
import pathlib
import urllib.request
HIAPI_BASE_URL = os.environ["HIAPI_BASE_URL"].rstrip("/")
HIAPI_API_KEY = os.environ["HIAPI_API_KEY"]
MODEL = "recraft/creative-upscale"
def creative_upscale(image: str, upscale: int = 2, timeout: int = 120) -> dict:
"""Отправляет изображение в recraft/creative-upscale и возвращает разобранный JSON."""
payload = {
"input": {"image": image},
"parameters": {"upscale": upscale},
}
request = urllib.request.Request(
url=f"{HIAPI_BASE_URL}/v1/models/{MODEL}",
data=json.dumps(payload).encode("utf-8"),
headers={
"Authorization": f"Bearer {HIAPI_API_KEY}",
"Content-Type": "application/json",
},
method="POST",
)
with urllib.request.urlopen(request, timeout=timeout) as response:
return json.loads(response.read().decode("utf-8"))
def as_data_uri(path: str) -> str:
data = pathlib.Path(path).read_bytes()
mime = "image/png" if path.lower().endswith(".png") else "image/jpeg"
return f"data:{mime};base64,{base64.b64encode(data).decode('ascii')}"
if __name__ == "__main__":
result = creative_upscale(as_data_uri("test-input.png"), upscale=2)
print(json.dumps(result, indent=2)[:2000])
Почему именно такая форма
- Конфигурация из переменных окружения. Базовый URL и ключ читаются один раз при импорте, поэтому в файле нет секретов, а переключение окружения — это один export.
- Одна функция — одна ответственность.
creative_upscaleпринимает ссылку на изображение и множитель и возвращает разобранный JSON. Вся информация о параметрах остаётся видимой в точке вызова. - Явный тайм-аут. Модели изображений работают дольше текстовых эндпоинтов. Задавайте тайм-аут осознанно, а не наследуйте слишком короткое значение по умолчанию, и держите его достаточно длинным, чтобы медленный, но успешный вызов не повторялся без необходимости.
- Помощник для локальных файлов.
as_data_uriозначает, что вы можете передавать URL или локальный путь, не изменяя логику запроса.
Если вы предпочитаете клиент на основе сеансов
Тот же вызов с httpx требует замены всего двух строк — создайте клиент, задайте заголовок Authorization по умолчанию, затем выполните post с JSON-телом. Важные инварианты не меняются: ID модели остаётся одним неэкранированным сегментом пути, ключ остаётся в заголовке, тело сохраняет разделение на input / parameters. Совпадайте по этим трём пунктам, и ваш клиент будет взаимозаменяем с любым другим клиентом на платформе.
Когда вы подключаете это к конвейеру, возвращайте разобранный словарь, позволяя вызывающему коду решать, как сохранять изображение — такое разделение делает обработку ответа из следующего раздела переиспользуемой.
Параметры апскейлинга и креативности
Отправляемые значения менее важны, чем куда вы их отправляете. Сначала убедитесь в правильности размещения, затем настраивайте числовые значения.
Два контейнера, один контракт
Каждый запрос делится на:
input— само изображение. Объект операции. Всё, что связано с поведением модели, здесь не размещается.parameters— управляющие параметры. Множитель апскейлинга и настройки креативности принадлежат этому объекту как соседи.
Это разделение и есть контракт. Первый запуск должен подтвердить, что модель принимает ваше размещение — то есть вызов хотя бы возвращает изображение — прежде чем оптимизировать значения. Если параметр попал не в тот контейнер, вы обычно получите изображение, сгенерированное со значениями по умолчанию, или ошибку валидации с указанием неизвестного поля. В любом случае это ошибка размещения, а не качества, и погоня за настройками качества её не исправит.
Множитель апскейлинга
Множитель управляет размером вывода относительно входа. Рассуждения о нём:
- Это множитель, поэтому стоимость и задержка растут вместе с ним. Переход от умеренного множителя к максимальному — не линейный шаг по времени рендеринга. Считайте каждый шаг повышения новым экспериментом, а не подстройкой ползунка.
- Разрешение входа всё ещё важно. Креативной модели есть с чем работать, когда присутствует некоторая структура. Крошечный вход даёт ей больше свободы для изобретения, что иногда является целью, а иногда — сюрпризом.
- Выбирайте множитель по целевому размеру, а не по максимуму. Если изображению нужно 2×, чтобы поместиться на своём месте, запрашивайте 2×. Запрос максимума, а затем уменьшение отбрасывает выгоду и оплачивается.
Управление креативностью
Креативность — это ручка, определяющая, насколько модель может заменять (а не увеличивать). Низкие значения ведут себя ближе к точному апскейлингу; высокие заставляют модель более агрессивно пересобирать, что может спасти размытый или блочный исходник, но с той же вероятностью внести детали, которых вы не хотели.
Рассматривайте этот параметр как рычаг точности, у которого есть конкретные трактовки на обоих концах:
- Сохранение — логотипы, лица, изображения каталога продуктов, всё, что зритель может сравнить с оригиналом.
- Перегенерация — концепт-арт, фоны, текстуры, декоративные изображения, где правдоподобие важнее точности.
Метод работы
Меняйте по одному параметру за раз, держите вход фиксированным и записывайте значения вместе с выводами. Небольшой матрицы — одно и то же изображение при двух множителях, каждый при двух настройках креативности — достаточно, чтобы охарактеризовать особенности эндпоинта на вашем собственном контенте. Не заимствуйте чьи-то «лучшие» значения; креативные модели сильно взаимодействуют со входом, и настройки, подходящие для фотографий, редко подходят для плоских иллюстраций.
Если значение прямо отклонено, а не даёт плохой результат, это контракт сообщает вам о домене параметра — обратитесь к справочнику параметров эндпоинта за допустимыми диапазонами, а не угадывайте.
Чтение ответа и сохранение изображения
Разбирайте ответ защитно. Тип нагрузки является частью договора, но может различаться между URL и встроенным блоком base64, и ваш клиент не должен падать из-за того, какой из них он получил.
Сначала посмотрите на сырой JSON
Перед написанием парсера запустите один раз вызов curl с -o response.json и прочитайте файл. Определите поле, несущее изображение. Обычно это одно из:
- URL, указывающий на сгенерированный файл, или
- Встроенная строка, обычно base64 или data URI.
Также поищите метаданные, которые стоит записать: размеры, отражённый ID модели и любые идентификаторы, полезные для запроса в поддержку.
Устойчивая к ошибкам функция сохранения
import base64
import pathlib
import urllib.request
def extract_image(result: dict) -> str:
"""Находит нагрузку изображения, в какой бы форме она ни возвращалась."""
for container in (result, result.get("data"), result.get("output")):
if isinstance(container, list) and container:
container = container[0]
if isinstance(container, dict):
for key in ("image", "url", "b64_json", "image_url"):
value = container.get(key)
if isinstance(value, str) and value:
return value
raise ValueError(f"no image field in response: {sorted(result)}")
def save_image(payload: str, out_path: str = "upscaled.png") -> pathlib.Path:
path = pathlib.Path(out_path)
if payload.startswith("data:"):
payload = payload.split(",", 1)[1]
path.write_bytes(base64.b64decode(payload))
elif payload.startswith("http://") or payload.startswith("https://"):
with urllib.request.urlopen(payload) as response:
path.write_bytes(response.read())
else:
path.write_bytes(base64.b64decode(payload))
return path
Главное не в том, что это единственно правильный парсер, а в том, что функция излагает свои допущения (data:, http(s)://, чистый base64) и выдаёт чёткую ошибку, когда ничего не совпадает. Когда форма ответа изменится, нужно обновить одну функцию, а не каждый скрипт, потребляющий изображения.
Безопасное сохранение в процессе curl
curl -sS -X POST "$HIAPI_BASE_URL/v1/models/recraft/creative-upscale" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d @request.json -o response.json
python - <<'PY'
import json
from save_image import extract_image, save_image
result = json.load(open("response.json"))
print(save_image(extract_image(result), "out.png"))
PY
Две привычки, которые стоит поддерживать: записывать новое имя файла при каждом запуске, чтобы сбой или частичная запись никогда не перезаписали хороший результат; проверять размеры вывода после сохранения — успешный HTTP 200 с неожиданными размерами означает, что параметры не применились, и здесь это легче заметить, чем после трёх этапов конвейера.
Отладка распространённых сбоев
Большинство сбоев при первом запуске тривиальны. Пройдите этот список по порядку; он охватывает подавляющее большинство случаев.
401 / 403 — аутентификация
- Загружен ли ключ в той же оболочке, в которой выполняется команда?
echo $HIAPI_API_KEYдолжен вывести непустое значение. - Заголовок точно
Authorization: Bearer <key>— включая пробел и словоBearer? - Не оказался ли ключ в URL или JSON-теле вместо заголовка? Верните его на место.
- Не ограничен ли ключ моделями изображений? Ключ, действительный для какой-то продуктовой области, может не подходить для этого эндпоинта.
404 — модель или маршрут не найдены
Это почти всегда проблема ID модели. Сравните посимвольно с опубликованным идентификатором recraft/creative-upscale: косая черта, нижний регистр и дефис в creative-upscale — всё критично. Связанная ловушка — экранирование URL в клиенте: если в строке запроса вы видите recraft%2Fcreative-upscale и вызов возвращает 404, ваш HTTP-слой закодировал косую черту; настройте его не трогать эту часть пути.
Также убедитесь, что вы не дублируете префикс пути (например, базовый URL уже оканчивается сегментом версии, а путь повторяет его). Использование одной переменной для базового URL делает это легко заметным.
400 — запрос понят, но отклонён
Читайте сообщение, а не угадывайте. Частые причины:
- Неверный формат входного изображения. Обрезанный base64 (обычно из-за усечения shell-переменной или отсутствия префикса
data:image/png;base64,, когда режим ожидает полный data URI) или URL, недоступный публично. - Параметр вне диапазона или не на месте. Множитель, который модель не принимает, или
upscale, отправленный на верхнем уровне вместоparameters. - Отсутствует тип содержимого.
Content-Typeсо значениемtext/plainили полностью отсутствующий превращает JSON-тело в неразбираемый документ.
413 / 422 / тайм-аут — размер и длительность
Очень большие исходные изображения могут не пройти валидацию ещё до запуска модели. Умеренно уменьшите вход, повторите и подтвердите, что форма запроса разумна, прежде чем отправлять файл в полном разрешении. Что касается тайм-аутов, различайте медленно и сбой: увеличьте клиентский тайм-аут один раз, и если вызов после этого успешен, исправление относится к конфигурации клиента, а не к нагрузке.
Правило быстрой триажной сортировки
Если ошибка упоминает аутентификацию, модель или формат ввода, вы вообще не дошли до логики апскейлинга — значения креативности или множителя ещё ни при чём. Исправьте обёртку, повторите с минимально возможным запросом (маленькое тестовое изображение, параметры по умолчанию) и только затем начинайте менять настройки. Отладка в этом порядке предотвращает классическую ошибку: компенсацию сломанного заголовка подстройкой параметров.
Построение воспроизводимого сравнительного теста
Креативный апскейлинг сильно зависит от суждения, поэтому используйте фиксированные приспособления вместо памяти. Цель — небольшой тестовый стенд, отвечающий на вопрос «действительно ли эта настройка помогает?» без повторного просмотра старых файлов.
Фиксированные входы
- Одно тестовое изображение, зафиксированное в репозитории. Выберите что-то с восстанавливаемыми деталями — ткань, растительность, архитектурные края. Закоммитьте его рядом со скриптом, чтобы каждый запуск и каждый член команды использовали один и тот же источник.
- Фиксированные параметры. Множитель и значения креативности хранятся в списке в скрипте, а не в вашей голове или в чате.
- Фиксированный ID модели. По той же причине, что и в контрольном списке заголовков:
recraft/creative-upscaleуказан один раз в константе.
Минимальный прогонщик матрицы
import itertools, json, pathlib
FACTORS = [2, 4]
CREATIVITY = ["preserve", "regenerate"] # используйте точные значения, принимаемые согласно документации
src = as_data_uri("fixtures/test-input.png")
out_dir = pathlib.Path("runs"); out_dir.mkdir(exist_ok=True)
for factor, mode in itertools.product(FACTORS, CREATIVITY):
result = creative_upscale(src, upscale=factor, creativity=mode)
name = f"f{factor}-{mode}"
save_image(extract_image(result), out_dir / f"{name}.png")
(out_dir / f"{name}.json").write_text(json.dumps(result, indent=2))
print(name, "ok")
Две детали важнее кода. Первая: сохраняйте сырой JSON-ответ рядом с каждым изображением — когда результат выглядит неправильным, ответ говорит вам, были ли параметры применены или молча проигнорированы. Вторая: называйте файлы по значениям параметров, чтобы список каталога и был матрицей, и вам никогда не приходилось сомневаться, какой файл из какой настройки.
Сравнивайте фиксированным образом
- Смотрите на выводы в предполагаемом размере отображения, а не в увеличенном виде. Впечатляющие креативные детали при 400% могут выглядеть неестественно в размере, который реально видит пользователь.
- Проверяйте размеры программно как часть прогона. Несовпадение означает, что множитель не применился — это отчёт об ошибке в вашем собственном запросе, а не эстетическая проблема.
- Судите по определённым критериям: точность относительно исходника против воспринимаемой резкости, в зависимости от категории актива. Запишите этот критерий рядом с матрицей, чтобы следующий человек знал, что означает «лучше».
Как только матрица стабилизируется, стенд превращается в регрессионный тест: перезапускайте его после любого изменения клиентского кода и сравнивайте с предыдущим каталогом прогонов. Поскольку каждый вызов в этом руководстве имеет ту же форму запроса, что и другие эндпоинты изображений платформы, построенный вами прогонщик обобщается на любую модель, которую вы интегрируете дальше.
Похожие статьи
Все статьи →-
Руководство
Как вызвать hailuo-2.3-fast/image-to-video через HiAPI API: практика с curl и Python
Первый рабочий запрос к быстрому и недорогому уровню генерации видео по изображению — от ID модели до загрузки MP4
-
Руководство
Как вызывать hailuo-2.3/text-to-video через API HiAPI: curl, Python и рабочие примеры запросов
-
Руководство
Использование Kandinsky 6.0 Pro для преобразования текста в видео на HiAPI: руководство по curl и Python
Практическая демонстрация с упором на запросы: построение вызова от промпта до видеоклипа, отправка запроса, опрос статуса завершения и скачивание результата