使用ガイド
hiapi API で DeepSeek V4.1 Flash を使ってEC商品画像を処理する
画像は生成しません——しかし商品リスティングを取り巻くその他のあらゆるテキストを執筆します。
DeepSeek V4.1 Flash は商品画像を生成しません——EC技術スタックで本当に得意なことを以下で説明します
「商品画像」という言葉につられてここに来たなら、DeepSeek V4.1 Flash はそれを生成できません——完全なテキスト専用モデルであり、画像・音声・動画の出力は一切ありません。しかしECカタログが依存するテキストは画像よりもはるかに多く存在します。各リスティングには説明文が必要で、各画像には代替テキストが必要で、各顧客の質問には回答が必要で、各広告チャネルには同じセールスポイントの異なるバージョンが必要です。まさにこのモデルが得意とする領域であり、しかもこのタスクにおいて異常に安価で柔軟です——/v1/chat/completions と /v1/responses の両方をサポートしているため、単一のリクエスト形式を中心に統合を再構築する必要はありません。本ガイドでは、商品画像ワークフローにおけるテキスト部分を扱います。構造化出力によるバッチ説明文生成、カスタマーサポートQ&A、そしてマルチチャネル向けコピーバリエーション——hiapi API に基づく実際のリクエスト例付きです。画像そのものが必要な場合は、GPT Image 2 のような画像モデルと組み合わせ、画像を取り巻くすべてのテキストを DeepSeek V4.1 Flash に処理させてください。
デュアルAPIインターフェースが重要な理由
hiapi 上の推論級モデルのほとんどは、Chat Completions か Responses のどちらか一方のパスだけを選び、それを使い続けます。DeepSeek V4.1 Flash は POST /v1/chat/completions と POST /v1/responses をネイティブにサポートしており、つまりこのモデルのために新しいクライアントを構築するのではなく、既存の統合にそのまま組み込めます。以下の点は両方のエンドポイントに当てはまります:
reasoning_effortには実質5つのレベルがあります。 料金ページの文言にはnone、high、maxしか記載されていませんが、モデルは実際のリクエストでlowとmediumも受け付けます——5つすべてが有効です。リスティングコピーのような短く決定的なタスクにはnoneまたはlowで十分です。high/maxは、ポリシーに敏感なカスタマーサポート対応など判断を要するシナリオに取っておきましょう。- 構造化出力はエンドポイントによって動作が異なります。 このモデルでは、
/v1/chat/completions上でresponse_format: {"type": "json_schema", ...}を使ってもスキーマ検証済みの結果は返されません——代わりにresponse_format: {"type": "json_object"}を使い、プロンプト内で構造を記述してください。スキーマ検証を強制したい場合は、同じリクエストを/v1/responsesに送信し、text.format.type=json_schemaを設定すれば、それが尊重されます。 - 関数呼び出しとストリーミングは期待どおりに動作します——
/v1/chat/completions上で、tools、tool_choice、stream: trueは hiapi 上の他の OpenAI 互換チャットモデルと同じように動作するため、既存のツール呼び出しコードを調整する必要はありません。
ベースURLは https://api.hiapi.ai/v1 で、他の hiapi モデルと同じキーを使います。両エンドポイントの完全なリクエスト/レスポンス形式はモデルページをご覧ください。
ユースケース1: 構造化出力による商品説明文のバッチ生成
最も直接的な用途は、仕様表を大規模にブランドトーンに合ったリスティングコピーへ変換し、CMSが後処理なしで直接インポートできる形式で出力することです。Chat Completions では、json_object モードとプロンプト内の明確なスキーマを組み合わせることで、これを確実に実現できます:
import json
import requests
resp = requests.post(
"https://api.hiapi.ai/v1/chat/completions",
headers={
"Authorization": f"Bearer {HIAPI_KEY}",
"Content-Type": "application/json",
},
json={
"model": "deepseek-v4.1-flash",
"reasoning_effort": "none",
"response_format": {"type": "json_object"},
"messages": [
{
"role": "system",
"content": (
"You write concise, factual e-commerce listing copy. "
"Never invent specs that aren't in the input. "
"Respond with JSON matching this shape: "
'{"title": str, "short_description": str, '
'"long_description": str, "bullet_points": [str]}'
),
},
{
"role": "user",
"content": (
"Product: ceramic pour-over coffee dripper, 400ml, "
"matte white, dishwasher safe, fits standard filters. "
"Write listing copy for this product."
),
},
],
},
)
listing = json.loads(resp.json()["choices"][0]["message"]["content"])
これを商品データベース内の各SKUに対して実行すれば、チャットウィンドウから手動でテキストを編集することなく、一貫したコピーが得られます。レスポンスが形式エラーの際にモデルのプロンプト遵守に頼るのではなく明示的にエラーを返してほしい場合は、同等のリクエストを /v1/responses に送信し、text.format.type=json_schema を設定してください——このパスは返却前に出力をスキーマに対して検証します。
ユースケース2: 自社ドキュメントに基づくカスタマーサポートQ&A
サポートアシスタントの場合、両エンドポイントとも進行中の会話を再送信する必要があります——どちらもデフォルトでは呼び出し間で状態を保持しないため、会話履歴はベンダーではなくあなたのアプリケーションが管理します。これは、ベンダーのセッションストレージを信頼するのではなく、自社データベースから会話をマスキングしたり、分岐させたり、復元したりする必要がある場合に有用です。
history = [
{"role": "system", "content": "Answer only from the provided product FAQ context. "
"If the answer isn't in context, say so and offer to escalate."},
]
def ask(user_message: str, faq_context: str) -> str:
history.append({"role": "user", "content": f"Context:\n{faq_context}\n\nQuestion: {user_message}"})
resp = requests.post(
"https://api.hiapi.ai/v1/chat/completions",
headers={"Authorization": f"Bearer {HIAPI_KEY}", "Content-Type": "application/json"},
json={
"model": "deepseek-v4.1-flash",
"reasoning_effort": "low",
"messages": history,
},
)
answer = resp.json()["choices"][0]["message"]["content"]
history.append({"role": "assistant", "content": answer})
return answer
注文状況の確認や返品のトリガーなど、何らかのアクションが必要な場合は、tools 内で関数として宣言してください——モデルは tool_calls エントリを返し、あなたのバックエンドがそれを実行し、結果を含む role: "tool" メッセージを追加して再度呼び出します。これによりモデルが注文データベースに直接触れることは一切なく、動作は hiapi 上の他の OpenAI 互換チャットモデルと同じです。
ユースケース3: チャネル別のマーケティングコピーバリエーション
同じ商品事実でも、商品ページ、メール件名、30文字の広告見出しでは異なる言い回しが必要です。/v1/chat/completions 上で stream: true を使えば、1回のリクエストで複数のチャネルバリエーションを生成し、完全なレスポンスを待つのではなく到着次第レンダリングできます——これが社内ツールのライブプレビューに流れ込む場合に有用です。ここでも reasoning_effort は none または low に保ってください。短いコピーのトーンを合わせるのに重い推論は不要であり、マーケターがリアルタイムで反復する際の低レイテンシを維持できます。
料金はいくらか
DeepSeek V4.1 Flash はトークン単位の均一課金で、事前に計画すべき段階的な崖はありません:
| 入力 | 出力 | キャッシュ入力 |
|---|---|---|
| $0.44 / 1M tokens | $1.32 / 1M tokens | $0.014 / 1M tokens |
上記のユースケース——単一の商品説明文、1ターンのサポート会話、1バッチのチャネルバリエーション——では、呼び出しごとのコストは数セントの端数にすぎません。キャッシュ入力料金は意識的に使う価値があります。システムプロンプトが長く、数千回のSKU呼び出しで繰り返される場合、リクエスト間でバイト単位で同一に保つことで初めてキャッシュ料金の対象になります。料金は使用量に基づき変更される可能性があります——大規模バッチ処理を約束する前に hiapi.ai/pricing をご確認ください。
これは技術スタックの残りの部分とどう関係するか
これらのいずれも実際の画像モデルの代わりにはなりません——DeepSeek V4.1 Flash には /v1/tasks へのアクセス権がなく、視覚的出力を生成することもできません。ワークフローでこれらのコピーに付随する商品写真やライフスタイル写真が必要な場合、それは GPT Image 2 などの画像モデルへの別途呼び出しであり、両者はリクエスト形式もエンドポイントも共有しません。GPT-6 Astra ECガイドをすでに読んでいるなら、この問題の形はまったく同じです——違いは、DeepSeek V4.1 Flash が階層的なコスト曲線ではなく、エンドポイントの選択肢とフラットなコスト曲線を提供する点です。
FAQ
DeepSeek V4.1 Flash は商品画像を生成できますか?
いいえ。テキスト専用モデルであり、画像・音声・動画の出力はなく、/v1/chat/completions または /v1/responses 経由でアクセスします。商品リスティングの視覚部分を処理するには、画像モデルと組み合わせてください。
このモデルには Chat Completions と Responses のどちらを使うべきですか?
どちらでも構いません——既存の統合に合う方を選んでください。唯一違いが出るのは構造化出力を強制する場合です:json_schema 検証は /v1/responses では有効ですが /v1/chat/completions では無効であり、後者では代わりに json_object モードを使ってください。
reasoning_effort は何をし、どのレベルを使うべきですか?
モデルが回答前にどれだけ内部推論を行うかを制御し、レイテンシとコストを判断品質と引き換えにします。5つのレベル(none、low、medium、high、max)はすべて実際のリクエストで有効ですが、料金ページには3つしか記載されていません。説明文生成のような短く決定的なタスクには none または low を使い、判断を伴うサポート返信には high または max を取っておいてください。
ストリーミングはツール呼び出しと同時に使えますか?
はい——stream: true と tools は /v1/chat/completions 上でそれぞれ独立して動作し、同じリクエスト内で組み合わせることもできます。hiapi 上の他の OpenAI 互換チャットモデルと同じです。
サポート会話の各ターンで完全な会話を再送信する必要がありますか? はい、両エンドポイントで必要です。どちらもデフォルトでは呼び出し間で会話状態を保持しないため、アプリケーションは毎回必要な履歴を再送信する必要があります。これにより再送信する入力トークンのコストは増えますが、含めるコンテキストを制御でき、自社データベースから会話をマスキングしたり分岐させたりできるという利点があります。
キャッシュ入力料金は自動ですか?
リクエストの先頭部分(通常はシステムプロンプト)が呼び出し間でバイト単位で同一である場合にのみ自動適用されます。割引が適用されたと仮定するのではなく、レスポンスの usage オブジェクト内の cached_tokens を確認してください。