clarifai 11.6.4__py3-none-any.whl → 11.6.4rc2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. clarifai/__init__.py +1 -1
  2. clarifai/__pycache__/__init__.cpython-311.pyc +0 -0
  3. clarifai/__pycache__/__init__.cpython-39.pyc +0 -0
  4. clarifai/__pycache__/errors.cpython-311.pyc +0 -0
  5. clarifai/__pycache__/errors.cpython-39.pyc +0 -0
  6. clarifai/__pycache__/versions.cpython-311.pyc +0 -0
  7. clarifai/__pycache__/versions.cpython-39.pyc +0 -0
  8. clarifai/cli/__pycache__/__init__.cpython-39.pyc +0 -0
  9. clarifai/cli/__pycache__/base.cpython-39.pyc +0 -0
  10. clarifai/cli/__pycache__/compute_cluster.cpython-39.pyc +0 -0
  11. clarifai/cli/__pycache__/deployment.cpython-39.pyc +0 -0
  12. clarifai/cli/__pycache__/model.cpython-39.pyc +0 -0
  13. clarifai/cli/__pycache__/nodepool.cpython-39.pyc +0 -0
  14. clarifai/cli/base.py +11 -27
  15. clarifai/cli/model.py +171 -41
  16. clarifai/cli/model_templates.py +243 -0
  17. clarifai/cli/pipeline_step_templates.py +64 -0
  18. clarifai/client/__pycache__/__init__.cpython-311.pyc +0 -0
  19. clarifai/client/__pycache__/__init__.cpython-39.pyc +0 -0
  20. clarifai/client/__pycache__/app.cpython-311.pyc +0 -0
  21. clarifai/client/__pycache__/app.cpython-39.pyc +0 -0
  22. clarifai/client/__pycache__/base.cpython-311.pyc +0 -0
  23. clarifai/client/__pycache__/base.cpython-39.pyc +0 -0
  24. clarifai/client/__pycache__/compute_cluster.cpython-311.pyc +0 -0
  25. clarifai/client/__pycache__/dataset.cpython-311.pyc +0 -0
  26. clarifai/client/__pycache__/dataset.cpython-39.pyc +0 -0
  27. clarifai/client/__pycache__/deployment.cpython-311.pyc +0 -0
  28. clarifai/client/__pycache__/deployment.cpython-39.pyc +0 -0
  29. clarifai/client/__pycache__/input.cpython-311.pyc +0 -0
  30. clarifai/client/__pycache__/input.cpython-39.pyc +0 -0
  31. clarifai/client/__pycache__/lister.cpython-311.pyc +0 -0
  32. clarifai/client/__pycache__/lister.cpython-39.pyc +0 -0
  33. clarifai/client/__pycache__/model.cpython-311.pyc +0 -0
  34. clarifai/client/__pycache__/model.cpython-39.pyc +0 -0
  35. clarifai/client/__pycache__/model_client.cpython-311.pyc +0 -0
  36. clarifai/client/__pycache__/model_client.cpython-39.pyc +0 -0
  37. clarifai/client/__pycache__/module.cpython-311.pyc +0 -0
  38. clarifai/client/__pycache__/nodepool.cpython-311.pyc +0 -0
  39. clarifai/client/__pycache__/runner.cpython-311.pyc +0 -0
  40. clarifai/client/__pycache__/search.cpython-311.pyc +0 -0
  41. clarifai/client/__pycache__/user.cpython-311.pyc +0 -0
  42. clarifai/client/__pycache__/workflow.cpython-311.pyc +0 -0
  43. clarifai/client/auth/__pycache__/__init__.cpython-311.pyc +0 -0
  44. clarifai/client/auth/__pycache__/__init__.cpython-39.pyc +0 -0
  45. clarifai/client/auth/__pycache__/helper.cpython-311.pyc +0 -0
  46. clarifai/client/auth/__pycache__/helper.cpython-39.pyc +0 -0
  47. clarifai/client/auth/__pycache__/register.cpython-311.pyc +0 -0
  48. clarifai/client/auth/__pycache__/register.cpython-39.pyc +0 -0
  49. clarifai/client/auth/__pycache__/stub.cpython-311.pyc +0 -0
  50. clarifai/client/auth/__pycache__/stub.cpython-39.pyc +0 -0
  51. clarifai/constants/__pycache__/base.cpython-311.pyc +0 -0
  52. clarifai/constants/__pycache__/base.cpython-39.pyc +0 -0
  53. clarifai/constants/__pycache__/dataset.cpython-311.pyc +0 -0
  54. clarifai/constants/__pycache__/dataset.cpython-39.pyc +0 -0
  55. clarifai/constants/__pycache__/input.cpython-311.pyc +0 -0
  56. clarifai/constants/__pycache__/input.cpython-39.pyc +0 -0
  57. clarifai/constants/__pycache__/model.cpython-311.pyc +0 -0
  58. clarifai/constants/__pycache__/model.cpython-39.pyc +0 -0
  59. clarifai/constants/__pycache__/search.cpython-311.pyc +0 -0
  60. clarifai/constants/__pycache__/workflow.cpython-311.pyc +0 -0
  61. clarifai/datasets/__pycache__/__init__.cpython-311.pyc +0 -0
  62. clarifai/datasets/__pycache__/__init__.cpython-39.pyc +0 -0
  63. clarifai/datasets/export/__pycache__/__init__.cpython-311.pyc +0 -0
  64. clarifai/datasets/export/__pycache__/__init__.cpython-39.pyc +0 -0
  65. clarifai/datasets/export/__pycache__/inputs_annotations.cpython-311.pyc +0 -0
  66. clarifai/datasets/export/__pycache__/inputs_annotations.cpython-39.pyc +0 -0
  67. clarifai/datasets/upload/__pycache__/__init__.cpython-311.pyc +0 -0
  68. clarifai/datasets/upload/__pycache__/__init__.cpython-39.pyc +0 -0
  69. clarifai/datasets/upload/__pycache__/base.cpython-311.pyc +0 -0
  70. clarifai/datasets/upload/__pycache__/base.cpython-39.pyc +0 -0
  71. clarifai/datasets/upload/__pycache__/features.cpython-311.pyc +0 -0
  72. clarifai/datasets/upload/__pycache__/features.cpython-39.pyc +0 -0
  73. clarifai/datasets/upload/__pycache__/image.cpython-311.pyc +0 -0
  74. clarifai/datasets/upload/__pycache__/image.cpython-39.pyc +0 -0
  75. clarifai/datasets/upload/__pycache__/multimodal.cpython-311.pyc +0 -0
  76. clarifai/datasets/upload/__pycache__/multimodal.cpython-39.pyc +0 -0
  77. clarifai/datasets/upload/__pycache__/text.cpython-311.pyc +0 -0
  78. clarifai/datasets/upload/__pycache__/text.cpython-39.pyc +0 -0
  79. clarifai/datasets/upload/__pycache__/utils.cpython-311.pyc +0 -0
  80. clarifai/datasets/upload/__pycache__/utils.cpython-39.pyc +0 -0
  81. clarifai/models/model_serving/README.md +158 -0
  82. clarifai/models/model_serving/__init__.py +14 -0
  83. clarifai/models/model_serving/cli/__init__.py +12 -0
  84. clarifai/models/model_serving/cli/_utils.py +53 -0
  85. clarifai/models/model_serving/cli/base.py +14 -0
  86. clarifai/models/model_serving/cli/build.py +79 -0
  87. clarifai/models/model_serving/cli/clarifai_clis.py +33 -0
  88. clarifai/models/model_serving/cli/create.py +171 -0
  89. clarifai/models/model_serving/cli/example_cli.py +34 -0
  90. clarifai/models/model_serving/cli/login.py +26 -0
  91. clarifai/models/model_serving/cli/upload.py +179 -0
  92. clarifai/models/model_serving/constants.py +21 -0
  93. clarifai/models/model_serving/docs/cli.md +161 -0
  94. clarifai/models/model_serving/docs/concepts.md +229 -0
  95. clarifai/models/model_serving/docs/dependencies.md +11 -0
  96. clarifai/models/model_serving/docs/inference_parameters.md +139 -0
  97. clarifai/models/model_serving/docs/model_types.md +19 -0
  98. clarifai/models/model_serving/model_config/__init__.py +16 -0
  99. clarifai/models/model_serving/model_config/base.py +369 -0
  100. clarifai/models/model_serving/model_config/config.py +312 -0
  101. clarifai/models/model_serving/model_config/inference_parameter.py +129 -0
  102. clarifai/models/model_serving/model_config/model_types_config/multimodal-embedder.yaml +25 -0
  103. clarifai/models/model_serving/model_config/model_types_config/text-classifier.yaml +19 -0
  104. clarifai/models/model_serving/model_config/model_types_config/text-embedder.yaml +20 -0
  105. clarifai/models/model_serving/model_config/model_types_config/text-to-image.yaml +19 -0
  106. clarifai/models/model_serving/model_config/model_types_config/text-to-text.yaml +19 -0
  107. clarifai/models/model_serving/model_config/model_types_config/visual-classifier.yaml +22 -0
  108. clarifai/models/model_serving/model_config/model_types_config/visual-detector.yaml +32 -0
  109. clarifai/models/model_serving/model_config/model_types_config/visual-embedder.yaml +19 -0
  110. clarifai/models/model_serving/model_config/model_types_config/visual-segmenter.yaml +19 -0
  111. clarifai/models/model_serving/model_config/output.py +133 -0
  112. clarifai/models/model_serving/model_config/triton/__init__.py +14 -0
  113. clarifai/models/model_serving/model_config/triton/serializer.py +136 -0
  114. clarifai/models/model_serving/model_config/triton/triton_config.py +182 -0
  115. clarifai/models/model_serving/model_config/triton/wrappers.py +281 -0
  116. clarifai/models/model_serving/repo_build/__init__.py +14 -0
  117. clarifai/models/model_serving/repo_build/build.py +198 -0
  118. clarifai/models/model_serving/repo_build/static_files/_requirements.txt +2 -0
  119. clarifai/models/model_serving/repo_build/static_files/base_test.py +169 -0
  120. clarifai/models/model_serving/repo_build/static_files/inference.py +26 -0
  121. clarifai/models/model_serving/repo_build/static_files/sample_clarifai_config.yaml +25 -0
  122. clarifai/models/model_serving/repo_build/static_files/test.py +40 -0
  123. clarifai/models/model_serving/repo_build/static_files/triton/model.py +75 -0
  124. clarifai/models/model_serving/utils.py +23 -0
  125. clarifai/runners/__pycache__/__init__.cpython-311.pyc +0 -0
  126. clarifai/runners/__pycache__/__init__.cpython-39.pyc +0 -0
  127. clarifai/runners/models/__pycache__/__init__.cpython-311.pyc +0 -0
  128. clarifai/runners/models/__pycache__/__init__.cpython-39.pyc +0 -0
  129. clarifai/runners/models/__pycache__/mcp_class.cpython-311.pyc +0 -0
  130. clarifai/runners/models/__pycache__/model_builder.cpython-311.pyc +0 -0
  131. clarifai/runners/models/__pycache__/model_builder.cpython-39.pyc +0 -0
  132. clarifai/runners/models/__pycache__/model_class.cpython-311.pyc +0 -0
  133. clarifai/runners/models/__pycache__/model_runner.cpython-311.pyc +0 -0
  134. clarifai/runners/models/__pycache__/openai_class.cpython-311.pyc +0 -0
  135. clarifai/runners/models/base_typed_model.py +238 -0
  136. clarifai/runners/models/model_upload.py +607 -0
  137. clarifai/runners/server.py +1 -0
  138. clarifai/runners/utils/__pycache__/__init__.cpython-311.pyc +0 -0
  139. clarifai/runners/utils/__pycache__/__init__.cpython-39.pyc +0 -0
  140. clarifai/runners/utils/__pycache__/code_script.cpython-311.pyc +0 -0
  141. clarifai/runners/utils/__pycache__/code_script.cpython-39.pyc +0 -0
  142. clarifai/runners/utils/__pycache__/const.cpython-311.pyc +0 -0
  143. clarifai/runners/utils/__pycache__/data_utils.cpython-311.pyc +0 -0
  144. clarifai/runners/utils/__pycache__/data_utils.cpython-39.pyc +0 -0
  145. clarifai/runners/utils/__pycache__/loader.cpython-311.pyc +0 -0
  146. clarifai/runners/utils/__pycache__/method_signatures.cpython-311.pyc +0 -0
  147. clarifai/runners/utils/__pycache__/model_utils.cpython-311.pyc +0 -0
  148. clarifai/runners/utils/__pycache__/openai_convertor.cpython-311.pyc +0 -0
  149. clarifai/runners/utils/__pycache__/serializers.cpython-311.pyc +0 -0
  150. clarifai/runners/utils/__pycache__/url_fetcher.cpython-311.pyc +0 -0
  151. clarifai/runners/utils/code_script.py +52 -46
  152. clarifai/runners/utils/data_handler.py +231 -0
  153. clarifai/runners/utils/data_types/__pycache__/__init__.cpython-311.pyc +0 -0
  154. clarifai/runners/utils/data_types/__pycache__/__init__.cpython-39.pyc +0 -0
  155. clarifai/runners/utils/data_types/__pycache__/data_types.cpython-311.pyc +0 -0
  156. clarifai/runners/utils/data_types/__pycache__/data_types.cpython-39.pyc +0 -0
  157. clarifai/runners/utils/data_types.py +471 -0
  158. clarifai/runners/utils/temp.py +59 -0
  159. clarifai/schema/__pycache__/search.cpython-311.pyc +0 -0
  160. clarifai/urls/__pycache__/helper.cpython-311.pyc +0 -0
  161. clarifai/urls/__pycache__/helper.cpython-39.pyc +0 -0
  162. clarifai/utils/__pycache__/__init__.cpython-311.pyc +0 -0
  163. clarifai/utils/__pycache__/__init__.cpython-39.pyc +0 -0
  164. clarifai/utils/__pycache__/cli.cpython-39.pyc +0 -0
  165. clarifai/utils/__pycache__/config.cpython-311.pyc +0 -0
  166. clarifai/utils/__pycache__/config.cpython-39.pyc +0 -0
  167. clarifai/utils/__pycache__/constants.cpython-311.pyc +0 -0
  168. clarifai/utils/__pycache__/constants.cpython-39.pyc +0 -0
  169. clarifai/utils/__pycache__/logging.cpython-311.pyc +0 -0
  170. clarifai/utils/__pycache__/logging.cpython-39.pyc +0 -0
  171. clarifai/utils/__pycache__/misc.cpython-311.pyc +0 -0
  172. clarifai/utils/__pycache__/misc.cpython-39.pyc +0 -0
  173. clarifai/utils/__pycache__/model_train.cpython-311.pyc +0 -0
  174. clarifai/utils/__pycache__/protobuf.cpython-311.pyc +0 -0
  175. clarifai/utils/__pycache__/protobuf.cpython-39.pyc +0 -0
  176. clarifai/utils/cli.py +14 -15
  177. clarifai/utils/constants.py +2 -0
  178. clarifai/utils/misc.py +382 -1
  179. clarifai/workflows/__pycache__/__init__.cpython-311.pyc +0 -0
  180. clarifai/workflows/__pycache__/export.cpython-311.pyc +0 -0
  181. clarifai/workflows/__pycache__/utils.cpython-311.pyc +0 -0
  182. clarifai/workflows/__pycache__/validate.cpython-311.pyc +0 -0
  183. {clarifai-11.6.4.dist-info → clarifai-11.6.4rc2.dist-info}/METADATA +1 -1
  184. clarifai-11.6.4rc2.dist-info/RECORD +301 -0
  185. {clarifai-11.6.4.dist-info → clarifai-11.6.4rc2.dist-info}/WHEEL +1 -1
  186. clarifai-11.6.4.dist-info/RECORD +0 -127
  187. {clarifai-11.6.4.dist-info → clarifai-11.6.4rc2.dist-info}/entry_points.txt +0 -0
  188. {clarifai-11.6.4.dist-info → clarifai-11.6.4rc2.dist-info}/licenses/LICENSE +0 -0
  189. {clarifai-11.6.4.dist-info → clarifai-11.6.4rc2.dist-info}/top_level.txt +0 -0
