Python

PythonでChatGPT APIを連携する方法|インストールから基本・エラー処理・ストリーミングまで

PythonからChatGPTを使うとは、実際にはOpenAIが公式提供するライブラリ(PyPI上のパッケージ名はopenai)でOpenAI APIを呼び出すことを指します。ここでつまずきやすいのが情報の鮮度です。2023年11月のライブラリv1.0で書き方が刷新され、ネットに残るopenai.ChatCompletion.create()のような古いサンプルはそのままでは動きません。この記事は、現行版で確実に動く最小コードを軸に、導入・APIキー設定・基本リクエスト・エラー処理・ストリーミング、そして業務システムへ組み込むときの判断までを一気通貫で解説します。

まとめ:PythonでChatGPT APIを連携する要点

  • 導入はpip install openaiの1コマンド。2026年時点の最新はv2系(執筆時点2.46.0/正確なバージョンは公式PyPIで確認)。
  • APIキーは環境変数OPENAI_API_KEYに置き、コードへ直書きしない。client = OpenAI()が既定で読み込む。
  • 基本の呼び出しはclient.chat.completions.create()。新規開発ではより新しいclient.responses.create()も選べる。
  • 本番では例外を型(RateLimitErrorAPIConnectionErrorなど)で捕まえる。接続エラーや429は既定で2回まで自動リトライされる。
  • 逐次表示はstream=Trueで実装する。応答をためずに1トークンずつ返せる。
  • 古いサンプルでopenai.ChatCompletion.create()AttributeErrorになるのはv0記法のため。現行クライアント方式に置き換える。

以下、準備から順に実コードで進めます。ライブラリのバージョン体系や旧v0.xからの移行、画像・埋め込み・音声まで含めた網羅はOpenAI Python SDKの使い方(インストールから最新クライアント・Responses APIまで)で詳しく扱っています。

準備:openaiライブラリの導入とAPIキー設定

連携の土台はライブラリの導入とAPIキーの2つです。ここを環境変数で正しく組んでおくと、以降のコードは引数なしで動きます。

pip install openai とバージョン確認

公式パッケージ名はopenaiです。新規導入と、古い版が入った環境の更新は次のとおりです。

# 新規インストール(最新版)
pip install openai

# すでに入っている場合は最新へ更新(旧v0.x環境の移行で必須)
pip install --upgrade openai

# 入っているバージョンを確認
python -c "import openai; print(openai.__version__)"

バージョンを確認する理由は明確で、古いサンプルが動かない原因のほとんどが版のズレだからです。2から始まる番号が表示されれば現行のクライアント方式で動きます。0.xが表示されたら旧記法の環境なので、更新したうえでコードも現行方式へ直します。再現性が要る本番ではpip install openai==2.46.0のように固定し、requirements.txtへ記載します。

APIキーを環境変数 OPENAI_API_KEY に設定する

APIキーはOpenAIのダッシュボード(API keys画面)で発行します。SDKは既定で環境変数OPENAI_API_KEYを読み込むため、キーはコードに書かず環境変数へ置くのが基本です。

# macOS / Linux
export OPENAI_API_KEY="sk-あなたのAPIキー"

# Windows (PowerShell)
setx OPENAI_API_KEY "sk-あなたのAPIキー"

キーはアカウント単位で課金に直結します。GitHubへ誤って公開すると不正利用と請求につながるため、.envファイルに書く運用なら必ず.gitignoreへ加えてください。料金体系や無料で試せる範囲など「そもそもChatGPT APIとは何か」を先に押さえたい場合はChatGPT APIとは(できること・料金の仕組み・使い方と企業導入の判断基準)が入口になります。

基本のリクエスト:クライアント初期化と応答取得

準備ができたら、クライアントを作って最初の応答を取ります。ここが連携コードの中心で、以降のエラー処理もストリーミングもこの形の拡張です。

client = OpenAI() でクライアントを作る

すべての呼び出しはOpenAIクラスのインスタンスから始まります。環境変数にキーがあれば引数は不要です。

from openai import OpenAI

# OPENAI_API_KEY を環境変数から自動読み込み
client = OpenAI()

# 環境変数を使わず明示的に渡す場合
# import os
# client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])

1つのクライアントから、対話生成・画像・埋め込み・音声を同じ作法で呼び分けます。まずは対話生成(Chat Completions)を通します。

Chat Completions で応答を得る

messagesに会話の役割(systemuserassistant)ごとの発話を並べて渡します。応答本文はchoices[0].message.contentに入ります。

