HiAPI
Блог

Руководство

Как использовать recraft/creative-upscale через HiAPI API: руководство по запросам curl и Python

Nov 3, 2026
文章封面图:深青底色上以扁平几何切面构成的水晶矿物剖面,青绿双色点缀,印刷图版风格。

Роль 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_KEY
  • Content-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% могут выглядеть неестественно в размере, который реально видит пользователь.
  • Проверяйте размеры программно как часть прогона. Несовпадение означает, что множитель не применился — это отчёт об ошибке в вашем собственном запросе, а не эстетическая проблема.
  • Судите по определённым критериям: точность относительно исходника против воспринимаемой резкости, в зависимости от категории актива. Запишите этот критерий рядом с матрицей, чтобы следующий человек знал, что означает «лучше».

Как только матрица стабилизируется, стенд превращается в регрессионный тест: перезапускайте его после любого изменения клиентского кода и сравнивайте с предыдущим каталогом прогонов. Поскольку каждый вызов в этом руководстве имеет ту же форму запроса, что и другие эндпоинты изображений платформы, построенный вами прогонщик обобщается на любую модель, которую вы интегрируете дальше.

Похожие статьи

Все статьи →

Начните работать с постоянными артефактами ИИ

Получите API-ключ и вызывайте модели изображений, видео и аудио через один API на основе tasks.

Читать документацию API