- AI ⚙️
- Python
OpenAI API Python入門|Responses APIのコピペ集
Python から OpenAI のモデルを呼ぶには、pip install openai で SDK を入れ、client.responses.create() を使います。 返答の文字は response.output_text で取り出せます。Responses API は、OpenAI が新しいプロジェクトに勧めている API です(Chat Completions も引き続き使えます)。
from openai import OpenAI
client = OpenAI() # 環境変数 OPENAI_API_KEY を読む
response = client.responses.create(
model="gpt-6-luna",
input="Responses APIを一言で説明して",
)
print(response.output_text)
| やりたいこと | 書き方 | 見出し |
|---|---|---|
| 1回だけ聞く | responses.create(model=..., input="...") |
最小コード |
| 役割を決める | instructions="..." |
instructions と主な引数 |
| 会話を続ける | previous_response_id=response.id か、input に履歴を積む |
会話の続け方 |
| 少しずつ表示する | stream=True か responses.stream() |
ストリーミング |
| 決まった形の JSON | responses.parse(..., text_format=Pydanticのクラス) |
構造化出力 |
| 関数を呼ばせる | tools → function_call → function_call_output |
function calling |
| 画像を読ませる | {"type": "input_image", "image_url": ...} |
画像入力 |
確認環境:openai 3.29.0(pip の最新版)・pydantic 2.14.1・Python 3.11.15(Linux)。SDK が送る URL と JSON、受け取ったときの取り出し方、ストリームのイベント、例外の種類と再試行の回数は、base_url を手元の擬似エンドポイント(Responses API の応答の形を返す小さな HTTP サーバー)に向けて確かめました。再試行の既定値は SDK のソース(_constants.py・_base_client.py)で確かめました。モデル名・料金・仕様は OpenAI の公式ドキュメントに基づきます(確認日 2026年10月12日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「OpenAI API Python入門|Responses APIのコピペ集」
最初に用意するもの
| 用意するもの | 内容 |
|---|---|
| SDK | pip install openai。2026年10月12日時点の最新は 3.29.0 |
| API キー | ダッシュボードで作り、環境変数 OPENAI_API_KEY に入れる |
| クレジット | API は従量課金。ドキュメントのクイックスタートは、残高の追加(billing)を案内している |
| モデル名 | 下の表から選ぶ |
pip install openai
export OPENAI_API_KEY="sk-..." # Windows PowerShell は $env:OPENAI_API_KEY="sk-..."
API キーが見つからないと、OpenAI() を作った時点で止まります。手元では次の文でした。
openai.OpenAIError: Missing credentials. Please pass an `api_key`, `workload_identity`, `admin_api_key`, or set the `OPENAI_API_KEY` or `OPENAI_ADMIN_KEY` environment variable.
キーをコードに直書きしない方法は、関連記事「.envの使い方と注意点|APIキーを安全に管理する方法」で扱っています。
モデルと料金(2026年10月12日に公式ドキュメントで確認)
モデルのページでは、迷ったら gpt-6-astra、性能と費用の釣り合いなら gpt-6.1-sol、件数が多く費用を抑えたい処理なら gpt-6-luna を勧めています。料金は 100万トークンあたりの Standard の値(短いコンテキスト)です。
| モデル | 向いている用途(ドキュメントの説明) | 入力 | キャッシュ入力 | 出力 |
|---|---|---|---|---|
gpt-6-astra |
難しい推論・コーディング | $10.00 | $1.00 | $50.00 |
gpt-6.1-sol |
astra に近い性能を低い費用で | $2.00 | $0.10 | $10.00 |
gpt-6-luna |
決まった作業を大量に | $0.10 | $0.01 | $0.50 |
長いコンテキストのプロンプトは単価が上がります(例:gpt-6-luna は入力 $0.20・出力 $0.75)。料金ページには、モデルのトークンについての無料枠の記載はありませんでした。本文のコードは、安い gpt-6-luna で書いています。
最小コード
response.output_text は、output の中にある文字(output_text)を全部つなげた便利プロパティです。 文字が1つも無いときは空文字になります(SDK のソースで確認)。
from openai import OpenAI
client = OpenAI()
response = client.responses.create(model="gpt-6-luna", input="こんにちは")
print(response.output_text) # 返答の文字
print(response.id) # resp_... 会話を続けるときに使う
print(response.status) # completed / incomplete など
print(response.usage.input_tokens, response.usage.output_tokens)
print(response._request_id) # x-request-id(問い合わせ用)
擬似エンドポイントで受けたとき、SDK は次の URL と JSON を送っていました。
POST /v1/responses
{"model":"gpt-6-luna","input":"こんにちは"}
レスポンスの中身
| 属性 | 中身 |
|---|---|
output |
出力の項目のリスト。message・function_call・reasoning などが入る |
output[0].content[0].text |
message の中の文字(type は output_text) |
output_text |
上の文字を全部つなげたもの(SDK の便利プロパティ) |
usage |
input_tokens・output_tokens・total_tokens。input_tokens_details.cached_tokens も入る |
status |
completed・incomplete(上限で途中終了など)・failed など |
output[0] が文字とは限りません。推論するモデルは、先頭に reasoning の項目が入ることがあります。文字は output_text で取るのが確実です。
instructions と主な引数
instructions は Chat Completions の system メッセージにあたります。 input とは別の引数です。
response = client.responses.create(
model="gpt-6-luna",
instructions="あなたは社内ヘルプデスクです。100文字以内で答えます。",
input="VPNにつながりません",
max_output_tokens=300,
)
POST /v1/responses
{"model":"gpt-6-luna","input":"VPNにつながりません","instructions":"あなたは社内ヘルプデスクです。","max_output_tokens":300}
| 引数 | 意味 |
|---|---|
model |
モデル名 |
input |
文字列、または項目(メッセージ・関数の結果など)のリスト |
instructions |
役割や話し方の指示 |
max_output_tokens |
出力の上限(推論のトークンも含む) |
reasoning |
{"effort": "low"} など。SDK の型では none〜max の7段階 |
store |
返答を OpenAI 側に保存するか。既定は保存する(30日) |
previous_response_id |
前の返答の続きとして扱う |
tools・tool_choice |
関数や組み込みツール |
text |
出力の形({"format": {...}}) |
temperature・top_p |
ランダムさ |
instructions は previous_response_id で続けても引き継がれません。続きのリクエストにも毎回付けます。指示の書き方は、関連記事「システムプロンプトの書き方と例|エンジニア向けカスタム指示テンプレート」で扱っています。
会話の続け方:previous_response_id と履歴の積み上げ
会話を続ける方法は2つあります。 OpenAI 側に保存した前の返答を ID で指す方法と、自分で履歴を持って毎回送る方法です。
A. previous_response_id で続ける
first = client.responses.create(model="gpt-6-luna", input="私の名前は山田です。")
second = client.responses.create(
model="gpt-6-luna",
previous_response_id=first.id,
input="私の名前は?",
)
print(second.output_text)
送られるのは新しい質問と ID だけです。
{"model":"gpt-6-luna","input":"私の名前は?","previous_response_id":"resp_001"}
B. input に履歴を積み上げる
history = [{"role": "user", "content": "私の名前は山田です。"}]
r = client.responses.create(model="gpt-6-luna", input=history, store=False)
history += r.output # 返答の項目をそのまま足す
history.append({"role": "user", "content": "私の名前は?"})
r = client.responses.create(model="gpt-6-luna", input=history, store=False)
print(r.output_text)
2回目は、返答の項目(type: message)がそのまま入って送られていました。
{"model":"gpt-6-luna","input":[{"role":"user","content":"私の名前は山田です。"},{"id":"msg_001","content":[{"annotations":[],"text":"こんにちは。ご用件をどうぞ。","type":"output_text"}],"role":"assistant","status":"completed","type":"message"},{"role":"user","content":"私の名前は?"}],"store":false}
| 比べる点 | A. previous_response_id | B. 履歴を積み上げる |
|---|---|---|
| 送るデータ | 新しい質問と ID だけ | 毎回、全部の履歴 |
| 保存 | store が有効なことが前提(既定で30日保存) |
store=False にでき、OpenAI 側に残さない |
| 料金 | ドキュメントでは、前の入力も入力トークンとして課金される | 送った分が課金される |
| 履歴の編集 | できない(前の返答の続きになる) | 前のやり取りを消す・要約するなど自由 |
| 向く場面 | 手軽に続けたいとき | 保存したくないデータ、DB で履歴を持つ設計 |
A でも料金は安くなりません。 会話の状態のガイドには、previous_response_id を使っても前の入力が課金される旨が書かれています。長い会話は B で前半を削るほうが、トークンを抑えやすくなります。セッションや端末をまたいで会話を持ちたいときは、client.conversations.create() で作る Conversations API もあります(会話オブジェクトは 30日の保存期限の対象外とドキュメントにあります)。
トークンの数え方は、関連記事「トークンとは|生成AIの数え方・日本語の文字数目安と節約方法」で扱っています。
ストリーミング:イベントの種類
stream=True を付けると、返り値を for で回してイベントを順に受け取れます。 文字の断片は response.output_text.delta の delta に入ります。
stream = client.responses.create(model="gpt-6-luna", input="Responses APIを説明して", stream=True)
for event in stream:
if event.type == "response.output_text.delta":
print(event.delta, end="", flush=True)
elif event.type == "response.completed":
print()
print(event.response.usage)
擬似エンドポイントから文字を2つに分けて返したとき、SDK は次の順でイベントを返しました。
response.created
response.in_progress
response.output_item.added
response.content_part.added
response.output_text.delta Responses APIは
response.output_text.delta OpenAIの新しいAPIです。
response.output_text.done
response.content_part.done
response.output_item.done
response.completed
| イベント | 中身 |
|---|---|
response.created・response.in_progress |
始まり。response に途中の状態 |
response.output_item.added・.done |
出力の項目(message・function_call など)の始まりと終わり |
response.output_text.delta |
文字の断片(delta) |
response.output_text.done |
文字の全体(text) |
response.function_call_arguments.delta・.done |
関数の引数(JSON 文字列)の断片と全体 |
response.refusal.delta・.done |
安全上の理由で断った文 |
response.completed |
完了。response に usage を含む最終の状態 |
response.failed・response.incomplete・error |
失敗・途中終了・エラー |
SDK の型には、ほかに推論の要約(response.reasoning_summary_text.delta)や、web 検索・ファイル検索などのツールのイベントもあります。
最後の返答もまとめて欲しいとき:responses.stream()
with client.responses.stream(...) を使うと、イベントを回したあとに get_final_response() で組み立て済みの返答が取れます。
with client.responses.stream(model="gpt-6-luna", input="Responses APIを説明して") as stream:
for event in stream:
if event.type == "response.output_text.delta":
print(event.delta, end="", flush=True)
final = stream.get_final_response()
print()
print(final.output_text) # Responses APIはOpenAIの新しいAPIです。
関数の引数もストリームでは分かれて届きます。{"city": と "東京"} に分けて返したとき、response.function_call_arguments.done の arguments には {"city": "東京"} がつながって入っていました。
構造化出力:Pydantic のクラスで受け取る
responses.parse() に Pydantic のクラスを text_format で渡すと、output_parsed にそのクラスのオブジェクトが入ります。 JSON の文字列を自分で json.loads しなくて済みます。
from openai import OpenAI
from pydantic import BaseModel
class CalendarEvent(BaseModel):
name: str
date: str
participants: list[str]
client = OpenAI()
response = client.responses.parse(
model="gpt-6-luna",
input=[{"role": "user", "content": "金曜に佐藤さんと鈴木さんと定例会議"}],
text_format=CalendarEvent,
)
event = response.output_parsed
print(event.name, event.participants)
SDK はクラスを JSON Schema に変えて、text.format に入れて送っていました。strict: true と additionalProperties: false が自動で付きます。
"text":{"format":{"type":"json_schema","strict":true,"name":"CalendarEvent","schema":{"properties":{"name":{"title":"Name","type":"string"},"date":{"title":"Date","type":"string"},"participants":{"items":{"type":"string"},"title":"Participants","type":"array"}},"required":["name","date","participants"],"title":"CalendarEvent","type":"object","additionalProperties":false}}}
手元で分かったこと:
| 試したこと | 結果 |
|---|---|
省略できる項目(b: Optional[int] = None)を足す |
required に b も入り、型は anyOf: [integer, null] で送られた(省略できる項目は「null も可」で表す形になる) |
| 返ってきた JSON がクラスと合わない | pydantic_core.ValidationError(Field required)が parse() の中で出た |
| 断られた(refusal) | ドキュメントでは、安全上の拒否はプログラムで見分けられるとされる。output_parsed が無いときは refusal の項目を確かめる |
ドキュメントは、スキーマを強制しない「JSON mode」より、Structured Outputs を勧めています。辞書でスキーマを書くときは text={"format": {"type": "json_schema", "name": ..., "schema": ..., "strict": True}} を create() に渡します。方式ごとの違いは、関連記事「LLMの構造化出力とJSON|4方式の違いとPydantic検証の実行結果」で扱っています。Pydantic 自体は、関連記事「Pydantic v2の使い方|BaseModelとバリデーションをエラー例で解説」で扱っています。
function calling:ツールの往復
モデルは関数を実行しません。 function_call の項目で「この名前の関数を、この引数で呼びたい」と返すので、自分で実行し、結果を function_call_output として call_id つきで送り返します。
toolsに関数の名前・説明・引数の JSON Schema を書いてcreateresponse.outputの中のtype == "function_call"を探し、arguments(JSON 文字列)をjson.loadsして実行- 返答の項目と
function_call_outputをinputに足して、もう一度create
import json
from openai import OpenAI
client = OpenAI()
def get_weather(city: str) -> dict:
return {"city": city, "weather": "晴れ"} # 本当は天気APIを呼ぶ
FUNCS = {"get_weather": get_weather}
tools = [{
"type": "function",
"name": "get_weather",
"description": "都市名を受け取り、今日の天気を返す",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string", "description": "都市名"}},
"required": ["city"],
"additionalProperties": False,
},
"strict": True,
}]
input_items = [{"role": "user", "content": "東京の天気は?"}]
while True:
response = client.responses.create(model="gpt-6-luna", input=input_items, tools=tools)
calls = [item for item in response.output if item.type == "function_call"]
if not calls:
break
input_items += response.output # function_call の項目も履歴に入れる
for call in calls:
result = FUNCS[call.name](**json.loads(call.arguments))
input_items.append({
"type": "function_call_output",
"call_id": call.call_id,
"output": json.dumps(result, ensure_ascii=False),
})
print(response.output_text)
擬似エンドポイントで function_call を返したとき、取り出せた値と、2回目に送られた input です。
call: get_weather call_abc123 '{"city": "東京"}'
"input":[{"role":"user","content":"東京の天気は?"},
{"arguments":"{\"city\": \"東京\"}","call_id":"call_abc123","name":"get_weather","type":"function_call","id":"fc_001","status":"completed"},
{"type":"function_call_output","call_id":"call_abc123","output":"{\"city\": \"東京\", \"weather\": \"晴れ\"}"}]
| つまずきやすい点 | 内容 |
|---|---|
arguments は文字列 |
dict ではない。json.loads してから使う |
ID は call_id |
id(fc_...)ではなく call_id(call_...)を function_call_output に入れる |
| 1回に複数呼ぶことがある | ドキュメントでも、0個・1個・複数のどれもありうるとしている。リストで回す |
| ツールの書き方 | Chat Completions は {"type": "function", "function": {...}}。Responses は name などを直接並べる |
strict の既定 |
移行ガイドでは、Responses は strict を省くと strict を試みる(Chat Completions は既定で非 strict) |
仕組みの全体は、関連記事「Function Calling(tool use)の仕組みとPython実装」で扱っています。
画像入力
画像は input_image で渡します。 URL か、base64 の data URL(data:image/png;base64,...)か、Files API にあげたファイルの ID を使えます。
import base64
from pathlib import Path
b64 = base64.b64encode(Path("screen.png").read_bytes()).decode()
response = client.responses.create(
model="gpt-6-luna",
input=[{
"role": "user",
"content": [
{"type": "input_text", "text": "この画面のエラーの原因を推測して"},
{"type": "input_image", "image_url": f"data:image/png;base64,{b64}"},
# URL なら {"type": "input_image", "image_url": "https://example.com/a.png"}
],
}],
)
print(response.output_text)
SDK は data URL をそのまま JSON の文字列として送っていました(Bedrock の boto3 のようにバイト列を自動で base64 にする仕組みは無いため、自分で変換します)。
| 項目 | ドキュメントの値 |
|---|---|
| 形式 | PNG・JPEG・WEBP・アニメーションでない GIF |
detail |
low・high・original・auto(省略時は auto) |
| 1リクエストの上限 | 合計 512MB まで、画像 1,500 枚まで |
| ファイル ID | Files API に purpose="vision" であげたもの |
ドキュメントには「low が high より常にトークンが少ないとは限らない」との注意もあります。
Chat Completions との対応表
移行ガイドでは「Chat Completions は引き続きサポートされるが、新しいプロジェクトには Responses を勧める」とされています。
| 項目 | Chat Completions | Responses |
|---|---|---|
| 呼び出し | client.chat.completions.create() |
client.responses.create() |
| 送り先 | POST /v1/chat/completions |
POST /v1/responses |
| 入力 | messages=[...] |
input="..." または項目のリスト |
| システム指示 | {"role": "system", ...} |
instructions="..." |
| 文字の取り出し | choices[0].message.content |
output_text |
| 出力の上限 | max_completion_tokens |
max_output_tokens |
| 構造化出力 | response_format=... |
text={"format": ...}/parse(text_format=...) |
| 関数の定義 | {"type": "function", "function": {...}} |
{"type": "function", "name": ..., "parameters": ...} |
| 関数の結果 | {"role": "tool", "tool_call_id": ...} |
{"type": "function_call_output", "call_id": ...} |
| 会話の続き | 毎回 messages を全部送る |
previous_response_id か、履歴を積む |
複数候補 n |
使える | 無い(1つだけ返す。複数欲しいなら別に呼ぶ) |
| 保存 | 新しいアカウントは既定で保存 | 既定で保存(store=False で止める) |
手元では、同じクライアントで client.chat.completions.create(model=..., messages=[...]) が POST /v1/chat/completions に送られ、choices[0].message.content で文字が取れました。
エラーと再試行
よく出る例外
例外はすべて openai.APIError の子です。HTTP の応答があるものは APIStatusError の子で、status_code・code・request_id を持ちます。
| 例外 | HTTP | 主な原因 | 直し方 |
|---|---|---|---|
AuthenticationError |
401 | キーの打ち間違い・空白・削除済み・別のプロジェクトのキー | キーを確かめる。作り直して差し替える |
PermissionDeniedError |
403 | 対応していない国・地域から、権限の無いリソース | 利用できる地域・プロジェクトの権限を確かめる |
NotFoundError |
404 | 指定したリソースが無い(モデル名・ID の間違いなど) | 名前・ID を確かめる |
BadRequestError |
400 | 引数の形・値が違う | e.message と param を見る |
RateLimitError |
429 | 速すぎる・トークンが多すぎる。クレジット切れ・支出上限も 429 | 待って再試行。残高・上限の場合は再試行では戻らない |
InternalServerError |
500・503 | OpenAI 側のエラー、モデルの混雑 | 待って再試行 |
APIConnectionError |
なし | ネットワーク・プロキシ・SSL | 接続先とプロキシを確かめる(SDK は既定で再試行してから出す) |
APITimeoutError |
なし | 時間切れ | timeout を延ばす。ストリームにする |
エラーコードのページでは、429 にも種類があります。rate_limit_exceeded のほか、credit_balance_exhausted(前払いクレジットの使い切り)や支出上限のときは、再試行しても戻らないと書かれています。e.code で見分けます。
import openai
from openai import OpenAI
client = OpenAI()
try:
response = client.responses.create(model="gpt-6-luna", input="こんにちは")
except openai.AuthenticationError as e:
print("キーを確かめる:", e.status_code, e.code)
except openai.RateLimitError as e:
if e.code == "credit_balance_exhausted":
print("クレジットを追加する")
else:
print("混雑。あとで再試行:", e.request_id)
except openai.BadRequestError as e:
print("引数の誤り:", e.message)
except openai.APIConnectionError as e:
print("接続できない:", e)
擬似エンドポイントで返したときの例外です。
| 返したもの | 受け取った例外 | e.code |
|---|---|---|
401 invalid_api_key |
AuthenticationError |
invalid_api_key |
400 invalid_value |
BadRequestError |
invalid_value |
429 rate_limit_exceeded |
RateLimitError |
rate_limit_exceeded |
| 500 | InternalServerError |
None |
| 接続できないポート | APIConnectionError(Connection error.) |
なし |
再試行の既定値(SDK のソースで確認)
openai 3.29.0 は、既定で最大2回まで自動で再試行します。 _constants.py の値です。
| 項目 | 既定値 |
|---|---|
max_retries |
2 |
timeout |
600秒(接続は 5秒) |
| 待ち時間 | 0.5秒 × 2^回数、上限 8秒。0〜25% を引くジッターつき |
Retry-After ヘッダ |
120秒以下なら、その秒数だけ待つ。120秒を超えると再試行しない |
| 再試行する応答 | 408・409・429・500以上、と接続エラー・タイムアウト |
| サーバーの指示 | x-should-retry: true/false があればそれに従う |
擬似エンドポイントで同じエラーを返し続けたときの結果です。
| 条件 | 届いたリクエスト | かかった時間 |
|---|---|---|
| 429(既定) | 3回 | 1.45秒 |
429・Retry-After: 1 |
3回 | 2.01秒(1秒ずつ待った) |
429・x-should-retry: false |
1回 | 0.00秒 |
| 500(既定) | 3回 | 1.46秒 |
| 401・400 | 1回 | 再試行しない |
429・max_retries=0 |
1回 | 0.00秒 |
429・max_retries=5 |
6回 | 13.29秒 |
再試行のたびに、リクエストヘッダ x-stainless-retry-count が 0・1・2 と増えていました。回数と時間は、クライアントごとか1回ごとに変えられます。
client = OpenAI(max_retries=5, timeout=60.0)
# この1回だけ変える
response = client.with_options(max_retries=0, timeout=20).responses.create(
model="gpt-6-luna", input="こんにちは",
)
429 の考え方と自前の再試行は、関連記事「LLM APIの429・529エラー対処|リトライ実装とエラー一覧」で扱っています。待ち時間の決め方は、関連記事「指数バックオフとは?リトライ間隔の決め方とジッターの実装」で扱っています。
Claude API・Bedrock Converse との書き方の対応表
同じことを、OpenAI の Responses API、Anthropic SDK の Claude API、Amazon Bedrock の Converse API で書くときの対応です。
| 項目 | OpenAI Responses | Claude API(anthropic) | Bedrock Converse(boto3) |
|---|---|---|---|
| 呼び出し | responses.create() |
messages.create() |
converse() |
| 入力 | input= 文字列か項目 |
messages=[...] |
messages=[{"content": [{"text": ...}]}] |
| システム指示 | instructions= |
system= |
system=[{"text": ...}] |
| 出力の上限 | max_output_tokens(省略可) |
max_tokens(必須) |
inferenceConfig={"maxTokens": ...} |
| 文字の取り出し | output_text |
content の text ブロック |
output.message.content の text |
| 会話の続き | previous_response_id か履歴 |
毎回 messages を全部 |
毎回 messages を全部 |
| 関数の定義 | parameters |
input_schema |
toolSpec.inputSchema.json |
| 関数の呼び出し | function_call(引数は文字列) |
tool_use(input は dict) |
toolUse(input は dict) |
| 結果の返し方 | function_call_output |
user の tool_result |
user の toolResult |
| 止まった理由 | status・incomplete_details |
stop_reason |
stopReason |
| 既定の再試行 | 2回 | 2回 | 4回(legacy モード) |
Anthropic SDK 1.13.0 の messages.create は max_tokens が必須の引数で、DEFAULT_MAX_RETRIES は 2 でした。Bedrock の回数は、関連記事「Bedrock Python入門|Converse APIでClaudeを呼ぶ」で確かめた値です。Claude API の書き方は、関連記事「Claude API Python入門|Anthropic SDKコピペレシピ集」で扱っています。Google の Gemini は、関連記事「Gemini API Python入門|google-genaiのコピペ集」で扱っています。手元の PC で動かすローカル LLM は、関連記事「Ollamaの使い方|ローカルLLMのコマンド一覧とAPIの呼び方」で扱っています。
よくある質問
Q. 非同期(async)で呼べますか。
A. from openai import AsyncOpenAI で作ったクライアントで、await client.responses.create(...) と書けます。引数は同じです。
Q. base_url は何に使いますか。
A. 送り先を変える引数です。OpenAI 互換の API を持つサーバー(例:Ollama の /v1)や、社内のプロキシに向けるときに使います。環境変数 OPENAI_BASE_URL でも指定できます。
Q. 返答が途中で切れます。
A. status が incomplete なら、incomplete_details に理由が入ります。max_output_tokens が小さいと起きます。推論するモデルは、推論のトークンも上限に含まれます。
Q. 料金を抑えるには?
A. 安いモデル(gpt-6-luna)を選ぶ、履歴を短くする、同じ前置きを繰り返してキャッシュ入力の単価を使う、などの方法があります。考え方は関連記事「LLM APIのコスト削減方法|キャッシュとバッチの仕組みと計算例」で扱っています。
Q. 保存されたくないデータを送るときは?
A. store=False を付けると、返答は OpenAI 側に保存されません。そのかわり previous_response_id で続けられないので、履歴を自分で積み上げます。
まとめ
pip install openai→client.responses.create(model=..., input=...)→response.output_text- システム指示は
instructions。続きのリクエストにも毎回付ける - 会話は
previous_response_id(手軽)か 履歴の積み上げ(store=Falseにできる)。どちらも前の入力は課金される - ストリームは
stream=Trueでresponse.output_text.deltaを拾う。最後の返答も欲しいならresponses.stream() - 構造化出力は
responses.parse(text_format=Pydanticのクラス)→output_parsed - 関数は
function_callのargumentsをjson.loadsし、call_idつきのfunction_call_outputで返す - 再試行は既定で 2回(429・408・409・5xx・接続エラー)。クレジット切れの 429 は再試行では戻らない
参考・出典
確認日はいずれも 2026年10月12日です。
- OpenAI API ドキュメント「Developer quickstart」:https://developers.openai.com/api/docs/quickstart
- OpenAI API ドキュメント「Models」:https://developers.openai.com/api/docs/models
- OpenAI API ドキュメント「Pricing」:https://developers.openai.com/api/docs/pricing
- OpenAI API ドキュメント「Conversation state」:https://developers.openai.com/api/docs/guides/conversation-state
- OpenAI API ドキュメント「Streaming API responses」:https://developers.openai.com/api/docs/guides/streaming-responses
- OpenAI API ドキュメント「Structured model outputs」:https://developers.openai.com/api/docs/guides/structured-outputs
- OpenAI API ドキュメント「Function calling」:https://developers.openai.com/api/docs/guides/function-calling
- OpenAI API ドキュメント「Images and vision」:https://developers.openai.com/api/docs/guides/images-vision
- OpenAI API ドキュメント「Migrate to the Responses API」:https://developers.openai.com/api/docs/guides/migrate-to-responses
- OpenAI API ドキュメント「Error codes」:https://developers.openai.com/api/docs/guides/error-codes
- PyPI「openai」:https://pypi.org/project/openai/
- GitHub「openai/openai-python」:https://github.com/openai/openai-python
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「OpenAI API Python入門|Responses APIのコピペ集」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。