AI最新ニュース 2026.06.24

OpenAI API「ChatCompletion廃止」|openai>=1.0.0の破壊的変更と移行手順【2026年版】

タグ:OpenAI API / ChatCompletion / 破壊的変更 / バージョンアップグレード / APIマイグレーション

TL;DR

  • OpenAI Python SDK バージョン 1.0.0 以降、openai.ChatCompletion は廃止されAttributeErrorでエラーになります
  • レスポンスがオブジェクト形式に変更されたため、辞書のようなブラケット記法(response['choices'] など)でアクセスすると「'ChatCompletion' object is not subscriptable」エラーが発生します
  • OpenAI APIの古いエンドポイント「v1/completions」も廃止予定。チャットモデル(GPT-4、GPT-3.5 Turbo)はこのエンドポイントに対応していません
  • 全ての既存コードは新しい Client ベースの API に書き換え必須。ドット記法(response.choices[0].message.content)での操作が必須です
  • パッケージ更新時に必ず公式マイグレーションガイドを確認してください

背景:OpenAI SDK の大規模リファクタリング

OpenAI の Python SDK は大きな進化を遂げました。バージョン 1.0.0 より前は、旧形式のシンプルな関数形 API が提供されていました。

# 旧形式(0.x系)
import openai
openai.api_key = "your-key"
response = openai.ChatCompletion.create(
    model="gpt-4",
    messages=[{"role": "user", "content": "Hello"}]
)

しかし 1.0.0 から大きく変わり、新しい Client インスタンスを経由するオブジェクト指向スタイルへ統一されました。OpenAI は現在 v1.3.x 以降を推奨しており、古いバージョンへのダウングレードはセキュリティリスクもあるため、アップグレード+コード修正が必須です。

なぜこのような変更が入ったか

OpenAI は、以下の理由で API パッケージを再設計しました。

  1. 型安全性の強化:辞書形式では、存在しないキーにアクセスしてもキーエラーが発生するまで気づきにくい。オブジェクト形式なら IDE の自動補完が機能し、開発時に誤りを検出できます
  2. API スキーマとの一貫性:OpenAI の REST API 仕様と Python パッケージの実装ギャップを縮小するため
  3. 保守性:パッケージ内部の構造が明確になり、将来の拡張が容易になります

発生するエラーの詳細

バージョン 1.0.0 以降を導入した環境で古いコードを実行すると、以下のようなエラーが発生します:

AttributeError: module 'openai' has no attribute 'ChatCompletion'

また、別の場面では:

You tried to access openai.ChatCompletion, but this is no longer supported in openai>=1.0.0

というメッセージが表示される場合もあります。このエラーは、SDK のレイヤーが明示的に古い API へのアクセスを遮断していることを示しています。

パターン1: ChatCompletion object is not subscriptable

# ❌ 古いコード(失敗する例)
import openai

response = openai.ChatCompletion.create(
    model="gpt-3.5-turbo",
    messages=[{"role": "user", "content": "こんにちは"}]
)

# subscriptableでない(インデックスでアクセスできない)
print(response[0])  # TypeError: 'ChatCompletion' object is not subscriptable

原因:OpenAI Python SDK のバージョン 1.0.0 以降、レスポンスオブジェクトの構造が変更されました。辞書キーでのアクセス(response['choices'][0])ではなく、属性アクセス(response.choices[0])に変更する必要があります。

Python では「subscriptable(添え字操作可能)」とは、オブジェクトが [] 記法をサポートしている状態を指します。辞書やリストは subscriptable ですが、通常のクラスインスタンスは subscriptable ではありません。新形式ではレスポンスがデータクラス形式の構造化オブジェクトになったため、ブラケット記法を使うとこのエラーが発生します。

パターン2: This is a chat model and not supported in the v1/completions endpoint

# ❌ 古いエンドポイントを使用している場合
import requests
import os

headers = {
    "Authorization": f"Bearer {os.environ['OPENAI_API_KEY']}"
}