@@ -44,62 +44,66 @@ def generate_client_script(
44
44
  model_id,
45
45
  )
46
46
 
47
- _CLIENT_TEMPLATE = """
47
+ _CLIENT_TEMPLATE = f"""
48
48
  import asyncio
49
49
  import os
50
+
50
51
  from fastmcp import Client
51
52
  from fastmcp.client.transports import StreamableHttpTransport
52
53
 
53
- transport = StreamableHttpTransport(url="%s",
54
- headers={"Authorization": "Bearer " + os.environ["CLARIFAI_PAT"]})
54
+ transport = StreamableHttpTransport(
55
+ url="{mcp_url}",
56
+ headers={{"Authorization": "Bearer " + os.environ["CLARIFAI_PAT"]}},
57
+ )
55
58
 
56
59
  async def main():
57
- async with Client(transport) as client:
58
- tools = await client.list_tools()
59
- print(f"Available tools: {tools}")
60
- # TODO: update the dictionary of arguments passed to call_tool to make sense for your MCP.
61
- result = await client.call_tool(tools[0].name, {"a": 5, "b": 3})
62
- print(f"Result: {result[0].text}")
60
+ async with Client(transport) as client:
61
+ tools = await client.list_tools()
62
+ print(f"Available tools: {{tools}}")
63
+ # TODO: update the dictionary of arguments passed to call_tool to make sense for your MCP.
64
+ result = await client.call_tool(tools[0].name, {{"a": 5, "b": 3}})
65
+ print(f"Result: {{result[0].text}}")
63
66
 
