プログラミング
OpenAI: HTTPX2への移行
OpenAI: Migrating to HTTPX2 (github.com)
要約
OpenAIのPython SDKが、同期および非同期HTTPクライアントとしてHTTPX2を採用したことを説明する記事です。TLS証明書の検証方法の変更や、カスタムHTTPクライアントの設定方法など、SDKのHTTPレイヤーと連携するアプリケーション開発者向けの変更点について解説しています。
全文翻訳
HTTPX2への移行
OpenAI Python SDKは、同期および非同期HTTPクライアントとしてHTTPX2を使用するようになりました。HTTPX2はopenaiとともに自動的にインストールされ、以前のhttpxパッケージはインストールされません。このガイドでは、SDKのHTTPレイヤーとやり取りするアプリケーションにどのような変更があるかを説明します。
SDKのデフォルトHTTPクライアントを使用する場合
http_clientを指定せずにOpenAIまたはAsyncOpenAIクライアントを構築する場合、既存のAPI呼び出し、解析されたレスポンスモデル、ストリーミングAPI、認証、リトライ、数値タイムアウトは引き続き機能します。
from openai import OpenAI
client = OpenAI(timeout=30.0)
response = client.responses.create(model="gpt-5.5", input="Hello")
HTTPX2エクストラや個別のインストールは不要です。
pip install openai
以前のSDKが間接的にインストールしたためにhttpxをインポートしていたアプリケーションは、独自のhttpx依存関係を追加するか、それらのインポートをhttpx2に移行してください。SDKのインストールでは、もはやhttpxはインストールされません。
TLS証明書とトラストストア
HTTPX2は、SDKのデフォルトHTTPクライアントを使用するアプリケーションを含め、デフォルトのTLSトラストストアを変更します。以前は、HTTPXはcertifiによって提供されるCAバンドルに対して証明書を検証していました。HTTPX2は代わりにオペレーティングシステムのトラストストアを使用し、SDKはcertifiをインストールしなくなりました。これは、システムCA証明書を持たない最小限のコンテナイメージ、企業のTLSインスペクティングプロキシを使用する環境、およびカスタムまたは変更されたcertifiバンドルに依存していたデプロイメントで証明書検証が失敗する可能性があります。
オペレーティングシステムのトラストストアに必要なCA証明書をインストールするか、明示的な証明書バンドルを構成してください。
export SSL_CERT_FILE=/path/to/ca-bundle.pem
または、信頼されたCA証明書のディレクトリを構成してください。
export SSL_CERT_DIR=/path/to/ca-directory
これらの環境変数は、デフォルトであるtrust_env=Trueの場合に尊重されます。カスタムクライアントで信頼を明示的に制御するには、verifyにssl.SSLContextを渡します。
import ssl
from openai import OpenAI, DefaultHttpx2Client
ssl_context = ssl.create_default_context(cafile="/path/to/ca-bundle.pem")
client = OpenAI(http_client=DefaultHttpx2Client(verify=ssl_context))
同等の非同期構成には、DefaultAsyncHttpx2Client(verify=ssl_context)を使用します。SDKのaiohttpトランスポートは、同じHTTPX2 TLS設定を使用します。
カスタムHTTPクライアントを提供する場合
HTTPX2クライアントとHTTPX2構成オブジェクトを使用します。SDKは、推奨されるタイムアウト、接続プール、リダイレクトのデフォルトを保持するヘルパーを提供します。
import httpx2
from openai import OpenAI, AsyncOpenAI, DefaultHttpx2Client, DefaultAsyncHttpx2Client
proxy_client = OpenAI(http_client=DefaultHttpx2Client(proxy="http://proxy.example.com:8080"))
transport_client = OpenAI(
http_client=DefaultHttpx2Client(
transport=httpx2.HTTPTransport(local_address="0.0.0.0"),
timeout=httpx2.Timeout(30.0, connect=5.0),
)
)
async_client = AsyncOpenAI(http_client=DefaultAsyncHttpx2Client(timeout=httpx2.Timeout(30.0)))
直接構築されたhttpx2.Clientおよびhttpx2.AsyncClientインスタンスもサポートされます。クライアントを直接構築する場合、HTTPX2のデフォルトが適用されますが、自分で構成することもできます。既存のDefaultHttpxClientおよびDefaultAsyncHttpxClientという名前は引き続き機能しますが、これらはHTTPX2クライアントを構築します。HTTPクライアントファミリーを明示する場合は、DefaultHttpx2ClientおよびDefaultAsyncHttpx2Clientを優先してください。
モジュールレベルの構成も同様のルールに従います。
import openai
openai.http_client = openai.DefaultHttpx2Client()
タイムアウト、URL、トランスポート、接続設定
HTTPX固有のオブジェクトを対応するHTTPX2オブジェクトに置き換えます。
以前のオブジェクト HTTPX2オブジェクト
httpx.Client httpx2.Client
httpx.AsyncClient httpx2.AsyncClient
httpx.Timeout httpx2.Timeout
httpx.URL httpx2.URL
httpx.Limits httpx2.Limits
httpx.HTTPTransport httpx2.HTTPTransport
httpx.AsyncHTTPTransport httpx2.AsyncHTTPTransport
httpx.MockTransport httpx2.MockTransport
例えば、詳細なSDKタイムアウトは次のようになります。
import httpx2
from openai import OpenAI
client = OpenAI(timeout=httpx2.Timeout(60.0, connect=5.0, read=20.0))
数値タイムアウト値は変更されません。既存の文字列URLも変更されません。カスタムトランスポートサブクラス、マウントされたトランスポート、プロキシ統合、接続プールインストルメンテーションは、HTTPX2のトランスポートインターフェースを対象とする必要があります。
認証とイベントフック
認証ハンドラとフックは、HTTPX2のリクエストとレスポンスオブジェクトを受け取ります。カスタム認証クラスとアノテーションをそれに応じて更新してください。
import httpx2
from openai import OpenAI, DefaultHttpx2Client
def log_request(request: httpx2.Request) -> None:
print(request.method, request.url)
client = OpenAI(http_client=DefaultHttpx2Client(event_hooks={"request": [log_request]}))
HTTP認証またはトランスポートインターフェースをサブクラス化する場合、対応するhttpx2クラスをサブクラス化してください。サードパーティのインストルメンテーション、トレーシングミドルウェア、および認証統合は、HTTPX2を明示的にサポートする必要があります。
生のレスポンス、ストリーミング、例外
解析されたSDKレスポンスモデルは変更されません。ネイティブHTTPX2クライアントを使用する場合、トランスポートに面したオブジェクトはHTTPX2に属します。
import httpx2
from openai import OpenAI
client = OpenAI()
response = client.models.with_raw_response.list()
assert isinstance(response.http_response, httpx2.Response)
assert isinstance(response.http_request, httpx2.Request)
ネイティブクライアントの場合、パースされていないHTTPレスポンスを要求する際にcast_to=httpx2.Responseを使用します。ストリーミングレスポンスラッパーもHTTPX2レスポンスオブジェクトを公開します。アプリケーションコードは通常、openai.APITimeoutErrorやopenai.APIConnectionErrorなどのSDK例外をキャッチする必要があります。ネイティブクライアントの場合、例外の基になるトランスポート原因はHTTPX2例外です。これらの型保証は、ネイティブHTTPX2クライアントにのみ適用されます。注入されたレガシーHTTPXクライアントは、cast_to=httpx2.Responseが指定されていても、httpx.Request、httpx.Response、およびHTTPXトランスポート例外を生成します。
aiohttp
サポートされているaiohttpエクストラは、HTTPX2ネイティブのトランスポートを使用します。レガシーHTTPXや外部のhttpx-aiohttpアダプターはインストールしません。
pip install 'openai[aiohttp]'
from openai import AsyncOpenAI, DefaultAioHttpClient
client = AsyncOpenAI(http_client=DefaultAioHttpClient())
DefaultAioHttpClient()はhttpx2.AsyncClientです。このヘルパーを使用するアプリケーションは、トランスポートを直接構築またはインポートする必要はありません。
リクエストモックとテスト
モックはHTTPX2リクエストをインターセプトし、HTTPX2レスポンスを返す必要があります。例:
import httpx2
from openai import OpenAI
def handler(request: httpx2.Request) -> httpx2.Response:
return httpx2.Response(
200,
request=request,
json={"object": "list", "data": []},
)
client = OpenAI(http_client=httpx2.Client(transport=httpx2.MockTransport(handler)))
assert client.models.list().data == []
テストスイートがRESPXを使用している場合、HTTPX2互換のRESPXバージョンに更新するか、フォークしてください。レガシーHTTPXのみをパッチするRESPXバージョンは、SDKのデフォルトHTTPX2クライアントをインターセプトできません。この統合をすぐに移行できない場合、一時的なレガシークライアントエスケープハッチにより、移行中に既存のHTTPXのみのRESPXセットアップを引き続き機能させることができます。
一時的なエスケープハッチ: レガシーHTTPXクライアント
HTTPXのみのトランスポート、統合、またはモックライブラリに依存するアプリケーションは、レガシーHTTPXを明示的にインストールし、レガシークライアントを注入できます。
pip install openai httpx
レガシーHTTPXサポートは実行時のみです。SDKのパブリック型アノテーションはHTTPX2クライアントを受け入れるため、レガシークライアントを直接渡すと、mypy、Pyrightなどのツールで静的型チェックが失敗します。意図的にこの互換性パスを選択する場合は、cast(Any, ...)またはターゲットを絞ったtype-ignoreを使用してください。
from typing import Any, cast
import httpx
from openai import OpenAI
client = OpenAI(http_client=cast(Any, httpx.Client()))
非同期フォームも同様の回避策が必要です。
from typing import Any, cast
import httpx
from openai import AsyncOpenAI
client = AsyncOpenAI(http_client=cast(Any, httpx.AsyncClient()))
レガシークライアントは、HTTPXのリクエスト、レスポンス、および例外ファミリーを保持します。生のレスポンスをhttpx.Responseとして要求し、レガシーレスポンスに対して同じ型チェック回避策を使用します。