data = {
    "model": "gpt-3.5-turbo",  # チャットモデルをv1/completionsで使用
    "prompt": "こんにちは"
}

# POST https://api.openai.com/v1/completions
# → エラー: This is a chat model and not supported in the v1/completions endpoint
response = requests.post("https://api.openai.com/v1/completions", json=data, headers=headers)

原因gpt-3.5-turbogpt-4 はチャットモデル設計です。これらのモデルは v1/chat/completions エンドポイントのみで動作します。v1/completions エンドポイントは旧世代モデル(text-davinci-003 など)用であり、チャットモデルを指定するとエラーになります。


何が変わったのか:新しい API 形式

新形式の基本構造

新バージョンでは、まず Client インスタンスを生成し、そこから各機能にアクセスします:

from openai import OpenAI

# Client インスタンスを作成
client = OpenAI(api_key="your-api-key")

# チャットを実行
response = client.chat.completions.create(
    model="gpt-4",
    messages=[
        {"role": "user", "content": "Hello"}
    ]
)

# レスポンスは属性アクセスで取得
print(response.choices[0].message.content)

構造の解説

  • response.choices:メッセージ候補のリスト。create()n パラメータで複数の候補を要求できます
  • response.choices[0]:最初の選択肢(通常は唯一)
  • response.choices[0].message:メッセージオブジェクト
  • response.choices[0].message.content:テキスト本体

主な変更点

項目旧形式(0.x)新形式(1.0.0+)
モジュール導入import openaifrom openai import OpenAI
API キー設定openai.api_key = "..."client = OpenAI(api_key="...")
API 呼び出しopenai.ChatCompletion.create()client.chat.completions.create()
レスポンス辞書形式(['key']アクセス)オブジェクト形式(.keyアクセス)

レスポンス形式の詳細な変更点

v1/completions のレスポンス(廃止予定)

{
  "id": "cmpl-xxx",
  "object": "text_completion",
  "choices": [
    {
      "text": "東京です",
      "index": 0,
      "finish_reason": "stop"
    }
  ]
}

v1/chat/completions のレスポンス(推奨)

{
  "id": "chatcmpl-xxx",
  "object": "chat.completion",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "東京です"
      },
      "finish_reason": "stop"
    }
  ]
}
取得内容廃止予定推奨
レスポンステキストresponse["choices"][0]["text"]response.choices[0].message.content
トークン使用数response["usage"]["total_tokens"]response.usage.total_tokens
終了理由response["choices"][0]["finish_reason"]response.choices[0].finish_reason

既存ユーザーへの影響

どのコードが影響を受けるか

以下の形式を使っているすべての Python スクリプトが影響を受けます:

  • openai.ChatCompletion.create()
  • openai.Completion.create()
  • openai.Embedding.create()
  • openai.Image.generate()
  • その他、直接モジュール属性にアクセスするパターン
  • レスポンスにブラケット記法(response['choices'] など)でアクセスしているコード
  • REST API で https://api.openai.com/v1/completions を直接呼び出しているコード

影響を受けるケース

  1. 個人開発者の小規模スクリプト:古いコードをそのまま使っている場合、すぐに動作しなくなります

  2. 既存の商用アプリケーション:バージョン管理が曖昧(pip install openai で最新版が入る環境)の場合、更新後に本番障害が発生する可能性があります

  3. バッチ処理・スケジュール実行スクリプト:エラーで処理が停止し、気づかないまま障害が継続するリスクがあります

  4. ウェブアプリケーション:Flask、Django、FastAPI などのフレームワークを使うアプリケーションで OpenAI 連携が機能しなくなります

  5. チームプロジェクト:ドキュメント、テストコード、CI/CD パイプラインまで、一括更新の手間が発生します

  6. 旧世代モデルに依存している場合:text-davinci-003、text-davinci-002、text-curie-001 などを使用中の場合、これらモデルの提供終了に伴い、コード修正が避けられません


必要な対応と移行手順

ステップ 1:現在の SDK バージョンを確認

pip show openai

v1.0 以降であれば、以下の修正が必要です。本番環境で障害が起きている場合は、まず旧バージョンを固定します:

