infinite_client.py 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. #! usr/bin/python
  2. # coding=utf-8
  3. # Copyright 2014 Baidu, Inc.
  4. #
  5. # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
  6. # except in compliance with the License. You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software distributed under the
  11. # License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
  12. # either express or implied. See the License for the specific language governing permissions
  13. # and limitations under the License.
  14. """
  15. This module provides a client class for infinite.
  16. """
  17. import copy
  18. import logging
  19. import warnings
  20. import baidubce
  21. from baidubce import utils
  22. from baidubce import compat
  23. from baidubce.auth import bce_v1_signer
  24. from baidubce.bce_base_client import BceBaseClient
  25. from baidubce.http import bce_http_client
  26. from baidubce.http import handler
  27. from baidubce.http import http_headers
  28. from baidubce.http import http_content_types
  29. from baidubce.http import http_methods
  30. from baidubce.utils import required
  31. from baidubce.services import infinite
  32. import http.client
  33. from baidubce.exception import BceClientError
  34. from baidubce.exception import BceServerError
  35. from baidubce.bce_client_configuration import BceClientConfiguration
  36. import uuid
  37. _logger = logging.getLogger(__name__)
  38. def _parse_http_response(http_response, response):
  39. if http_response.status / 100 == http.client.CONTINUE / 100:
  40. raise BceClientError('Can not handle 1xx http status code')
  41. if http_response.status / 100 == http.client.OK / 100:
  42. body = http_response.read()
  43. if body:
  44. response.__dict__.update({'Body': body})
  45. http_response.close()
  46. return True
  47. bse = BceServerError(http_response.reason, request_id=response.metadata.bce_request_id)
  48. bse.status_code = http_response.status
  49. http_response.close()
  50. raise bse
  51. class InfiniteClient(BceBaseClient):
  52. """
  53. Infinite sdk client
  54. """
  55. def __init__(self, config=None):
  56. BceBaseClient.__init__(self, config)
  57. def predict(self, endpoint_name, body,
  58. variant_name=None, content_type='application/json', config=None,
  59. interface='predict'):
  60. """
  61. predict
  62. :param endpoint_name: endpoint name
  63. :type endpoint_name: string
  64. :param body: request data
  65. :type body: binary string or dict
  66. :param variant_name: variant name or None
  67. :type variant_name: string
  68. :param content_type: content type,supports application/json,x-image,and x-recordio-protobuf
  69. :type content_type: string
  70. :param config: None
  71. :type config: BceClientConfiguration
  72. :param interface: interface_name,
  73. several of predict/predict_proba/predict_log_proba/fit_predict/staged_predict/staged_predict are supported
  74. depend on frameworks and algorithm used
  75. :return: response as following format
  76. {
  77. Body: 'predict result'
  78. }
  79. :rtype: baidubce.bce_response.BceResponse
  80. """
  81. params = {}
  82. if variant_name is not None:
  83. params['variant'] = variant_name
  84. params['action'] = 'predict'
  85. params['interface'] = interface
  86. default_encoding = baidubce.DEFAULT_ENCODING
  87. content_type = content_type + '; charset=' + default_encoding
  88. headers = {
  89. http_headers.CONTENT_TYPE: content_type,
  90. http_headers.BCE_REQUEST_ID: uuid.uuid4()
  91. }
  92. return self._send_request(
  93. http_method=http_methods.POST,
  94. function_name=endpoint_name + '/invocations',
  95. body=body,
  96. headers=headers,
  97. params=params,
  98. config=config)
  99. def debug(self, endpoint_name, body, variant_name=None,
  100. content_type='application/json', config=None,
  101. interface='predict'):
  102. """
  103. debug
  104. :param endpoint_name: endpoint name
  105. :type endpoint_name: string
  106. :param body: request data
  107. :type body: binary or dict
  108. :param variant_name: variant name or None
  109. :type variant_name: string
  110. :param content_type: content type,supports application/json,x-image,and x-recordio-protobuf
  111. :type content_type: string
  112. :param config: None
  113. :type config: BceClientConfiguration
  114. :param interface: interface_name,
  115. several of predict/predict_proba/predict_log_proba/fit_predict/staged_predict/staged_predict are supported
  116. depend on frameworks and algorithm used
  117. :type config: string
  118. :return: response as following format
  119. {
  120. Body: 'debug info'
  121. }
  122. :rtype: baidubce.bce_response.BceResponse
  123. """
  124. params = {}
  125. if variant_name is not None:
  126. params['variant'] = variant_name
  127. params['action'] = 'debug'
  128. params['interface'] = interface
  129. default_encoding = baidubce.DEFAULT_ENCODING
  130. content_type = content_type + '; charset=' + default_encoding
  131. headers = {
  132. http_headers.CONTENT_TYPE: content_type,
  133. http_headers.BCE_REQUEST_ID: uuid.uuid4()
  134. }
  135. return self._send_request(
  136. http_method=http_methods.POST,
  137. function_name=endpoint_name + '/invocations',
  138. body=body,
  139. headers=headers,
  140. params=params,
  141. config=config)
  142. def get_endpoint_list(self, config=None):
  143. """
  144. get all endpoint
  145. :param config: None
  146. :type config: BceClientConfiguration
  147. :return: response as following format
  148. {
  149. Body: '{"endpointList":["ep1_name","ep2_name"]}'
  150. }
  151. :rtype: baidubce.bce_response.BceResponse
  152. """
  153. headers = {
  154. http_headers.CONTENT_TYPE: http_content_types.JSON,
  155. http_headers.BCE_REQUEST_ID: uuid.uuid4()
  156. }
  157. return self._send_request(
  158. http_method=http_methods.GET,
  159. function_name='list',
  160. headers=headers,
  161. config=config)
  162. def get_endpoint_info(self, endpoint_name, config=None):
  163. """
  164. get endpoint info
  165. :param endpoint_name: endpoint name
  166. :type endpoint_name: string
  167. :param config: None
  168. :type config: BceClientConfiguration
  169. :return: response as following format
  170. {
  171. Body: '{
  172. "endpoint_uuid":"ep1",
  173. "variant_configs":[
  174. {
  175. "variant_uuid":"v1",
  176. "variant_name":"v1_name",
  177. "...":"..."
  178. }
  179. ]
  180. }'
  181. }
  182. :rtype: baidubce.bce_response.BceResponse
  183. """
  184. headers = {
  185. http_headers.CONTENT_TYPE: http_content_types.JSON,
  186. http_headers.BCE_REQUEST_ID: uuid.uuid4()
  187. }
  188. return self._send_request(
  189. http_method=http_methods.GET,
  190. function_name=endpoint_name + '/info',
  191. headers=headers,
  192. config=config)
  193. @staticmethod
  194. def _get_path(config, function_name=None):
  195. return utils.append_uri(infinite.URL_PREFIX, compat.convert_to_bytes(function_name))
  196. def _merge_config(self, config):
  197. if config is None:
  198. return self._convert_config(self.config)
  199. else:
  200. new_config = copy.copy(self.config)
  201. new_config.merge_non_none_values(config)
  202. new_config = self._convert_config(new_config)
  203. return new_config
  204. def _convert_config(self, config=None):
  205. if config is not None:
  206. if config.endpoint is not None:
  207. config.endpoint = compat.convert_to_bytes(config.endpoint)
  208. if config.credentials is not None:
  209. config.credentials.access_key_id = \
  210. compat.convert_to_bytes(config.credentials.access_key_id)
  211. config.credentials.secret_access_key = \
  212. compat.convert_to_bytes(config.credentials.secret_access_key)
  213. return config
  214. def _send_request(
  215. self, http_method, function_name=None,
  216. body=None, headers=None, params=None,
  217. config=None,
  218. body_parser=None):
  219. config = self._merge_config(config)
  220. path = InfiniteClient._get_path(config, function_name)
  221. if body_parser is None:
  222. body_parser = _parse_http_response
  223. return bce_http_client.send_request(
  224. config, bce_v1_signer.sign, [body_parser],
  225. http_method, path, body, headers, params)