|
1 | 1 | # OpenAI Python API library
|
2 | 2 |
|
3 |
| -[](https://pypi.org/project/openai/) |
| 3 | +[>)](https://pypi.org/project/openai/) |
4 | 4 |
|
5 | 5 | The OpenAI Python library provides convenient access to the OpenAI REST API from any Python 3.8+
|
6 | 6 | application. The library includes type definitions for all request params and response fields,
|
@@ -145,6 +145,45 @@ asyncio.run(main())
|
145 | 145 |
|
146 | 146 | Functionality between the synchronous and asynchronous clients is otherwise identical.
|
147 | 147 |
|
| 148 | +### With aiohttp |
| 149 | + |
| 150 | +By default, the async client uses `httpx` for HTTP requests. However, for improved concurrency performance you may also use `aiohttp` as the HTTP backend. |
| 151 | + |
| 152 | +You can enable this by installing `aiohttp`: |
| 153 | + |
| 154 | +```sh |
| 155 | +# install from PyPI |
| 156 | +pip install openai[aiohttp] |
| 157 | +``` |
| 158 | + |
| 159 | +Then you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`: |
| 160 | + |
| 161 | +```python |
| 162 | +import os |
| 163 | +import asyncio |
| 164 | +from openai import DefaultAioHttpClient |
| 165 | +from openai import AsyncOpenAI |
| 166 | + |
| 167 | + |
| 168 | +async def main() -> None: |
| 169 | + async with AsyncOpenAI( |
| 170 | + api_key=os.environ.get("OPENAI_API_KEY"), # This is the default and can be omitted |
| 171 | + http_client=DefaultAioHttpClient(), |
| 172 | + ) as client: |
| 173 | + chat_completion = await client.chat.completions.create( |
| 174 | + messages=[ |
| 175 | + { |
| 176 | + "role": "user", |
| 177 | + "content": "Say this is a test", |
| 178 | + } |
| 179 | + ], |
| 180 | + model="gpt-4o", |
| 181 | + ) |
| 182 | + |
| 183 | + |
| 184 | +asyncio.run(main()) |
| 185 | +``` |
| 186 | + |
148 | 187 | ## Streaming responses
|
149 | 188 |
|
150 | 189 | We provide support for streaming responses using Server Side Events (SSE).
|
@@ -367,6 +406,86 @@ client.files.create(
|
367 | 406 |
|
368 | 407 | The async client uses the exact same interface. If you pass a [`PathLike`](https://docs.python.org/3/library/os.html#os.PathLike) instance, the file contents will be read asynchronously automatically.
|
369 | 408 |
|
| 409 | +## Webhook Verification |
| 410 | + |
| 411 | +Verifying webhook signatures is _optional but encouraged_. |
| 412 | + |
| 413 | +For more information about webhooks, see [the API docs](https://platform.openai.com/docs/guides/webhooks). |
| 414 | + |
| 415 | +### Parsing webhook payloads |
| 416 | + |
| 417 | +For most use cases, you will likely want to verify the webhook and parse the payload at the same time. To achieve this, we provide the method `client.webhooks.unwrap()`, which parses a webhook request and verifies that it was sent by OpenAI. This method will raise an error if the signature is invalid. |
| 418 | + |
| 419 | +Note that the `body` parameter must be the raw JSON string sent from the server (do not parse it first). The `.unwrap()` method will parse this JSON for you into an event object after verifying the webhook was sent from OpenAI. |
| 420 | + |
| 421 | +```python |
| 422 | +from openai import OpenAI |
| 423 | +from flask import Flask, request |
| 424 | + |
| 425 | +app = Flask(__name__) |
| 426 | +client = OpenAI() # OPENAI_WEBHOOK_SECRET environment variable is used by default |
| 427 | + |
| 428 | + |
| 429 | +@app.route("/webhook", methods=["POST"]) |
| 430 | +def webhook(): |
| 431 | + request_body = request.get_data(as_text=True) |
| 432 | + |
| 433 | + try: |
| 434 | + event = client.webhooks.unwrap(request_body, request.headers) |
| 435 | + |
| 436 | + if event.type == "response.completed": |
| 437 | + print("Response completed:", event.data) |
| 438 | + elif event.type == "response.failed": |
| 439 | + print("Response failed:", event.data) |
| 440 | + else: |
| 441 | + print("Unhandled event type:", event.type) |
| 442 | + |
| 443 | + return "ok" |
| 444 | + except Exception as e: |
| 445 | + print("Invalid signature:", e) |
| 446 | + return "Invalid signature", 400 |
| 447 | + |
| 448 | + |
| 449 | +if __name__ == "__main__": |
| 450 | + app.run(port=8000) |
| 451 | +``` |
| 452 | + |
| 453 | +### Verifying webhook payloads directly |
| 454 | + |
| 455 | +In some cases, you may want to verify the webhook separately from parsing the payload. If you prefer to handle these steps separately, we provide the method `client.webhooks.verify_signature()` to _only verify_ the signature of a webhook request. Like `.unwrap()`, this method will raise an error if the signature is invalid. |
| 456 | + |
| 457 | +Note that the `body` parameter must be the raw JSON string sent from the server (do not parse it first). You will then need to parse the body after verifying the signature. |
| 458 | + |
| 459 | +```python |
| 460 | +import json |
| 461 | +from openai import OpenAI |
| 462 | +from flask import Flask, request |
| 463 | + |
| 464 | +app = Flask(__name__) |
| 465 | +client = OpenAI() # OPENAI_WEBHOOK_SECRET environment variable is used by default |
| 466 | + |
| 467 | + |
| 468 | +@app.route("/webhook", methods=["POST"]) |
| 469 | +def webhook(): |
| 470 | + request_body = request.get_data(as_text=True) |
| 471 | + |
| 472 | + try: |
| 473 | + client.webhooks.verify_signature(request_body, request.headers) |
| 474 | + |
| 475 | + # Parse the body after verification |
| 476 | + event = json.loads(request_body) |
| 477 | + print("Verified event:", event) |
| 478 | + |
| 479 | + return "ok" |
| 480 | + except Exception as e: |
| 481 | + print("Invalid signature:", e) |
| 482 | + return "Invalid signature", 400 |
| 483 | + |
| 484 | + |
| 485 | +if __name__ == "__main__": |
| 486 | + app.run(port=8000) |
| 487 | +``` |
| 488 | + |
370 | 489 | ## Handling errors
|
371 | 490 |
|
372 | 491 | When the library is unable to connect to the API (for example, due to network connection problems or a timeout), a subclass of `openai.APIConnectionError` is raised.
|
|
0 commit comments