completion = client.chat.completions.create(
    model="gpt-5.6",  # モデル名は更新が速い。最新は公式のモデル一覧で確認
    messages=[
        {"role": "system", "content": "あなたは簡潔に答える技術アシスタントです。"},
        {"role": "user", "content": "Pythonのリスト内包表記を1文で説明して"},
    ],
)

print(completion.choices[0].message.content)

モデル名を差し替えるだけで別モデルへ切り替えられる構造です。コストを抑えたいバッチ処理には小型モデル(GPT-5.4 miniやnanoなど)、品質を優先する用途にはフラッグシップ、と用途で選び分けます。モデルごとの料金・性能差はGPT-5.4 mini・nanoの料金とmini/nanoの使い分けで比較しています。

Responses API での書き方

新規開発では、より新しい入口であるResponses APIも選べます。messages配列の代わりにinputへ直接プロンプトを渡し、生成テキストはoutput_textで受け取れます。

response = client.responses.create(
    model="gpt-5.6",
    input="Pythonでフィボナッチ数列を返す関数を書いて",
)

print(response.output_text)

どちらを使うべきかは既存資産で決めます。すでにChat Completionsで書かれたコードや、messagesの役割設計を細かく制御したい既存システムはChat Completionsのまま維持し、これから作る連携はResponses APIを起点にすると、後発の機能を取り込みやすくなります。両方が並行して使える点は変わりません。

エラー処理とリトライ設計

APIは必ず失敗しうる外部依存です。デモでは省けても、業務連携では例外処理を入れないと一時的なレート制限やネットワーク断でプロセスごと落ちます。

例外クラスを型で捕まえる

ライブラリは失敗の種類ごとに例外クラスを用意しています。まとめてexcept Exceptionで握りつぶさず、対処が変わる型ごとに分けて捕まえるのが要点です。

from openai import (
    OpenAI,
    RateLimitError,
    APIConnectionError,
    APIStatusError,
    AuthenticationError,
    BadRequestError,
)

client = OpenAI()

try:
    completion = client.chat.completions.create(
        model="gpt-5.6",
        messages=[{"role": "user", "content": "こんにちは"}],
    )
    print(completion.choices[0].message.content)
except AuthenticationError:
    print("APIキーが不正。OPENAI_API_KEY を確認する")
except BadRequestError as e:
    print("リクエスト内容が不正(モデル名・パラメータ):", e)
except RateLimitError:
    print("レート制限(429)。時間を置いて再試行する")
except APIConnectionError:
    print("接続失敗(ネットワーク/プロキシ/SSL)")
except APIStatusError as e:
    print("APIがエラー応答:", e.status_code)

切り分けの指針はシンプルです。AuthenticationErrorBadRequestErrorはコード側の誤りなので再試行しても直りません。逆にRateLimitErrorAPIConnectionError、サーバ側の500系は時間を置けば回復するため再試行が有効です。この「再試行して意味があるか」で分岐を設計します。

自動リトライとタイムアウトの設定

再試行は自前で書く前に、まずライブラリの標準機能を使います。接続エラー・408・409・429・500以上のステータスは既定で2回まで、指数バックオフ付きで自動リトライされます。回数やタイムアウトはクライアント生成時に変更できます。

# 全体の既定を変更(リトライ最大5回・タイムアウト30秒)
client = OpenAI(max_retries=5, timeout=30.0)

# 特定の呼び出しだけ設定を上書き(この1回はリトライしない)
client.with_options(max_retries=0).chat.completions.create(
    model="gpt-5.6",
    messages=[{"role": "user", "content": "至急の1回きりの処理"}],
)

注意したいのは、自動リトライがあるからといって上限を無闇に上げないことです。リトライは待ち時間とトークン消費を増やすため、応答時間が重要な同期処理ではtimeoutを短めにして早く諦めさせ、バッチ処理ではリトライ回数を厚くする、と処理の性格で振り分けます。

ストリーミングで応答を逐次表示する

長い回答を全文生成し終えるまで待つとUXが悪化します。stream=Trueを付けると、生成の途中経過をトークン単位で受け取れます。チャットUIや対話ツールでは実質必須の書き方です。

Chat Completions のストリーミング

戻り値がイテレータになり、断片(チャンク)を順に受け取ります。本文の差分はchoices[0].delta.contentに入り、末尾など内容が無いチャンクではNoneになるため空判定を挟みます。

stream = client.chat.completions.create(
    model="gpt-5.6",
    messages=[{"role": "user", "content": "宇宙について200字で説明して"}],
    stream=True,
)

for chunk in stream:
    delta = chunk.choices[0].delta.content
    if delta:
        print(delta, end="", flush=True)

Responses API のストリーミング

Responses APIでもstream=Trueで逐次受信できます。こちらはイベント列が流れてくるため、本文増分を表すresponse.output_text.deltaイベントだけを拾います。

