clarifai 11.4.3rc1__py3-none-any.whl → 11.4.4__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 (152) hide show
  1. clarifai/__init__.py +1 -1
  2. clarifai/cli/base.py +1 -2
  3. clarifai/cli/model.py +0 -2
  4. clarifai/client/app.py +2 -1
  5. clarifai/client/auth/helper.py +6 -4
  6. clarifai/client/compute_cluster.py +2 -1
  7. clarifai/client/dataset.py +2 -1
  8. clarifai/client/deployment.py +2 -1
  9. clarifai/client/input.py +2 -1
  10. clarifai/client/model.py +2 -1
  11. clarifai/client/model_client.py +2 -2
  12. clarifai/client/module.py +2 -1
  13. clarifai/client/nodepool.py +2 -1
  14. clarifai/client/runner.py +2 -1
  15. clarifai/client/search.py +2 -1
  16. clarifai/client/user.py +2 -1
  17. clarifai/client/workflow.py +2 -1
  18. clarifai/runners/models/mcp_class.py +6 -35
  19. clarifai/runners/models/model_builder.py +46 -42
  20. clarifai/runners/utils/code_script.py +40 -11
  21. clarifai/runners/utils/data_types/data_types.py +48 -0
  22. clarifai/runners/utils/data_utils.py +67 -43
  23. clarifai/runners/utils/method_signatures.py +0 -20
  24. clarifai/runners/utils/openai_convertor.py +103 -0
  25. clarifai/urls/helper.py +80 -12
  26. clarifai/utils/config.py +1 -1
  27. clarifai/utils/constants.py +4 -0
  28. {clarifai-11.4.3rc1.dist-info → clarifai-11.4.4.dist-info}/METADATA +13 -2
  29. clarifai-11.4.4.dist-info/RECORD +112 -0
  30. {clarifai-11.4.3rc1.dist-info → clarifai-11.4.4.dist-info}/WHEEL +1 -1
  31. clarifai/__pycache__/__init__.cpython-312.pyc +0 -0
  32. clarifai/__pycache__/__init__.cpython-39.pyc +0 -0
  33. clarifai/__pycache__/errors.cpython-312.pyc +0 -0
  34. clarifai/__pycache__/errors.cpython-39.pyc +0 -0
  35. clarifai/__pycache__/versions.cpython-312.pyc +0 -0
  36. clarifai/__pycache__/versions.cpython-39.pyc +0 -0
  37. clarifai/cli/__pycache__/__init__.cpython-312.pyc +0 -0
  38. clarifai/cli/__pycache__/base.cpython-312.pyc +0 -0
  39. clarifai/cli/__pycache__/compute_cluster.cpython-312.pyc +0 -0
  40. clarifai/cli/__pycache__/deployment.cpython-312.pyc +0 -0
  41. clarifai/cli/__pycache__/model.cpython-312.pyc +0 -0
  42. clarifai/cli/__pycache__/nodepool.cpython-312.pyc +0 -0
  43. clarifai/client/__pycache__/__init__.cpython-312.pyc +0 -0
  44. clarifai/client/__pycache__/__init__.cpython-39.pyc +0 -0
  45. clarifai/client/__pycache__/app.cpython-312.pyc +0 -0
  46. clarifai/client/__pycache__/app.cpython-39.pyc +0 -0
  47. clarifai/client/__pycache__/base.cpython-312.pyc +0 -0
  48. clarifai/client/__pycache__/base.cpython-39.pyc +0 -0
  49. clarifai/client/__pycache__/compute_cluster.cpython-312.pyc +0 -0
  50. clarifai/client/__pycache__/dataset.cpython-312.pyc +0 -0
  51. clarifai/client/__pycache__/deployment.cpython-312.pyc +0 -0
  52. clarifai/client/__pycache__/input.cpython-312.pyc +0 -0
  53. clarifai/client/__pycache__/lister.cpython-312.pyc +0 -0
  54. clarifai/client/__pycache__/model.cpython-312.pyc +0 -0
  55. clarifai/client/__pycache__/model_client.cpython-312.pyc +0 -0
  56. clarifai/client/__pycache__/module.cpython-312.pyc +0 -0
  57. clarifai/client/__pycache__/nodepool.cpython-312.pyc +0 -0
  58. clarifai/client/__pycache__/runner.cpython-312.pyc +0 -0
  59. clarifai/client/__pycache__/search.cpython-312.pyc +0 -0
  60. clarifai/client/__pycache__/user.cpython-312.pyc +0 -0
  61. clarifai/client/__pycache__/workflow.cpython-312.pyc +0 -0
  62. clarifai/client/auth/__pycache__/__init__.cpython-312.pyc +0 -0
  63. clarifai/client/auth/__pycache__/__init__.cpython-39.pyc +0 -0
  64. clarifai/client/auth/__pycache__/helper.cpython-312.pyc +0 -0
  65. clarifai/client/auth/__pycache__/helper.cpython-39.pyc +0 -0
  66. clarifai/client/auth/__pycache__/register.cpython-312.pyc +0 -0
  67. clarifai/client/auth/__pycache__/register.cpython-39.pyc +0 -0
  68. clarifai/client/auth/__pycache__/stub.cpython-312.pyc +0 -0
  69. clarifai/client/auth/__pycache__/stub.cpython-39.pyc +0 -0
  70. clarifai/constants/__pycache__/base.cpython-312.pyc +0 -0
  71. clarifai/constants/__pycache__/base.cpython-39.pyc +0 -0
  72. clarifai/constants/__pycache__/dataset.cpython-312.pyc +0 -0
  73. clarifai/constants/__pycache__/input.cpython-312.pyc +0 -0
  74. clarifai/constants/__pycache__/model.cpython-312.pyc +0 -0
  75. clarifai/constants/__pycache__/rag.cpython-312.pyc +0 -0
  76. clarifai/constants/__pycache__/search.cpython-312.pyc +0 -0
  77. clarifai/constants/__pycache__/workflow.cpython-312.pyc +0 -0
  78. clarifai/datasets/__pycache__/__init__.cpython-312.pyc +0 -0
  79. clarifai/datasets/export/__pycache__/__init__.cpython-312.pyc +0 -0
  80. clarifai/datasets/export/__pycache__/inputs_annotations.cpython-312.pyc +0 -0
  81. clarifai/datasets/upload/__pycache__/__init__.cpython-312.pyc +0 -0
  82. clarifai/datasets/upload/__pycache__/base.cpython-312.pyc +0 -0
  83. clarifai/datasets/upload/__pycache__/features.cpython-312.pyc +0 -0
  84. clarifai/datasets/upload/__pycache__/image.cpython-312.pyc +0 -0
  85. clarifai/datasets/upload/__pycache__/multimodal.cpython-312.pyc +0 -0
  86. clarifai/datasets/upload/__pycache__/text.cpython-312.pyc +0 -0
  87. clarifai/datasets/upload/__pycache__/utils.cpython-312.pyc +0 -0
  88. clarifai/datasets/upload/loaders/__pycache__/__init__.cpython-312.pyc +0 -0
  89. clarifai/datasets/upload/loaders/__pycache__/coco_detection.cpython-312.pyc +0 -0
  90. clarifai/datasets/upload/loaders/__pycache__/imagenet_classification.cpython-312.pyc +0 -0
  91. clarifai/modules/__pycache__/__init__.cpython-312.pyc +0 -0
  92. clarifai/modules/__pycache__/css.cpython-312.pyc +0 -0
  93. clarifai/rag/__pycache__/__init__.cpython-312.pyc +0 -0
  94. clarifai/rag/__pycache__/rag.cpython-312.pyc +0 -0
  95. clarifai/rag/__pycache__/utils.cpython-312.pyc +0 -0
  96. clarifai/runners/__pycache__/__init__.cpython-312.pyc +0 -0
  97. clarifai/runners/__pycache__/__init__.cpython-39.pyc +0 -0
  98. clarifai/runners/__pycache__/server.cpython-312.pyc +0 -0
  99. clarifai/runners/models/__pycache__/__init__.cpython-312.pyc +0 -0
  100. clarifai/runners/models/__pycache__/__init__.cpython-39.pyc +0 -0
  101. clarifai/runners/models/__pycache__/base_typed_model.cpython-312.pyc +0 -0
  102. clarifai/runners/models/__pycache__/mcp_class.cpython-312.pyc +0 -0
  103. clarifai/runners/models/__pycache__/model_builder.cpython-312.pyc +0 -0
  104. clarifai/runners/models/__pycache__/model_builder.cpython-39.pyc +0 -0
  105. clarifai/runners/models/__pycache__/model_class.cpython-312.pyc +0 -0
  106. clarifai/runners/models/__pycache__/model_run_locally.cpython-312.pyc +0 -0
  107. clarifai/runners/models/__pycache__/model_runner.cpython-312.pyc +0 -0
  108. clarifai/runners/models/__pycache__/model_servicer.cpython-312.pyc +0 -0
  109. clarifai/runners/models/__pycache__/test_model_builder.cpython-312-pytest-8.3.5.pyc +0 -0
  110. clarifai/runners/models/base_typed_model.py +0 -238
  111. clarifai/runners/models/example_mcp_server.py +0 -44
  112. clarifai/runners/models/mcp_class.py~ +0 -149
  113. clarifai/runners/models/test_model_builder.py +0 -89
  114. clarifai/runners/utils/__pycache__/__init__.cpython-312.pyc +0 -0
  115. clarifai/runners/utils/__pycache__/code_script.cpython-312.pyc +0 -0
  116. clarifai/runners/utils/__pycache__/const.cpython-312.pyc +0 -0
  117. clarifai/runners/utils/__pycache__/data_handler.cpython-312.pyc +0 -0
  118. clarifai/runners/utils/__pycache__/data_types.cpython-312.pyc +0 -0
  119. clarifai/runners/utils/__pycache__/data_utils.cpython-312.pyc +0 -0
  120. clarifai/runners/utils/__pycache__/loader.cpython-312.pyc +0 -0
  121. clarifai/runners/utils/__pycache__/method_signatures.cpython-312.pyc +0 -0
  122. clarifai/runners/utils/__pycache__/serializers.cpython-312.pyc +0 -0
  123. clarifai/runners/utils/__pycache__/url_fetcher.cpython-312.pyc +0 -0
  124. clarifai/runners/utils/data_handler.py +0 -231
  125. clarifai/runners/utils/data_types/__pycache__/__init__.cpython-312.pyc +0 -0
  126. clarifai/runners/utils/data_types/__pycache__/data_types.cpython-312.pyc +0 -0
  127. clarifai/schema/__pycache__/search.cpython-312.pyc +0 -0
  128. clarifai/urls/__pycache__/helper.cpython-312.pyc +0 -0
  129. clarifai/utils/__pycache__/__init__.cpython-312.pyc +0 -0
  130. clarifai/utils/__pycache__/__init__.cpython-39.pyc +0 -0
  131. clarifai/utils/__pycache__/cli.cpython-312.pyc +0 -0
  132. clarifai/utils/__pycache__/config.cpython-312.pyc +0 -0
  133. clarifai/utils/__pycache__/constants.cpython-312.pyc +0 -0
  134. clarifai/utils/__pycache__/constants.cpython-39.pyc +0 -0
  135. clarifai/utils/__pycache__/logging.cpython-312.pyc +0 -0
  136. clarifai/utils/__pycache__/logging.cpython-39.pyc +0 -0
  137. clarifai/utils/__pycache__/misc.cpython-312.pyc +0 -0
  138. clarifai/utils/__pycache__/misc.cpython-39.pyc +0 -0
  139. clarifai/utils/__pycache__/model_train.cpython-312.pyc +0 -0
  140. clarifai/utils/__pycache__/protobuf.cpython-312.pyc +0 -0
  141. clarifai/utils/config.py~ +0 -145
  142. clarifai/utils/evaluation/__pycache__/__init__.cpython-312.pyc +0 -0
  143. clarifai/utils/evaluation/__pycache__/helpers.cpython-312.pyc +0 -0
  144. clarifai/utils/evaluation/__pycache__/main.cpython-312.pyc +0 -0
  145. clarifai/workflows/__pycache__/__init__.cpython-312.pyc +0 -0
  146. clarifai/workflows/__pycache__/export.cpython-312.pyc +0 -0
  147. clarifai/workflows/__pycache__/utils.cpython-312.pyc +0 -0
  148. clarifai/workflows/__pycache__/validate.cpython-312.pyc +0 -0
  149. clarifai-11.4.3rc1.dist-info/RECORD +0 -230
  150. {clarifai-11.4.3rc1.dist-info → clarifai-11.4.4.dist-info}/entry_points.txt +0 -0
  151. {clarifai-11.4.3rc1.dist-info → clarifai-11.4.4.dist-info/licenses}/LICENSE +0 -0
  152. {clarifai-11.4.3rc1.dist-info → clarifai-11.4.4.dist-info}/top_level.txt +0 -0
