openai/openai-python

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.50.1

Branches

Tags

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

Clone

HTTPS

Download ZIP

README.md

715lines · 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
2e8ea52bstainless-app[bot]1 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
192b8f2bDan Corin1 years ago54### Vision
55
56With a hosted image:
57
58```python
59response = client.chat.completions.create(
60model="gpt-4o-mini",
61messages=[
62{
63"role": "user",
64"content": [
65{"type": "text", "text": prompt},
66{
67"type": "image_url",
68"image_url": {"url": f"{img_url}"},
69},
70],
71}
72],
73)
74```
75
76With the image as a base64 encoded string:
77
78```python
79response = client.chat.completions.create(
80model="gpt-4o-mini",
81messages=[
82{
83"role": "user",
84"content": [
85{"type": "text", "text": prompt},
86{
87"type": "image_url",
88"image_url": {"url": f"data:{img_type};base64,{img_b64_str}"},
89},
90],
91}
92],
93)
94```
95
595f3b36Stainless Bot2 years ago96### Polling Helpers
97
5b20698dStainless Bot2 years ago98When 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 ago99helper functions which will poll the status until it reaches a terminal state and then return the resulting object.
137f38baNino Risteski2 years ago100If an API method results in an action that could benefit from polling there will be a corresponding version of the
595f3b36Stainless Bot2 years ago101method ending in '\_and_poll'.
102
103For instance to create a Run and poll until it reaches a terminal state you can run:
104
105```python
106run = client.beta.threads.runs.create_and_poll(
107thread_id=thread.id,
108assistant_id=assistant.id,
109)
110```
111
112More 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)
113
5b20698dStainless Bot2 years ago114### Bulk Upload Helpers
115
137f38baNino Risteski2 years ago116When creating and interacting with vector stores, you can use polling helpers to monitor the status of operations.
5b20698dStainless Bot2 years ago117For convenience, we also provide a bulk upload helper to allow you to simultaneously upload several files at once.
118
119```python
120sample_files = [Path("sample-paper.pdf"), ...]
121
122batch = await client.vector_stores.file_batches.upload_and_poll(
123store.id,
124files=sample_files,
125)
126```
127
5cfb125aStainless Bot2 years ago128### Streaming Helpers
129
137f38baNino Risteski2 years ago130The SDK also includes helpers to process streams and handle incoming events.
5cfb125aStainless Bot2 years ago131
132```python
595f3b36Stainless Bot2 years ago133with client.beta.threads.runs.stream(
5cfb125aStainless Bot2 years ago134thread_id=thread.id,
135assistant_id=assistant.id,
136instructions="Please address the user as Jane Doe. The user has a premium account.",
137) as stream:
138for event in stream:
139# Print the text from text delta events
140if event.type == "thread.message.delta" and event.data.delta.content:
141print(event.data.delta.content[0].text)
142```
143
144More information on streaming helpers can be found in the dedicated documentation: [helpers.md](helpers.md)
145
08b8179aDavid Schnurr2 years ago146## Async usage
3c6d4cd6Greg Brockman5 years ago147
08b8179aDavid Schnurr2 years ago148Simply import `AsyncOpenAI` instead of `OpenAI` and use `await` with each API call:
ede08829Jakub Roztocil3 years ago149
08b8179aDavid Schnurr2 years ago150```python
fb5ba01cStainless Bot2 years ago151import os
08b8179aDavid Schnurr2 years ago152import asyncio
153from openai import AsyncOpenAI
ede08829Jakub Roztocil3 years ago154
08b8179aDavid Schnurr2 years ago155client = AsyncOpenAI(
fb5ba01cStainless Bot2 years ago156# This is the default and can be omitted
157api_key=os.environ.get("OPENAI_API_KEY"),
08b8179aDavid Schnurr2 years ago158)
ede08829Jakub Roztocil3 years ago159
160
08b8179aDavid Schnurr2 years ago161async def main() -> None:
162chat_completion = await client.chat.completions.create(
163messages=[
164{
165"role": "user",
166"content": "Say this is a test",
167}
168],
169model="gpt-3.5-turbo",
170)
ede08829Jakub Roztocil3 years ago171
172
08b8179aDavid Schnurr2 years ago173asyncio.run(main())
2b21516eAtty Eleti3 years ago174```
ede08829Jakub Roztocil3 years ago175
08b8179aDavid Schnurr2 years ago176Functionality between the synchronous and asynchronous clients is otherwise identical.
177
2b23eb53Stainless Bot2 years ago178## Streaming responses
08b8179aDavid Schnurr2 years ago179
180We provide support for streaming responses using Server Side Events (SSE).
d53d9efbRachel Lim5 years ago181
08b8179aDavid Schnurr2 years ago182```python
183from openai import OpenAI
184
185client = OpenAI()
d53d9efbRachel Lim5 years ago186
08b8179aDavid Schnurr2 years ago187stream = client.chat.completions.create(
188model="gpt-4",
189messages=[{"role": "user", "content": "Say this is a test"}],
190stream=True,
191)
54c7c512Stainless Bot2 years ago192for chunk in stream:
a3da0196Stainless Bot2 years ago193print(chunk.choices[0].delta.content or "", end="")
d53d9efbRachel Lim5 years ago194```
195
08b8179aDavid Schnurr2 years ago196The async client uses the exact same interface.
d53d9efbRachel Lim5 years ago197
198```python
08b8179aDavid Schnurr2 years ago199from openai import AsyncOpenAI
200
201client = AsyncOpenAI()
202
a3da0196Stainless Bot2 years ago203
dfe1c8daSahand Sojoodi2 years ago204async def main():
205stream = await client.chat.completions.create(
206model="gpt-4",
207messages=[{"role": "user", "content": "Say this is a test"}],
208stream=True,
209)
210async for chunk in stream:
a3da0196Stainless Bot2 years ago211print(chunk.choices[0].delta.content or "", end="")
212
dfe1c8daSahand Sojoodi2 years ago213
214asyncio.run(main())
53e5ba4bt-asutedjo4 years ago215```
2b21516eAtty Eleti3 years ago216
08b8179aDavid Schnurr2 years ago217## Module-level client
d53d9efbRachel Lim5 years ago218
08b8179aDavid Schnurr2 years ago219> [!IMPORTANT]
220> We highly recommend instantiating client instances instead of relying on the global client.
d53d9efbRachel Lim5 years ago221
08b8179aDavid Schnurr2 years ago222We also expose a global client instance that is accessible in a similar fashion to versions prior to v1.
6572ef4fZheNing Hu3 years ago223
08b8179aDavid Schnurr2 years ago224```py
225import openai
62b73b9bAtty Eleti3 years ago226
08b8179aDavid Schnurr2 years ago227# optional; defaults to `os.environ['OPENAI_API_KEY']`
228openai.api_key = '...'
229
230# all client options can be configured just like the `OpenAI` instantiation counterpart
231openai.base_url = "https://..."
232openai.default_headers = {"x-foo": "true"}
233
234completion = openai.chat.completions.create(
235model="gpt-4",
236messages=[
237{
238"role": "user",
239"content": "How do I output all files in a directory using Python?",
240},
241],
242)
62b73b9bAtty Eleti3 years ago243print(completion.choices[0].message.content)
244```
245
137f38baNino Risteski2 years ago246The API is the exact same as the standard client instance-based API.
376dd199Logan Kilpatrick2 years ago247
08b8179aDavid Schnurr2 years ago248This is intended to be used within REPLs or notebooks for faster iteration, **not** in application code.
2b21516eAtty Eleti3 years ago249
08b8179aDavid Schnurr2 years ago250We recommend that you always instantiate a client (e.g., with `client = OpenAI()`) in application code because:
2b21516eAtty Eleti3 years ago251
08b8179aDavid Schnurr2 years ago252- It can be difficult to reason about where client options are configured
253- It's not possible to change certain client options without potentially causing race conditions
254- It's harder to mock for testing purposes
255- It's not possible to control cleanup of network connections
256
257## Using types
258
47656567Stainless Bot2 years ago259Nested 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 ago260
47656567Stainless Bot2 years ago261- Serializing back into JSON, `model.to_json()`
262- Converting to a dictionary, `model.to_dict()`
2b21516eAtty Eleti3 years ago263
08b8179aDavid Schnurr2 years ago264Typed 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 ago265
08b8179aDavid Schnurr2 years ago266## Pagination
0e21703eTed Sanders4 years ago267
08b8179aDavid Schnurr2 years ago268List methods in the OpenAI API are paginated.
269
270This library provides auto-paginating iterators with each list response, so you do not have to request successive pages manually:
0e21703eTed Sanders4 years ago271
272```python
ff5add01stainless-app[bot]1 years ago273from openai import OpenAI
0e21703eTed Sanders4 years ago274
08b8179aDavid Schnurr2 years ago275client = OpenAI()
0e21703eTed Sanders4 years ago276
08b8179aDavid Schnurr2 years ago277all_jobs = []
278# Automatically fetches more pages as needed.
279for job in client.fine_tuning.jobs.list(
280limit=20,
281):
282# Do something with job here
283all_jobs.append(job)
284print(all_jobs)
0e21703eTed Sanders4 years ago285```
286
08b8179aDavid Schnurr2 years ago287Or, asynchronously:
0e21703eTed Sanders4 years ago288
08b8179aDavid Schnurr2 years ago289```python
290import asyncio
ff5add01stainless-app[bot]1 years ago291from openai import AsyncOpenAI
0e21703eTed Sanders4 years ago292
08b8179aDavid Schnurr2 years ago293client = AsyncOpenAI()
0e21703eTed Sanders4 years ago294
295
08b8179aDavid Schnurr2 years ago296async def main() -> None:
297all_jobs = []
298# Iterate through items across all pages, issuing requests as needed.
299async for job in client.fine_tuning.jobs.list(
300limit=20,
301):
302all_jobs.append(job)
303print(all_jobs)
0e21703eTed Sanders4 years ago304
62b51ca0Boris Dayma4 years ago305
08b8179aDavid Schnurr2 years ago306asyncio.run(main())
307```
2942bf4bLogan Kilpatrick2 years ago308
08b8179aDavid Schnurr2 years ago309Alternatively, 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 ago310
08b8179aDavid Schnurr2 years ago311```python
312first_page = await client.fine_tuning.jobs.list(
313limit=20,
314)
315if first_page.has_next_page():
316print(f"will fetch next page using these details: {first_page.next_page_info()}")
317next_page = await first_page.get_next_page()
318print(f"number of items we just fetched: {len(next_page.data)}")
319
320# Remove `await` for non-async usage.
62b51ca0Boris Dayma4 years ago321```
322
08b8179aDavid Schnurr2 years ago323Or just work directly with the returned data:
0e21703eTed Sanders4 years ago324
08b8179aDavid Schnurr2 years ago325```python
326first_page = await client.fine_tuning.jobs.list(
327limit=20,
328)
e389823bMorgan McGuire2 years ago329
08b8179aDavid Schnurr2 years ago330print(f"next page cursor: {first_page.after}") # => "next page cursor: ..."
331for job in first_page.data:
332print(job.id)
e389823bMorgan McGuire2 years ago333
08b8179aDavid Schnurr2 years ago334# Remove `await` for non-async usage.
335```
e389823bMorgan McGuire2 years ago336
08b8179aDavid Schnurr2 years ago337## Nested params
3c00e856hallacy3 years ago338
08b8179aDavid Schnurr2 years ago339Nested parameters are dictionaries, typed using `TypedDict`, for example:
3c00e856hallacy3 years ago340
341```python
08b8179aDavid Schnurr2 years ago342from openai import OpenAI
3c00e856hallacy3 years ago343
08b8179aDavid Schnurr2 years ago344client = OpenAI()
345
aa681899Stainless Bot2 years ago346completion = client.chat.completions.create(
347messages=[
348{
349"role": "user",
350"content": "Can you generate an example json object describing a fruit?",
351}
352],
9c8789c2Stainless Bot2 years ago353model="gpt-3.5-turbo-1106",
aa681899Stainless Bot2 years ago354response_format={"type": "json_object"},
355)
08b8179aDavid Schnurr2 years ago356```
3c00e856hallacy3 years ago357
2b23eb53Stainless Bot2 years ago358## File uploads
dc33cb9dMichelle Pokrass3 years ago359
08b8179aDavid Schnurr2 years ago360Request 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 ago361
376dd199Logan Kilpatrick2 years ago362```python
08b8179aDavid Schnurr2 years ago363from pathlib import Path
364from openai import OpenAI
365
366client = OpenAI()
367
368client.files.create(
369file=Path("input.jsonl"),
370purpose="fine-tune",
371)
dc33cb9dMichelle Pokrass3 years ago372```
373
08b8179aDavid Schnurr2 years ago374The 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 ago375
08b8179aDavid Schnurr2 years ago376## Handling errors
376dd199Logan Kilpatrick2 years ago377
08b8179aDavid Schnurr2 years ago378When 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 ago379
08b8179aDavid Schnurr2 years ago380When the API returns a non-success status code (that is, 4xx or 5xx
381response), a subclass of `openai.APIStatusError` is raised, containing `status_code` and `response` properties.
62b73b9bAtty Eleti3 years ago382
08b8179aDavid Schnurr2 years ago383All errors inherit from `openai.APIError`.
384
385```python
386import openai
387from openai import OpenAI
388
389client = OpenAI()
390
391try:
8dab1421Stainless Bot2 years ago392client.fine_tuning.jobs.create(
393model="gpt-3.5-turbo",
394training_file="file-abc123",
08b8179aDavid Schnurr2 years ago395)
396except openai.APIConnectionError as e:
397print("The server could not be reached")
398print(e.__cause__) # an underlying Exception, likely raised within httpx.
399except openai.RateLimitError as e:
400print("A 429 status code was received; we should back off a bit.")
401except openai.APIStatusError as e:
402print("Another non-200-range status code was received")
403print(e.status_code)
404print(e.response)
62b73b9bAtty Eleti3 years ago405```
406
08b8179aDavid Schnurr2 years ago407Error codes are as followed:
408
409| Status Code | Error Type |
410| ----------- | -------------------------- |
411| 400 | `BadRequestError` |
412| 401 | `AuthenticationError` |
413| 403 | `PermissionDeniedError` |
414| 404 | `NotFoundError` |
415| 422 | `UnprocessableEntityError` |
416| 429 | `RateLimitError` |
417| >=500 | `InternalServerError` |
418| N/A | `APIConnectionError` |
419
4b302346Robert Craigie1 years ago420## Request IDs
421
422> For more information on debugging requests, see [these docs](https://platform.openai.com/docs/api-reference/debugging-requests)
423
424All object responses in the SDK provide a `_request_id` property which is added from the `x-request-id` response header so that you can quickly log failing requests and report them back to OpenAI.
425
426```python
427completion = await client.chat.completions.create(
428messages=[{"role": "user", "content": "Say this is a test"}], model="gpt-4"
429)
430print(completion._request_id) # req_123
431```
432
433Note that unlike other properties that use an `_` prefix, the `_request_id` property
434*is* public. Unless documented otherwise, *all* other `_` prefix properties,
435methods and modules are *private*.
436
437
08b8179aDavid Schnurr2 years ago438### Retries
376dd199Logan Kilpatrick2 years ago439
08b8179aDavid Schnurr2 years ago440Certain errors are automatically retried 2 times by default, with a short exponential backoff.
441Connection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict,
442429 Rate Limit, and >=500 Internal errors are all retried by default.
0abf6413Andrew Chen Wang3 years ago443
08b8179aDavid Schnurr2 years ago444You can use the `max_retries` option to configure or disable retry settings:
0abf6413Andrew Chen Wang3 years ago445
446```python
08b8179aDavid Schnurr2 years ago447from openai import OpenAI
448
449# Configure the default for all requests:
450client = OpenAI(
451# default is 2
452max_retries=0,
453)
454
455# Or, configure per-request:
456client.with_options(max_retries=5).chat.completions.create(
457messages=[
458{
459"role": "user",
460"content": "How can I get the name of the current day in Node.js?",
461}
462],
463model="gpt-3.5-turbo",
464)
0abf6413Andrew Chen Wang3 years ago465```
466
08b8179aDavid Schnurr2 years ago467### Timeouts
0abf6413Andrew Chen Wang3 years ago468
08b8179aDavid Schnurr2 years ago469By default requests time out after 10 minutes. You can configure this with a `timeout` option,
470which accepts a float or an [`httpx.Timeout`](https://www.python-httpx.org/advanced/#fine-tuning-the-configuration) object:
376dd199Logan Kilpatrick2 years ago471
08b8179aDavid Schnurr2 years ago472```python
473from openai import OpenAI
474
475# Configure the default for all requests:
476client = OpenAI(
1381f46eStainless Bot2 years ago477# 20 seconds (default is 10 minutes)
08b8179aDavid Schnurr2 years ago478timeout=20.0,
479)
480
481# More granular control:
482client = OpenAI(
483timeout=httpx.Timeout(60.0, read=5.0, write=10.0, connect=2.0),
484)
485
486# Override per-request:
2a678e30Stainless Bot2 years ago487client.with_options(timeout=5.0).chat.completions.create(
08b8179aDavid Schnurr2 years ago488messages=[
489{
490"role": "user",
491"content": "How can I list all files in a directory using Python?",
492}
493],
494model="gpt-3.5-turbo",
495)
0abf6413Andrew Chen Wang3 years ago496```
497
08b8179aDavid Schnurr2 years ago498On timeout, an `APITimeoutError` is thrown.
376dd199Logan Kilpatrick2 years ago499
08b8179aDavid Schnurr2 years ago500Note that requests that time out are [retried twice by default](#retries).
376dd199Logan Kilpatrick2 years ago501
08b8179aDavid Schnurr2 years ago502## Advanced
376dd199Logan Kilpatrick2 years ago503
08b8179aDavid Schnurr2 years ago504### Logging
376dd199Logan Kilpatrick2 years ago505
08b8179aDavid Schnurr2 years ago506We use the standard library [`logging`](https://docs.python.org/3/library/logging.html) module.
376dd199Logan Kilpatrick2 years ago507
08b8179aDavid Schnurr2 years ago508You can enable logging by setting the environment variable `OPENAI_LOG` to `debug`.
376dd199Logan Kilpatrick2 years ago509
08b8179aDavid Schnurr2 years ago510```shell
511$ export OPENAI_LOG=debug
376dd199Logan Kilpatrick2 years ago512```
513
08b8179aDavid Schnurr2 years ago514### How to tell whether `None` means `null` or missing
dc33cb9dMichelle Pokrass3 years ago515
08b8179aDavid Schnurr2 years ago516In 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 ago517
08b8179aDavid Schnurr2 years ago518```py
519if response.my_field is None:
520if 'my_field' not in response.model_fields_set:
521print('Got json like {}, without a "my_field" key present at all.')
522else:
523print('Got json like {"my_field": null}.')
524```
376dd199Logan Kilpatrick2 years ago525
08b8179aDavid Schnurr2 years ago526### Accessing raw response data (e.g. headers)
376dd199Logan Kilpatrick2 years ago527
86379b44Stainless Bot2 years ago528The "raw" Response object can be accessed by prefixing `.with_raw_response.` to any HTTP method call, e.g.,
08b8179aDavid Schnurr2 years ago529
530```py
531from openai import OpenAI
532
533client = OpenAI()
534response = client.chat.completions.with_raw_response.create(
535messages=[{
536"role": "user",
537"content": "Say this is a test",
538}],
539model="gpt-3.5-turbo",
540)
541print(response.headers.get('X-My-Header'))
542
543completion = response.parse() # get the object that `chat.completions.create()` would have returned
544print(completion)
376dd199Logan Kilpatrick2 years ago545```
546
86379b44Stainless Bot2 years ago547These 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.
548
549For the sync client this will mostly be the same with the exception
550of `content` & `text` will be methods instead of properties. In the
551async client, all methods will be async.
552
553A migration script will be provided & the migration in general should
554be smooth.
555
556#### `.with_streaming_response`
557
558The above interface eagerly reads the full response body when you make the request, which may not always be what you want.
559
560To 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.
561
562As 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.
563
564```python
565with client.chat.completions.with_streaming_response.create(
566messages=[
567{
568"role": "user",
569"content": "Say this is a test",
570}
571],
572model="gpt-3.5-turbo",
573) as response:
574print(response.headers.get("X-My-Header"))
575
576for line in response.iter_lines():
577print(line)
578```
579
580The context manager is required so that the response will reliably be closed.
3c6d4cd6Greg Brockman5 years ago581
73869eeeStainless Bot2 years ago582### Making custom/undocumented requests
583
7931ebaaStainless Bot2 years ago584This library is typed for convenient access to the documented API.
73869eeeStainless Bot2 years ago585
586If you need to access undocumented endpoints, params, or response properties, the library can still be used.
587
588#### Undocumented endpoints
589
590To make requests to undocumented endpoints, you can make requests using `client.get`, `client.post`, and other
591http verbs. Options on the client will be respected (such as retries) will be respected when making this
592request.
593
594```py
595import httpx
596
597response = client.post(
598"/foo",
599cast_to=httpx.Response,
600body={"my_param": True},
601)
602
603print(response.headers.get("x-foo"))
604```
605
802819c8Stainless Bot2 years ago606#### Undocumented request params
73869eeeStainless Bot2 years ago607
608If you want to explicitly send an extra param, you can do so with the `extra_query`, `extra_body`, and `extra_headers` request
609options.
610
802819c8Stainless Bot2 years ago611#### Undocumented response properties
73869eeeStainless Bot2 years ago612
613To access undocumented response properties, you can access the extra fields like `response.unknown_prop`. You
614can also get all the extra fields on the Pydantic model as a dict with
615[`response.model_extra`](https://docs.pydantic.dev/latest/api/base_model/#pydantic.BaseModel.model_extra).
616
08b8179aDavid Schnurr2 years ago617### Configuring the HTTP client
376dd199Logan Kilpatrick2 years ago618
08b8179aDavid Schnurr2 years ago619You can directly override the [httpx client](https://www.python-httpx.org/api/#client) to customize it for your use case, including:
376dd199Logan Kilpatrick2 years ago620
08b8179aDavid Schnurr2 years ago621- Support for proxies
622- Custom transports
d3254d12stainless-app[bot]2 years ago623- Additional [advanced](https://www.python-httpx.org/advanced/clients/) functionality
376dd199Logan Kilpatrick2 years ago624
625```python
347363edStainless Bot2 years ago626from openai import OpenAI, DefaultHttpxClient
08b8179aDavid Schnurr2 years ago627
628client = OpenAI(
0733934fStainless Bot2 years ago629# Or use the `OPENAI_BASE_URL` env var
38dd5348Adrian Cole1 years ago630base_url="http://my.test.server.example.com:8083/v1",
347363edStainless Bot2 years ago631http_client=DefaultHttpxClient(
08b8179aDavid Schnurr2 years ago632proxies="http://my.test.proxy.example.com",
633transport=httpx.HTTPTransport(local_address="0.0.0.0"),
634),
635)
636```
637
f8f01a61stainless-app[bot]1 years ago638You can also customize the client on a per-request basis by using `with_options()`:
639
640```python
641client.with_options(http_client=DefaultHttpxClient(...))
642```
643
08b8179aDavid Schnurr2 years ago644### Managing HTTP resources
645
646By 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.
647
648## Microsoft Azure OpenAI
649
6e7d8548Scott Addie2 years ago650To use this library with [Azure OpenAI](https://learn.microsoft.com/azure/ai-services/openai/overview), use the `AzureOpenAI`
08b8179aDavid Schnurr2 years ago651class instead of the `OpenAI` class.
652
653> [!IMPORTANT]
654> The Azure API shape differs from the core API shape which means that the static types for responses / params
655> won't always be correct.
376dd199Logan Kilpatrick2 years ago656
08b8179aDavid Schnurr2 years ago657```py
658from openai import AzureOpenAI
376dd199Logan Kilpatrick2 years ago659
08b8179aDavid Schnurr2 years ago660# gets the API Key from environment variable AZURE_OPENAI_API_KEY
661client = AzureOpenAI(
6e7d8548Scott Addie2 years ago662# https://learn.microsoft.com/azure/ai-services/openai/reference#rest-api-versioning
819ae68dJackYu2 years ago663api_version="2023-07-01-preview",
6e7d8548Scott Addie2 years ago664# https://learn.microsoft.com/azure/cognitive-services/openai/how-to/create-resource?pivots=web-portal#create-a-resource
08b8179aDavid Schnurr2 years ago665azure_endpoint="https://example-endpoint.openai.azure.com",
666)
667
668completion = client.chat.completions.create(
669model="deployment-name", # e.g. gpt-35-instant
670messages=[
671{
672"role": "user",
673"content": "How do I output all files in a directory using Python?",
674},
675],
676)
47656567Stainless Bot2 years ago677print(completion.to_json())
376dd199Logan Kilpatrick2 years ago678```
3c6d4cd6Greg Brockman5 years ago679
08b8179aDavid Schnurr2 years ago680In addition to the options provided in the base `OpenAI` client, the following options are provided:
681
7758c54bStainless Bot2 years ago682- `azure_endpoint` (or the `AZURE_OPENAI_ENDPOINT` environment variable)
08b8179aDavid Schnurr2 years ago683- `azure_deployment`
7758c54bStainless Bot2 years ago684- `api_version` (or the `OPENAI_API_VERSION` environment variable)
685- `azure_ad_token` (or the `AZURE_OPENAI_AD_TOKEN` environment variable)
08b8179aDavid Schnurr2 years ago686- `azure_ad_token_provider`
687
6e7d8548Scott Addie2 years ago688An example of using the client with Microsoft Entra ID (formerly known as Azure Active Directory) can be found [here](https://github.com/openai/openai-python/blob/main/examples/azure_ad.py).
08b8179aDavid Schnurr2 years ago689
690## Versioning
691
692This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:
693
6941. Changes that only affect static types, without breaking runtime behavior.
6952. 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)_.
6963. Changes that we do not expect to impact the vast majority of users in practice.
697
698We take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.
699
700We are keen for your feedback; please open an [issue](https://www.github.com/openai/openai-python/issues) with questions, bugs, or suggestions.
701
fee10404stainless-app[bot]1 years ago702### Determining the installed version
703
704If you've upgraded to the latest version but aren't seeing any new features you were expecting then your python environment is likely still using an older version.
705
706You can determine the version that is being used at runtime with:
707
708```py
709import openai
710print(openai.__version__)
711```
712
08b8179aDavid Schnurr2 years ago713## Requirements
3c6d4cd6Greg Brockman5 years ago714
08b8179aDavid Schnurr2 years ago715Python 3.7 or higher.