stream = client.responses.create(
    model="gpt-5.6",
    input="宇宙について200字で説明して",
    stream=True,
)

for event in stream:
    if event.type == "response.output_text.delta":
        print(event.delta, end="", flush=True)

ストリーミングでも例外は発生します。とくに接続断(APIConnectionError)は受信ループの途中で起きうるため、forループ全体をtryで囲み、途中まで受け取った文字列を保持して再開・再試行できるようにしておくと堅牢です。

業務システムにChatGPTを連携するときの実装判断

単発スクリプトが動くことと、業務システムへ組み込めることは別物です。ここは公式サンプルが踏み込まない領域なので、連携を設計するときに実際に迷う3点へ立場を明確にして踏み込みます。

モデルとコストを運用前提で選ぶ

結論から言えば、最初から最上位モデルを本番の全処理へ当てるのは避けるべきです。APIは入力・出力トークンで従量課金されるため、大量件数をさばくバッチや分類・要約の下処理は小型モデルで十分な精度が出ることが多く、コストが桁で変わります。品質が要る最終出力だけ上位モデルに回す二段構えにすると、費用対効果が安定します。モデル名は更新が速いので、コードにハードコードせず設定値(環境変数や設定ファイル)で外出しし、差し替え可能にしておくのが実務の勘所です。

レート制限と並行処理の設計

連携で最初に当たる壁がレート制限です。件数をさばこうとしてリクエストを一気に並列投入すると、RateLimitErrorが多発してかえって遅くなります。並行数は上限を決めて絞り、429が返ったら待ってから再投入する、という制御を入れるのが定石です。ライブラリの自動リトライは単発の一時失敗には効きますが、恒常的に上限へ張り付く負荷は設計側で平準化する必要があります。大量処理では、非同期版のAsyncOpenAIクライアントで同時実行数を制御しつつ流量を管理すると破綻しにくくなります。

APIキー管理と本番の落とし穴

キーをコードやリポジトリに残さないのは最低条件で、本番では環境変数やシークレットマネージャ経由で注入します。加えて用途ごとにキーを分け、利用上限(使用量アラート)を設定しておくと、想定外のループやプロンプト暴走による請求膨張を早期に止められます。採用すべきでない典型は、フロントエンド(ブラウザ側のJavaScript)へキーを埋め込む構成です。キーが利用者に露出して悪用されるため、API呼び出しは必ずサーバ側(このPythonコード側)に置き、フロントは自社サーバ経由で叩く構成にします。

よくある質問

openai.ChatCompletion.create() が動かないのはなぜですか

それはライブラリv1.0(2023年11月)より前の旧v0.x記法だからです。現行版ではopenai.api_keyopenai.ChatCompletion.create()は廃止され、client = OpenAI()を作ってclient.chat.completions.create()を呼ぶ方式に変わりました。古いサンプルを見つけたら本記事の基本コードに置き換えてください。旧メソッドと新メソッドの対応はOpenAI Python SDKの使い方の移行解説にまとまっています。

requestsで直接APIを叩くのとライブラリのどちらがよいですか

特別な理由がなければ公式ライブラリ(openai)を使います。認証・リクエスト組み立て・レスポンス解析・リトライ・型付き補完まで面倒を見てくれるため、requestsで自作するより短く安全に書けます。requestsで直接叩く選択は、依存を極限まで削りたい特殊な環境や、ライブラリ未対応のエンドポイントを試すときに限られます。

無料でChatGPT APIを試せますか

APIの利用は基本的に従量課金で、ChatGPTの有料プラン(ChatGPT Plusなど)とは課金が別建てです。新規アカウントへ試用枠が付く場合もありますが、有無や金額は時期で変わるため、最新の条件はOpenAI公式の料金ページで確認してください。少額のクレジットを入れ、小型モデルで動作確認から始めると無駄がありません。

どのモデルを指定すればよいですか

用途で選びます。高品質な文章生成や複雑な推論はフラッグシップモデル、大量処理やコスト重視の下処理は小型モデル、という切り分けが基本です。モデル名は更新が速いので、コードに直書きせず設定で外出しし、最新の選択肢は公式のモデル一覧で確認してください。料金と性能の具体的な比較はGPT-5.4 mini・nanoの解説が参考になります。

Pythonから画像生成もできますか

できます。同じクライアントからclient.imagesで画像生成APIを呼び出します。テキスト生成とは指定パラメータや料金体系が異なるため、画像用途はOpenAIのGPT Image API(gpt-image-1)の概要と基本機能で個別に確認してください。

関連記事

資料請求

RELATED POSTS 関連記事