チュートリアル
HiAPI で gpt-image-2/image-to-image を呼び出す方法:curl、Python、そして確実に動くリクエスト
開発者向けの図生図リクエスト実践:参照画像の送信、タスクのポーリング、結果のダウンロード
image-to-image エンドポイントが期待するもの
HiAPI の gpt-image-2/image-to-image モデルは非同期の画像生成エンドポイントです。画像が返るまでブロックする同期呼び出しとは異なり、このエンドポイントはリクエストを受け取ってキューに入れ、タスクハンドルを返します。その後、タスクが完了するまで追跡を続ける必要があります。
リクエストのレベルでは、3 つのものを提供する必要があります:
- モデル id:
gpt-image-2/image-to-image。 - 参照画像 1 枚:モデルがそれを基に変換または構築するソース画像。これが図生図モードの決定的な入力です——これがなければ、あなたが行うのは文生図です。
- プロンプトとオプション:期待する出力を記述したテキスト指示、およびモデルドキュメントに記載された任意フィールド(例:サイズや出力形式)。モデルドキュメントに記載されたパラメータのみを送信してください。
レスポンスは画像そのものではなく、識別子とステータスを含むタスクオブジェクトです。このステータスを唯一の事実源として扱ってください:pending または processing は待機継続、succeeded は結果の準備完了、failed は問題が発生したためポーリングを停止すべきことを意味します。
最初からこのライフサイクルを中心にクライアントを設計してください。このチュートリアルの他のすべて——curl、Python、ポーリング、ダウンロード——は「送信と完了は 2 つの別々の瞬間である」という事実の上に成り立っています。
HiAPI キーと参照画像を準備する
コードを書く前に、2 つのものを準備します。
API キー。HiAPI コンソールで作成し、スクリプトに直接貼り付けるのではなく環境変数に保存します:
export HIAPI_API_KEY="your-key-here"
キーは機密として扱ってください。バージョン管理にコミットしたり、リクエストログに記録したりしないでください。
参照画像。変換したいローカル画像ファイルを選びます。適切なサイズに保ってください——過大で高解像度のソース画像は、リクエストが遅くなったり拒否されたりする最も一般的な原因です。PNG または JPEG をスクリプトと同じディレクトリに置くと、初回実行が最も簡単です:
ls -lh ./reference.png
ファイルパスを控えてください。curl と Python の両方の例で参照します。サーバーからモデルを呼び出す予定なら、プロセスがそのパスに対する読み取り権限を持ち、ファイルが有効な画像であること(拡張子だけ変えた名前のファイルでないこと)を確認してください。
キーをエクスポートし、画像をディスク上に用意すれば、最初のリクエストに必要なものはすべて揃います。
確実に動く curl リクエスト
認証情報とリクエストボディの構造を検証する最速の方法は、curl 呼び出しを 1 回実行することです。タスクを送信し、タスクオブジェクトを表示します:
curl -sS https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2/image-to-image",
"input": {
"image": "https://example.com/reference.png",
"prompt": "Turn this photo into a watercolor illustration"
}
}'
この例について 2 点説明します。第一に、参照画像は input.image フィールドで URL として渡されます。エンドポイントドキュメントがあなたのシナリオでインライン base64 や multipart アップロードをサポートしている場合はその形式を使用してください。ただしフィールド名は同じに保ってください。第二に、プロンプトは変換を記述する場所です——スタイル、構図、そして変更してはいけない内容を具体的に指定してください。
実行してレスポンスを読み取ります。送信が成功すると、タスク id と非終端状態が返ります。401 が返った場合、キーが欠落しているか誤っています。422 または同様の検証エラーが返った場合は、リクエストボディを確認してください——通常はモデル id または image フィールドの形式に誤りがあります。
タスク id を保存してください。以降のステップはすべてこれに依存します。
Python で同じことをする
Python 版は curl 呼び出しと完全に対応し、認証とリクエストボディの構築を明示的に保ち、何もラッパー層に隠されないようにします。requests を使用します:
import os
import requests
API_KEY = os.environ["HIAPI_API_KEY"]
BASE_URL = "https://api.hiapi.ai/v1"
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
payload = {
"model": "gpt-image-2/image-to-image",
"input": {
"image": "https://example.com/reference.png",
"prompt": "Turn this photo into a watercolor illustration",
},
}
response = requests.post(f"{BASE_URL}/tasks", json=payload, headers=headers, timeout=30)
response.raise_for_status()
task = response.json()
print(task["id"], task["status"])
統合が URL ではなくローカルファイルを送信する場合は、独自のフィールドを考案するのではなく、エンドポイントドキュメントに従って画像をエンコードして添付してください。規律は curl の場合と同じです:リクエストボディを通常の辞書として構築し、送信し、解析前に HTTP ステータスを確認します。
送信ロジックをタスク id を返す関数にカプセル化してください。そうすれば、次のセクションのポーリングコードはタスクがどのように作成されたかに依存しなくなります。
非同期タスクを完了までポーリングする
送信呼び出しは、画像がまだ生成されている間に返ります。結果を得るには、タスクが終端状態に入るまでタスクステータスエンドポイントをポーリングします。堅牢なループには 3 つの特性があります:ポーリング間の遅延、最大待機時間、そして失敗状態の明示的な処理です。
import time
def wait_for_task(task_id, headers, base_url, timeout=300, interval=3):
deadline = time.time() + timeout
while time.time() < deadline:
r = requests.get(f"{base_url}/tasks/{task_id}", headers=headers, timeout=30)
r.raise_for_status()
task = r.json()
status = task["status"]
if status == "succeeded":
return task
if status == "failed":
raise RuntimeError(f"Task failed: {task}")
time.sleep(interval)
raise TimeoutError(f"Task {task_id} did not finish within {timeout}s")
いくつかの実用的な改善点:
- バックオフ:短い間隔から始めて徐々に増やすか、API を頻繁に叩かないよう十分に余裕のある固定間隔を保ちます。画像生成は瞬時には完了しません。
- タイムアウト:総待機時間には常に上限を設定してください。そうしないと、スタックしたタスクがワーカーを無期限にぶら下げてしまいます。
- 終端状態:
succeededとfailedのみを終端状態として扱います。それ以外の状態はポーリング継続を意味します。API が将来中間状態を追加しても、ループは正しく動作し続けます。
大量のタスクを実行する場合は、Web リクエストをブロックするのではなく、バックグラウンドワーカーやキューでポーリングしてください。ライフサイクルは同じで、並行モデルだけが異なります。
結果をダウンロードして検証する
タスクが成功を報告すると、タスクオブジェクトには生成画像の場所——通常は出力フィールド内の URL——が含まれます。それをダウンロードしてディスクに書き込みます:
task = wait_for_task(task_id, headers, BASE_URL)
image_url = task["output"]["image"]
img = requests.get(image_url, timeout=60)
img.raise_for_status()
with open("result.png", "wb") as f:
f.write(img.content)
署名付き URL に有効期限がある場合は、完了後すぐにダウンロードするか、URL を保存して後で使うのではなくファイルを直接永続化してください。エンドポイントが URL ではなく base64 を返す場合は、デコードしてから書き込んでください。
簡単な整合性チェックで、混乱を招く下流の障害を防げます:
from PIL import Image
with Image.open("result.png") as im:
im.verify()
print("valid image, bytes:", os.path.getsize("result.png"))
ファイルがデコード可能な画像でない場合、verify() は例外をスローします。これにより、切り詰められたダウンロードや画像として保存されたエラーページを捕捉できます。バイトサイズを確認すれば、レスポンスが妥当かどうかもわかります。これでループが完成します:送信、ポーリング、ダウンロード、検証。
よくある障害のトラブルシューティング
ほとんどの初回統合は、いくつかの予測可能な方法で失敗します。次の順序で診断してください。
認証エラー(401/403)。キーの欠落、形式の誤り、または権限不足。環境変数がリクエストを実行するシェルまたはプロセスでエクスポートされていること、そして Authorization ヘッダーが API の期待する正確なプレフィックスを使用していることを確認してください。
参照画像が無効または過大(400/422)。画像 URL が API 側から到達不能かもしれない、ファイルが破損している、またはサイズやファイルサイズが制限を超えている可能性があります。まず小さく、動作確認済みの PNG でテストしてください。URL を渡す場合は公開アクセス可能であることを、インラインデータを渡す場合はエンコードが正しいことを確認してください。
ポーリングのタイムアウト。タスクがタイムアウトに達し続ける場合は、上限を増やすか間隔を延ばすか、タスクが実際には失敗しているのに理由を表示していないだけかどうかを確認してください。例外をスローする前に最後のタスクオブジェクトをログに記録して、状態を確認できるようにしてください。
レート制限(429)。即座に再試行するのではなく、ジッターを付けてバックオフしながら再試行してください。大量に並列送信する場合は、バーストトラフィックが制限をトリガーしないよう並行数を制限し、タスク id を記録して再試行を冪等にしてください。
どのエラーカテゴリでも、HTTP ステータス、切り詰めたレスポンスボディ、タスク id を記録してください——この 3 つがあれば通常、問題が認証、リクエストボディ、タイミングのどこにあるかを判断できます。まず curl の例で問題がコード側か入力側かを切り分け、その後修正を Python に移植してください。
関連記事
すべての記事を見る →-
チュートリアル
HiAPI API で hailuo-2.3-fast/image-to-video を呼び出す方法:curl と Python の実践
高速・低コストな画像から動画へのティアにおける最初の実行可能なリクエスト — モデル ID から MP4 のダウンロードまで
-
チュートリアル
HiAPI APIでhailuo-2.3/text-to-videoを呼び出す方法:curl、Python、実行可能なリクエスト例
-
チュートリアル
HiAPI で Kandinsky 6.0 Pro のテキストto動画を使用する:curl と Python チュートリアル
リクエスト優先の実践デモ:プロンプトから動画クリップへの呼び出しを構築し、リクエストを送信し、完了状態をポーリングし、結果をダウンロードする