예제 #1
0
    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)
        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.")
            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)

        elif typed_api_type == ApiType.OPEN_AI:
            if engine is None:
                return "/%ss" % (base)

            extn = quote_plus(engine)
            return "/engines/%s/%ss" % (extn, base)

        else:
            raise error.InvalidAPIType('Unsupported API type %s' % api_type)
예제 #2
0
    def instance_url(self):
        id = self.get("id")

        if not isinstance(id, str):
            raise error.InvalidRequestError(
                f"Could not determine which URL to request: {type(self).__name__} instance has invalid ID: {id}, {type(id)}. ID should be of type str.",
                "id",
            )

        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.")
            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 = '&'

        elif self.typed_api_type == ApiType.OPEN_AI:
            base = self.class_url(self.engine, self.api_type, self.api_version)
            extn = quote_plus(id)
            url = "%s/%s" % (base, extn)

        else:
            raise error.InvalidAPIType('Unsupported API type %s' %
                                       self.api_type)

        timeout = self.get("timeout")
        if timeout is not None:
            timeout = quote_plus(str(timeout))
            url += params_connector + "timeout={}".format(timeout)
        return url
예제 #3
0
    def instance_url(self, operation=None):
        id = self.get("id")

        if not isinstance(id, str):
            raise error.InvalidRequestError(
                "Could not determine which URL to request: %s instance "
                "has invalid ID: %r, %s. ID should be of type `str` (or"
                " `unicode`)" % (type(self).__name__, id, type(id)),
                "id",
            )
        api_version = self.api_version or openai.api_version

        if self.typed_api_type == ApiType.AZURE:
            if not api_version:
                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)

        elif self.typed_api_type == ApiType.OPEN_AI:
            base = self.class_url()
            extn = quote_plus(id)
            return "%s/%s" % (base, extn)

        else:
            raise error.InvalidAPIType('Unsupported API type %s' %
                                       self.api_type)
예제 #4
0
    def handle_error_response(self, rbody, rcode, resp, rheaders, stream_error=False):
        try:
            error_data = resp["error"]
        except (KeyError, TypeError):
            raise error.APIError(
                "Invalid response object from API: %r (HTTP response code "
                "was %d)" % (rbody, rcode),
                rbody,
                rcode,
                resp,
            )

        if "internal_message" in error_data:
            error_data["message"] += "\n\n" + error_data["internal_message"]

        util.log_info(
            "OpenAI API error received",
            error_code=error_data.get("code"),
            error_type=error_data.get("type"),
            error_message=error_data.get("message"),
            error_param=error_data.get("param"),
            stream_error=stream_error,
        )

        # Rate limits were previously coded as 400's with code 'rate_limit'
        if rcode == 429:
            return error.RateLimitError(
                error_data.get("message"), rbody, rcode, resp, rheaders
            )
        elif rcode in [400, 404, 415]:
            return error.InvalidRequestError(
                error_data.get("message"),
                error_data.get("param"),
                error_data.get("code"),
                rbody,
                rcode,
                resp,
                rheaders,
            )
        elif rcode == 401:
            return error.AuthenticationError(
                error_data.get("message"), rbody, rcode, resp, rheaders
            )
        elif rcode == 403:
            return error.PermissionError(
                error_data.get("message"), rbody, rcode, resp, rheaders
            )
        elif rcode == 409:
            return error.TryAgain(
                error_data.get("message"), rbody, rcode, resp, rheaders
            )
        elif stream_error:
            # TODO: we will soon attach status codes to stream errors
            parts = [error_data.get("message"), "(Error occurred while streaming.)"]
            message = " ".join([p for p in parts if p is not None])
            return error.APIError(message, rbody, rcode, resp, rheaders)
        else:
            return error.APIError(
                error_data.get("message"), rbody, rcode, resp, rheaders
            )
예제 #5
0
    def instance_url(self):
        id = self.get("id")

        if not isinstance(id, six.string_types):
            raise error.InvalidRequestError(
                "Could not determine which URL to request: %s instance "
                "has invalid ID: %r, %s. ID should be of type `str` (or"
                " `unicode`)" % (type(self).__name__, id, type(id)),
                "id",
            )

        id = util.utf8(id)
        base = self.class_url()
        extn = quote_plus(id)
        return "%s/%s" % (base, extn)