clarifai/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "11.4.3rc1"
1
+ __version__ = "11.4.4"
clarifai/cli/base.py CHANGED
@@ -144,9 +144,8 @@ def dump(ctx_obj, output_format):
144
144
 
145
145
 
146
146
  @config.command(['cat'])
147
- @click.option('-o', '--output-format', default='yaml', type=click.Choice(['yaml', 'json']))
148
147
  @click.pass_obj
149
- def env(ctx_obj, output_format):
148
+ def env(ctx_obj):
150
149
  """Print env vars. Use: eval "$(clarifai config env)" """
151
150
  ctx_obj.current.print_env_vars()
152
151
 
clarifai/cli/model.py CHANGED
@@ -546,8 +546,6 @@ def local_dev(ctx, model_path):
546
546
  base_url=ctx.obj.current.api_base,
547
547
  )
548
548
 
549
- # TODO: put in the ClarifaiUrlHelper to create the model url.
550
-
551
549
  logger.info("""\n
552
550
  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
553
551
  # About to start up the local dev runner in this terminal...
clarifai/client/app.py CHANGED
@@ -19,6 +19,7 @@ from clarifai.client.workflow import Workflow
19
19
  from clarifai.constants.model import TRAINABLE_MODEL_TYPES
20
20
  from clarifai.errors import UserError
21
21
  from clarifai.urls.helper import ClarifaiUrlHelper
22
+ from clarifai.utils.constants import DEFAULT_BASE
22
23
  from clarifai.utils.logging import display_concept_relations_tree, display_workflow_tree, logger
23
24
  from clarifai.utils.misc import concept_relations_accumulation
24
25
  from clarifai.workflows.utils import get_yaml_output_info_proto, is_same_yaml_model
@@ -33,7 +34,7 @@ class App(Lister, BaseClient):
33
34
  url: str = None,
34
35
  app_id: str = None,
35
36
  user_id: str = None,
36
- base_url: str = "https://api.clarifai.com",
37
+ base_url: str = DEFAULT_BASE,
37
38
  pat: str = None,
38
39
  token: str = None,
39
40
  root_certificates_path: str = None,
@@ -7,10 +7,12 @@ from clarifai_grpc.channel.clarifai_channel import ClarifaiChannel
7
7
  from clarifai_grpc.grpc.api import resources_pb2, service_pb2_grpc
8
8
 
9
9
  from clarifai import __version__
10
- from clarifai.utils.constants import CLARIFAI_PAT_ENV_VAR, CLARIFAI_SESSION_TOKEN_ENV_VAR
11
-
12
- DEFAULT_BASE = "https://api.clarifai.com"
13
- DEFAULT_UI = "https://clarifai.com"
10
+ from clarifai.utils.constants import (
11
+ CLARIFAI_PAT_ENV_VAR,
12
+ CLARIFAI_SESSION_TOKEN_ENV_VAR,
13
+ DEFAULT_BASE,
14
+ DEFAULT_UI,
15
+ )
14
16
 
15
17
  REQUEST_ID_PREFIX_HEADER = "x-clarifai-request-id-prefix"
16
18
  REQUEST_ID_PREFIX = f"sdk-python-{__version__}"
@@ -10,6 +10,7 @@ from clarifai.client.base import BaseClient
10
10
  from clarifai.client.lister import Lister
11
11
  from clarifai.client.nodepool import Nodepool
12
12
  from clarifai.errors import UserError
13
+ from clarifai.utils.constants import DEFAULT_BASE
13
14
  from clarifai.utils.logging import logger
14
15
 
15
16
 
@@ -20,7 +21,7 @@ class ComputeCluster(Lister, BaseClient):
20
21
  self,
21
22
  compute_cluster_id: str = None,
22
23
  user_id: str = None,
23
- base_url: str = "https://api.clarifai.com",
24
+ base_url: str = DEFAULT_BASE,
24
25
  pat: str = None,
25
26
  token: str = None,
26
27
  root_certificates_path: str = None,
@@ -45,6 +45,7 @@ ClarifaiDatasetType = TypeVar(
45
45
  VisualSegmentationDataset,
46
46
  TextClassificationDataset,
47
47
  )
48
+ from clarifai.utils.constants import DEFAULT_BASE
48
49
 
49
50
 
50
51
  class Dataset(Lister, BaseClient):
@@ -55,7 +56,7 @@ class Dataset(Lister, BaseClient):
55
56
  url: str = None,
56
57
  dataset_id: str = None,
57
58
  dataset_version_id: str = None,
58
- base_url: str = "https://api.clarifai.com",
59
+ base_url: str = DEFAULT_BASE,
59
60
  pat: str = None,
60
61
  token: str = None,
61
62
  root_certificates_path: str = None,
@@ -2,6 +2,7 @@ from clarifai_grpc.grpc.api import resources_pb2
2
2
 
3
3
  from clarifai.client.base import BaseClient
4
4
  from clarifai.client.lister import Lister
5
+ from clarifai.utils.constants import DEFAULT_BASE
5
6
  from clarifai.utils.logging import logger
6
7
  from clarifai.utils.protobuf import dict_to_protobuf
7
8
 
@@ -13,7 +14,7 @@ class Deployment(Lister, BaseClient):
13
14
  self,
14
15
  deployment_id: str = None,
15
16
  user_id: str = None,
16
- base_url: str = "https://api.clarifai.com",
17
+ base_url: str = DEFAULT_BASE,
17
18
  pat: str = None,
18
19
  token: str = None,
19
20
  root_certificates_path: str = None,
clarifai/client/input.py CHANGED
@@ -21,6 +21,7 @@ from clarifai.client.lister import Lister
21
21
  from clarifai.constants.dataset import MAX_RETRIES
22
22
  from clarifai.constants.input import MAX_UPLOAD_BATCH_SIZE
23
23
  from clarifai.errors import UserError
24
+ from clarifai.utils.constants import DEFAULT_BASE
24
25
  from clarifai.utils.logging import logger
25
26
  from clarifai.utils.misc import BackoffIterator, Chunker, clean_input_id
26
27
 
@@ -33,7 +34,7 @@ class Inputs(Lister, BaseClient):
33
34
  user_id: str = None,
34
35
  app_id: str = None,
35
36
  logger_level: str = "INFO",
36
- base_url: str = "https://api.clarifai.com",
37
+ base_url: str = DEFAULT_BASE,
37
38
  pat: str = None,
38
39
  token: str = None,
39
40
  root_certificates_path: str = None,
clarifai/client/model.py CHANGED
@@ -34,6 +34,7 @@ from clarifai.constants.model import (
34
34
  )
35
35
  from clarifai.errors import UserError
36
36
  from clarifai.urls.helper import ClarifaiUrlHelper
37
+ from clarifai.utils.constants import DEFAULT_BASE
37
38
  from clarifai.utils.logging import logger
38
39
  from clarifai.utils.misc import BackoffIterator
39
40
  from clarifai.utils.model_train import (
@@ -58,7 +59,7 @@ class Model(Lister, BaseClient):
58
59
  url: str = None,
59
60
  model_id: str = None,
60
61
  model_version: Dict = {'id': ""},
61
- base_url: str = "https://api.clarifai.com",
62
+ base_url: str = DEFAULT_BASE,
62
63
  pat: str = None,
63
64
  token: str = None,
64
65
  root_certificates_path: str = None,
@@ -8,7 +8,6 @@ from clarifai_grpc.grpc.api.status import status_code_pb2
8
8
  from clarifai.constants.model import MAX_MODEL_PREDICT_INPUTS
9
9
  from clarifai.errors import UserError
10
10
  from clarifai.runners.utils import code_script, method_signatures
11
- from clarifai.runners.utils.data_utils import is_openai_chat_format
12
11
  from clarifai.runners.utils.method_signatures import (
13
12
  CompatibilitySerializer,
14
13
  deserialize,
@@ -16,6 +15,7 @@ from clarifai.runners.utils.method_signatures import (
16
15
  serialize,
17
16
  signatures_from_json,
18
17
  )
18
+ from clarifai.runners.utils.openai_convertor import is_openai_chat_format
19
19
  from clarifai.utils.logging import logger
20
20
  from clarifai.utils.misc import BackoffIterator, status_is_retryable
21
21
 
@@ -196,7 +196,7 @@ class ModelClient:
196
196
  f.__name__ = method_name
197
197
  f.__qualname__ = f'{self.__class__.__name__}.{method_name}'
198
198
  input_annotations = code_script._get_annotations_source(method_signature)
199
- return_annotation = input_annotations.pop('return', (None, None))[0]
199
+ return_annotation = input_annotations.pop('return', (None, None, None))[0]
200
200
  sig = inspect.signature(f).replace(
201
201
  parameters=[
202
202
  inspect.Parameter(k, inspect.Parameter.POSITIONAL_OR_KEYWORD, annotation=v[0])
clarifai/client/module.py CHANGED
@@ -6,6 +6,7 @@ from clarifai.client.base import BaseClient
6
6
  from clarifai.client.lister import Lister
7
7
  from clarifai.errors import UserError
8
8
  from clarifai.urls.helper import ClarifaiUrlHelper
9
+ from clarifai.utils.constants import DEFAULT_BASE
9
10
  from clarifai.utils.logging import logger
10
11
 
11
12
 
@@ -17,7 +18,7 @@ class Module(Lister, BaseClient):
17
18
  url: str = None,
18
19
  module_id: str = None,
19
20
  module_version: Dict = {'id': ""},
20
- base_url: str = "https://api.clarifai.com",
21
+ base_url: str = DEFAULT_BASE,
21
22
  pat: str = None,
22
23
  token: str = None,
23
24
  root_certificates_path: str = None,
@@ -11,6 +11,7 @@ from clarifai.client.deployment import Deployment
11
11
  from clarifai.client.lister import Lister
12
12
  from clarifai.client.runner import Runner
13
13
  from clarifai.errors import UserError
14
+ from clarifai.utils.constants import DEFAULT_BASE
14
15
  from clarifai.utils.logging import logger
15
16
 
16
17
 
@@ -21,7 +22,7 @@ class Nodepool(Lister, BaseClient):
21
22
  self,
22
23
  nodepool_id: str = None,
23
24
  user_id: str = None,
24
- base_url: str = "https://api.clarifai.com",
25
+ base_url: str = DEFAULT_BASE,
25
26
  pat: str = None,
26
27
  token: str = None,
27
28
  root_certificates_path: str = None,
clarifai/client/runner.py CHANGED
@@ -2,6 +2,7 @@ from clarifai_grpc.grpc.api import resources_pb2
2
2
 
3
3
  from clarifai.client.base import BaseClient
4
4
  from clarifai.client.lister import Lister
5
+ from clarifai.utils.constants import DEFAULT_BASE
5
6
  from clarifai.utils.logging import logger
6
7
  from clarifai.utils.protobuf import dict_to_protobuf
7
8
 
@@ -13,7 +14,7 @@ class Runner(Lister, BaseClient):
13
14
  self,
14
15
  runner_id: str = None,
15
16
  user_id: str = None,
16
- base_url: str = "https://api.clarifai.com",
17
+ base_url: str = DEFAULT_BASE,
17
18
  pat: str = None,
18
19
  token: str = None,
19
20
  root_certificates_path: str = None,
clarifai/client/search.py CHANGED
@@ -17,6 +17,7 @@ from clarifai.constants.search import (
17
17
  )
18
18
  from clarifai.errors import UserError
19
19
  from clarifai.schema.search import get_schema
20
+ from clarifai.utils.constants import DEFAULT_BASE
20
21
 
21
22
 
22
23
  class Search(Lister, BaseClient):
@@ -28,7 +29,7 @@ class Search(Lister, BaseClient):
28
29
  metric: str = DEFAULT_SEARCH_METRIC,
29
30
  algorithm: str = DEFAULT_SEARCH_ALGORITHM,
30
31
  pagination: bool = False,
31
- base_url: str = "https://api.clarifai.com",
32
+ base_url: str = DEFAULT_BASE,
32
33
  pat: str = None,
33
34
  token: str = None,
34
35
  root_certificates_path: str = None,
clarifai/client/user.py CHANGED
@@ -12,6 +12,7 @@ from clarifai.client.base import BaseClient
12
12
  from clarifai.client.compute_cluster import ComputeCluster
13
13
  from clarifai.client.lister import Lister
14
14
  from clarifai.errors import UserError
15
+ from clarifai.utils.constants import DEFAULT_BASE
15
16
  from clarifai.utils.logging import logger
16
17
 
17
18
 
@@ -21,7 +22,7 @@ class User(Lister, BaseClient):
21
22
  def __init__(
22
23
  self,
23
24
  user_id: str = None,
24
- base_url: str = "https://api.clarifai.com",
25
+ base_url: str = DEFAULT_BASE,
25
26
  pat: str = None,
26
27
  token: str = None,
27
28
  root_certificates_path: str = None,
@@ -14,6 +14,7 @@ from clarifai.client.model import Model
14
14
  from clarifai.constants.workflow import MAX_WORKFLOW_PREDICT_INPUTS
15
15
  from clarifai.errors import UserError
16
16
  from clarifai.urls.helper import ClarifaiUrlHelper
17
+ from clarifai.utils.constants import DEFAULT_BASE
17
18
  from clarifai.utils.logging import logger
18
19
  from clarifai.utils.misc import BackoffIterator, status_is_retryable
19
20
  from clarifai.workflows.export import Exporter
@@ -28,7 +29,7 @@ class Workflow(Lister, BaseClient):
28
29
  workflow_id: str = None,
29
30
  workflow_version: Dict = {'id': ""},
30
31
  output_config: Dict = {'min_value': 0},
31
- base_url: str = "https://api.clarifai.com",
32
+ base_url: str = DEFAULT_BASE,
32
33
  pat: str = None,
33
34
  token: str = None,
34
35
  root_certificates_path: str = None,
@@ -10,32 +10,6 @@ from mcp.shared.exceptions import McpError
10
10
 
11
11
  from clarifai.runners.models.model_class import ModelClass
12
12
 
13
- # class MCPServerProvider(abc.ABC):
14
- # """
15
- # Base class for creating Model Context Protocol (MCP) servers.
16
-
17
- # This class provides a base implementation of the MCP server, including
18
- # methods for handling requests and responses, as well as error handling and
19
- # logging.
20
-
21
- # Attributes:
22
- # _server: The FastMCP server instance.
23
- # _tools: List of tools available in the server.
24
- # _resources: List of resources available in the server.
25
- # _prompts: List of prompts available in the server.
26
-
27
- # Methods:
28
- # get_server(): Returns the FastMCP server instance.
29
- # mcp_transport(msg): Handles incoming messages and sends them to the FastMCP server.
30
- # """
31
-
32
- # @abc.abstractmethod
33
- # def get_server(self) -> FastMCP:
34
- # """Required method for each subclass to implement to return the FastMCP server to use."""
35
- # if self._server is None:
36
- # raise ValueError("Server not initialized")
37
- # return self._server
38
-
39
13
 
40
14
  class MCPModelClass(ModelClass):
41
15
  """Base class for wrapping FastMCP servers as a model running in Clarfai. This handles
@@ -82,8 +56,6 @@ class MCPModelClass(ModelClass):
82
56
  )
83
57
 
84
58
  result_type = None
85
- print("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")
86
- print(types.PingRequest)
87
59
  if isinstance(client_message.root, types.PingRequest):
88
60
  result_type = types.EmptyResult
89
61
  elif isinstance(client_message.root, types.InitializeRequest):
@@ -125,19 +97,18 @@ class MCPModelClass(ModelClass):
125
97
  # The JSONRPCRequest are supposed to have an id but the InitializeRequest
126
98
  # does not have it.
127
99
  d = json.loads(msg)
100
+ id = d.get('id', "")
128
101
 
129
102
  # If we have an id it's a JSONRPCRequest
130
- if not d.get('method', None).startswith("notifications/"):
131
- # rpc_message2 = types.JSONRPCRequest.model_validate(rpc_message)
132
- # underlying: types.JSONRPCRequest = rpc_message.root
103
+ if not d.get('method', '').startswith("notifications/"):
133
104
  client_message = types.ClientRequest.model_validate(d)
134
- response = asyncio.run(
135
- send_request(client_message, id=d.get('id', ""))
136
- ) # underlying.id))
105
+ response = asyncio.run(send_request(client_message, id=id))
137
106
  else: # JSONRPCRequest
138
107
  client_message = types.ClientNotification.model_validate(d)
139
108
  response = asyncio.run(send_notification(client_message))
140
109
  if response is None:
141
- return ""
110
+ response = types.JSONRPCError(
111
+ jsonrpc="2.0", id=id, error="Got empty response from MCP server."
112
+ )
142
113
  # return as a serialized json string
143
114
  return response.model_dump_json(by_alias=True, exclude_none=True)
@@ -413,6 +413,12 @@ class ModelBuilder:
413
413
  def get_method_signatures(self, mocking=True):
414
414
  """
415
415
  Returns the method signatures for the model class.
416
+
417
+ Args:
418
+ mocking (bool): Whether to mock the model class or not. Defaults to False.
419
+
420
+ Returns:
421
+ list: A list of method signatures for the model class.
416
422
  """
417
423
  model_class = self.load_model_class(mocking=mocking)
418
424
  method_info = model_class._get_method_info()
@@ -436,22 +442,42 @@ class ModelBuilder:
436
442
  return self._client
437
443
 
438
444
  @property
439
- def model_url(self):
445
+ def model_ui_url(self):
446
+ url_helper = ClarifaiUrlHelper(self._client.auth_helper)
447
+ # Note(zeiler): the UI experience isn't the best when including version id right now.
448
+ # if self.model_version_id is not None:
449
+ # return url_helper.clarifai_url(
450
+ # self.client.user_app_id.user_id,
451
+ # self.client.user_app_id.app_id,
452
+ # "models",
453
+ # self.model_id,
454
+ # self.model_version_id,
455
+ # )
456
+ # else:
457
+ return url_helper.clarifai_url(
458
+ self.client.user_app_id.user_id,
459
+ self.client.user_app_id.app_id,
460
+ "models",
461
+ self.model_id,
462
+ )
463
+
464
+ @property
465
+ def model_api_url(self):
440
466
  url_helper = ClarifaiUrlHelper(self._client.auth_helper)
441
467
  if self.model_version_id is not None:
442
- return url_helper.clarifai_url(
468
+ return url_helper.api_url(
443
469
  self.client.user_app_id.user_id,
444
470
  self.client.user_app_id.app_id,
445
471
  "models",
446
472
  self.model_id,
473
+ self.model_version_id,
447
474
  )
448
475
  else:
449
- return url_helper.clarifai_url(
476
+ return url_helper.api_url(
450
477
  self.client.user_app_id.user_id,
451
478
  self.client.user_app_id.app_id,
452
479
  "models",
453
480
  self.model_id,
454
- self.model_version_id,
455
481
  )
456
482
 
457
483
  def _get_model_proto(self):
@@ -930,44 +956,20 @@ class ModelBuilder:
930
956
  return
931
957
  self.model_version_id = response.model_version_id
932
958
  logger.info(f"Created Model Version ID: {self.model_version_id}")
933
- logger.info(f"Full url to that version is: {self.model_url}")
959
+ logger.info(f"Full url to that version is: {self.model_ui_url}")
934
960
  try:
935
961
  is_uploaded = self.monitor_model_build()
936
962
  if is_uploaded:
937
- # Provide an mcp client config
938
- if model_type_id == "mcp":
939
- snippet = (
940
- """
941
- import asyncio
942
- import os
943
- from fastmcp import Client
944
- from fastmcp.client.transports import StreamableHttpTransport
945
-
946
- transport = StreamableHttpTransport(url="%s/mcp",
947
- headers={"Authorization": "Bearer " + os.environ["CLARIFAI_PAT"]})
948
-
949
- async def main():
950
- async with Client(transport) as client:
951
- tools = await client.list_tools()
952
- print(f"Available tools: {tools}")
953
- result = await client.call_tool(tools[0].name, {"a": 5, "b": 3})
954
- print(f"Result: {result[0].text}")
955
-
956
- if __name__ == "__main__":
957
- asyncio.run(main())
958
- """
959
- % self.model_url
960
- )
961
- else: # python code to run the model.
962
- from clarifai.runners.utils import code_script
963
-
964
- method_signatures = self.get_method_signatures()
965
- snippet = code_script.generate_client_script(
966
- method_signatures,
967
- user_id=self.client.user_app_id.user_id,
968
- app_id=self.client.user_app_id.app_id,
969
- model_id=self.model_proto.id,
970
- )
963
+ # python code to run the model.
964
+ from clarifai.runners.utils import code_script
965
+
966
+ method_signatures = self.get_method_signatures()
967
+ snippet = code_script.generate_client_script(
968
+ method_signatures,
969
+ user_id=self.client.user_app_id.user_id,
970
+ app_id=self.client.user_app_id.app_id,
971
+ model_id=self.model_proto.id,
972
+ )
971
973
  logger.info("""\n
972
974
  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
973
975
  # Here is a code snippet to use this model:
@@ -1074,7 +1076,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1074
1076
  logger.info("Model build complete!")
1075
1077
  logger.info(f"Build time elapsed {time.time() - st:.1f}s)")
1076
1078
  logger.info(
1077
- f"Check out the model at {self.model_url} version: {self.model_version_id}"
1079
+ f"Check out the model at {self.model_ui_url} version: {self.model_version_id}"
1078
1080
  )
1079
1081
  return True
1080
1082
  else:
@@ -1099,10 +1101,12 @@ def upload_model(folder, stage, skip_dockerfile):
1099
1101
  exists = builder.check_model_exists()
1100
1102
  if exists:
1101
1103
  logger.info(
1102
- f"Model already exists at {builder.model_url}, this upload will create a new version for it."
1104
+ f"Model already exists at {builder.model_ui_url}, this upload will create a new version for it."
1103
1105
  )
1104
1106
  else:
1105
- logger.info(f"New model will be created at {builder.model_url} with it's first version.")
1107
+ logger.info(
1108
+ f"New model will be created at {builder.model_ui_url} with it's first version."
1109
+ )
1106
1110
 
1107
1111
  input("Press Enter to continue...")
1108
1112
  builder.upload_model_version()
@@ -4,6 +4,7 @@ from typing import List
4
4
  from clarifai_grpc.grpc.api import resources_pb2
5
5
 
6
6
  from clarifai.runners.utils import data_utils
7
+ from clarifai.urls.helper import ClarifaiUrlHelper
7
8
 
8
9
 
9
10
  def generate_client_script(
@@ -15,6 +16,38 @@ def generate_client_script(
15
16
  deployment_id: str = None,
16
17
  use_ctx: bool = False,
17
18
  ) -> str:
19
+ url_helper = ClarifaiUrlHelper()
20
+
21
+ # Provide an mcp client config
22
+ if len(method_signatures) == 1 and method_signatures[0].name == "mcp_transport":
23
+ api_url = url_helper.api_url(
24
+ user_id,
25
+ app_id,
26
+ "models",
27
+ model_id,
28
+ )
29
+
30
+ _CLIENT_TEMPLATE = """
31
+ import asyncio
32
+ import os
33
+ from fastmcp import Client
34
+ from fastmcp.client.transports import StreamableHttpTransport
35
+
36
+ transport = StreamableHttpTransport(url="%s/mcp",
37
+ headers={"Authorization": "Bearer " + os.environ["CLARIFAI_PAT"]})
38
+
39
+ async def main():
40
+ async with Client(transport) as client:
41
+ tools = await client.list_tools()
42
+ print(f"Available tools: {tools}")
43
+ result = await client.call_tool(tools[0].name, {"a": 5, "b": 3})
44
+ print(f"Result: {result[0].text}")
45
+
46
+ if __name__ == "__main__":
47
+ asyncio.run(main())
48
+ """
49
+ return _CLIENT_TEMPLATE % api_url
50
+
18
51
  _CLIENT_TEMPLATE = """\
19
52
  import os
20
53
 
@@ -35,8 +68,9 @@ from clarifai.runners.utils import data_types
35
68
  model_section = """
36
69
  model = Model.from_current_context()"""
37
70
  else:
71
+ model_ui_url = url_helper.clarifai_url(user_id, app_id, "models", model_id)
38
72
  model_section = f"""
39
- model = Model("https://clarifai.com/{user_id}/{app_id}/models/{model_id}",
73
+ model = Model({model_ui_url},
40
74
  deployment_id = {deployment_id}, # Only needed for dedicated deployed models
41
75
  {base_url_str}
42
76
  )
@@ -53,13 +87,13 @@ model = Model("https://clarifai.com/{user_id}/{app_id}/models/{model_id}",
53
87
  method_name = method_signature.name
54
88
  client_script_str = f'response = model.{method_name}('
55
89
  annotations = _get_annotations_source(method_signature)
56
- for param_name, (param_type, default_value) in annotations.items():
90
+ for param_name, (param_type, default_value, required) in annotations.items():
57
91
  print(
58
92
  f"param_name: {param_name}, param_type: {param_type}, default_value: {default_value}"
59
93
  )
60
94
  if param_name == "return":
61
95
  continue
62
- if default_value is None:
96
+ if default_value is None and required:
63
97
  default_value = _set_default_value(param_type)
64
98
  client_script_str += f"{param_name}={default_value}, "
65
99
  client_script_str = client_script_str.rstrip(", ") + ")"
@@ -98,7 +132,7 @@ def _get_annotations_source(method_signature: resources_pb2.MethodSignature) ->
98
132
  default_value = None
99
133
  if data_utils.Param.get_default(input_field):
100
134
  default_value = _parse_default_value(input_field)
101
- annotations[param_name] = (param_type, default_value)
135
+ annotations[param_name] = (param_type, default_value, input_field.required)
102
136
  if not method_signature.output_fields:
103
137
  raise ValueError("MethodSignature must have at least one output field")
104
138
  for output_field in method_signature.output_fields:
@@ -106,7 +140,7 @@ def _get_annotations_source(method_signature: resources_pb2.MethodSignature) ->
106
140
  param_type = _get_base_type(output_field)
107
141
  if output_field.iterator:
108
142
  param_type = f"Iterator[{param_type}]"
109
- annotations[param_name] = (param_type, None)
143
+ annotations[param_name] = (param_type, None, output_field.required)
110
144
  return annotations
111
145
 
112
146
 
@@ -155,7 +189,7 @@ def _map_default_value(field_type):
155
189
  default_value = None
156
190
 
157
191
  if field_type == "str":
158
- default_value = 'What is the future of AI?'
192
+ default_value = repr('What is the future of AI?')
159
193
  elif field_type == "bytes":
160
194
  default_value = b""
161
195
  elif field_type == "int":
@@ -190,11 +224,9 @@ def _set_default_value(field_type):
190
224
  Set the default value of a field if it is not set.
191
225
  """
192
226
  is_iterator = False
193
- print(f"before field_type: {field_type}")
194
227
  if field_type.startswith("Iterator["):
195
228
  is_iterator = True
196
229
  field_type = field_type[9:-1]
197
- print(f"after field_type: {field_type}")
198
230
  default_value = None
199
231
  default_value = _map_default_value(field_type)
200
232
  if field_type.startswith("List["):
@@ -211,11 +243,8 @@ def _set_default_value(field_type):
211
243
  element_type_defaults = [_map_default_value(et) for et in element_types]
212
244
  default_value = f"{{{', '.join([str(et) for et in element_type_defaults])}}}"
213
245
 
214
- if field_type == 'str':
215
- default_value = repr(default_value)
216
246
  if is_iterator:
217
247
  default_value = f'iter([{default_value}])'
218
- print(f"after default_value: {default_value}")
219
248
  return default_value
220
249
 
221
250