265 lines
8.7 KiB
Python
265 lines
8.7 KiB
Python
#! usr/bin/python
|
|
# coding=utf-8
|
|
|
|
# Copyright 2014 Baidu, Inc.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
|
|
# except in compliance with the License. You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software distributed under the
|
|
# License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
|
# either express or implied. See the License for the specific language governing permissions
|
|
# and limitations under the License.
|
|
|
|
|
|
"""
|
|
This module provides a client class for infinite.
|
|
"""
|
|
import copy
|
|
import logging
|
|
import warnings
|
|
|
|
import baidubce
|
|
from baidubce import utils
|
|
from baidubce import compat
|
|
from baidubce.auth import bce_v1_signer
|
|
from baidubce.bce_base_client import BceBaseClient
|
|
from baidubce.http import bce_http_client
|
|
from baidubce.http import handler
|
|
from baidubce.http import http_headers
|
|
from baidubce.http import http_content_types
|
|
from baidubce.http import http_methods
|
|
from baidubce.utils import required
|
|
from baidubce.services import infinite
|
|
import http.client
|
|
from baidubce.exception import BceClientError
|
|
from baidubce.exception import BceServerError
|
|
from baidubce.bce_client_configuration import BceClientConfiguration
|
|
import uuid
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
def _parse_http_response(http_response, response):
|
|
if http_response.status / 100 == http.client.CONTINUE / 100:
|
|
raise BceClientError('Can not handle 1xx http status code')
|
|
if http_response.status / 100 == http.client.OK / 100:
|
|
body = http_response.read()
|
|
if body:
|
|
response.__dict__.update({'Body': body})
|
|
http_response.close()
|
|
return True
|
|
bse = BceServerError(http_response.reason, request_id=response.metadata.bce_request_id)
|
|
bse.status_code = http_response.status
|
|
http_response.close()
|
|
raise bse
|
|
|
|
|
|
class InfiniteClient(BceBaseClient):
|
|
"""
|
|
Infinite sdk client
|
|
"""
|
|
def __init__(self, config=None):
|
|
BceBaseClient.__init__(self, config)
|
|
|
|
def predict(self, endpoint_name, body,
|
|
variant_name=None, content_type='application/json', config=None,
|
|
interface='predict'):
|
|
"""
|
|
predict
|
|
|
|
:param endpoint_name: endpoint name
|
|
:type endpoint_name: string
|
|
|
|
:param body: request data
|
|
:type body: binary string or dict
|
|
|
|
:param variant_name: variant name or None
|
|
:type variant_name: string
|
|
|
|
:param content_type: content type,supports application/json,x-image,and x-recordio-protobuf
|
|
:type content_type: string
|
|
|
|
:param config: None
|
|
:type config: BceClientConfiguration
|
|
|
|
:param interface: interface_name,
|
|
several of predict/predict_proba/predict_log_proba/fit_predict/staged_predict/staged_predict are supported
|
|
depend on frameworks and algorithm used
|
|
|
|
:return: response as following format
|
|
{
|
|
Body: 'predict result'
|
|
}
|
|
:rtype: baidubce.bce_response.BceResponse
|
|
"""
|
|
params = {}
|
|
if variant_name is not None:
|
|
params['variant'] = variant_name
|
|
params['action'] = 'predict'
|
|
params['interface'] = interface
|
|
|
|
default_encoding = baidubce.DEFAULT_ENCODING
|
|
content_type = content_type + '; charset=' + default_encoding
|
|
headers = {
|
|
http_headers.CONTENT_TYPE: content_type,
|
|
http_headers.BCE_REQUEST_ID: uuid.uuid4()
|
|
}
|
|
|
|
return self._send_request(
|
|
http_method=http_methods.POST,
|
|
function_name=endpoint_name + '/invocations',
|
|
body=body,
|
|
headers=headers,
|
|
params=params,
|
|
config=config)
|
|
|
|
def debug(self, endpoint_name, body, variant_name=None,
|
|
content_type='application/json', config=None,
|
|
interface='predict'):
|
|
"""
|
|
debug
|
|
|
|
:param endpoint_name: endpoint name
|
|
:type endpoint_name: string
|
|
|
|
:param body: request data
|
|
:type body: binary or dict
|
|
|
|
:param variant_name: variant name or None
|
|
:type variant_name: string
|
|
|
|
:param content_type: content type,supports application/json,x-image,and x-recordio-protobuf
|
|
:type content_type: string
|
|
|
|
:param config: None
|
|
:type config: BceClientConfiguration
|
|
|
|
:param interface: interface_name,
|
|
several of predict/predict_proba/predict_log_proba/fit_predict/staged_predict/staged_predict are supported
|
|
depend on frameworks and algorithm used
|
|
:type config: string
|
|
|
|
:return: response as following format
|
|
{
|
|
Body: 'debug info'
|
|
}
|
|
:rtype: baidubce.bce_response.BceResponse
|
|
"""
|
|
params = {}
|
|
if variant_name is not None:
|
|
params['variant'] = variant_name
|
|
params['action'] = 'debug'
|
|
params['interface'] = interface
|
|
|
|
default_encoding = baidubce.DEFAULT_ENCODING
|
|
content_type = content_type + '; charset=' + default_encoding
|
|
headers = {
|
|
http_headers.CONTENT_TYPE: content_type,
|
|
http_headers.BCE_REQUEST_ID: uuid.uuid4()
|
|
}
|
|
|
|
return self._send_request(
|
|
http_method=http_methods.POST,
|
|
function_name=endpoint_name + '/invocations',
|
|
body=body,
|
|
headers=headers,
|
|
params=params,
|
|
config=config)
|
|
|
|
def get_endpoint_list(self, config=None):
|
|
"""
|
|
get all endpoint
|
|
|
|
:param config: None
|
|
:type config: BceClientConfiguration
|
|
|
|
:return: response as following format
|
|
{
|
|
Body: '{"endpointList":["ep1_name","ep2_name"]}'
|
|
}
|
|
:rtype: baidubce.bce_response.BceResponse
|
|
"""
|
|
headers = {
|
|
http_headers.CONTENT_TYPE: http_content_types.JSON,
|
|
http_headers.BCE_REQUEST_ID: uuid.uuid4()
|
|
}
|
|
return self._send_request(
|
|
http_method=http_methods.GET,
|
|
function_name='list',
|
|
headers=headers,
|
|
config=config)
|
|
|
|
def get_endpoint_info(self, endpoint_name, config=None):
|
|
"""
|
|
get endpoint info
|
|
|
|
:param endpoint_name: endpoint name
|
|
:type endpoint_name: string
|
|
|
|
:param config: None
|
|
:type config: BceClientConfiguration
|
|
|
|
:return: response as following format
|
|
{
|
|
Body: '{
|
|
"endpoint_uuid":"ep1",
|
|
"variant_configs":[
|
|
{
|
|
"variant_uuid":"v1",
|
|
"variant_name":"v1_name",
|
|
"...":"..."
|
|
}
|
|
]
|
|
}'
|
|
}
|
|
:rtype: baidubce.bce_response.BceResponse
|
|
"""
|
|
headers = {
|
|
http_headers.CONTENT_TYPE: http_content_types.JSON,
|
|
http_headers.BCE_REQUEST_ID: uuid.uuid4()
|
|
}
|
|
return self._send_request(
|
|
http_method=http_methods.GET,
|
|
function_name=endpoint_name + '/info',
|
|
headers=headers,
|
|
config=config)
|
|
|
|
@staticmethod
|
|
def _get_path(config, function_name=None):
|
|
return utils.append_uri(infinite.URL_PREFIX, compat.convert_to_bytes(function_name))
|
|
|
|
def _merge_config(self, config):
|
|
if config is None:
|
|
return self._convert_config(self.config)
|
|
else:
|
|
new_config = copy.copy(self.config)
|
|
new_config.merge_non_none_values(config)
|
|
new_config = self._convert_config(new_config)
|
|
return new_config
|
|
|
|
def _convert_config(self, config=None):
|
|
if config is not None:
|
|
if config.endpoint is not None:
|
|
config.endpoint = compat.convert_to_bytes(config.endpoint)
|
|
if config.credentials is not None:
|
|
config.credentials.access_key_id = \
|
|
compat.convert_to_bytes(config.credentials.access_key_id)
|
|
config.credentials.secret_access_key = \
|
|
compat.convert_to_bytes(config.credentials.secret_access_key)
|
|
return config
|
|
|
|
def _send_request(
|
|
self, http_method, function_name=None,
|
|
body=None, headers=None, params=None,
|
|
config=None,
|
|
body_parser=None):
|
|
config = self._merge_config(config)
|
|
path = InfiniteClient._get_path(config, function_name)
|
|
if body_parser is None:
|
|
body_parser = _parse_http_response
|
|
return bce_http_client.send_request(
|
|
config, bce_v1_signer.sign, [body_parser],
|
|
http_method, path, body, headers, params)
|