Skip to content

Commit

Permalink
update readme, rework streaming and function support
Browse files Browse the repository at this point in the history
  • Loading branch information
trisongz committed Oct 6, 2023
1 parent 93a4443 commit 4ad50e0
Show file tree
Hide file tree
Showing 14 changed files with 1,156 additions and 18 deletions.
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
# Changelogs

#### v0.0.35 (2023-10-06)

**Additions**

- Added `auto_retry` option to `OpenAI` client, which will automatically retry failed requests.
- Added `RotatingClients` class which handles the rotation of multiple clients. This can be enabled by passing `rotating_clients=True` to the `OpenAI` client while configuring.
- Added `OpenAI.chat_create` and `OpenAI.async_chat_create` methods which automatically handles rotating clients and retrying failed requests.
- Added `azure_model_mapping` which allows automatically mapping of Azure models to OpenAI models when passing `openai` models as a parameter, it will automatically convert it to the Azure model. This is only done in `chat` implementation.

**Fixes**

- Fixed `api_version` Configuration handling.
- Fixed parsing of `function_call` in streaming implementation.



#### v0.0.34 (2023-10-06)

**Changes**
Expand Down
172 changes: 172 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,178 @@ result: CompletionResponse = asyncio.run(

```

### Initialize Clients Manually

```python

from async_openai import OpenAI

# Configure your primary client (default)


OpenAI.configure(
api_key = "sk-XXXX",
organization = "org-XXXX",
debug_enabled = False,

# Azure Configuration
azure_api_base = 'https://....openai.azure.com/',
azure_api_version = '2023-07-01-preview',
azure_api_key = '....',
)

# Returns the default client (openai)
oai = OpenAI.init_api_client()

# Configure your secondary client (azure) and use it directly
az = OpenAI.init_api_client('az', set_as_default = False, debug_enabled = True)
result = az.completions.create(
prompt = 'say this is a test',
max_tokens = 4,
stream = True
)


# Use the default client (openai)
result = OpenAI.completions.create(
prompt = 'say this is a test',
max_tokens = 4,
stream = True
)
# Or
result = oai.completions.create(
prompt = 'say this is a test',
max_tokens = 4,
stream = True
)

```

### Handling Errors, Retries, and Rotations

The below will show you how to rotate between multiple clients when you hit an error.

**Important** Auto-rotation is only supported with `chat_create` and `async_chat_create` methods. Otherwise, you should handle the rotation manually.

```python

import asyncio
from async_openai import OpenAI, ChatResponse
from async_openai.utils import logger

OpenAI.configure(
api_key = "sk-XXXX",
organization = "org-XXXX",
debug_enabled = False,

# Azure Configuration
azure_api_base = 'https://....openai.azure.com/',
azure_api_version = '2023-07-01-preview',
azure_api_key = '....',

# This will allow you to auto rotate clients when you hit an error.
# But only if you have multiple clients configured and are using `OpenAI.chat_create`
enable_rotating_clients = True,

# This will prioritize Azure over OpenAI when using `OpenAI.chat_create`
prioritize = "azure",
)

# Display the current client
OpenAI.get_current_client_info(verbose = True)

# Rotate to the next client
# OpenAI.rotate_client(verbose = True)

###
# [Sync] create a completion with auto-rotation and auto-retry
###

result: ChatResponse = OpenAI.chat_create(
model = "gpt-3.5-turbo-16k",
messages = [
{"role": "user", "content": "Translate the following English text to French: “Multiple models, each with different capabilities and price points. Prices are per 1,000 tokens. You can think of tokens as pieces of words, where 1,000 tokens is about 750 words. This paragraph is 35 tokens”"}
],
auto_retry = True,

)

logger.info(f'Result Chat Message: {result.messages}')
logger.info(f'Result Usage: {result.usage}')
logger.info(f'Result Consumption: {result.consumption}')

###
# [Async] create a completion with auto-rotation and auto-retry
###

result: ChatResponse = asyncio.run(
OpenAI.async_chat_create(
model = "gpt-3.5-turbo-16k",
messages = [
{"role": "user", "content": "Translate the following English text to French: “Multiple models, each with different capabilities and price points. Prices are per 1,000 tokens. You can think of tokens as pieces of words, where 1,000 tokens is about 750 words. This paragraph is 35 tokens”"}
],
auto_retry = True,
)
)

```

### Function Calls

The latest version of the API allows for function calls to be made. This is currently only supported in `Chat` and requires api version: `2023-07-01-preview` for `azure`.

Function calls support using `pydantic` models to auto-generate the schemas

```python

import asyncio
from enum import Enum
from client_rotate import OpenAI
from async_openai.utils import logger
from pydantic import BaseModel, Field

class Unit(str, Enum):
celsius = "celsius"
fahrenheit = "fahrenheit"

class Weather(BaseModel):
location: str = Field(..., description="The city and state, e.g. San Francisco, CA.")
unit: Unit = Field(Unit.fahrenheit)

functions = [
{
"name": "get_current_weather",
"description": "Get the current weather in a given location",
"parameters": Weather,
}
]

result: ChatResponse = OpenAI.chat_create(
model = "gpt-3.5-turbo-16k",
messages = [
{"role": "user", "content": "What's the weather like in Boston today?"}
],
functions = functions,
auto_retry = True,
)

logger.info(f'Result Chat Message: {result.messages}')
logger.info(f'Result Chat Function: {result.function_results}')
logger.info(f'Result Usage: {result.usage}')
logger.info(f'Result Consumption: {result.consumption}')

"""
Result:
> Result Chat Message: [ChatMessage(content='', role='assistant', function_call=FunctionCall(name='get_current_weather', arguments={'location': 'Boston, MA'}), name=None)]
> Result Chat Function: [FunctionCall(name='get_current_weather', arguments={'location': 'Boston, MA'})]
> Result Usage: prompt_tokens=16 completion_tokens=19 total_tokens=35
> Result Consumption: 0.00012399999999999998
"""

```



---

Expand Down
14 changes: 10 additions & 4 deletions async_openai/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class OpenAIClient:
settings: Optional[OpenAISettings] = None
name: Optional[str] = None
is_azure: Optional[bool] = None
azure_model_mapping: Optional[Dict[str, str]] = None

auth: Optional[OpenAIAuth] = None
_client: Optional[aiohttpx.Client] = None
Expand Down Expand Up @@ -118,6 +119,7 @@ def configure_params(
settings: Optional[OpenAISettings] = None,
name: Optional[str] = None,
is_azure: Optional[bool] = None,
azure_model_mapping: Optional[Dict[str, str]] = None,
auth: Optional[OpenAIAuth] = None,
**kwargs
): # sourcery skip: low-code-quality
Expand All @@ -136,10 +138,6 @@ def configure_params(
self.api_type = api_type
elif self.api_type is None:
self.api_type = self.settings.api_type
if api_version is not None:
self.api_version = api_version
elif self.api_version is None:
self.api_version = self.settings.api_version
if organization is not None:
self.organization = organization
elif self.organization is None:
Expand Down Expand Up @@ -214,10 +212,17 @@ def configure_params(
self.is_azure = is_azure
elif self.is_azure is None:
self.is_azure = isinstance(self.settings, AzureOpenAISettings)
if azure_model_mapping is not None:
self.azure_model_mapping = azure_model_mapping
if name is not None:
self.name = name
elif self.name is None:
self.name = 'default'
if api_version is not None:
self.api_version = api_version
elif self.api_version is None:
self.api_version = self.settings.api_version


if auth is not None:
self.auth = auth
Expand Down Expand Up @@ -264,6 +269,7 @@ def configure_routes(self, **kwargs):
max_retries = self.max_retries,
settings = self.settings,
is_azure = self.is_azure,
azure_model_mapping = self.azure_model_mapping,
disable_retries = self.disable_retries,
retry_function = self.retry_function,
**kwargs
Expand Down
Loading

0 comments on commit 4ad50e0

Please sign in to comment.