openai/openai-python

Public

mirrored from https://github.com/openai/openai-pythonAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.28.1

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

README.md

638lines · modeblame

08b8179aDavid Schnurr2 years ago1# OpenAI Python API library
3c6d4cd6Greg Brockman5 years ago2
08b8179aDavid Schnurr2 years ago3[![PyPI version](https://img.shields.io/pypi/v/openai.svg)](https://pypi.org/project/openai/)
3c6d4cd6Greg Brockman5 years ago4
08b8179aDavid Schnurr2 years ago5The OpenAI Python library provides convenient access to the OpenAI REST API from any Python 3.7+
6application. The library includes type definitions for all request params and response fields,
7and offers both synchronous and asynchronous clients powered by [httpx](https://github.com/encode/httpx).
8
9It is generated from our [OpenAPI specification](https://github.com/openai/openai-openapi) with [Stainless](https://stainlessapi.com/).
10
11## Documentation
12
986f3128Stainless Bot2 years ago13The REST API documentation can be found [on platform.openai.com](https://platform.openai.com/docs). The full API of this library can be found in [api.md](api.md).
3c6d4cd6Greg Brockman5 years ago14
15## Installation
16
448ac7d0Stainless Bot2 years ago17> [!IMPORTANT]
db6cd764Stainless Bot2 years ago18> The SDK was rewritten in v1, which was released November 6th 2023. See the [v1 migration guide](https://github.com/openai/openai-python/discussions/742), which includes scripts to automatically update your code.
448ac7d0Stainless Bot2 years ago19
3c6d4cd6Greg Brockman5 years ago20```sh
1879c97aStainless Bot2 years ago21# install from PyPI
6d217096Robert Craigie2 years ago22pip install openai
3c6d4cd6Greg Brockman5 years ago23```
24
08b8179aDavid Schnurr2 years ago25## Usage
26
986f3128Stainless Bot2 years ago27The full API of this library can be found in [api.md](api.md).
376dd199Logan Kilpatrick2 years ago28
29```python
fb5ba01cStainless Bot2 years ago30import os
08b8179aDavid Schnurr2 years ago31from openai import OpenAI
32
33client = OpenAI(
fb5ba01cStainless Bot2 years ago34# This is the default and can be omitted
35api_key=os.environ.get("OPENAI_API_KEY"),
08b8179aDavid Schnurr2 years ago36)
37
38chat_completion = client.chat.completions.create(
39messages=[
40{
41"role": "user",
42"content": "Say this is a test",
43}
44],
45model="gpt-3.5-turbo",
46)
376dd199Logan Kilpatrick2 years ago47```
48
08b8179aDavid Schnurr2 years ago49While you can provide an `api_key` keyword argument,
50we recommend using [python-dotenv](https://pypi.org/project/python-dotenv/)
51to add `OPENAI_API_KEY="My API Key"` to your `.env` file
52so that your API Key is not stored in source control.
3c6d4cd6Greg Brockman5 years ago53
595f3b36Stainless Bot2 years ago54### Polling Helpers
55
5b20698dStainless Bot2 years ago56When interacting with the API some actions such as starting a Run and adding files to vector stores are asynchronous and take time to complete. The SDK includes
595f3b36Stainless Bot2 years ago57helper functions which will poll the status until it reaches a terminal state and then return the resulting object.
58If an API method results in an action which could benefit from polling there will be a corresponding version of the
59method ending in '\_and_poll'.
60
61For instance to create a Run and poll until it reaches a terminal state you can run:
62
63```python
64run = client.beta.threads.runs.create_and_poll(
65thread_id=thread.id,
66assistant_id=assistant.id,
67)
68```
69
70More information on the lifecycle of a Run can be found in the [Run Lifecycle Documentation](https://platform.openai.com/docs/assistants/how-it-works/run-lifecycle)
71
5b20698dStainless Bot2 years ago72### Bulk Upload Helpers
73
74When creating an interacting with vector stores, you can use the polling helpers to monitor the status of operations.
75For convenience, we also provide a bulk upload helper to allow you to simultaneously upload several files at once.
76
77```python
78sample_files = [Path("sample-paper.pdf"), ...]
79
80batch = await client.vector_stores.file_batches.upload_and_poll(
81store.id,
82files=sample_files,
83)
84```
85
5cfb125aStainless Bot2 years ago86### Streaming Helpers
87
88The SDK also includes helpers to process streams and handle the incoming events.
89
90```python
595f3b36Stainless Bot2 years ago91with client.beta.threads.runs.stream(
5cfb125aStainless Bot2 years ago92thread_id=thread.id,
93assistant_id=assistant.id,
94instructions="Please address the user as Jane Doe. The user has a premium account.",
95) as stream:
96for event in stream:
97# Print the text from text delta events
98if event.type == "thread.message.delta" and event.data.delta.content:
99print(event.data.delta.content[0].text)
100```
101
102More information on streaming helpers can be found in the dedicated documentation: [helpers.md](helpers.md)
103
08b8179aDavid Schnurr2 years ago104## Async usage
3c6d4cd6Greg Brockman5 years ago105
08b8179aDavid Schnurr2 years ago106Simply import `AsyncOpenAI` instead of `OpenAI` and use `await` with each API call:
ede08829Jakub Roztocil3 years ago107
08b8179aDavid Schnurr2 years ago108```python
fb5ba01cStainless Bot2 years ago109import os
08b8179aDavid Schnurr2 years ago110import asyncio
111from openai import AsyncOpenAI
ede08829Jakub Roztocil3 years ago112
08b8179aDavid Schnurr2 years ago113client = AsyncOpenAI(
fb5ba01cStainless Bot2 years ago114# This is the default and can be omitted
115api_key=os.environ.get("OPENAI_API_KEY"),
08b8179aDavid Schnurr2 years ago116)
ede08829Jakub Roztocil3 years ago117
118
08b8179aDavid Schnurr2 years ago119async def main() -> None:
120chat_completion = await client.chat.completions.create(
121messages=[
122{
123"role": "user",
124"content": "Say this is a test",
125}
126],
127model="gpt-3.5-turbo",
128)
ede08829Jakub Roztocil3 years ago129
130
08b8179aDavid Schnurr2 years ago131asyncio.run(main())
2b21516eAtty Eleti3 years ago132```
ede08829Jakub Roztocil3 years ago133
08b8179aDavid Schnurr2 years ago134Functionality between the synchronous and asynchronous clients is otherwise identical.
135
2b23eb53Stainless Bot2 years ago136## Streaming responses
08b8179aDavid Schnurr2 years ago137
138We provide support for streaming responses using Server Side Events (SSE).
d53d9efbRachel Lim5 years ago139
08b8179aDavid Schnurr2 years ago140```python
141from openai import OpenAI
142
143client = OpenAI()
d53d9efbRachel Lim5 years ago144
08b8179aDavid Schnurr2 years ago145stream = client.chat.completions.create(
146model="gpt-4",
147messages=[{"role": "user", "content": "Say this is a test"}],
148stream=True,
149)
54c7c512Stainless Bot2 years ago150for chunk in stream:
a3da0196Stainless Bot2 years ago151print(chunk.choices[0].delta.content or "", end="")
d53d9efbRachel Lim5 years ago152```
153
08b8179aDavid Schnurr2 years ago154The async client uses the exact same interface.
d53d9efbRachel Lim5 years ago155
156```python
08b8179aDavid Schnurr2 years ago157from openai import AsyncOpenAI
158
159client = AsyncOpenAI()
160
a3da0196Stainless Bot2 years ago161
dfe1c8daSahand Sojoodi2 years ago162async def main():
163stream = await client.chat.completions.create(
164model="gpt-4",
165messages=[{"role": "user", "content": "Say this is a test"}],
166stream=True,
167)
168async for chunk in stream:
a3da0196Stainless Bot2 years ago169print(chunk.choices[0].delta.content or "", end="")
170
dfe1c8daSahand Sojoodi2 years ago171
172asyncio.run(main())
53e5ba4bt-asutedjo4 years ago173```
2b21516eAtty Eleti3 years ago174
08b8179aDavid Schnurr2 years ago175## Module-level client
d53d9efbRachel Lim5 years ago176
08b8179aDavid Schnurr2 years ago177> [!IMPORTANT]
178> We highly recommend instantiating client instances instead of relying on the global client.
d53d9efbRachel Lim5 years ago179
08b8179aDavid Schnurr2 years ago180We also expose a global client instance that is accessible in a similar fashion to versions prior to v1.
6572ef4fZheNing Hu3 years ago181
08b8179aDavid Schnurr2 years ago182```py
183import openai
62b73b9bAtty Eleti3 years ago184
08b8179aDavid Schnurr2 years ago185# optional; defaults to `os.environ['OPENAI_API_KEY']`
186openai.api_key = '...'
187
188# all client options can be configured just like the `OpenAI` instantiation counterpart
189openai.base_url = "https://..."
190openai.default_headers = {"x-foo": "true"}
191
192completion = openai.chat.completions.create(
193model="gpt-4",
194messages=[
195{
196"role": "user",
197"content": "How do I output all files in a directory using Python?",
198},
199],
200)
62b73b9bAtty Eleti3 years ago201print(completion.choices[0].message.content)
202```
203
08b8179aDavid Schnurr2 years ago204The API is the exact same as the standard client instance based API.
376dd199Logan Kilpatrick2 years ago205
08b8179aDavid Schnurr2 years ago206This is intended to be used within REPLs or notebooks for faster iteration, **not** in application code.
2b21516eAtty Eleti3 years ago207
08b8179aDavid Schnurr2 years ago208We recommend that you always instantiate a client (e.g., with `client = OpenAI()`) in application code because:
2b21516eAtty Eleti3 years ago209
08b8179aDavid Schnurr2 years ago210- It can be difficult to reason about where client options are configured
211- It's not possible to change certain client options without potentially causing race conditions
212- It's harder to mock for testing purposes
213- It's not possible to control cleanup of network connections
214
215## Using types
216
47656567Stainless Bot2 years ago217Nested request parameters are [TypedDicts](https://docs.python.org/3/library/typing.html#typing.TypedDict). Responses are [Pydantic models](https://docs.pydantic.dev) which also provide helper methods for things like:
f4b9655fStainless Bot2 years ago218
47656567Stainless Bot2 years ago219- Serializing back into JSON, `model.to_json()`
220- Converting to a dictionary, `model.to_dict()`
2b21516eAtty Eleti3 years ago221
08b8179aDavid Schnurr2 years ago222Typed requests and responses provide autocomplete and documentation within your editor. If you would like to see type errors in VS Code to help catch bugs earlier, set `python.analysis.typeCheckingMode` to `basic`.
0e21703eTed Sanders4 years ago223
08b8179aDavid Schnurr2 years ago224## Pagination
0e21703eTed Sanders4 years ago225
08b8179aDavid Schnurr2 years ago226List methods in the OpenAI API are paginated.
227
228This library provides auto-paginating iterators with each list response, so you do not have to request successive pages manually:
0e21703eTed Sanders4 years ago229
230```python
08b8179aDavid Schnurr2 years ago231import openai
0e21703eTed Sanders4 years ago232
08b8179aDavid Schnurr2 years ago233client = OpenAI()
0e21703eTed Sanders4 years ago234
08b8179aDavid Schnurr2 years ago235all_jobs = []
236# Automatically fetches more pages as needed.
237for job in client.fine_tuning.jobs.list(
238limit=20,
239):
240# Do something with job here
241all_jobs.append(job)
242print(all_jobs)
0e21703eTed Sanders4 years ago243```
244
08b8179aDavid Schnurr2 years ago245Or, asynchronously:
0e21703eTed Sanders4 years ago246
08b8179aDavid Schnurr2 years ago247```python
248import asyncio
249import openai
0e21703eTed Sanders4 years ago250
08b8179aDavid Schnurr2 years ago251client = AsyncOpenAI()
0e21703eTed Sanders4 years ago252
253
08b8179aDavid Schnurr2 years ago254async def main() -> None:
255all_jobs = []
256# Iterate through items across all pages, issuing requests as needed.
257async for job in client.fine_tuning.jobs.list(
258limit=20,
259):
260all_jobs.append(job)
261print(all_jobs)
0e21703eTed Sanders4 years ago262
62b51ca0Boris Dayma4 years ago263
08b8179aDavid Schnurr2 years ago264asyncio.run(main())
265```
2942bf4bLogan Kilpatrick2 years ago266
08b8179aDavid Schnurr2 years ago267Alternatively, you can use the `.has_next_page()`, `.next_page_info()`, or `.get_next_page()` methods for more granular control working with pages:
2942bf4bLogan Kilpatrick2 years ago268
08b8179aDavid Schnurr2 years ago269```python
270first_page = await client.fine_tuning.jobs.list(
271limit=20,
272)
273if first_page.has_next_page():
274print(f"will fetch next page using these details: {first_page.next_page_info()}")
275next_page = await first_page.get_next_page()
276print(f"number of items we just fetched: {len(next_page.data)}")
277
278# Remove `await` for non-async usage.
62b51ca0Boris Dayma4 years ago279```
280
08b8179aDavid Schnurr2 years ago281Or just work directly with the returned data:
0e21703eTed Sanders4 years ago282
08b8179aDavid Schnurr2 years ago283```python
284first_page = await client.fine_tuning.jobs.list(
285limit=20,
286)
e389823bMorgan McGuire2 years ago287
08b8179aDavid Schnurr2 years ago288print(f"next page cursor: {first_page.after}") # => "next page cursor: ..."
289for job in first_page.data:
290print(job.id)
e389823bMorgan McGuire2 years ago291
08b8179aDavid Schnurr2 years ago292# Remove `await` for non-async usage.
293```
e389823bMorgan McGuire2 years ago294
08b8179aDavid Schnurr2 years ago295## Nested params
3c00e856hallacy3 years ago296
08b8179aDavid Schnurr2 years ago297Nested parameters are dictionaries, typed using `TypedDict`, for example:
3c00e856hallacy3 years ago298
299```python
08b8179aDavid Schnurr2 years ago300from openai import OpenAI
3c00e856hallacy3 years ago301
08b8179aDavid Schnurr2 years ago302client = OpenAI()
303
aa681899Stainless Bot2 years ago304completion = client.chat.completions.create(
305messages=[
306{
307"role": "user",
308"content": "Can you generate an example json object describing a fruit?",
309}
310],
9c8789c2Stainless Bot2 years ago311model="gpt-3.5-turbo-1106",
aa681899Stainless Bot2 years ago312response_format={"type": "json_object"},
313)
08b8179aDavid Schnurr2 years ago314```
3c00e856hallacy3 years ago315
2b23eb53Stainless Bot2 years ago316## File uploads
dc33cb9dMichelle Pokrass3 years ago317
08b8179aDavid Schnurr2 years ago318Request parameters that correspond to file uploads can be passed as `bytes`, a [`PathLike`](https://docs.python.org/3/library/os.html#os.PathLike) instance or a tuple of `(filename, contents, media type)`.
dc33cb9dMichelle Pokrass3 years ago319
376dd199Logan Kilpatrick2 years ago320```python
08b8179aDavid Schnurr2 years ago321from pathlib import Path
322from openai import OpenAI
323
324client = OpenAI()
325
326client.files.create(
327file=Path("input.jsonl"),
328purpose="fine-tune",
329)
dc33cb9dMichelle Pokrass3 years ago330```
331
08b8179aDavid Schnurr2 years ago332The 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.
376dd199Logan Kilpatrick2 years ago333
08b8179aDavid Schnurr2 years ago334## Handling errors
376dd199Logan Kilpatrick2 years ago335
08b8179aDavid Schnurr2 years ago336When 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.
2b21516eAtty Eleti3 years ago337
08b8179aDavid Schnurr2 years ago338When the API returns a non-success status code (that is, 4xx or 5xx
339response), a subclass of `openai.APIStatusError` is raised, containing `status_code` and `response` properties.
62b73b9bAtty Eleti3 years ago340
08b8179aDavid Schnurr2 years ago341All errors inherit from `openai.APIError`.
342
343```python
344import openai
345from openai import OpenAI
346
347client = OpenAI()
348
349try:
8dab1421Stainless Bot2 years ago350client.fine_tuning.jobs.create(
351model="gpt-3.5-turbo",
352training_file="file-abc123",
08b8179aDavid Schnurr2 years ago353)
354except openai.APIConnectionError as e:
355print("The server could not be reached")
356print(e.__cause__) # an underlying Exception, likely raised within httpx.
357except openai.RateLimitError as e:
358print("A 429 status code was received; we should back off a bit.")
359except openai.APIStatusError as e:
360print("Another non-200-range status code was received")
361print(e.status_code)
362print(e.response)
62b73b9bAtty Eleti3 years ago363```
364
08b8179aDavid Schnurr2 years ago365Error codes are as followed:
366
367| Status Code | Error Type |
368| ----------- | -------------------------- |
369| 400 | `BadRequestError` |
370| 401 | `AuthenticationError` |
371| 403 | `PermissionDeniedError` |
372| 404 | `NotFoundError` |
373| 422 | `UnprocessableEntityError` |
374| 429 | `RateLimitError` |
375| >=500 | `InternalServerError` |
376| N/A | `APIConnectionError` |
377
378### Retries
376dd199Logan Kilpatrick2 years ago379
08b8179aDavid Schnurr2 years ago380Certain errors are automatically retried 2 times by default, with a short exponential backoff.
381Connection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict,
382429 Rate Limit, and >=500 Internal errors are all retried by default.
0abf6413Andrew Chen Wang3 years ago383
08b8179aDavid Schnurr2 years ago384You can use the `max_retries` option to configure or disable retry settings:
0abf6413Andrew Chen Wang3 years ago385
386```python
08b8179aDavid Schnurr2 years ago387from openai import OpenAI
388
389# Configure the default for all requests:
390client = OpenAI(
391# default is 2
392max_retries=0,
393)
394
395# Or, configure per-request:
396client.with_options(max_retries=5).chat.completions.create(
397messages=[
398{
399"role": "user",
400"content": "How can I get the name of the current day in Node.js?",
401}
402],
403model="gpt-3.5-turbo",
404)
0abf6413Andrew Chen Wang3 years ago405```
406
08b8179aDavid Schnurr2 years ago407### Timeouts
0abf6413Andrew Chen Wang3 years ago408
08b8179aDavid Schnurr2 years ago409By default requests time out after 10 minutes. You can configure this with a `timeout` option,
410which accepts a float or an [`httpx.Timeout`](https://www.python-httpx.org/advanced/#fine-tuning-the-configuration) object:
376dd199Logan Kilpatrick2 years ago411
08b8179aDavid Schnurr2 years ago412```python
413from openai import OpenAI
414
415# Configure the default for all requests:
416client = OpenAI(
1381f46eStainless Bot2 years ago417# 20 seconds (default is 10 minutes)
08b8179aDavid Schnurr2 years ago418timeout=20.0,
419)
420
421# More granular control:
422client = OpenAI(
423timeout=httpx.Timeout(60.0, read=5.0, write=10.0, connect=2.0),
424)
425
426# Override per-request:
2a678e30Stainless Bot2 years ago427client.with_options(timeout=5.0).chat.completions.create(
08b8179aDavid Schnurr2 years ago428messages=[
429{
430"role": "user",
431"content": "How can I list all files in a directory using Python?",
432}
433],
434model="gpt-3.5-turbo",
435)
0abf6413Andrew Chen Wang3 years ago436```
437
08b8179aDavid Schnurr2 years ago438On timeout, an `APITimeoutError` is thrown.
376dd199Logan Kilpatrick2 years ago439
08b8179aDavid Schnurr2 years ago440Note that requests that time out are [retried twice by default](#retries).
376dd199Logan Kilpatrick2 years ago441
08b8179aDavid Schnurr2 years ago442## Advanced
376dd199Logan Kilpatrick2 years ago443
08b8179aDavid Schnurr2 years ago444### Logging
376dd199Logan Kilpatrick2 years ago445
08b8179aDavid Schnurr2 years ago446We use the standard library [`logging`](https://docs.python.org/3/library/logging.html) module.
376dd199Logan Kilpatrick2 years ago447
08b8179aDavid Schnurr2 years ago448You can enable logging by setting the environment variable `OPENAI_LOG` to `debug`.
376dd199Logan Kilpatrick2 years ago449
08b8179aDavid Schnurr2 years ago450```shell
451$ export OPENAI_LOG=debug
376dd199Logan Kilpatrick2 years ago452```
453
08b8179aDavid Schnurr2 years ago454### How to tell whether `None` means `null` or missing
dc33cb9dMichelle Pokrass3 years ago455
08b8179aDavid Schnurr2 years ago456In an API response, a field may be explicitly `null`, or missing entirely; in either case, its value is `None` in this library. You can differentiate the two cases with `.model_fields_set`:
3c6d4cd6Greg Brockman5 years ago457
08b8179aDavid Schnurr2 years ago458```py
459if response.my_field is None:
460if 'my_field' not in response.model_fields_set:
461print('Got json like {}, without a "my_field" key present at all.')
462else:
463print('Got json like {"my_field": null}.')
464```
376dd199Logan Kilpatrick2 years ago465
08b8179aDavid Schnurr2 years ago466### Accessing raw response data (e.g. headers)
376dd199Logan Kilpatrick2 years ago467
86379b44Stainless Bot2 years ago468The "raw" Response object can be accessed by prefixing `.with_raw_response.` to any HTTP method call, e.g.,
08b8179aDavid Schnurr2 years ago469
470```py
471from openai import OpenAI
472
473client = OpenAI()
474response = client.chat.completions.with_raw_response.create(
475messages=[{
476"role": "user",
477"content": "Say this is a test",
478}],
479model="gpt-3.5-turbo",
480)
481print(response.headers.get('X-My-Header'))
482
483completion = response.parse() # get the object that `chat.completions.create()` would have returned
484print(completion)
376dd199Logan Kilpatrick2 years ago485```
486
86379b44Stainless Bot2 years ago487These methods return an [`LegacyAPIResponse`](https://github.com/openai/openai-python/tree/main/src/openai/_legacy_response.py) object. This is a legacy class as we're changing it slightly in the next major version.
488
489For the sync client this will mostly be the same with the exception
490of `content` & `text` will be methods instead of properties. In the
491async client, all methods will be async.
492
493A migration script will be provided & the migration in general should
494be smooth.
495
496#### `.with_streaming_response`
497
498The above interface eagerly reads the full response body when you make the request, which may not always be what you want.
499
500To stream the response body, use `.with_streaming_response` instead, which requires a context manager and only reads the response body once you call `.read()`, `.text()`, `.json()`, `.iter_bytes()`, `.iter_text()`, `.iter_lines()` or `.parse()`. In the async client, these are async methods.
501
502As such, `.with_streaming_response` methods return a different [`APIResponse`](https://github.com/openai/openai-python/tree/main/src/openai/_response.py) object, and the async client returns an [`AsyncAPIResponse`](https://github.com/openai/openai-python/tree/main/src/openai/_response.py) object.
503
504```python
505with client.chat.completions.with_streaming_response.create(
506messages=[
507{
508"role": "user",
509"content": "Say this is a test",
510}
511],
512model="gpt-3.5-turbo",
513) as response:
514print(response.headers.get("X-My-Header"))
515
516for line in response.iter_lines():
517print(line)
518```
519
520The context manager is required so that the response will reliably be closed.
3c6d4cd6Greg Brockman5 years ago521
73869eeeStainless Bot2 years ago522### Making custom/undocumented requests
523
7931ebaaStainless Bot2 years ago524This library is typed for convenient access to the documented API.
73869eeeStainless Bot2 years ago525
526If you need to access undocumented endpoints, params, or response properties, the library can still be used.
527
528#### Undocumented endpoints
529
530To make requests to undocumented endpoints, you can make requests using `client.get`, `client.post`, and other
531http verbs. Options on the client will be respected (such as retries) will be respected when making this
532request.
533
534```py
535import httpx
536
537response = client.post(
538"/foo",
539cast_to=httpx.Response,
540body={"my_param": True},
541)
542
543print(response.headers.get("x-foo"))
544```
545
802819c8Stainless Bot2 years ago546#### Undocumented request params
73869eeeStainless Bot2 years ago547
548If you want to explicitly send an extra param, you can do so with the `extra_query`, `extra_body`, and `extra_headers` request
549options.
550
802819c8Stainless Bot2 years ago551#### Undocumented response properties
73869eeeStainless Bot2 years ago552
553To access undocumented response properties, you can access the extra fields like `response.unknown_prop`. You
554can also get all the extra fields on the Pydantic model as a dict with
555[`response.model_extra`](https://docs.pydantic.dev/latest/api/base_model/#pydantic.BaseModel.model_extra).
556
08b8179aDavid Schnurr2 years ago557### Configuring the HTTP client
376dd199Logan Kilpatrick2 years ago558
08b8179aDavid Schnurr2 years ago559You can directly override the [httpx client](https://www.python-httpx.org/api/#client) to customize it for your use case, including:
376dd199Logan Kilpatrick2 years ago560
08b8179aDavid Schnurr2 years ago561- Support for proxies
562- Custom transports
563- Additional [advanced](https://www.python-httpx.org/advanced/#client-instances) functionality
376dd199Logan Kilpatrick2 years ago564
565```python
347363edStainless Bot2 years ago566from openai import OpenAI, DefaultHttpxClient
08b8179aDavid Schnurr2 years ago567
568client = OpenAI(
0733934fStainless Bot2 years ago569# Or use the `OPENAI_BASE_URL` env var
08b8179aDavid Schnurr2 years ago570base_url="http://my.test.server.example.com:8083",
347363edStainless Bot2 years ago571http_client=DefaultHttpxClient(
08b8179aDavid Schnurr2 years ago572proxies="http://my.test.proxy.example.com",
573transport=httpx.HTTPTransport(local_address="0.0.0.0"),
574),
575)
576```
577
578### Managing HTTP resources
579
580By default the library closes underlying HTTP connections whenever the client is [garbage collected](https://docs.python.org/3/reference/datamodel.html#object.__del__). You can manually close the client using the `.close()` method if desired, or with a context manager that closes when exiting.
581
582## Microsoft Azure OpenAI
583
584To use this library with [Azure OpenAI](https://learn.microsoft.com/en-us/azure/ai-services/openai/overview), use the `AzureOpenAI`
585class instead of the `OpenAI` class.
586
587> [!IMPORTANT]
588> The Azure API shape differs from the core API shape which means that the static types for responses / params
589> won't always be correct.
376dd199Logan Kilpatrick2 years ago590
08b8179aDavid Schnurr2 years ago591```py
592from openai import AzureOpenAI
376dd199Logan Kilpatrick2 years ago593
08b8179aDavid Schnurr2 years ago594# gets the API Key from environment variable AZURE_OPENAI_API_KEY
595client = AzureOpenAI(
596# https://learn.microsoft.com/en-us/azure/ai-services/openai/reference#rest-api-versioning
819ae68dJackYu2 years ago597api_version="2023-07-01-preview",
08b8179aDavid Schnurr2 years ago598# https://learn.microsoft.com/en-us/azure/cognitive-services/openai/how-to/create-resource?pivots=web-portal#create-a-resource
599azure_endpoint="https://example-endpoint.openai.azure.com",
600)
601
602completion = client.chat.completions.create(
603model="deployment-name", # e.g. gpt-35-instant
604messages=[
605{
606"role": "user",
607"content": "How do I output all files in a directory using Python?",
608},
609],
610)
47656567Stainless Bot2 years ago611print(completion.to_json())
376dd199Logan Kilpatrick2 years ago612```
3c6d4cd6Greg Brockman5 years ago613
08b8179aDavid Schnurr2 years ago614In addition to the options provided in the base `OpenAI` client, the following options are provided:
615
7758c54bStainless Bot2 years ago616- `azure_endpoint` (or the `AZURE_OPENAI_ENDPOINT` environment variable)
08b8179aDavid Schnurr2 years ago617- `azure_deployment`
7758c54bStainless Bot2 years ago618- `api_version` (or the `OPENAI_API_VERSION` environment variable)
619- `azure_ad_token` (or the `AZURE_OPENAI_AD_TOKEN` environment variable)
08b8179aDavid Schnurr2 years ago620- `azure_ad_token_provider`
621
812839cbMikyo King2 years ago622An example of using the client with Azure Active Directory can be found [here](https://github.com/openai/openai-python/blob/main/examples/azure_ad.py).
08b8179aDavid Schnurr2 years ago623
624## Versioning
625
626This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:
627
6281. Changes that only affect static types, without breaking runtime behavior.
6292. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals)_.
6303. Changes that we do not expect to impact the vast majority of users in practice.
631
632We take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.
633
634We are keen for your feedback; please open an [issue](https://www.github.com/openai/openai-python/issues) with questions, bugs, or suggestions.
635
636## Requirements
3c6d4cd6Greg Brockman5 years ago637
08b8179aDavid Schnurr2 years ago638Python 3.7 or higher.