pip install 'openai<1.0.0'

これで即座に動作を復旧できます。ただし、古いバージョンへのダウングレードは以下の理由から長期運用には非推奨です:

  1. セキュリティアップデート:新バージョンで脆弱性が修正されても、旧バージョンには反映されない可能性があります
  2. API 廃止予定:OpenAI が古い SDK のサポート終了を公表する可能性があります
  3. 新機能の利用不可:最新の OpenAI API(Vision、Fine-tuning 等)に対応していない可能性があります

ステップ 2:開発環境で新バージョンをインストール

pip install --upgrade openai

最新の 1.0.0 以降が入ります。

ステップ 3:コード移行の具体例

旧形式のコード例:

import openai

openai.api_key = "sk-..."

def chat_with_gpt(user_message):
    response = openai.ChatCompletion.create(
        model="gpt-4",
        messages=[
            {"role": "system", "content": "You are a helpful assistant."},
            {"role": "user", "content": user_message}
        ],
        temperature=0.7
    )
    return response["choices"][0]["message"]["content"]

print(chat_with_gpt("What is the capital of France?"))

新形式への移行後:

from openai import OpenAI

client = OpenAI(api_key="sk-...")

def chat_with_gpt(user_message):
    response = client.chat.completions.create(
        model="gpt-4",
        messages=[
            {"role": "system", "content": "You are a helpful assistant."},
            {"role": "user", "content": user_message}
        ],
        temperature=0.7
    )
    return response.choices[0].message.content

print(chat_with_gpt("What is the capital of France?"))

変更のポイント:

  • from openai import OpenAI で Client クラスをインポート
  • client = OpenAI(api_key="sk-...") でインスタンス生成
  • openai.ChatCompletion.create()client.chat.completions.create()
  • レスポンス取得:response["choices"][0]["message"]["content"]response.choices[0].message.content(属性アクセス)

ステップ 4:環境変数からの API キー読み込み(推奨)

ハードコードされた API キーはセキュリティリスクです。環境変数から読み込むことを推奨します。

from openai import OpenAI

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

response = client.chat.completions.create(
    model="gpt-4",
    messages=[{"role": "user", "content": "Hello"}]
)

環境変数の設定:

# Linux/Mac
export OPENAI_API_KEY="sk-..."

# Windows (PowerShell)
$env:OPENAI_API_KEY="sk-..."

ステップ 5:エラーハンドリングの追加(本番環境向け)

from openai import OpenAI
from openai import APIError, APIConnectionError, RateLimitError

client = OpenAI()

try:
    response = client.chat.completions.create(
        model="gpt-3.5-turbo",
        messages=[{"role": "user", "content": "Hello"}]
    )
    print(response.choices[0].message.content)
    
except RateLimitError:
    print("API rate limit に達しました。しばらく待ってから再試行してください。")
except APIConnectionError as e:
    print(f"API 接続エラー: {e}")
except APIError as e:
    print(f"API エラー: {e}")

ステップ 6:REST API を直接使用している場合

廃止対象の古いエンドポイント:

# ❌ 廃止予定
curl https://api.openai.com/v1/completions \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{"model":"gpt-3.5-turbo","prompt":"こんにちは"}'

推奨される新しいエンドポイント:

# ✅ 推奨
curl https://api.openai.com/v1/chat/completions \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-3.5-turbo",
    "messages": [
      {"role": "user", "content": "こんにちは"}
    ]
  }'

主な違い

  • エンドポイントが /completions から /chat/completions に変更
  • リクエスト形式が prompt から messages 配列に変更
  • レスポンス形式も text から choices[0].message.content に変更

ステップ 7:他のエンドポイントの対応

ChatCompletion 以外の API も同じ方針で移行します:

埋め込みベクトル化(Embedding):

# 旧形式
embedding = openai.Embedding.create(
    model="text-embedding-3-small",
    input="Hello world"
)

# 新形式
embedding = client.embeddings.create(
    model="text-embedding-3-small",
    input="Hello world"
)

