clarifai 11.4.3rc1__py3-none-any.whl → 11.4.5__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 (155) 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/__init__.py +2 -0
  19. clarifai/runners/models/dummy_openai_model.py +197 -0
  20. clarifai/runners/models/mcp_class.py +19 -39
  21. clarifai/runners/models/model_builder.py +46 -42
  22. clarifai/runners/models/openai_class.py +219 -0
  23. clarifai/runners/utils/code_script.py +41 -15
  24. clarifai/runners/utils/data_types/data_types.py +48 -0
  25. clarifai/runners/utils/data_utils.py +67 -43
  26. clarifai/runners/utils/method_signatures.py +0 -20
  27. clarifai/runners/utils/openai_convertor.py +103 -0
  28. clarifai/urls/helper.py +80 -12
  29. clarifai/utils/config.py +1 -1
  30. clarifai/utils/constants.py +4 -0
  31. {clarifai-11.4.3rc1.dist-info → clarifai-11.4.5.dist-info}/METADATA +13 -2
  32. clarifai-11.4.5.dist-info/RECORD +114 -0
  33. {clarifai-11.4.3rc1.dist-info → clarifai-11.4.5.dist-info}/WHEEL +1 -1
  34. clarifai/__pycache__/__init__.cpython-312.pyc +0 -0
  35. clarifai/__pycache__/__init__.cpython-39.pyc +0 -0
  36. clarifai/__pycache__/errors.cpython-312.pyc +0 -0
  37. clarifai/__pycache__/errors.cpython-39.pyc +0 -0
  38. clarifai/__pycache__/versions.cpython-312.pyc +0 -0
  39. clarifai/__pycache__/versions.cpython-39.pyc +0 -0
  40. clarifai/cli/__pycache__/__init__.cpython-312.pyc +0 -0
  41. clarifai/cli/__pycache__/base.cpython-312.pyc +0 -0
  42. clarifai/cli/__pycache__/compute_cluster.cpython-312.pyc +0 -0
  43. clarifai/cli/__pycache__/deployment.cpython-312.pyc +0 -0
  44. clarifai/cli/__pycache__/model.cpython-312.pyc +0 -0
  45. clarifai/cli/__pycache__/nodepool.cpython-312.pyc +0 -0
  46. clarifai/client/__pycache__/__init__.cpython-312.pyc +0 -0
  47. clarifai/client/__pycache__/__init__.cpython-39.pyc +0 -0
  48. clarifai/client/__pycache__/app.cpython-312.pyc +0 -0
  49. clarifai/client/__pycache__/app.cpython-39.pyc +0 -0
  50. clarifai/client/__pycache__/base.cpython-312.pyc +0 -0
  51. clarifai/client/__pycache__/base.cpython-39.pyc +0 -0
  52. clarifai/client/__pycache__/compute_cluster.cpython-312.pyc +0 -0
  53. clarifai/client/__pycache__/dataset.cpython-312.pyc +0 -0
  54. clarifai/client/__pycache__/deployment.cpython-312.pyc +0 -0
  55. clarifai/client/__pycache__/input.cpython-312.pyc +0 -0
  56. clarifai/client/__pycache__/lister.cpython-312.pyc +0 -0
  57. clarifai/client/__pycache__/model.cpython-312.pyc +0 -0
  58. clarifai/client/__pycache__/model_client.cpython-312.pyc +0 -0
  59. clarifai/client/__pycache__/module.cpython-312.pyc +0 -0
  60. clarifai/client/__pycache__/nodepool.cpython-312.pyc +0 -0
  61. clarifai/client/__pycache__/runner.cpython-312.pyc +0 -0
  62. clarifai/client/__pycache__/search.cpython-312.pyc +0 -0
  63. clarifai/client/__pycache__/user.cpython-312.pyc +0 -0
  64. clarifai/client/__pycache__/workflow.cpython-312.pyc +0 -0
  65. clarifai/client/auth/__pycache__/__init__.cpython-312.pyc +0 -0
  66. clarifai/client/auth/__pycache__/__init__.cpython-39.pyc +0 -0
  67. clarifai/client/auth/__pycache__/helper.cpython-312.pyc +0 -0
  68. clarifai/client/auth/__pycache__/helper.cpython-39.pyc +0 -0
  69. clarifai/client/auth/__pycache__/register.cpython-312.pyc +0 -0
  70. clarifai/client/auth/__pycache__/register.cpython-39.pyc +0 -0
  71. clarifai/client/auth/__pycache__/stub.cpython-312.pyc +0 -0
  72. clarifai/client/auth/__pycache__/stub.cpython-39.pyc +0 -0
  73. clarifai/constants/__pycache__/base.cpython-312.pyc +0 -0
  74. clarifai/constants/__pycache__/base.cpython-39.pyc +0 -0
  75. clarifai/constants/__pycache__/dataset.cpython-312.pyc +0 -0
  76. clarifai/constants/__pycache__/input.cpython-312.pyc +0 -0
  77. clarifai/constants/__pycache__/model.cpython-312.pyc +0 -0
  78. clarifai/constants/__pycache__/rag.cpython-312.pyc +0 -0
  79. clarifai/constants/__pycache__/search.cpython-312.pyc +0 -0
  80. clarifai/constants/__pycache__/workflow.cpython-312.pyc +0 -0
  81. clarifai/datasets/__pycache__/__init__.cpython-312.pyc +0 -0
  82. clarifai/datasets/export/__pycache__/__init__.cpython-312.pyc +0 -0
  83. clarifai/datasets/export/__pycache__/inputs_annotations.cpython-312.pyc +0 -0
  84. clarifai/datasets/upload/__pycache__/__init__.cpython-312.pyc +0 -0
  85. clarifai/datasets/upload/__pycache__/base.cpython-312.pyc +0 -0
  86. clarifai/datasets/upload/__pycache__/features.cpython-312.pyc +0 -0
  87. clarifai/datasets/upload/__pycache__/image.cpython-312.pyc +0 -0
  88. clarifai/datasets/upload/__pycache__/multimodal.cpython-312.pyc +0 -0
  89. clarifai/datasets/upload/__pycache__/text.cpython-312.pyc +0 -0
  90. clarifai/datasets/upload/__pycache__/utils.cpython-312.pyc +0 -0
  91. clarifai/datasets/upload/loaders/__pycache__/__init__.cpython-312.pyc +0 -0
  92. clarifai/datasets/upload/loaders/__pycache__/coco_detection.cpython-312.pyc +0 -0
  93. clarifai/datasets/upload/loaders/__pycache__/imagenet_classification.cpython-312.pyc +0 -0
  94. clarifai/modules/__pycache__/__init__.cpython-312.pyc +0 -0
  95. clarifai/modules/__pycache__/css.cpython-312.pyc +0 -0
  96. clarifai/rag/__pycache__/__init__.cpython-312.pyc +0 -0
  97. clarifai/rag/__pycache__/rag.cpython-312.pyc +0 -0
  98. clarifai/rag/__pycache__/utils.cpython-312.pyc +0 -0
  99. clarifai/runners/__pycache__/__init__.cpython-312.pyc +0 -0
  100. clarifai/runners/__pycache__/__init__.cpython-39.pyc +0 -0
  101. clarifai/runners/__pycache__/server.cpython-312.pyc +0 -0
  102. clarifai/runners/models/__pycache__/__init__.cpython-312.pyc +0 -0
  103. clarifai/runners/models/__pycache__/__init__.cpython-39.pyc +0 -0
  104. clarifai/runners/models/__pycache__/base_typed_model.cpython-312.pyc +0 -0
  105. clarifai/runners/models/__pycache__/mcp_class.cpython-312.pyc +0 -0
  106. clarifai/runners/models/__pycache__/model_builder.cpython-312.pyc +0 -0
  107. clarifai/runners/models/__pycache__/model_builder.cpython-39.pyc +0 -0
  108. clarifai/runners/models/__pycache__/model_class.cpython-312.pyc +0 -0
  109. clarifai/runners/models/__pycache__/model_run_locally.cpython-312.pyc +0 -0
  110. clarifai/runners/models/__pycache__/model_runner.cpython-312.pyc +0 -0
  111. clarifai/runners/models/__pycache__/model_servicer.cpython-312.pyc +0 -0
  112. clarifai/runners/models/__pycache__/test_model_builder.cpython-312-pytest-8.3.5.pyc +0 -0
  113. clarifai/runners/models/base_typed_model.py +0 -238
  114. clarifai/runners/models/example_mcp_server.py +0 -44
  115. clarifai/runners/models/mcp_class.py~ +0 -149
  116. clarifai/runners/models/test_model_builder.py +0 -89
  117. clarifai/runners/utils/__pycache__/__init__.cpython-312.pyc +0 -0
  118. clarifai/runners/utils/__pycache__/code_script.cpython-312.pyc +0 -0
  119. clarifai/runners/utils/__pycache__/const.cpython-312.pyc +0 -0
  120. clarifai/runners/utils/__pycache__/data_handler.cpython-312.pyc +0 -0
  121. clarifai/runners/utils/__pycache__/data_types.cpython-312.pyc +0 -0
  122. clarifai/runners/utils/__pycache__/data_utils.cpython-312.pyc +0 -0
  123. clarifai/runners/utils/__pycache__/loader.cpython-312.pyc +0 -0
  124. clarifai/runners/utils/__pycache__/method_signatures.cpython-312.pyc +0 -0
  125. clarifai/runners/utils/__pycache__/serializers.cpython-312.pyc +0 -0
  126. clarifai/runners/utils/__pycache__/url_fetcher.cpython-312.pyc +0 -0
  127. clarifai/runners/utils/data_handler.py +0 -231
  128. clarifai/runners/utils/data_types/__pycache__/__init__.cpython-312.pyc +0 -0
  129. clarifai/runners/utils/data_types/__pycache__/data_types.cpython-312.pyc +0 -0
  130. clarifai/schema/__pycache__/search.cpython-312.pyc +0 -0
  131. clarifai/urls/__pycache__/helper.cpython-312.pyc +0 -0
  132. clarifai/utils/__pycache__/__init__.cpython-312.pyc +0 -0
  133. clarifai/utils/__pycache__/__init__.cpython-39.pyc +0 -0
  134. clarifai/utils/__pycache__/cli.cpython-312.pyc +0 -0
  135. clarifai/utils/__pycache__/config.cpython-312.pyc +0 -0
  136. clarifai/utils/__pycache__/constants.cpython-312.pyc +0 -0
  137. clarifai/utils/__pycache__/constants.cpython-39.pyc +0 -0
  138. clarifai/utils/__pycache__/logging.cpython-312.pyc +0 -0
  139. clarifai/utils/__pycache__/logging.cpython-39.pyc +0 -0
  140. clarifai/utils/__pycache__/misc.cpython-312.pyc +0 -0
  141. clarifai/utils/__pycache__/misc.cpython-39.pyc +0 -0
  142. clarifai/utils/__pycache__/model_train.cpython-312.pyc +0 -0
  143. clarifai/utils/__pycache__/protobuf.cpython-312.pyc +0 -0
  144. clarifai/utils/config.py~ +0 -145
  145. clarifai/utils/evaluation/__pycache__/__init__.cpython-312.pyc +0 -0
  146. clarifai/utils/evaluation/__pycache__/helpers.cpython-312.pyc +0 -0
  147. clarifai/utils/evaluation/__pycache__/main.cpython-312.pyc +0 -0
  148. clarifai/workflows/__pycache__/__init__.cpython-312.pyc +0 -0
  149. clarifai/workflows/__pycache__/export.cpython-312.pyc +0 -0
  150. clarifai/workflows/__pycache__/utils.cpython-312.pyc +0 -0
  151. clarifai/workflows/__pycache__/validate.cpython-312.pyc +0 -0
  152. clarifai-11.4.3rc1.dist-info/RECORD +0 -230
  153. {clarifai-11.4.3rc1.dist-info → clarifai-11.4.5.dist-info}/entry_points.txt +0 -0
  154. {clarifai-11.4.3rc1.dist-info → clarifai-11.4.5.dist-info/licenses}/LICENSE +0 -0
  155. {clarifai-11.4.3rc1.dist-info → clarifai-11.4.5.dist-info}/top_level.txt +0 -0
