You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

GRPC.md 6.7 kB

5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. # gRPC接口使用说明
  2. ## 概述
  3. MindSpore Serving提供gRPC接口访问Serving服务。在Python环境下,我们提供[mindspore_serving.client](../mindspore_serving/client/python/client.py) 接口填写请求、解析回复。接下来我们详细说明`mindspore_serving.client`如何使用。
  4. ## 样例
  5. 在详细说明接口之前,我们先看几个样例。
  6. ### add样例
  7. 样例来源于[add example](../mindspore_serving/example/add/client.py)
  8. ```
  9. from mindspore_serving.client import Client
  10. import numpy as np
  11. def run_add_common():
  12. """invoke Servable add method add_common"""
  13. client = Client("localhost", 5500, "add", "add_common")
  14. instances = []
  15. # instance 1
  16. x1 = np.asarray([[1, 1], [1, 1]]).astype(np.float32)
  17. x2 = np.asarray([[1, 1], [1, 1]]).astype(np.float32)
  18. instances.append({"x1": x1, "x2": x2})
  19. # instance 2
  20. x1 = np.asarray([[2, 2], [2, 2]]).astype(np.float32)
  21. x2 = np.asarray([[2, 2], [2, 2]]).astype(np.float32)
  22. instances.append({"x1": x1, "x2": x2})
  23. # instance 3
  24. x1 = np.asarray([[3, 3], [3, 3]]).astype(np.float32)
  25. x2 = np.asarray([[3, 3], [3, 3]]).astype(np.float32)
  26. instances.append({"x1": x1, "x2": x2})
  27. result = client.infer(instances)
  28. print(result)
  29. if __name__ == '__main__':
  30. run_add_common()
  31. ```
  32. 按照[入门流程](../README_CN.md/#%E5%BF%AB%E9%80%9F%E5%85%A5%E9%97%A8) 导出模型,启动Serving服务器,并执行客户端代码。当运行正常后,将打印以下结果,为了展示方便,格式作了调整:
  33. ```
  34. [{'y': array([[2., 2.], [2., 2.]], dtype=float32)},
  35. {'y': array([[4., 4.], [4., 4.]], dtype=float32)},
  36. {'y': array([[6., 6.], [6., 6.]], dtype=float32)}]
  37. ```
  38. 以下将对其中的细节进行说明。
  39. 1. 构造`Client`
  40. 构造`Client`时,指示Serving的ip和端口号,并给定Servable名称和它提供的方法。这里的Servable可以是单个模型,也可以是多个模型的组合,一个Servable可以提供多种方法以提供不同的服务。
  41. 上面的`add`样例, Serving运行在本地(`localhost`),指定的gRPC端口号为`5500`,运行了`add` Servable,`add` Servable提供了`add_common`方法。
  42. 2. 添加实例
  43. 每次请求可包括一个或多个实例,每个实例之间相互独立,结果互不影响。
  44. 比如:`add` Servable提供的`add_common`方法提供两个2x2 Tensor相加功能,即一个实例包含两个2x2 Tensor输入,一个2x2 Tensor输出。一次请求可包括一个、两个或者多个这样的实例,针对每个实例返回一个结果。上述`add`样例提供了三个实例,预期将返回三个实例的结果。
  45. ```
  46. Given Request:
  47. instance1:
  48. x1 = [[1, 1], [1, 1]]
  49. x2 = [[1, 1], [1, 1]]
  50. instance2:
  51. x1 = [[2, 2], [2, 2]]
  52. x2 = [[2, 2], [2, 2]]
  53. instance3:
  54. x1 = [[3, 3], [3, 3]]
  55. x2 = [[3, 3], [3, 3]]
  56. Expected Relpy:
  57. instance1:
  58. y = [[2., 2.], [2., 2.]] # instance1 x1 + x2
  59. instance2:
  60. y = [[4., 4.], [4., 4.]] # instance2 x1 + x2
  61. instance3:
  62. y = [[6., 6.], [6., 6.]] # instance3 x1 + x2
  63. ```
  64. `Client.infer`接口入参可为实例的list、tuple或者单个实例。每个实例的输入由dict表示,dict的key即为输入的名称,value为输入的值。
  65. value可以是以下格式的值:
  66. | 值类型 | 说明 | 举例 |
  67. | ---- | ---- | ---- |
  68. | numpy array | 用以表示Tensor | np.ones((3,224), np.float32) |
  69. | numpy scalar | 用以表示Scalar | np.int8(5) |
  70. | python bool int float | 用以表示Scalar, 当前int将作为int32, float将作为float32 | 32.0 |
  71. | python str | 用以表示字符串 | "this is a text" |
  72. | python bytes | 用以表示二进制数据 | 图片数据 |
  73. 上面的add样例,`add` Servable提供的`add_common`方法入参名为`x1`和`x2`,添加每个实例时指定每个输入的值。
  74. 3. 获取推理结果
  75. 通过`Client.infer`填入一个或多个实例。
  76. 返回可能有以下形式:
  77. 所有实例推理正确:
  78. ```
  79. [{'y': array([[2., 2.], [2., 2.]], dtype=float32)},
  80. {'y': array([[4., 4.], [4., 4.]], dtype=float32)},
  81. {'y': array([[6., 6.], [6., 6.]], dtype=float32)}]
  82. ```
  83. 针对所有实例共同的错误,返回一个包含`error`的dict。将例子中Client构造时填入的`add_common`改为`add_common2`,将返回结果:
  84. ```
  85. {'error', 'Request Servable(add) method(add_common2), method is not available'}
  86. ```
  87. 部分实例推理错误,出错的推理实例将返回包含`error`的dict。将instance2一个输入的`dtype`改为`np.int32`,将返回结果:
  88. ```
  89. [{'y': array([[2., 2.], [2., 2.]], dtype=float32)},
  90. {'error': 'Given model input 1 data type kMSI_Int32 not match ...'},
  91. {'y': array([[6., 6.], [6., 6.]], dtype=float32)}]
  92. ```
  93. 每个实例返回一个dict,key的值来自于Servable的方法定义,例如本例子中,`add` Servable提供的`add_common`方法输出仅有一个,为`y`。value为以下格式:
  94. | Serving输出类型 | Client返回类型 | 说明 | 举例 |
  95. | ---- | ---- | ---- | ---- |
  96. | Tensor | numpy array | tensor array | np.ones((3,224), np.float32) |
  97. | Scalar: <br>int8, int16, int32, int64, <br>uint8, uint16, uint32, uint64, <br>bool, float16, float32, float64 | numpy scalar | Scalar格式的数据转为numpy scalar | np.int8(5) |
  98. | String | python str | 字符串格式输出转为python str | "news_car" |
  99. | Bytes | python bytes | 二进制格式输出转为python bytes | 图片数据 |
  100. ### lenet样例
  101. 样例来源于[lenet example](../mindspore_serving/example/lenet/client.py) 。通过lenet样例来说明二进制的输入,lenet输入为二进制,输出为Scalar。
  102. ```
  103. import os
  104. from mindspore_serving.client import Client
  105. def run_predict():
  106. client = Client("localhost", 5500, "lenet", "predict")
  107. instances = []
  108. for path, _, file_list in os.walk("./test_image/"):
  109. for file_name in file_list:
  110. image_file = os.path.join(path, file_name)
  111. print(image_file)
  112. with open(image_file, "rb") as fp:
  113. instances.append({"image": fp.read()})
  114. result = client.infer(instances)
  115. if "error" in result:
  116. print("error happen:", result["error"])
  117. return
  118. print(result)
  119. if __name__ == '__main__':
  120. run_predict()
  121. ```
  122. 上面lenet例子中,输入的每个实例的唯一的输入`image`为文件二进制方式读取的bytes。
  123. 正常结束执行后,可能将会有以下打印:
  124. ```
  125. [{'result': 4}, {'result': 4}, {'result': 4}, {'result': 4}]
  126. ```

A lightweight and high-performance service module that helps MindSpore developers efficiently deploy online inference services in the production environment.