64
67
  if __name__ == "__main__":
65
- asyncio.run(main())
68
+ asyncio.run(main())
66
69
  """
67
- return _CLIENT_TEMPLATE % mcp_url
70
+ return _CLIENT_TEMPLATE
68
71
 
69
72
  if has_signature_method(OPENAI_TRANSPORT_NAME, method_signatures):
70
73
  openai_api_base = url_helper.openai_api_url()
71
74
  model_ui_url = url_helper.clarifai_url(user_id, app_id, "models", model_id)
72
- _CLIENT_TEMPLATE = """
75
+ _CLIENT_TEMPLATE = f"""
73
76
  import os
77
+
74
78
  from openai import OpenAI
75
79
 
76
80
  client = OpenAI(
77
- base_url="%s",
81
+ base_url="{openai_api_base}",
78
82
  api_key=os.environ['CLARIFAI_PAT'],
79
83
  )
84
+
80
85
  response = client.chat.completions.create(
81
- model="%s",
86
+ model="{model_ui_url}",
82
87
  messages=[
83
- {"role": "system", "content": "Talk like a pirate."},
84
- {
88
+ {{"role": "system", "content": "Talk like a pirate."}},
89
+ {{
85
90
  "role": "user",
86
91
  "content": "How do I check if a Python object is an instance of a class?",
87
- },
92
+ }},
88
93
  ],
89
94
  temperature=0.7,
90
- stream=False, # stream=True also works, just iterator over the response
95
+ stream=False, # stream=True also works, just iterator over the response
91
96
  )
92
97
  print(response)
93
98
  """