clarifai/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "11.4.3rc1"
1
+ __version__ = "11.4.5"
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,
@@ -1,9 +1,11 @@
1
1
  from .models.model_builder import ModelBuilder
2
2
  from .models.model_class import ModelClass
3
3
  from .models.model_runner import ModelRunner
4
+ from .models.openai_class import OpenAIModelClass
4
5
 
5
6
  __all__ = [
6
7
  "ModelRunner",
7
8
  "ModelBuilder",
8
9
  "ModelClass",
10
+ "OpenAIModelClass",
9
11
  ]
@@ -0,0 +1,197 @@
1
+ """Dummy OpenAI model implementation for testing."""
2
+
3
+ import json
4
+ from typing import Any, Dict, Iterator
5
+
6
+ from clarifai.runners.models.openai_class import OpenAIModelClass
7
+
8
+
9
+ class MockOpenAIClient:
10
+ """Mock OpenAI client for testing."""
11
+
12
+ class Completions:
13
+ def create(self, **kwargs):
14
+ """Mock create method for compatibility."""
15
+ if kwargs.get("stream", False):
16
+ return MockCompletionStream(kwargs.get("messages", []))
17
+ else:
18
+ return MockCompletion(kwargs.get("messages", []))
19
+
20
+ def __init__(self):
21
+ self.chat = self # Make self.chat point to self for compatibility
22
+ self.completions = self.Completions() # For compatibility with some clients
23
+
24
+
25
+ class MockCompletion:
26
+ """Mock completion object that mimics the OpenAI completion response structure."""
27
+
28
+ class Choice:
29
+ class Message:
30
+ def __init__(self, content):
31
+ self.content = content
32
+ self.role = "assistant"
33
+
34
+ def __init__(self, content):
35
+ self.message = self.Message(content)
36
+ self.finish_reason = "stop"
37
+ self.index = 0
38
+
39
+ def __init__(self, messages):
40
+ # Generate a simple response based on the last message
41
+ last_message = messages[-1] if messages else {"content": ""}
42
+ response_text = f"Echo: {last_message.get('content', '')}"
43
+
44
+ self.choices = [self.Choice(response_text)]
45
+ self.usage = {
46
+ "prompt_tokens": len(str(messages)),
47
+ "completion_tokens": len(response_text),
48
+ "total_tokens": len(str(messages)) + len(response_text),
49
+ }
50
+ self.id = "dummy-completion-id"
51
+ self.created = 1234567890
52
+ self.model = "dummy-model"
53
+
54
+ def to_dict(self) -> Dict[str, Any]:
55
+ """Convert the completion object to a dictionary."""
56
+ return {
57
+ "id": self.id,
58
+ "created": self.created,
59
+ "model": self.model,
60
+ "choices": [
61
+ {
62
+ "message": {"role": choice.message.role, "content": choice.message.content},
63
+ "finish_reason": choice.finish_reason,
64
+ "index": choice.index,
65
+ }
66
+ for choice in self.choices
67
+ ],
68
+ "usage": self.usage,
69
+ }
70
+
71
+
72
+ class MockCompletionStream:
73
+ """Mock completion stream that mimics the OpenAI streaming response structure."""
74
+
75
+ class Chunk:
76
+ class Choice:
77
+ class Delta:
78
+ def __init__(self, content=None):
79
+ self.content = content
80
+ self.role = "assistant" if content is None else None
81
+
82
+ def __init__(self, content=None, include_usage=False):
83
+ self.delta = self.Delta(content)
84
+ self.finish_reason = None if content else "stop"
85
+ self.index = 0
86
+ self.usage = (
87
+ {"prompt_tokens": 10, "completion_tokens": 5, "total_tokens": 15}
88
+ if include_usage
89
+ else None
90
+ )
91
+
92
+ def __init__(self, content=None, include_usage=False):
93
+ self.choices = [self.Choice(content, include_usage)]
94
+ self.id = "dummy-chunk-id"
95
+ self.created = 1234567890
96
+ self.model = "dummy-model"
97
+ self.usage = self.choices[0].usage
98
+
99
+ def to_dict(self) -> Dict[str, Any]:
100
+ """Convert the chunk to a dictionary."""
101
+ result = {
102
+ "id": self.id,
103
+ "created": self.created,
104
+ "model": self.model,
105
+ "choices": [
106
+ {
107
+ "delta": {"role": choice.delta.role, "content": choice.delta.content}
108
+ if choice.delta.content is not None
109
+ else {"role": choice.delta.role},
110
+ "finish_reason": choice.finish_reason,
111
+ "index": choice.index,
112
+ }
113
+ for choice in self.choices
114
+ ],
115
+ }
116
+ if self.usage:
117
+ result["usage"] = self.usage
118
+ return result
119
+
120
+ def __init__(self, messages):
121
+ # Generate a simple response based on the last message
122
+ last_message = messages[-1] if messages else {"content": ""}
123
+ self.response_text = f"Echo: {last_message.get('content', '')}"
124
+ # Create chunks that ensure the full text is included in the first chunk
125
+ self.chunks = [
126
+ self.response_text, # First chunk contains the full text
127
+ "", # Final chunk is empty to indicate completion
128
+ ]
129
+ self.current_chunk = 0
130
+ self.include_usage = False
131
+
132
+ def __iter__(self):
133
+ return self
134
+
135
+ def __next__(self):
136
+ if self.current_chunk < len(self.chunks):
137
+ chunk = self.Chunk(self.chunks[self.current_chunk], self.include_usage)
138
+ self.current_chunk += 1
139
+ return chunk
140
+ else:
141
+ raise StopIteration
142
+
143
+
144
+ class DummyOpenAIModel(OpenAIModelClass):
145
+ """Dummy OpenAI model implementation for testing."""
146
+
147
+ openai_client = MockOpenAIClient()
148
+ model_name = "dummy-model"
149
+
150
+ def _process_request(self, **kwargs) -> Dict[str, Any]:
151
+ """Process a request for non-streaming responses."""
152
+ completion_args = self._create_completion_args(kwargs)
153
+ return self.client.chat.completions.create(**completion_args).to_dict()
154
+
155
+ def _process_streaming_request(self, **kwargs) -> Iterator[Dict[str, Any]]:
156
+ """Process a request for streaming responses."""
157
+ completion_args = self._create_completion_args(kwargs, stream=True)
158
+ completion_stream = self.client.chat.completions.create(**completion_args)
159
+ completion_stream.include_usage = kwargs.get('stream_options', {}).get(
160
+ 'include_usage', False
161
+ )
162
+
163
+ for chunk in completion_stream:
164
+ yield chunk.to_dict()
165
+
166
+ # Override the method directly for testing
167
+ @OpenAIModelClass.method
168
+ def openai_stream_transport(self, req: str) -> Iterator[str]:
169
+ """Direct implementation for testing purposes."""
170
+ try:
171
+ request_data = json.loads(req)
172
+ params = self._extract_request_params(request_data)
173
+
174
+ # Validate messages
175
+ if not params.get("messages"):
176
+ yield "Error: No messages provided"
177
+ return
178
+
179
+ for message in params["messages"]:
180
+ if (
181
+ not isinstance(message, dict)
182
+ or "role" not in message
183
+ or "content" not in message
184
+ ):
185
+ yield "Error: Invalid message format"
186
+ return
187
+
188
+ for chunk in self._process_streaming_request(**params):
189
+ yield json.dumps(chunk)
190
+ except Exception as e:
191
+ yield f"Error: {str(e)}"
192
+
193
+ # Additional example method that could be added for specific model implementations
194
+ @OpenAIModelClass.method
195
+ def test_method(self, prompt: str) -> str:
196
+ """Test method that simply echoes the input."""
197
+ return f"Test: {prompt}"
@@ -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,27 @@ 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
+ # Note(zeiler): this response is the "result" field of the JSONRPCResponse.
106
+ # the API will fill in the "id" and "jsonrpc" fields.
107
+ response = asyncio.run(send_request(client_message, id=id))
108
+ if response is None:
109
+ response = types.JSONRPCError(
110
+ jsonrpc="2.0",
111
+ id=id,
112
+ error=types.ErrorData(
113
+ code=types.INTERNAL_ERROR, message="Got empty response from MCP server."
114
+ ),
115
+ )
116
+ # return as a serialized json string
117
+ res = response.model_dump_json(by_alias=True, exclude_none=True)
118
+ return res
137
119
  else: # JSONRPCRequest
138
120
  client_message = types.ClientNotification.model_validate(d)
139
- response = asyncio.run(send_notification(client_message))
140
- if response is None:
141
- return ""
142
- # return as a serialized json string
143
- return response.model_dump_json(by_alias=True, exclude_none=True)
121
+ # send_notification returns None always so nothing to return.
122
+ asyncio.run(send_notification(client_message))
123
+ return "{}"