Commit db4750c1
Changed files (14)
openai/api_resources/abstract/api_resource.py
@@ -1,14 +1,14 @@
from urllib.parse import quote_plus
-from openai import api_requestor, error, util
import openai
+from openai import api_requestor, error, util
from openai.openai_object import OpenAIObject
from openai.util import ApiType
class APIResource(OpenAIObject):
api_prefix = ""
- azure_api_prefix = 'openai/deployments'
+ azure_api_prefix = "openai/deployments"
@classmethod
def retrieve(cls, id, api_key=None, request_id=None, **params):
@@ -49,13 +49,20 @@ class APIResource(OpenAIObject):
if self.typed_api_type == ApiType.AZURE:
if not api_version:
- raise error.InvalidRequestError("An API version is required for the Azure API type.")
+ raise error.InvalidRequestError(
+ "An API version is required for the Azure API type."
+ )
if not operation:
raise error.InvalidRequestError(
"The request needs an operation (eg: 'search') for the Azure OpenAI API type."
)
extn = quote_plus(id)
- return "/%s/%s/%s?api-version=%s" % (self.azure_api_prefix, extn, operation, api_version)
+ return "/%s/%s/%s?api-version=%s" % (
+ self.azure_api_prefix,
+ extn,
+ operation,
+ api_version,
+ )
elif self.typed_api_type == ApiType.OPEN_AI:
base = self.class_url()
@@ -63,8 +70,7 @@ class APIResource(OpenAIObject):
return "%s/%s" % (base, extn)
else:
- raise error.InvalidAPIType('Unsupported API type %s' % self.api_type)
-
+ raise error.InvalidAPIType("Unsupported API type %s" % self.api_type)
# The `method_` and `url_` arguments are suffixed with an underscore to
# avoid conflicting with actual request parameters in `params`.
openai/api_resources/abstract/engine_api_resource.py
@@ -1,5 +1,5 @@
-from pydoc import apropos
import time
+from pydoc import apropos
from typing import Optional
from urllib.parse import quote_plus
@@ -15,28 +15,44 @@ MAX_TIMEOUT = 20
class EngineAPIResource(APIResource):
engine_required = True
plain_old_data = False
- azure_api_prefix = 'openai/deployments'
+ azure_api_prefix = "openai/deployments"
def __init__(self, engine: Optional[str] = None, **kwargs):
super().__init__(engine=engine, **kwargs)
@classmethod
- def class_url(cls, engine: Optional[str] = None, api_type : Optional[str] = None, api_version: Optional[str] = None):
+ def class_url(
+ cls,
+ engine: Optional[str] = None,
+ api_type: Optional[str] = None,
+ api_version: Optional[str] = None,
+ ):
# Namespaces are separated in object names with periods (.) and in URLs
# with forward slashes (/), so replace the former with the latter.
base = cls.OBJECT_NAME.replace(".", "/") # type: ignore
- typed_api_type = ApiType.from_str(api_type) if api_type else ApiType.from_str(openai.api_type)
+ typed_api_type = (
+ ApiType.from_str(api_type)
+ if api_type
+ else ApiType.from_str(openai.api_type)
+ )
api_version = api_version or openai.api_version
if typed_api_type == ApiType.AZURE:
if not api_version:
- raise error.InvalidRequestError("An API version is required for the Azure API type.")
+ raise error.InvalidRequestError(
+ "An API version is required for the Azure API type."
+ )
if engine is None:
raise error.InvalidRequestError(
"You must provide the deployment name in the 'engine' parameter to access the Azure OpenAI service"
)
extn = quote_plus(engine)
- return "/%s/%s/%ss?api-version=%s" % (cls.azure_api_prefix, extn, base, api_version)
+ return "/%s/%s/%ss?api-version=%s" % (
+ cls.azure_api_prefix,
+ extn,
+ base,
+ api_version,
+ )
elif typed_api_type == ApiType.OPEN_AI:
if engine is None:
@@ -46,8 +62,7 @@ class EngineAPIResource(APIResource):
return "/engines/%s/%ss" % (extn, base)
else:
- raise error.InvalidAPIType('Unsupported API type %s' % api_type)
-
+ raise error.InvalidAPIType("Unsupported API type %s" % api_type)
@classmethod
def create(
@@ -133,15 +148,23 @@ class EngineAPIResource(APIResource):
"id",
)
- params_connector = '?'
+ params_connector = "?"
if self.typed_api_type == ApiType.AZURE:
api_version = self.api_version or openai.api_version
if not api_version:
- raise error.InvalidRequestError("An API version is required for the Azure API type.")
+ raise error.InvalidRequestError(
+ "An API version is required for the Azure API type."
+ )
extn = quote_plus(id)
base = self.OBJECT_NAME.replace(".", "/")
- url = "/%s/%s/%ss/%s?api-version=%s" % (self.azure_api_prefix, self.engine, base, extn, api_version)
- params_connector = '&'
+ url = "/%s/%s/%ss/%s?api-version=%s" % (
+ self.azure_api_prefix,
+ self.engine,
+ base,
+ extn,
+ api_version,
+ )
+ params_connector = "&"
elif self.typed_api_type == ApiType.OPEN_AI:
base = self.class_url(self.engine, self.api_type, self.api_version)
@@ -149,7 +172,7 @@ class EngineAPIResource(APIResource):
url = "%s/%s" % (base, extn)
else:
- raise error.InvalidAPIType('Unsupported API type %s' % self.api_type)
+ raise error.InvalidAPIType("Unsupported API type %s" % self.api_type)
timeout = self.get("timeout")
if timeout is not None:
openai/api_resources/engine.py
@@ -33,7 +33,7 @@ class Engine(ListableAPIResource, UpdateableAPIResource):
elif self.typed_api_type == ApiType.OPEN_AI:
return self.request("post", self.instance_url() + "/search", params)
else:
- raise InvalidAPIType('Unsupported API type %s' % self.api_type)
+ raise InvalidAPIType("Unsupported API type %s" % self.api_type)
def embeddings(self, **params):
warnings.warn(
openai/tests/test_api_requestor.py
@@ -1,4 +1,5 @@
import json
+
import pytest
import requests
from pytest_mock import MockerFixture
@@ -6,6 +7,7 @@ from pytest_mock import MockerFixture
from openai import Model
from openai.api_requestor import APIRequestor
+
@pytest.mark.requestor
def test_requestor_sets_request_id(mocker: MockerFixture) -> None:
# Fake out 'requests' and confirm that the X-Request-Id header is set.
@@ -27,24 +29,30 @@ def test_requestor_sets_request_id(mocker: MockerFixture) -> None:
got_request_id = got_headers.get("X-Request-Id")
assert got_request_id == fake_request_id
+
@pytest.mark.requestor
def test_requestor_open_ai_headers() -> None:
api_requestor = APIRequestor(key="test_key", api_type="open_ai")
headers = {"Test_Header": "Unit_Test_Header"}
- headers = api_requestor.request_headers(method="get", extra=headers, request_id="test_id")
+ headers = api_requestor.request_headers(
+ method="get", extra=headers, request_id="test_id"
+ )
print(headers)
- assert "Test_Header"in headers
+ assert "Test_Header" in headers
assert headers["Test_Header"] == "Unit_Test_Header"
- assert "Authorization"in headers
+ assert "Authorization" in headers
assert headers["Authorization"] == "Bearer test_key"
+
@pytest.mark.requestor
def test_requestor_azure_headers() -> None:
api_requestor = APIRequestor(key="test_key", api_type="azure")
headers = {"Test_Header": "Unit_Test_Header"}
- headers = api_requestor.request_headers(method="get", extra=headers, request_id="test_id")
+ headers = api_requestor.request_headers(
+ method="get", extra=headers, request_id="test_id"
+ )
print(headers)
- assert "Test_Header"in headers
+ assert "Test_Header" in headers
assert headers["Test_Header"] == "Unit_Test_Header"
- assert "api-key"in headers
+ assert "api-key" in headers
assert headers["api-key"] == "test_key"
openai/tests/test_url_composition.py
@@ -1,81 +1,123 @@
from sys import api_version
+
import pytest
-from openai import Completion
-from openai import Engine
+from openai import Completion, Engine
from openai.util import ApiType
+
@pytest.mark.url
def test_completions_url_composition_azure() -> None:
- url = Completion.class_url("test_engine", "azure", '2021-11-01-preview')
- assert url == '/openai/deployments/test_engine/completions?api-version=2021-11-01-preview'
+ url = Completion.class_url("test_engine", "azure", "2021-11-01-preview")
+ assert (
+ url
+ == "/openai/deployments/test_engine/completions?api-version=2021-11-01-preview"
+ )
+
@pytest.mark.url
def test_completions_url_composition_default() -> None:
url = Completion.class_url("test_engine")
- assert url == '/engines/test_engine/completions'
+ assert url == "/engines/test_engine/completions"
+
@pytest.mark.url
def test_completions_url_composition_open_ai() -> None:
url = Completion.class_url("test_engine", "open_ai")
- assert url == '/engines/test_engine/completions'
+ assert url == "/engines/test_engine/completions"
+
@pytest.mark.url
def test_completions_url_composition_invalid_type() -> None:
with pytest.raises(Exception):
url = Completion.class_url("test_engine", "invalid")
+
@pytest.mark.url
def test_completions_url_composition_instance_url_azure() -> None:
- completion = Completion(id="test_id", engine="test_engine", api_type="azure", api_version='2021-11-01-preview')
+ completion = Completion(
+ id="test_id",
+ engine="test_engine",
+ api_type="azure",
+ api_version="2021-11-01-preview",
+ )
url = completion.instance_url()
- assert url == "/openai/deployments/test_engine/completions/test_id?api-version=2021-11-01-preview"
+ assert (
+ url
+ == "/openai/deployments/test_engine/completions/test_id?api-version=2021-11-01-preview"
+ )
+
@pytest.mark.url
def test_completions_url_composition_instance_url_azure_no_version() -> None:
- completion = Completion(id="test_id", engine="test_engine", api_type="azure", api_version=None)
+ completion = Completion(
+ id="test_id", engine="test_engine", api_type="azure", api_version=None
+ )
with pytest.raises(Exception):
completion.instance_url()
+
@pytest.mark.url
def test_completions_url_composition_instance_url_default() -> None:
completion = Completion(id="test_id", engine="test_engine")
url = completion.instance_url()
assert url == "/engines/test_engine/completions/test_id"
+
@pytest.mark.url
def test_completions_url_composition_instance_url_open_ai() -> None:
- completion = Completion(id="test_id", engine="test_engine", api_type="open_ai", api_version='2021-11-01-preview')
+ completion = Completion(
+ id="test_id",
+ engine="test_engine",
+ api_type="open_ai",
+ api_version="2021-11-01-preview",
+ )
url = completion.instance_url()
assert url == "/engines/test_engine/completions/test_id"
+
@pytest.mark.url
def test_completions_url_composition_instance_url_invalid() -> None:
completion = Completion(id="test_id", engine="test_engine", api_type="invalid")
with pytest.raises(Exception):
url = completion.instance_url()
+
@pytest.mark.url
def test_completions_url_composition_instance_url_timeout_azure() -> None:
- completion = Completion(id="test_id", engine="test_engine", api_type="azure", api_version='2021-11-01-preview')
+ completion = Completion(
+ id="test_id",
+ engine="test_engine",
+ api_type="azure",
+ api_version="2021-11-01-preview",
+ )
completion["timeout"] = 12
url = completion.instance_url()
- assert url == "/openai/deployments/test_engine/completions/test_id?api-version=2021-11-01-preview&timeout=12"
+ assert (
+ url
+ == "/openai/deployments/test_engine/completions/test_id?api-version=2021-11-01-preview&timeout=12"
+ )
+
@pytest.mark.url
def test_completions_url_composition_instance_url_timeout_openai() -> None:
- completion = Completion(id="test_id", engine="test_engine", api_type="open_ai" )
+ completion = Completion(id="test_id", engine="test_engine", api_type="open_ai")
completion["timeout"] = 12
url = completion.instance_url()
assert url == "/engines/test_engine/completions/test_id?timeout=12"
+
@pytest.mark.url
def test_engine_search_url_composition_azure() -> None:
- engine = Engine(id="test_id", api_type="azure", api_version='2021-11-01-preview')
+ engine = Engine(id="test_id", api_type="azure", api_version="2021-11-01-preview")
assert engine.api_type == "azure"
assert engine.typed_api_type == ApiType.AZURE
url = engine.instance_url("test_operation")
- assert url == '/openai/deployments/test_id/test_operation?api-version=2021-11-01-preview'
+ assert (
+ url
+ == "/openai/deployments/test_id/test_operation?api-version=2021-11-01-preview"
+ )
+
@pytest.mark.url
def test_engine_search_url_composition_azure_no_version() -> None:
@@ -85,13 +127,15 @@ def test_engine_search_url_composition_azure_no_version() -> None:
with pytest.raises(Exception):
engine.instance_url("test_operation")
+
@pytest.mark.url
def test_engine_search_url_composition_azure_no_operation() -> None:
- engine = Engine(id="test_id", api_type="azure", api_version='2021-11-01-preview')
+ engine = Engine(id="test_id", api_type="azure", api_version="2021-11-01-preview")
assert engine.api_type == "azure"
assert engine.typed_api_type == ApiType.AZURE
with pytest.raises(Exception):
- engine.instance_url()
+ engine.instance_url()
+
@pytest.mark.url
def test_engine_search_url_composition_default() -> None:
@@ -99,7 +143,8 @@ def test_engine_search_url_composition_default() -> None:
assert engine.api_type == None
assert engine.typed_api_type == ApiType.OPEN_AI
url = engine.instance_url()
- assert url == '/engines/test_id'
+ assert url == "/engines/test_id"
+
@pytest.mark.url
def test_engine_search_url_composition_open_ai() -> None:
@@ -107,7 +152,8 @@ def test_engine_search_url_composition_open_ai() -> None:
assert engine.api_type == "open_ai"
assert engine.typed_api_type == ApiType.OPEN_AI
url = engine.instance_url()
- assert url == '/engines/test_id'
+ assert url == "/engines/test_id"
+
@pytest.mark.url
def test_engine_search_url_composition_invalid_type() -> None:
@@ -116,6 +162,7 @@ def test_engine_search_url_composition_invalid_type() -> None:
with pytest.raises(Exception):
assert engine.typed_api_type == ApiType.OPEN_AI
+
@pytest.mark.url
def test_engine_search_url_composition_invalid_search() -> None:
engine = Engine(id="test_id", api_type="invalid")
openai/__init__.py
@@ -28,7 +28,7 @@ api_key_path: Optional[str] = os.environ.get("OPENAI_API_KEY_PATH")
organization = os.environ.get("OPENAI_ORGANIZATION")
api_base = os.environ.get("OPENAI_API_BASE", "https://api.openai.com/v1")
api_type = os.environ.get("OPENAI_API_TYPE", "open_ai")
-api_version = '2021-11-01-preview' if api_type == "azure" else None
+api_version = "2021-11-01-preview" if api_type == "azure" else None
verify_ssl_certs = True # No effect. Certificates are always verified.
proxy = None
app_info = None
openai/api_requestor.py
@@ -1,8 +1,8 @@
-from email import header
import json
import platform
import threading
import warnings
+from email import header
from json import JSONDecodeError
from typing import Dict, Iterator, Optional, Tuple, Union
from urllib.parse import urlencode, urlsplit, urlunsplit
@@ -71,10 +71,21 @@ def parse_stream(rbody):
class APIRequestor:
- def __init__(self, key=None, api_base=None, api_type=None, api_version=None, organization=None):
+ def __init__(
+ self,
+ key=None,
+ api_base=None,
+ api_type=None,
+ api_version=None,
+ organization=None,
+ ):
self.api_base = api_base or openai.api_base
self.api_key = key or util.default_api_key()
- self.api_type = ApiType.from_str(api_type) if api_type else ApiType.from_str(openai.api_type)
+ self.api_type = (
+ ApiType.from_str(api_type)
+ if api_type
+ else ApiType.from_str(openai.api_type)
+ )
self.api_version = api_version or openai.api_version
self.organization = organization or openai.organization
@@ -324,7 +335,10 @@ class APIRequestor:
) -> OpenAIResponse:
if rcode == 503:
raise error.ServiceUnavailableError(
- "The server is overloaded or not ready yet.", rbody, rcode, headers=rheaders
+ "The server is overloaded or not ready yet.",
+ rbody,
+ rcode,
+ headers=rheaders,
)
try:
if hasattr(rbody, "decode"):
openai/cli.py
@@ -9,6 +9,7 @@ from typing import Optional
import requests
import openai
+import openai.wandb_logger
from openai.upload_progress import BufferReader
from openai.validators import (
apply_necessary_remediation,
@@ -19,7 +20,6 @@ from openai.validators import (
write_out_file,
write_out_search_file,
)
-import openai.wandb_logger
class bcolors:
openai/error.py
@@ -146,6 +146,7 @@ class RateLimitError(OpenAIError):
class ServiceUnavailableError(OpenAIError):
pass
+
class InvalidAPIType(OpenAIError):
pass
openai/openai_object.py
@@ -248,7 +248,11 @@ class OpenAIObject(dict):
@property
def typed_api_type(self):
- return ApiType.from_str(self.api_type) if self.api_type else ApiType.from_str(openai.api_type)
+ return (
+ ApiType.from_str(self.api_type)
+ if self.api_type
+ else ApiType.from_str(openai.api_type)
+ )
# This class overrides __setitem__ to throw exceptions on inputs that it
# doesn't like. This can cause problems when we try to copy an object
openai/util.py
@@ -2,8 +2,8 @@ import logging
import os
import re
import sys
-from typing import Optional
from enum import Enum
+from typing import Optional
import openai
@@ -18,7 +18,12 @@ __all__ = [
"logfmt",
]
-api_key_to_header = lambda api, key: {"Authorization": f"Bearer {key}"} if api == ApiType.OPEN_AI else {"api-key": f"{key}"}
+api_key_to_header = (
+ lambda api, key: {"Authorization": f"Bearer {key}"}
+ if api == ApiType.OPEN_AI
+ else {"api-key": f"{key}"}
+)
+
class ApiType(Enum):
AZURE = 1
@@ -26,12 +31,14 @@ class ApiType(Enum):
@staticmethod
def from_str(label):
- if label.lower() == 'azure':
+ if label.lower() == "azure":
return ApiType.AZURE
- elif label.lower() in ('open_ai', 'openai'):
+ elif label.lower() in ("open_ai", "openai"):
return ApiType.OPEN_AI
else:
- raise openai.error.InvalidAPIType("The API type provided in invalid. Please select one of the supported API types: 'azure', 'open_ai'")
+ raise openai.error.InvalidAPIType(
+ "The API type provided in invalid. Please select one of the supported API types: 'azure', 'open_ai'"
+ )
def _console_log_level():
.isort.cfg
@@ -1,6 +0,0 @@
-[settings]
-include_trailing_comma=True
-line_length=88
-known_first_party=
-multi_line_output=3
-py_version=36
pyproject.toml
@@ -0,0 +1,9 @@
+[tool.black]
+target-version = ['py36']
+exclude = '.*\.ipynb'
+
+[tool.isort]
+py_version = 36
+include_trailing_comma = "true"
+line_length = 88
+multi_line_output = 3
\ No newline at end of file
setup.py
@@ -23,8 +23,8 @@ setup(
extras_require={"dev": ["black~=21.6b0", "pytest==6.*"]},
python_requires=">=3.7.1",
entry_points={
- 'console_scripts': [
- 'openai=openai._openai_scripts:main',
+ "console_scripts": [
+ "openai=openai._openai_scripts:main",
],
},
packages=find_packages(exclude=["tests", "tests.*"]),