94
- return _CLIENT_TEMPLATE % (openai_api_base, model_ui_url)
95
-
96
- _CLIENT_TEMPLATE = """\
97
- import os
98
-
99
- from clarifai.client import Model
100
- from clarifai.runners.utils import data_types
101
- {model_section}
102
- """
99
+ return _CLIENT_TEMPLATE
100
+ # Generate client template
101
+ _CLIENT_TEMPLATE = (
102
+ "import os\n\n"
103
+ "from clarifai.client import Model\n"
104
+ "from clarifai.runners.utils import data_types\n\n"
105
+ "{model_section}\n"
106
+ )
103
107
  if deployment_id and (compute_cluster_id or nodepool_id):
104
108
  raise ValueError(
105
109
  "You can only specify one of deployment_id or compute_cluster_id and nodepool_id."
@@ -108,26 +112,26 @@ from clarifai.runners.utils import data_types
108
112
  deployment_id = None
109
113
  else:
110
114
  deployment_id = (
111
- "os.environ['CLARIFAI_DEPLOYMENT_ID']" if not deployment_id else repr(deployment_id)
115
+ 'os.environ["CLARIFAI_DEPLOYMENT_ID"]' if not deployment_id else repr(deployment_id)
112
116
  )
113
117
 
114
118
  deployment_line = (
115
- f'deployment_id = {deployment_id}, # Only needed for dedicated deployed models'
119
+ f'deployment_id={deployment_id}, # Only needed for dedicated deployed models'
116
120
  if deployment_id
117
121
  else ""
118
122
  )
119
123
  compute_cluster_line = (
120
- f'compute_cluster_id = "{compute_cluster_id}",' if compute_cluster_id else ""
124
+ f'compute_cluster_id="{compute_cluster_id}",' if compute_cluster_id else ""
121
125
  )
122
126
  nodepool_line = (
123
- f'nodepool_id = "{nodepool_id}", # Only needed for dedicated nodepool'
127
+ f'nodepool_id="{nodepool_id}", # Only needed for dedicated nodepool'
124
128
  if nodepool_id
125
129
  else ""
126
130
  )
127
131
 
128
132
  base_url_str = ""
129
133
  if base_url is not None:
130
- base_url_str = f"base_url='{base_url}',"
134
+ base_url_str = f'base_url="{base_url}",'
131
135
 
132
136
  # Join all non-empty lines
133
137
  optional_lines = "\n ".join(
@@ -138,19 +142,17 @@ from clarifai.runners.utils import data_types
138
142
 
139
143
  if use_ctx:
140
144
  model_section = """
141
- model = Model.from_current_context()"""
145
+ model = Model.from_current_context()
146
+ """
142
147
  else:
143
148
  model_ui_url = url_helper.clarifai_url(user_id, app_id, "models", model_id)
144
- model_section = f"""
145
- model = Model("{model_ui_url}",
146
- {optional_lines}
147
- )
148
- """
149
+ if optional_lines:
150
+ model_args = f'"{model_ui_url}",\n {optional_lines}'
151
+ else:
152
+ model_args = f'"{model_ui_url}"'
153
+ model_section = f"model = Model(\n {model_args}\n)"
149
154
 
150
- # Generate client template
151
- client_template = _CLIENT_TEMPLATE.format(
152
- model_section=model_section,
153
- )
155
+ client_template = _CLIENT_TEMPLATE.format(model_section=model_section.strip("\n"))
154
156
 
155
157
  # Generate method signatures
156
158
  method_signatures_str = []
@@ -158,8 +160,9 @@ model = Model("{model_ui_url}",
158
160
  if method_signature is None:
159
161
  continue
160
162
  method_name = method_signature.name
161
- client_script_str = f'response = model.{method_name}('
163
+ client_script_str = f"response = model.{method_name}("
162
164
  annotations = _get_annotations_source(method_signature)
165
+ param_lines = []
163
166
  for idx, (param_name, (param_type, default_value, required)) in enumerate(
164
167
  annotations.items()
165
168
  ):
@@ -172,8 +175,11 @@ model = Model("{model_ui_url}",
172
175
  if param_type == "str" and default_value is not None:
173
176
  default_value = json.dumps(default_value)
174
177
  if default_value is not None:
175
- client_script_str += f"{param_name}={default_value}, "
176
- client_script_str = client_script_str.rstrip(", ") + ")"
178
+ param_lines.append(f" {param_name}={default_value},")
179
+ if param_lines:
180
+ client_script_str += "\n" + "\n".join(param_lines) + "\n)"
181
+ else:
182
+ client_script_str += ")"
177
183
  if method_signature.method_type == resources_pb2.RunnerMethodType.UNARY_UNARY:
178
184
  client_script_str += "\nprint(response)"
179
185
  elif method_signature.method_type == resources_pb2.RunnerMethodType.UNARY_STREAMING:
@@ -191,7 +197,7 @@ model = Model("{model_ui_url}",
191
197
  )
192
198
  script_lines.append("# Example usage:")
193
199
  script_lines.append(client_template)
194
- script_lines.append("# Example model prediction from different model methods: \n")
200
+ script_lines.append("# Example model prediction from different model methods:\n")
195
201
  script_lines.append(method_signatures_str)
196
202
  script_lines.append("")
197
203
  script = "\n".join(script_lines)
@@ -0,0 +1,231 @@
1
+ from typing import Dict, List, Tuple, Union
2
+
3
+ import numpy as np
4
+ from clarifai_grpc.grpc.api import resources_pb2
5
+ from clarifai_grpc.grpc.api.status import status_code_pb2, status_pb2
6
+ from PIL import Image
7
+
8
+ from clarifai.client.auth.helper import ClarifaiAuthHelper
9
+
10
+ from .data_utils import bytes_to_image, image_to_bytes
11
+
12
+
13
+ class BaseDataHandler:
14
+
15
+ def __init__(self,
16
+ proto: Union[resources_pb2.Input, resources_pb2.Output],
17
+ auth: ClarifaiAuthHelper = None):
18
+ self._proto = proto
19
+ self._auth = auth
20
+
21
+ #
22
+ def to_python(self):
23
+ return dict(text=self.text, image=self.image, audio=self.audio)
24
+
25
+ # ---------------- Start get/setters ---------------- #
26
+ # Proto
27
+ @property
28
+ def proto(self):
29
+ return self._proto
30
+
31
+ # Status
32
+ @property
33
+ def status(self) -> status_pb2.Status:
34
+ return self._proto.status
35
+
36
+ def set_status(self, code: str, description: str = ""):
37
+ self._proto.status.code = code
38
+ self._proto.status.description = description
39
+
40
+ # Text
41
+ @property
42
+ def text(self) -> Union[None, str]:
43
+ data = self._proto.data.text
44
+ text = None
45
+ if data.ByteSize():
46
+ if data.raw:
47
+ text = data.raw
48
+ else:
49
+ raise NotImplementedError
50
+ return text
51
+
52
+ def set_text(self, text: str):
53
+ self._proto.data.text.raw = text
54
+
55
+ # Image
56
+ @property
57
+ def image(self, format: str = "np") -> Union[None, Image.Image, np.ndarray]:
58
+ data = self._proto.data.image
59
+ image = None
60
+ if data.ByteSize():
61
+ data: resources_pb2.Image = data
62
+ if data.base64:
63
+ image = data.base64
64
+ elif data.url:
65
+ raise NotImplementedError
66
+ image = bytes_to_image(image)
67
+ image = image if not format == "np" else np.asarray(image).astype("uint8")
68
+ return image
69
+
70
+ def set_image(self, image: Union[Image.Image, np.ndarray]):
71
+ if isinstance(image, np.ndarray):
72
+ image = Image.fromarray(image)
73
+ self._proto.data.image.base64 = image_to_bytes(image)
74
+
75
+ # Audio
76
+ @property
77
+ def audio(self) -> bytes:
78
+ data = self._proto.data.audio
79
+ audio = None
80
+ if data.ByteSize():
81
+ if data.base64:
82
+ audio = data.base64
83
+ return audio
84
+
85
+ def set_audio(self, audio: bytes):
86
+ self._proto.data.audio.base64 = audio
87
+
88
+ # Bboxes
89
+ @property
90
+ def bboxes(self, real_coord: bool = False, image_width: int = None,
91
+ image_height: int = None) -> Tuple[List, List, List]:
92
+ if real_coord:
93
+ assert (image_height or image_width
94
+ ), "image_height and image_width are required when when return real coordinates"
95
+ xyxy = []
96
+ scores = []
97
+ concepts = []
98
+ for _, each in enumerate(self._proto.data.regions):
99
+ box = each.region_info
100
+ score = each.value
101
+ concept = each.data.concepts[0].id
102
+ x1 = box.left_col
103
+ y1 = box.top_row
104
+ x2 = box.right_col
105
+ y2 = box.bottom_row
106
+ if real_coord:
107
+ x1 = x1 * image_width
108
+ y1 = y1 * image_height
109
+ x2 = x2 * image_width
110
+ y2 = y2 * image_height
111
+ xyxy.append([x1, y1, x2, y2])
112
+ scores.append(score)
113
+ concepts.append(concept)
114
+
115
+ return xyxy, scores, concepts
116
+
117
+ def set_bboxes(self,
118
+ boxes: list,
119
+ scores: list,
120
+ concepts: list,
121
+ real_coord: bool = False,
122
+ image_width: int = None,
123
+ image_height: int = None):
124
+ if real_coord:
125
+ assert (image_height and
126
+ image_width), "image_height and image_width are required when `real_coord` is set"
127
+ bboxes = [[x[1] / image_height, x[0] / image_width, x[3] / image_height, x[2] / image_width]
128
+ for x in boxes] # normalize the bboxes to [0,1] and [y1 x1 y2 x2]
129
+ bboxes = np.clip(bboxes, 0, 1.0)
130
+
131
+ regions = []
132
+ for ith, bbox in enumerate(bboxes):
133
+ score = scores[ith]
134
+ concept = concepts[ith]
135
+ if any([each > 1.0 for each in bbox]):
136
+ assert ValueError(
137
+ "Box coordinates is not normalized between [0, 1]. Please set format_box to True and provide image_height and image_width to normalize"
138
+ )
139
+ region = resources_pb2.RegionInfo(bounding_box=resources_pb2.BoundingBox(
140
+ top_row=bbox[0], # y_min
141
+ left_col=bbox[1], # x_min
142
+ bottom_row=bbox[2], # y_max
143
+ right_col=bbox[3], # x_max
144
+ ))
145
+ data = resources_pb2.Data(concepts=resources_pb2.Concept(id=concept, value=score))
146
+ regions.append(resources_pb2.Region(region_info=region, data=data))
147
+
148
+ self._proto.data.regions = regions
149
+
150
+ # Concepts
151
+ @property
152
+ def concepts(self) -> Dict[str, float]:
153
+ con_scores = {}
154
+ for each in self.proto.data.concepts:
155
+ con_scores.update({each.id: each.value})
156
+ return con_scores
157
+
158
+ def set_concepts(self, concept_score_pairs: Dict[str, float]):
159
+ concepts = []
160
+ for concept, score in concept_score_pairs.items():
161
+ con_score = resources_pb2.Concept(id=concept, name=concept, value=score)
162
+ concepts.append(con_score)
163
+ if concepts:
164
+ self._proto.data.ClearField("concepts")
165
+ for each in concepts:
166
+ self._proto.data.concepts.append(each)
167
+
168
+ # Embeddings
169
+ @property
170
+ def embeddings(self) -> List[List[float]]:
171
+ return [each.vector for each in self.proto.data.embeddings]
172
+
173
+ def set_embeddings(self, list_vectors: List[List[float]]):
174
+ if list_vectors[0]:
175
+ self._proto.data.ClearField("embeddings")
176
+ for vec in list_vectors:
177
+ self._proto.data.embeddings.append(
178
+ resources_pb2.Embedding(vector=vec, num_dimensions=len(vec)))
179
+
180
+ # ---------------- End get/setters ---------------- #
181
+
182
+ # Constructors
183
+ @classmethod
184
+ def from_proto(cls, proto):
185
+ clss = cls(proto=proto)
186
+ return clss
187
+
188
+ @classmethod
189
+ def from_data(
190
+ cls,
191
+ status_code: int = status_code_pb2.SUCCESS,
192
+ status_description: str = "",
193
+ text: str = None,
194
+ image: Union[Image.Image, np.ndarray] = None,
195
+ audio: bytes = None,
196
+ boxes: dict = None,
197
+ concepts: Dict[str, float] = {},
198
+ embeddings: List[List[float]] = [],
199
+ ) -> 'OutputDataHandler':
200
+ clss = cls(proto=resources_pb2.Output())
201
+ if isinstance(image, Image.Image) or isinstance(image, np.ndarray):
202
+ clss.set_image(image)
203
+ if text:
204
+ clss.set_text(text)
205
+ if audio:
206
+ clss.set_audio(audio)
207
+ if boxes:
208
+ clss.set_bboxes(**boxes)
209
+ if concepts:
210
+ clss.set_concepts(concepts)
211
+ if embeddings:
212
+ clss.set_embeddings(embeddings)
213
+
214
+ clss.set_status(code=status_code, description=status_description)
215
+ return clss
216
+
217
+
218
+ class InputDataHandler(BaseDataHandler):
219
+
220
+ def __init__(self,
221
+ proto: resources_pb2.Input = resources_pb2.Input(),
222
+ auth: ClarifaiAuthHelper = None):
223
+ super().__init__(proto=proto, auth=auth)
224
+
225
+
226
+ class OutputDataHandler(BaseDataHandler):
227
+
228
+ def __init__(self,
229
+ proto: resources_pb2.Output = resources_pb2.Output(),
230
+ auth: ClarifaiAuthHelper = None):
231
+ super().__init__(proto=proto, auth=auth)