OpenAI互換APIには現在、主に2つのリクエスト形式があります。従来からある /v1/chat/completions と、新しい /v1/responses です。GetVibe APIでは、1つのキーと1つのベースURL https://getvibeapi.com/v1 で両方を利用できます。ここでは、実際の違い、どちらを選ぶべきか、そして移行時に注意すべき1つの落とし穴について説明します。
簡単にまとめると
| Chat Completions | Responses | |
|---|---|---|
| エンドポイント | POST /v1/chat/completions | POST /v1/responses |
| 入力 | messages 配列 | input:文字列またはアイテムの配列 |
| システムプロンプト | system ロールのメッセージ | instructions フィールド |
| 回答 | choices[0].message | output 配列:推論、メッセージ、関数呼び出し |
| 出力上限 | max_tokens | max_output_tokens |
| 利用者 | ほとんどのSDK、フレームワーク、チャットアプリ | Codex CLIと新しいエージェントSDK |
形式によってモデル、価格、トークン数が変わることはありません。どちらを使っても、モデルの入力トークンと出力トークンに対して課金されます。
両方の形式で同じリクエストを送る
Chat Completions:
curl https://getvibeapi.com/v1/chat/completions \
-H "Authorization: Bearer $GETVIBE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-6-luna",
"messages": [
{"role": "system", "content": "1文で回答してください。"},
{"role": "user", "content": "HTTP 429は何を意味しますか?"}
],
"max_tokens": 300
}'
Responses:
curl https://getvibeapi.com/v1/responses \
-H "Authorization: Bearer $GETVIBE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-6-luna",
"instructions": "1文で回答してください。",
"input": "HTTP 429は何を意味しますか?",
"max_output_tokens": 300
}'
Chat Completionsでは、テキストは choices[0].message.content に格納されます。Responsesでは output の中にあり、推論モデルの場合、最初のアイテムは reasoning アイテムで、回答はタイプが message のアイテムです。配列を自分でたどる必要はありません。Python SDKには output_text プロパティがあります。
import os
from openai import OpenAI
client = OpenAI(base_url="https://getvibeapi.com/v1", api_key=os.environ["GETVIBE_API_KEY"])
chat = client.chat.completions.create(
model="gpt-6-luna",
messages=[{"role": "system", "content": "1文で回答してください。"},
{"role": "user", "content": "HTTP 429は何を意味しますか?"}],
)
print(chat.choices[0].message.content)
resp = client.responses.create(
model="gpt-6-luna",
instructions="1文で回答してください。",
input="HTTP 429は何を意味しますか?",
)
print(resp.output_text)
ResponsesはOpenAIモデルに限定されません。公開前に、同じResponsesリクエストを gpt-6-luna、claude-sonnet-5.5、deepseek-v4.1-flash に送信したところ、3つとも回答しました。DeepSeekは、上記の説明どおり、message の前に reasoning アイテムを返しました。
会話履歴:自分で送信する
切り替える前に知っておくべきことはこれだけです。OpenAI独自のResponses APIでは、サーバー上で会話を保持できるため、次のリクエストで previous_response_id を使って前のレスポンスを指定できます。GetVibe APIは会話を保存しないため、previous_response_id はサポートされず、store は無視されます。実際に試したところ、リクエストは400エラーで拒否されました。
動作するパターンはChat Completionsの場合と同じです。履歴全体を input に含めて送信します。
history = [{"role": "user", "content": "私の名前はAnaです。覚えておいてください。"}]
first = client.responses.create(model="gpt-6-luna", input=history)
history.append({"role": "assistant", "content": first.output_text})
history.append({"role": "user", "content": "私の名前は何ですか?1語で答えてください。"})
second = client.responses.create(model="gpt-6-luna", input=history)
print(second.output_text) # Ana
ツール:異なる形式
Function callingは両方の形式で利用できますが、ツール定義の形が異なります。Chat Completionsでは関数のフィールドが function オブジェクトの中にネストされます。一方、Responsesではツール上に直接配置されます。呼び出しは個別の function_call アイテムとして届き、同じ call_id を持つ function_call_output アイテムとして結果を返します。
import json
tools = [{
"type": "function",
"name": "get_weather",
"description": "都市の現在の天気",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
"additionalProperties": False,
},
}]
items = [{"role": "user", "content": "デンバーの天気はどうですか?"}]
resp = client.responses.create(model="gpt-6-luna", input=items, tools=tools)
for item in resp.output:
if item.type == "function_call":
result = {"city": "Denver", "temp_f": 54, "sky": "overcast"} # あなたの関数
items.append({"type": "function_call", "call_id": item.call_id,
"name": item.name, "arguments": item.arguments})
items.append({"type": "function_call_output", "call_id": item.call_id,
"output": json.dumps(result)})
final = client.responses.create(model="gpt-6-luna", input=items, tools=tools)
print(final.output_text)
今回の実行では、モデルは get_weather を {"city":"Denver"} とともに呼び出し、2回目のリクエストでは、デンバーは54°Fで曇りだと回答しました。同じループのChat Completions版については、function callingガイドをご覧ください。
ストリーミング
どちらの形式も "stream": true をサポートしていますが、イベントは異なります。Chat Completionsは均一な data: 行を送り、新しいテキストの各部分は choices[0].delta.content に含まれます。Responsesは名前付きイベントを送信します。最初に response.created、テキストの各部分とともに response.output_text.delta、最後に response.completed が送られます。SDKを使わずに自分でストリームを解析する場合は、形式ごとのパーサーが必要です。
どちらを選ぶべきか
- Chat Completions:すでにこれを使ったコードがある場合、またはフレームワーク、チャットアプリ、ノーコードプラットフォームを使っている場合に適しています。ほぼすべてのツールが対応しているため、動作しているコードを形式変更のためだけに書き換える理由はありません。
- Responses:ツールがResponsesを要求する場合に適しています。主な例はCodex CLIで、
/v1/responsesと通信します。セットアップ方法は Codex CLIのドキュメント と Codex CLIガイドで説明しています。
どちらを使っても、モデル一覧と価格は同じです。すべてのフィールドについては APIリファレンスを、最新の価格については モデルページをご覧ください。