예제 #6
0
    def instance_url(self):
        id = self.get("id")

        if not isinstance(id, six.string_types):
            raise error.InvalidRequestError(
                "Could not determine which URL to request: %s instance "
                "has invalid ID: %r, %s. ID should be of type `str` (or"
                " `unicode`)" % (type(self).__name__, id, type(id)),
                "id",
            )

        id = util.utf8(id)
        base = self.class_url(self.engine)
        extn = quote_plus(id)
        url = "%s/%s" % (base, extn)

        timeout = self.get("timeout")
        if timeout is not None:
            timeout = quote_plus(str(timeout))
            url += "?timeout={}".format(timeout)
        return url
예제 #7
0
    def create(
        cls,
        api_key=None,
        api_base=None,
        idempotency_key=None,
        request_id=None,
        api_version=None,
        organization=None,
        **params,
    ):
        """
        Create a new instance of this model.

        Parameters:
        timeout (float): the number of seconds to wait on the promise returned by the API, where 0 means wait forever.
        """
        engine = params.pop("engine", None)
        timeout = params.pop("timeout", None)
        stream = params.get("stream", False)
        if engine is None and cls.engine_required:
            raise error.InvalidRequestError(
                "Must provide an 'engine' parameter to create a %s" % cls,
                "engine")

        if timeout is None:
            # No special timeout handling
            pass
        elif timeout > 0:
            # API only supports timeouts up to MAX_TIMEOUT
            params["timeout"] = min(timeout, MAX_TIMEOUT)
            timeout = (timeout - params["timeout"]) or None
        elif timeout == 0:
            params["timeout"] = MAX_TIMEOUT

        requestor = api_requestor.APIRequestor(
            api_key,
            api_base=api_base,
            api_version=api_version,
            organization=organization,
        )
        url = cls.class_url(engine)
        headers = util.populate_headers(idempotency_key, request_id)
        response, _, api_key = requestor.request("post",
                                                 url,
                                                 params,
                                                 headers,
                                                 stream=stream)

        if stream:
            return (util.convert_to_openai_object(
                line,
                api_key,
                api_version,
                organization,
                engine=engine,
                plain_old_data=cls.plain_old_data,
            ) for line in response)
        else:
            obj = util.convert_to_openai_object(
                response,
                api_key,
                api_version,
                organization,
                engine=engine,
                plain_old_data=cls.plain_old_data,
            )

            if timeout is not None:
                obj.wait(timeout=timeout or None)

        return obj
예제 #8
0
    def create(
        cls,
        api_key=None,
        api_base=None,
        api_type=None,
        request_id=None,
        api_version=None,
        organization=None,
        **params,
    ):
        engine = params.pop("engine", None)
        timeout = params.pop("timeout", None)
        stream = params.get("stream", False)
        headers = params.pop("headers", None)
        if engine is None and cls.engine_required:
            raise error.InvalidRequestError(
                "Must provide an 'engine' parameter to create a %s" % cls,
                "engine")

        if timeout is None:
            # No special timeout handling
            pass
        elif timeout > 0:
            # API only supports timeouts up to MAX_TIMEOUT
            params["timeout"] = min(timeout, MAX_TIMEOUT)
            timeout = (timeout - params["timeout"]) or None
        elif timeout == 0:
            params["timeout"] = MAX_TIMEOUT

        requestor = api_requestor.APIRequestor(
            api_key,
            api_base=api_base,
            api_type=api_type,
            api_version=api_version,
            organization=organization,
        )
        url = cls.class_url(engine, api_type, api_version)
        response, _, api_key = requestor.request(
            "post",
            url,
            params=params,
            headers=headers,
            stream=stream,
            request_id=request_id,
        )

        if stream:
            assert not isinstance(response,
                                  OpenAIResponse)  # must be an iterator
            return (util.convert_to_openai_object(
                line,
                api_key,
                api_version,
                organization,
                engine=engine,
                plain_old_data=cls.plain_old_data,
            ) for line in response)
        else:
            obj = util.convert_to_openai_object(
                response,
                api_key,
                api_version,
                organization,
                engine=engine,
                plain_old_data=cls.plain_old_data,
            )

            if timeout is not None:
                obj.wait(timeout=timeout or None)

        return obj