画像生成(Image):

# 旧形式
image = openai.Image.create(
    prompt="A cat on a chair",
    n=1,
    size="1024x1024"
)

# 新形式
image = client.images.generate(
    prompt="A cat on a chair",
    n=1,
    size="1024x1024"
)

ステップ 8:影響範囲の確認

コードベース全体で以下の検索を実行し、変更が必要な箇所を洗い出します:

# v1/completions への直接参照
grep -r "v1/completions" .

# ChatCompletion.create の使用箇所
grep -r "ChatCompletion.create" .

# Completion.create の使用箇所(テキスト補完)
grep -r "Completion.create" .

# ブラケット記法(古いレスポンス形式)
grep -r 'response\["choices"\]' .
grep -r "response\['choices'\]" .
grep -r 'response\[0\]' .

ステップ 9:テストと段階的ロールアウト

  1. ユニットテストを実行:新形式で動作確認
  2. ステージング環境でテスト:実際の API 呼び出しで検証
  3. 段階的なロールアウト:小規模ユーザーから本番展開
  4. 監視:エラーログを監視し、問題が生じないか確認

既存プロジェクトでの一括対応

複数のファイルで旧形式を使っている場合、以下のアプローチが効率的です:

方法 1:検索と置換(エディタの機能を活用)

テキストエディタ(VS Code など)の正規表現検索で Find and Replace 機能を使い、複数ファイルを同時置換できます:

  • 検索:openai\.ChatCompletion\.create\( → 置換:client.chat.completions.create(
  • 検索:response\['choices'\]\[0\]\['message'\]\['content'\] → 置換:response.choices[0].message.content

方法 2:コード生成ツール

簡単な Python スクリプトで、ファイル内の旧形式を新形式に自動変換することもできます(ただし完全な自動変換は困難なため、手動確認は必須)。

方法 3:ラッパー関数を用意(短期対応)

移行期間の間、互換性レイヤーを作成することもできます:

from openai import OpenAI

_client = OpenAI()

class CompatOpenAI:
    class ChatCompletion:
        @staticmethod
        def create(**kwargs):
            return _client.chat.completions.create(**kwargs)

openai.ChatCompletion = CompatOpenAI.ChatCompletion

ただし、これは一時的な対応であり、根本的な移行を遅延させるだけです。最終的には正式な新形式への移行を完了させてください。


移行時のチェックリスト

  • OpenAI Python SDK をバージョン 1.0 以上にアップグレード
  • from openai import OpenAI でインポートしている
  • グローバルの openai.api_key 設定を削除している
  • client = OpenAI() でインスタンスを作成している
  • client.chat.completions.create() メソッドを使用している
  • 返却値へのアクセスをドット記法(.choices[0].message.content)に変更している(ブラケット記法を使用していない)
  • REST API 直接呼び出しの場合、エンドポイントを /v1/completions から /v1/chat/completions に変更
  • テストケースを実行し、新しい形式でのレスポンス処理が正常に動作することを確認
  • API キーの管理方法を環境変数に統一
  • エラーハンドリングが実装されている
  • 本番環境へのデプロイ前に、ステージング環境で十分な検証を実施

実装サンプル:本番環境への適用例

シンプルな会話実装

from openai import OpenAI

class ChatBot:
    def __init__(self, api_key: str):
        self.client = OpenAI(api_key=api_key)
    
    def ask(self, message: str) -> str:
        response = self.client.chat.completions.create(
            model="gpt-3.5-turbo",
            messages=[
                {"role": "user", "content": message}
            ],
            temperature=0.7,
            max_tokens=150
        )
        return response.choices[0].message.content

# 使用例
bot = ChatBot(api_key="sk-...")
answer = bot.ask("OpenAIのAPIについて教えてください")
print(answer)

複数のキーにアクセスする場合

レスポンスには、コンテンツ以外にも以下の情報が含まれます。

from openai import OpenAI

client = OpenAI(api_key="your-api-key")

response = client.chat.completions.create(
    model="gpt-3.5-turbo",
    messages=[{"role": "user", "content": "Say 'hello' in Spanish"}]
)

# 各種情報をアクセス
print(f"Content: {response.choices[0].message.content}")
print(f"Model: {response.model}")
print(f"Usage tokens: {response.usage.total_tokens}")
print(f"Finish reason: {response.choices[0].finish_reason}")

複数回の会話(会話履歴を維持する実装)

from openai import OpenAI

client = OpenAI()

messages = [
    {"role": "system", "content": "You are a helpful assistant."}
]

user_inputs = [
    "What is Python?",
    "How do I install it?",
    "Show me a simple example."
]

for user_input in user_inputs:
    messages.append({"role": "user", "content": user_input})
    
    response = client.chat.completions.create(
        model="gpt-3.5-turbo",
        messages=messages
    )
    
    assistant_message = response.choices[0].message.content
    messages.append({"role": "assistant", "content": assistant_message})
    
    print(f"User: {user_input}")
    print(f"Assistant: {assistant_message}\n")

ストリーミング対応版

from openai import OpenAI

client = OpenAI(api_key="sk-...")

# ストリーミングレスポンスを取得
stream = client.chat.completions.create(
    model="gpt-3.5-turbo",
    messages=[
        {"role": "user", "content": "短い詩を書いてください"}
    ],
    stream=True
)

# レスポンスを逐次出力
for chunk in stream:
    if chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)

よくあるトラブルと対処法

「ModuleNotFoundError: No module named ‘openai’」

pip install openai

「openai.error.AuthenticationError: Invalid API key」

API キーが間違っているか、環境変数が設定されていません。

export OPENAI_API_KEY="sk-your-actual-key-here"

「openai.error.RateLimitError: Rate limit exceeded」

API のレート制限に達しています。待機してから再試行するか、プランをアップグレードしてください。

「KeyError: ‘choices’」

# ❌ 旧形式のコード
response = client.chat.completions.create(...)
choices = response['choices']  # KeyError が発生

対応response.choices に修正してください。

「AttributeError: ‘dict’ object has no attribute ‘content’」

# ❌ オブジェクトを無理に辞書に変換
response_dict = dict(response)
text = response_dict.message.content  # AttributeError

対応:変換せずにドット記法をそのまま使用してください。


バージョン管理のベストプラクティス

今後、同様の大規模な非互換変更に対応する際は、以下の対策が有効です:

  1. バージョン固定を明示的に記載requirements.txtpyproject.toml に固定版を指定

    openai>=1.0.0,<2.0.0
    
  2. 自動テストの実行:CI/CD パイプラインで、バージョン更新時に全テストを実行

  3. 定期的なセキュリティ監視:OpenAI の公式ブログやリリースノート、GitHub の Releases ページを監視

  4. チーム内の知識共有:破壊的変更に対応する手順をドキュメント化


関連サービスの対応状況

LangChain、LlamaIndex、Semantic Kernel などのフレームワークは既に新しい OpenAI API に対応しており、これらのツール経由で OpenAI を使用している場合は、ライブラリのアップグレードで自動的に対応できる可能性があります。

ただし、独自の統合実装やレガシーフレームワークを使用している場合は、上記の手動修正が必要になります。


まとめ

OpenAI SDK 1.0.0 への移行、および v1/completions エンドポイントの廃止対応は、多くの既存コードに影響をもたらす重大な変更です。しかし、新しい Client ベース API と v1/chat/completions エンドポイントは、以下の点で改善されています:

  • より明確なインターフェース:Client インスタンスを通じた体系的なアクセス
  • 型安全性の向上:Python の型ヒント対応、IDE の自動補完が機能
  • 拡張性:今後の機能追加に対応しやすい設計

既存プロジェクトの移行は手間がかかりますが、公式ドキュメントとコード例を参考に、段階的に進めることで、スムーズに新バージョンへ移行できます。本番環境での障害を避けるため、開発環境での十分なテストと、ステージング環境での検証を強くお勧めします。


あわせて読みたい

参考ソース