HN 日本語サマリー

← 一覧へ戻る
プログラミング

OpenAI: HTTPX2への移行

OpenAI: Migrating to HTTPX2 (github.com)

46 pointsby tosh16 コメント

要約

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として要求し、レガシーレスポンスに対して同じ型チェック回避策を使用します。