service_utils.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. import base64
  2. import mimetypes
  3. from io import BytesIO
  4. import json
  5. import numpy as np
  6. import requests
  7. from modelscope.outputs import TASK_OUTPUTS, OutputKeys
  8. from modelscope.pipeline_inputs import TASK_INPUTS, InputType
  9. # service data decoder func decodes data from network and convert it to pipeline's input
  10. # for example
  11. def ExampleDecoder(data):
  12. # Assuming the pipeline inputs is a dict contains an image and a text,
  13. # to decode the data from network we decode the image as base64
  14. data_json = json.loads(data)
  15. # data: {"image": "xxxxxxxx=="(base64 str), "text": "a question"}
  16. # pipeline(inputs) as follows:
  17. # pipeline({'image': image, 'text': text})
  18. inputs = {
  19. 'image': decode_base64_to_image(data_json.get('image')),
  20. 'text': data_json.get('text')
  21. }
  22. return inputs
  23. # service data encoder func encodes data from pipeline outputs and convert to network response (such as json)
  24. # for example
  25. def ExampleEncoder(data):
  26. # Assuming the pipeline outputs is a dict contains an image and a text,
  27. # and transmit it through network, this func encode image to base64 and dumps into json
  28. # data (for e.g. python dict):
  29. # {"image": a numpy array represents a image, "text": "output"}
  30. image = data['image']
  31. text = data['text']
  32. data = {'image': encode_array_to_img_base64(image), 'text': text}
  33. return json.dumps(data, cls=NumpyEncoder)
  34. CustomEncoder = {
  35. # Tasks.visual_question_answering: ExampleEncoder
  36. }
  37. CustomDecoder = {
  38. # Tasks.visual_question_answering: ExampleDecoder
  39. }
  40. class NumpyEncoder(json.JSONEncoder):
  41. def default(self, obj):
  42. if isinstance(obj, np.ndarray):
  43. return obj.tolist()
  44. if isinstance(obj, np.floating):
  45. return float(obj)
  46. if isinstance(obj, np.integer):
  47. return int(obj)
  48. return json.JSONEncoder.default(self, obj)
  49. def get_extension(encoding):
  50. encoding = encoding.replace('audio/wav', 'audio/x-wav')
  51. tp = mimetypes.guess_type(encoding)[0]
  52. if tp == 'audio/flac': # flac is not supported by mimetypes
  53. return 'flac'
  54. extension = mimetypes.guess_extension(tp)
  55. if extension is not None and extension.startswith('.'):
  56. extension = extension[1:]
  57. return extension
  58. def get_mimetype(filename):
  59. mimetype = mimetypes.guess_type(filename)[0]
  60. if mimetype is not None:
  61. mimetype = mimetype.replace('x-wav', 'wav').replace('x-flac', 'flac')
  62. return mimetype
  63. def decode_base64_to_binary(encoding):
  64. extension = get_extension(encoding)
  65. data = encoding.split(',')[1]
  66. return base64.b64decode(data), extension
  67. def decode_base64_to_image(encoding):
  68. from PIL import Image
  69. content = encoding.split(';')[1]
  70. image_encoded = content.split(',')[1]
  71. return Image.open(BytesIO(base64.b64decode(image_encoded)))
  72. def encode_array_to_img_base64(image_array):
  73. from PIL import Image
  74. with BytesIO() as output_bytes:
  75. pil_image = Image.fromarray(image_array.astype(np.uint8))
  76. pil_image.save(output_bytes, 'PNG')
  77. bytes_data = output_bytes.getvalue()
  78. base64_str = str(base64.b64encode(bytes_data), 'utf-8')
  79. return 'data:image/png;base64,' + base64_str
  80. def encode_pcm_to_base64(bytes_data):
  81. from scipy.io.wavfile import write
  82. with BytesIO() as out_mem_file:
  83. write(out_mem_file, 16000, bytes_data)
  84. base64_str = str(base64.b64encode(out_mem_file.getvalue()), 'utf-8')
  85. return 'data:audio/pcm;base64,' + base64_str
  86. def encode_url_to_base64(url):
  87. encoded_string = base64.b64encode(requests.get(url).content)
  88. base64_str = str(encoded_string, 'utf-8')
  89. mimetype = get_mimetype(url)
  90. return ('data:' + (mimetype if mimetype is not None else '') + ';base64,'
  91. + base64_str)
  92. def encode_file_to_base64(f):
  93. with open(f, 'rb') as file:
  94. encoded_string = base64.b64encode(file.read())
  95. base64_str = str(encoded_string, 'utf-8')
  96. mimetype = get_mimetype(f)
  97. return ('data:' + (mimetype if mimetype is not None else '')
  98. + ';base64,' + base64_str)
  99. def encode_url_or_file_to_base64(path):
  100. try:
  101. requests.get(path)
  102. return encode_url_to_base64(path)
  103. except (requests.exceptions.MissingSchema,
  104. requests.exceptions.InvalidSchema):
  105. return encode_file_to_base64(path)
  106. def service_data_decoder(task, data):
  107. if CustomDecoder.get(task) is not None:
  108. return CustomDecoder[task](data)
  109. input_data = data.decode('utf-8')
  110. input_type = TASK_INPUTS[task]
  111. if isinstance(input_type, list):
  112. input_type = input_type[0]
  113. if input_type == InputType.IMAGE:
  114. return decode_base64_to_image(input_data)
  115. elif input_type == InputType.AUDIO:
  116. return decode_base64_to_binary(input_data)[0]
  117. elif input_type == InputType.TEXT:
  118. return input_data
  119. elif isinstance(input_type, dict):
  120. input_data = {}
  121. data = json.loads(data)
  122. for key, val in input_type.items():
  123. if val == InputType.IMAGE:
  124. input_data[key] = decode_base64_to_image(data[key])
  125. elif val == InputType.AUDIO:
  126. input_data[key] = decode_base64_to_binary(data[key])[0]
  127. elif val == InputType.TEXT:
  128. input_data[key] = data[key]
  129. else:
  130. return data
  131. return input_data
  132. def service_data_encoder(task, data):
  133. if CustomEncoder.get(task) is not None:
  134. return CustomEncoder[task](data)
  135. output_keys = TASK_OUTPUTS[task]
  136. result = data
  137. for output_key in output_keys:
  138. if output_key == OutputKeys.OUTPUT_IMG:
  139. result[OutputKeys.OUTPUT_IMG] = encode_array_to_img_base64(
  140. data[OutputKeys.OUTPUT_IMG][..., ::-1])
  141. elif output_key == OutputKeys.OUTPUT_PCM:
  142. result[OutputKeys.OUTPUT_PCM] = encode_pcm_to_base64(
  143. data[OutputKeys.OUTPUT_PCM])
  144. result = bytes(json.dumps(result, cls=NumpyEncoder), encoding='utf8')
  145. return result