clarifai 11.6.4rc2__py3-none-any.whl → 11.6.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.
- clarifai/__init__.py +1 -1
- clarifai/cli/README.md +39 -0
- clarifai/cli/base.py +107 -118
- clarifai/cli/model.py +62 -79
- clarifai/client/app.py +1 -1
- clarifai/client/auth/helper.py +7 -2
- clarifai/client/base.py +35 -8
- clarifai/client/compute_cluster.py +1 -1
- clarifai/client/model.py +3 -1
- clarifai/client/nodepool.py +4 -2
- clarifai/client/user.py +4 -2
- clarifai/runners/models/model_runner.py +55 -0
- clarifai/runners/server.py +1 -1
- clarifai/runners/utils/url_fetcher.py +51 -12
- clarifai/utils/cli.py +127 -0
- clarifai/utils/constants.py +5 -0
- clarifai/utils/misc.py +47 -0
- {clarifai-11.6.4rc2.dist-info → clarifai-11.6.5.dist-info}/METADATA +2 -2
- clarifai-11.6.5.dist-info/RECORD +127 -0
- {clarifai-11.6.4rc2.dist-info → clarifai-11.6.5.dist-info}/WHEEL +1 -1
- clarifai/__pycache__/__init__.cpython-311.pyc +0 -0
- clarifai/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/__pycache__/errors.cpython-311.pyc +0 -0
- clarifai/__pycache__/errors.cpython-39.pyc +0 -0
- clarifai/__pycache__/versions.cpython-311.pyc +0 -0
- clarifai/__pycache__/versions.cpython-39.pyc +0 -0
- clarifai/cli/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/cli/__pycache__/base.cpython-39.pyc +0 -0
- clarifai/cli/__pycache__/compute_cluster.cpython-39.pyc +0 -0
- clarifai/cli/__pycache__/deployment.cpython-39.pyc +0 -0
- clarifai/cli/__pycache__/model.cpython-39.pyc +0 -0
- clarifai/cli/__pycache__/nodepool.cpython-39.pyc +0 -0
- clarifai/cli/model_templates.py +0 -243
- clarifai/cli/pipeline_step_templates.py +0 -64
- clarifai/client/__pycache__/__init__.cpython-311.pyc +0 -0
- clarifai/client/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/client/__pycache__/app.cpython-311.pyc +0 -0
- clarifai/client/__pycache__/app.cpython-39.pyc +0 -0
- clarifai/client/__pycache__/base.cpython-311.pyc +0 -0
- clarifai/client/__pycache__/base.cpython-39.pyc +0 -0
- clarifai/client/__pycache__/compute_cluster.cpython-311.pyc +0 -0
- clarifai/client/__pycache__/dataset.cpython-311.pyc +0 -0
- clarifai/client/__pycache__/dataset.cpython-39.pyc +0 -0
- clarifai/client/__pycache__/deployment.cpython-311.pyc +0 -0
- clarifai/client/__pycache__/deployment.cpython-39.pyc +0 -0
- clarifai/client/__pycache__/input.cpython-311.pyc +0 -0
- clarifai/client/__pycache__/input.cpython-39.pyc +0 -0
- clarifai/client/__pycache__/lister.cpython-311.pyc +0 -0
- clarifai/client/__pycache__/lister.cpython-39.pyc +0 -0
- clarifai/client/__pycache__/model.cpython-311.pyc +0 -0
- clarifai/client/__pycache__/model.cpython-39.pyc +0 -0
- clarifai/client/__pycache__/model_client.cpython-311.pyc +0 -0
- clarifai/client/__pycache__/model_client.cpython-39.pyc +0 -0
- clarifai/client/__pycache__/module.cpython-311.pyc +0 -0
- clarifai/client/__pycache__/nodepool.cpython-311.pyc +0 -0
- clarifai/client/__pycache__/runner.cpython-311.pyc +0 -0
- clarifai/client/__pycache__/search.cpython-311.pyc +0 -0
- clarifai/client/__pycache__/user.cpython-311.pyc +0 -0
- clarifai/client/__pycache__/workflow.cpython-311.pyc +0 -0
- clarifai/client/auth/__pycache__/__init__.cpython-311.pyc +0 -0
- clarifai/client/auth/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/client/auth/__pycache__/helper.cpython-311.pyc +0 -0
- clarifai/client/auth/__pycache__/helper.cpython-39.pyc +0 -0
- clarifai/client/auth/__pycache__/register.cpython-311.pyc +0 -0
- clarifai/client/auth/__pycache__/register.cpython-39.pyc +0 -0
- clarifai/client/auth/__pycache__/stub.cpython-311.pyc +0 -0
- clarifai/client/auth/__pycache__/stub.cpython-39.pyc +0 -0
- clarifai/constants/__pycache__/base.cpython-311.pyc +0 -0
- clarifai/constants/__pycache__/base.cpython-39.pyc +0 -0
- clarifai/constants/__pycache__/dataset.cpython-311.pyc +0 -0
- clarifai/constants/__pycache__/dataset.cpython-39.pyc +0 -0
- clarifai/constants/__pycache__/input.cpython-311.pyc +0 -0
- clarifai/constants/__pycache__/input.cpython-39.pyc +0 -0
- clarifai/constants/__pycache__/model.cpython-311.pyc +0 -0
- clarifai/constants/__pycache__/model.cpython-39.pyc +0 -0
- clarifai/constants/__pycache__/search.cpython-311.pyc +0 -0
- clarifai/constants/__pycache__/workflow.cpython-311.pyc +0 -0
- clarifai/datasets/__pycache__/__init__.cpython-311.pyc +0 -0
- clarifai/datasets/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/datasets/export/__pycache__/__init__.cpython-311.pyc +0 -0
- clarifai/datasets/export/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/datasets/export/__pycache__/inputs_annotations.cpython-311.pyc +0 -0
- clarifai/datasets/export/__pycache__/inputs_annotations.cpython-39.pyc +0 -0
- clarifai/datasets/upload/__pycache__/__init__.cpython-311.pyc +0 -0
- clarifai/datasets/upload/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/datasets/upload/__pycache__/base.cpython-311.pyc +0 -0
- clarifai/datasets/upload/__pycache__/base.cpython-39.pyc +0 -0
- clarifai/datasets/upload/__pycache__/features.cpython-311.pyc +0 -0
- clarifai/datasets/upload/__pycache__/features.cpython-39.pyc +0 -0
- clarifai/datasets/upload/__pycache__/image.cpython-311.pyc +0 -0
- clarifai/datasets/upload/__pycache__/image.cpython-39.pyc +0 -0
- clarifai/datasets/upload/__pycache__/multimodal.cpython-311.pyc +0 -0
- clarifai/datasets/upload/__pycache__/multimodal.cpython-39.pyc +0 -0
- clarifai/datasets/upload/__pycache__/text.cpython-311.pyc +0 -0
- clarifai/datasets/upload/__pycache__/text.cpython-39.pyc +0 -0
- clarifai/datasets/upload/__pycache__/utils.cpython-311.pyc +0 -0
- clarifai/datasets/upload/__pycache__/utils.cpython-39.pyc +0 -0
- clarifai/models/model_serving/README.md +0 -158
- clarifai/models/model_serving/__init__.py +0 -14
- clarifai/models/model_serving/cli/__init__.py +0 -12
- clarifai/models/model_serving/cli/_utils.py +0 -53
- clarifai/models/model_serving/cli/base.py +0 -14
- clarifai/models/model_serving/cli/build.py +0 -79
- clarifai/models/model_serving/cli/clarifai_clis.py +0 -33
- clarifai/models/model_serving/cli/create.py +0 -171
- clarifai/models/model_serving/cli/example_cli.py +0 -34
- clarifai/models/model_serving/cli/login.py +0 -26
- clarifai/models/model_serving/cli/upload.py +0 -179
- clarifai/models/model_serving/constants.py +0 -21
- clarifai/models/model_serving/docs/cli.md +0 -161
- clarifai/models/model_serving/docs/concepts.md +0 -229
- clarifai/models/model_serving/docs/dependencies.md +0 -11
- clarifai/models/model_serving/docs/inference_parameters.md +0 -139
- clarifai/models/model_serving/docs/model_types.md +0 -19
- clarifai/models/model_serving/model_config/__init__.py +0 -16
- clarifai/models/model_serving/model_config/base.py +0 -369
- clarifai/models/model_serving/model_config/config.py +0 -312
- clarifai/models/model_serving/model_config/inference_parameter.py +0 -129
- clarifai/models/model_serving/model_config/model_types_config/multimodal-embedder.yaml +0 -25
- clarifai/models/model_serving/model_config/model_types_config/text-classifier.yaml +0 -19
- clarifai/models/model_serving/model_config/model_types_config/text-embedder.yaml +0 -20
- clarifai/models/model_serving/model_config/model_types_config/text-to-image.yaml +0 -19
- clarifai/models/model_serving/model_config/model_types_config/text-to-text.yaml +0 -19
- clarifai/models/model_serving/model_config/model_types_config/visual-classifier.yaml +0 -22
- clarifai/models/model_serving/model_config/model_types_config/visual-detector.yaml +0 -32
- clarifai/models/model_serving/model_config/model_types_config/visual-embedder.yaml +0 -19
- clarifai/models/model_serving/model_config/model_types_config/visual-segmenter.yaml +0 -19
- clarifai/models/model_serving/model_config/output.py +0 -133
- clarifai/models/model_serving/model_config/triton/__init__.py +0 -14
- clarifai/models/model_serving/model_config/triton/serializer.py +0 -136
- clarifai/models/model_serving/model_config/triton/triton_config.py +0 -182
- clarifai/models/model_serving/model_config/triton/wrappers.py +0 -281
- clarifai/models/model_serving/repo_build/__init__.py +0 -14
- clarifai/models/model_serving/repo_build/build.py +0 -198
- clarifai/models/model_serving/repo_build/static_files/_requirements.txt +0 -2
- clarifai/models/model_serving/repo_build/static_files/base_test.py +0 -169
- clarifai/models/model_serving/repo_build/static_files/inference.py +0 -26
- clarifai/models/model_serving/repo_build/static_files/sample_clarifai_config.yaml +0 -25
- clarifai/models/model_serving/repo_build/static_files/test.py +0 -40
- clarifai/models/model_serving/repo_build/static_files/triton/model.py +0 -75
- clarifai/models/model_serving/utils.py +0 -23
- clarifai/runners/__pycache__/__init__.cpython-311.pyc +0 -0
- clarifai/runners/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/runners/models/__pycache__/__init__.cpython-311.pyc +0 -0
- clarifai/runners/models/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/runners/models/__pycache__/mcp_class.cpython-311.pyc +0 -0
- clarifai/runners/models/__pycache__/model_builder.cpython-311.pyc +0 -0
- clarifai/runners/models/__pycache__/model_builder.cpython-39.pyc +0 -0
- clarifai/runners/models/__pycache__/model_class.cpython-311.pyc +0 -0
- clarifai/runners/models/__pycache__/model_runner.cpython-311.pyc +0 -0
- clarifai/runners/models/__pycache__/openai_class.cpython-311.pyc +0 -0
- clarifai/runners/models/base_typed_model.py +0 -238
- clarifai/runners/models/model_upload.py +0 -607
- clarifai/runners/utils/__pycache__/__init__.cpython-311.pyc +0 -0
- clarifai/runners/utils/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/runners/utils/__pycache__/code_script.cpython-311.pyc +0 -0
- clarifai/runners/utils/__pycache__/code_script.cpython-39.pyc +0 -0
- clarifai/runners/utils/__pycache__/const.cpython-311.pyc +0 -0
- clarifai/runners/utils/__pycache__/data_utils.cpython-311.pyc +0 -0
- clarifai/runners/utils/__pycache__/data_utils.cpython-39.pyc +0 -0
- clarifai/runners/utils/__pycache__/loader.cpython-311.pyc +0 -0
- clarifai/runners/utils/__pycache__/method_signatures.cpython-311.pyc +0 -0
- clarifai/runners/utils/__pycache__/model_utils.cpython-311.pyc +0 -0
- clarifai/runners/utils/__pycache__/openai_convertor.cpython-311.pyc +0 -0
- clarifai/runners/utils/__pycache__/serializers.cpython-311.pyc +0 -0
- clarifai/runners/utils/__pycache__/url_fetcher.cpython-311.pyc +0 -0
- clarifai/runners/utils/data_handler.py +0 -231
- clarifai/runners/utils/data_types/__pycache__/__init__.cpython-311.pyc +0 -0
- clarifai/runners/utils/data_types/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/runners/utils/data_types/__pycache__/data_types.cpython-311.pyc +0 -0
- clarifai/runners/utils/data_types/__pycache__/data_types.cpython-39.pyc +0 -0
- clarifai/runners/utils/data_types.py +0 -471
- clarifai/runners/utils/temp.py +0 -59
- clarifai/schema/__pycache__/search.cpython-311.pyc +0 -0
- clarifai/urls/__pycache__/helper.cpython-311.pyc +0 -0
- clarifai/urls/__pycache__/helper.cpython-39.pyc +0 -0
- clarifai/utils/__pycache__/__init__.cpython-311.pyc +0 -0
- clarifai/utils/__pycache__/__init__.cpython-39.pyc +0 -0
- clarifai/utils/__pycache__/cli.cpython-39.pyc +0 -0
- clarifai/utils/__pycache__/config.cpython-311.pyc +0 -0
- clarifai/utils/__pycache__/config.cpython-39.pyc +0 -0
- clarifai/utils/__pycache__/constants.cpython-311.pyc +0 -0
- clarifai/utils/__pycache__/constants.cpython-39.pyc +0 -0
- clarifai/utils/__pycache__/logging.cpython-311.pyc +0 -0
- clarifai/utils/__pycache__/logging.cpython-39.pyc +0 -0
- clarifai/utils/__pycache__/misc.cpython-311.pyc +0 -0
- clarifai/utils/__pycache__/misc.cpython-39.pyc +0 -0
- clarifai/utils/__pycache__/model_train.cpython-311.pyc +0 -0
- clarifai/utils/__pycache__/protobuf.cpython-311.pyc +0 -0
- clarifai/utils/__pycache__/protobuf.cpython-39.pyc +0 -0
- clarifai/workflows/__pycache__/__init__.cpython-311.pyc +0 -0
- clarifai/workflows/__pycache__/export.cpython-311.pyc +0 -0
- clarifai/workflows/__pycache__/utils.cpython-311.pyc +0 -0
- clarifai/workflows/__pycache__/validate.cpython-311.pyc +0 -0
- clarifai-11.6.4rc2.dist-info/RECORD +0 -301
- {clarifai-11.6.4rc2.dist-info → clarifai-11.6.5.dist-info}/entry_points.txt +0 -0
- {clarifai-11.6.4rc2.dist-info → clarifai-11.6.5.dist-info}/licenses/LICENSE +0 -0
- {clarifai-11.6.4rc2.dist-info → clarifai-11.6.5.dist-info}/top_level.txt +0 -0
clarifai/__init__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = "11.6.
|
1
|
+
__version__ = "11.6.5"
|
clarifai/cli/README.md
CHANGED
@@ -8,6 +8,45 @@ Clarifai offers a user-friendly interface for deploying your local model into pr
|
|
8
8
|
* Easy implementation and testing in Python
|
9
9
|
* No need for MLops expertise.
|
10
10
|
|
11
|
+
## Context Management
|
12
|
+
|
13
|
+
Manage CLI contexts for authentication and environment configuration:
|
14
|
+
### List all contexts
|
15
|
+
```bash
|
16
|
+
clarifai config get-contexts
|
17
|
+
```
|
18
|
+
|
19
|
+
### Switch context
|
20
|
+
```bash
|
21
|
+
clarifai config use-context production
|
22
|
+
```
|
23
|
+
### Show current context
|
24
|
+
```bash
|
25
|
+
clarifai config current-context
|
26
|
+
```
|
27
|
+
|
28
|
+
### Create new context
|
29
|
+
```bash
|
30
|
+
clarifai config create-context staging --user-id myuser --pat 678***
|
31
|
+
```
|
32
|
+
### View entire configuration
|
33
|
+
```bash
|
34
|
+
clarifai config view
|
35
|
+
```
|
36
|
+
### Delete a context
|
37
|
+
```bash
|
38
|
+
clarifai config delete-context old-context
|
39
|
+
```
|
40
|
+
### Edit configuration file
|
41
|
+
```bash
|
42
|
+
clarifai config edit
|
43
|
+
```
|
44
|
+
|
45
|
+
### Print environment variables for the active context
|
46
|
+
```bash
|
47
|
+
clarifai context env
|
48
|
+
```
|
49
|
+
|
11
50
|
## Compute Orchestration
|
12
51
|
|
13
52
|
Quick example for deploying a `visual-classifier` model
|
clarifai/cli/base.py
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
import json
|
2
2
|
import os
|
3
|
-
import shutil
|
4
3
|
import sys
|
5
4
|
|
6
5
|
import click
|
@@ -13,7 +12,6 @@ from clarifai.utils.constants import DEFAULT_BASE, DEFAULT_CONFIG, DEFAULT_UI
|
|
13
12
|
from clarifai.utils.logging import logger
|
14
13
|
|
15
14
|
|
16
|
-
# @click.group(cls=CustomMultiGroup)
|
17
15
|
@click.group(cls=AliasedGroup)
|
18
16
|
@click.version_option(version=__version__)
|
19
17
|
@click.option('--config', default=DEFAULT_CONFIG)
|
@@ -54,42 +52,71 @@ def shell_completion(shell):
|
|
54
52
|
os.system(f"_CLARIFAI_COMPLETE={shell}_source clarifai")
|
55
53
|
|
56
54
|
|
57
|
-
@cli.group(
|
58
|
-
['cfg'],
|
59
|
-
cls=AliasedGroup,
|
60
|
-
context_settings={'max_content_width': shutil.get_terminal_size().columns - 10},
|
61
|
-
)
|
55
|
+
@cli.group(cls=AliasedGroup)
|
62
56
|
def config():
|
63
|
-
"""
|
57
|
+
"""
|
58
|
+
Manage multiple configuration profiles (contexts).
|
59
|
+
|
60
|
+
Authentication Precedence:\n
|
61
|
+
1. Environment variables (e.g., `CLARIFAI_PAT`) are used first if set.
|
62
|
+
2. The settings from the active context are used if no environment variables are provided.\n
|
63
|
+
"""
|
64
64
|
|
65
65
|
|
66
|
-
@
|
66
|
+
@cli.command()
|
67
|
+
@click.argument('api_url', default=DEFAULT_BASE)
|
68
|
+
@click.option('--user_id', required=False, help='User ID')
|
67
69
|
@click.pass_context
|
68
|
-
def
|
69
|
-
"""
|
70
|
-
|
70
|
+
def login(ctx, api_url, user_id):
|
71
|
+
"""Login command to set PAT and other configurations."""
|
72
|
+
from clarifai.utils.cli import validate_context_auth
|
71
73
|
|
74
|
+
name = input('context name (default: "default"): ')
|
75
|
+
user_id = user_id if user_id is not None else input('user id: ')
|
76
|
+
pat = input_or_default(
|
77
|
+
'personal access token value (default: "ENVVAR" to get out of env var rather than config): ',
|
78
|
+
'ENVVAR',
|
79
|
+
)
|
72
80
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
81
|
+
# Validate the Context Credentials
|
82
|
+
validate_context_auth(pat, user_id, api_url)
|
83
|
+
|
84
|
+
context = Context(
|
85
|
+
name,
|
86
|
+
CLARIFAI_API_BASE=api_url,
|
87
|
+
CLARIFAI_USER_ID=user_id,
|
88
|
+
CLARIFAI_PAT=pat,
|
89
|
+
)
|
90
|
+
|
91
|
+
if context.name == '':
|
92
|
+
context.name = 'default'
|
93
|
+
|
94
|
+
ctx.obj.contexts[context.name] = context
|
95
|
+
ctx.obj.current_context = context.name
|
96
|
+
|
97
|
+
ctx.obj.to_yaml()
|
98
|
+
logger.info(
|
99
|
+
f"Login successful and Configuration saved successfully for context '{context.name}'"
|
100
|
+
)
|
101
|
+
|
102
|
+
|
103
|
+
def pat_display(pat):
|
104
|
+
return pat[:5] + "****"
|
105
|
+
|
106
|
+
|
107
|
+
def input_or_default(prompt, default):
|
108
|
+
value = input(prompt)
|
109
|
+
return value if value else default
|
84
110
|
|
85
111
|
|
86
|
-
|
112
|
+
# Context management commands under config group
|
113
|
+
@config.command(aliases=['get-contexts', 'list-contexts'])
|
87
114
|
@click.option(
|
88
115
|
'-o', '--output-format', default='wide', type=click.Choice(['wide', 'name', 'json', 'yaml'])
|
89
116
|
)
|
90
117
|
@click.pass_context
|
91
118
|
def get_contexts(ctx, output_format):
|
92
|
-
"""
|
119
|
+
"""List all available contexts."""
|
93
120
|
if output_format == 'wide':
|
94
121
|
columns = {
|
95
122
|
'': lambda c: '*' if c.name == ctx.obj.current_context else '',
|
@@ -106,7 +133,6 @@ def get_contexts(ctx, output_format):
|
|
106
133
|
additional_columns.add(key)
|
107
134
|
for key in sorted(additional_columns):
|
108
135
|
columns[key] = lambda c, k=key: getattr(c, k) if hasattr(c, k) else ""
|
109
|
-
|
110
136
|
formatter = TableFormatter(
|
111
137
|
custom_columns=columns,
|
112
138
|
)
|
@@ -123,101 +149,45 @@ def get_contexts(ctx, output_format):
|
|
123
149
|
print(yaml.safe_dump(dicts))
|
124
150
|
|
125
151
|
|
126
|
-
@config.command(['use'])
|
127
|
-
@click.argument('
|
152
|
+
@config.command(aliases=['use-context'])
|
153
|
+
@click.argument('name', type=str)
|
128
154
|
@click.pass_context
|
129
|
-
def use_context(ctx,
|
130
|
-
"""Set the current context"""
|
131
|
-
if
|
155
|
+
def use_context(ctx, name):
|
156
|
+
"""Set the current context."""
|
157
|
+
if name not in ctx.obj.contexts:
|
132
158
|
raise click.UsageError('Context not found')
|
133
|
-
ctx.obj.current_context =
|
159
|
+
ctx.obj.current_context = name
|
134
160
|
ctx.obj.to_yaml()
|
135
|
-
print(f'Set {
|
136
|
-
|
137
|
-
|
138
|
-
@config.command(['cat'])
|
139
|
-
@click.option('-o', '--output-format', default='yaml', type=click.Choice(['yaml', 'json']))
|
140
|
-
@click.pass_obj
|
141
|
-
def dump(ctx_obj, output_format):
|
142
|
-
"""Dump the configuration to stdout"""
|
143
|
-
if output_format == 'yaml':
|
144
|
-
yaml.safe_dump(ctx_obj.to_dict(), sys.stdout)
|
145
|
-
else:
|
146
|
-
json.dump(ctx_obj.to_dict(), sys.stdout, indent=2)
|
147
|
-
|
148
|
-
|
149
|
-
@config.command(['cat'])
|
150
|
-
@click.pass_obj
|
151
|
-
def env(ctx_obj):
|
152
|
-
"""Print env vars. Use: eval "$(clarifai config env)" """
|
153
|
-
ctx_obj.current.print_env_vars()
|
161
|
+
print(f'Set {name} as the current context')
|
154
162
|
|
155
163
|
|
156
|
-
@
|
157
|
-
@click.
|
158
|
-
@click.option('--user_id', required=False, help='User ID')
|
164
|
+
@config.command(aliases=['current-context'])
|
165
|
+
@click.option('-o', '--output-format', default='name', type=click.Choice(['name', 'json', 'yaml']))
|
159
166
|
@click.pass_context
|
160
|
-
def
|
161
|
-
"""
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
'ENVVAR',
|
169
|
-
)
|
170
|
-
|
171
|
-
# Validate the Context Credentials
|
172
|
-
validate_context_auth(pat, user_id, api_url)
|
173
|
-
|
174
|
-
context = Context(
|
175
|
-
name,
|
176
|
-
CLARIFAI_API_BASE=api_url,
|
177
|
-
CLARIFAI_USER_ID=user_id,
|
178
|
-
CLARIFAI_PAT=pat,
|
179
|
-
)
|
180
|
-
|
181
|
-
if context.name == '':
|
182
|
-
context.name = 'default'
|
183
|
-
|
184
|
-
ctx.obj.contexts[context.name] = context
|
185
|
-
ctx.obj.current_context = context.name
|
186
|
-
|
187
|
-
ctx.obj.to_yaml()
|
188
|
-
logger.info(
|
189
|
-
f"Login successful and Configuration saved successfully for context '{context.name}'"
|
190
|
-
)
|
191
|
-
|
192
|
-
|
193
|
-
@cli.group(cls=AliasedGroup)
|
194
|
-
def context():
|
195
|
-
"""Manage contexts"""
|
196
|
-
|
197
|
-
|
198
|
-
def pat_display(pat):
|
199
|
-
return pat[:5] + "****"
|
200
|
-
|
201
|
-
|
202
|
-
def input_or_default(prompt, default):
|
203
|
-
value = input(prompt)
|
204
|
-
return value if value else default
|
167
|
+
def current_context(ctx, output_format):
|
168
|
+
"""Show the current context's details."""
|
169
|
+
if output_format == 'name':
|
170
|
+
print(ctx.obj.current_context)
|
171
|
+
elif output_format == 'json':
|
172
|
+
print(json.dumps(ctx.obj.contexts[ctx.obj.current_context].to_serializable_dict()))
|
173
|
+
else:
|
174
|
+
print(yaml.safe_dump(ctx.obj.contexts[ctx.obj.current_context].to_serializable_dict()))
|
205
175
|
|
206
176
|
|
207
|
-
@
|
177
|
+
@config.command(aliases=['create-context', 'set-context'])
|
208
178
|
@click.argument('name')
|
209
179
|
@click.option('--user-id', required=False, help='User ID')
|
210
180
|
@click.option('--base-url', required=False, help='Base URL')
|
211
181
|
@click.option('--pat', required=False, help='Personal access token')
|
212
182
|
@click.pass_context
|
213
|
-
def
|
183
|
+
def create_context(
|
214
184
|
ctx,
|
215
185
|
name,
|
216
186
|
user_id=None,
|
217
187
|
base_url=None,
|
218
188
|
pat=None,
|
219
189
|
):
|
220
|
-
"""Create a new context"""
|
190
|
+
"""Create a new context."""
|
221
191
|
from clarifai.utils.cli import validate_context_auth
|
222
192
|
|
223
193
|
if name in ctx.obj.contexts:
|
@@ -234,22 +204,28 @@ def create(
|
|
234
204
|
'personal access token value (default: "ENVVAR" to get our of env var rather than config): ',
|
235
205
|
'ENVVAR',
|
236
206
|
)
|
237
|
-
|
238
|
-
# Validate the Context Credentials
|
239
207
|
validate_context_auth(pat, user_id, base_url)
|
240
|
-
|
241
208
|
context = Context(name, CLARIFAI_USER_ID=user_id, CLARIFAI_API_BASE=base_url, CLARIFAI_PAT=pat)
|
242
209
|
ctx.obj.contexts[context.name] = context
|
243
210
|
ctx.obj.to_yaml()
|
244
211
|
logger.info(f"Context '{name}' created successfully")
|
245
212
|
|
246
213
|
|
247
|
-
|
248
|
-
@
|
214
|
+
@config.command(aliases=['e'])
|
215
|
+
@click.pass_context
|
216
|
+
def edit(
|
217
|
+
ctx,
|
218
|
+
):
|
219
|
+
"""Open the configuration file for editing."""
|
220
|
+
# For now, just open the config file (not per-context)
|
221
|
+
os.system(f'{os.environ.get("EDITOR", "vi")} {ctx.obj.filename}')
|
222
|
+
|
223
|
+
|
224
|
+
@config.command(aliases=['delete-context'])
|
249
225
|
@click.argument('name')
|
250
226
|
@click.pass_context
|
251
|
-
def
|
252
|
-
"""Delete a context"""
|
227
|
+
def delete_context(ctx, name):
|
228
|
+
"""Delete a context."""
|
253
229
|
if name not in ctx.obj.contexts:
|
254
230
|
print(f'{name} is not a valid context')
|
255
231
|
sys.exit(1)
|
@@ -258,16 +234,29 @@ def delete(ctx, name):
|
|
258
234
|
print(f'{name} deleted')
|
259
235
|
|
260
236
|
|
261
|
-
@
|
262
|
-
@click.argument('name', type=str)
|
237
|
+
@config.command(aliases=['get-env'])
|
263
238
|
@click.pass_context
|
264
|
-
def
|
265
|
-
"""
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
239
|
+
def env(ctx):
|
240
|
+
"""Print env vars for the active context."""
|
241
|
+
ctx.obj.current.print_env_vars()
|
242
|
+
|
243
|
+
|
244
|
+
@config.command(aliases=['show'])
|
245
|
+
@click.option('-o', '--output-format', default='yaml', type=click.Choice(['json', 'yaml']))
|
246
|
+
@click.pass_context
|
247
|
+
def view(ctx, output_format):
|
248
|
+
"""Display the current configuration."""
|
249
|
+
config_dict = {
|
250
|
+
'current-context': ctx.obj.current_context,
|
251
|
+
'contexts': {
|
252
|
+
name: context.to_serializable_dict() for name, context in ctx.obj.contexts.items()
|
253
|
+
},
|
254
|
+
}
|
255
|
+
|
256
|
+
if output_format == 'json':
|
257
|
+
print(json.dumps(config_dict, indent=2))
|
258
|
+
else:
|
259
|
+
print(yaml.safe_dump(config_dict, default_flow_style=False))
|
271
260
|
|
272
261
|
|
273
262
|
@cli.command()
|
clarifai/cli/model.py
CHANGED
@@ -5,7 +5,12 @@ import tempfile
|
|
5
5
|
import click
|
6
6
|
|
7
7
|
from clarifai.cli.base import cli, pat_display
|
8
|
-
from clarifai.utils.cli import
|
8
|
+
from clarifai.utils.cli import (
|
9
|
+
check_ollama_installed,
|
10
|
+
check_requirements_installed,
|
11
|
+
customize_ollama_model,
|
12
|
+
validate_context,
|
13
|
+
)
|
9
14
|
from clarifai.utils.constants import (
|
10
15
|
DEFAULT_LOCAL_RUNNER_APP_ID,
|
11
16
|
DEFAULT_LOCAL_RUNNER_COMPUTE_CLUSTER_CONFIG,
|
@@ -22,49 +27,6 @@ from clarifai.utils.logging import logger
|
|
22
27
|
from clarifai.utils.misc import GitHubDownloader, clone_github_repo, format_github_repo_url
|
23
28
|
|
24
29
|
|
25
|
-
def customize_ollama_model(model_path, model_name, port, context_length):
|
26
|
-
"""Customize the Ollama model name in the cloned template files.
|
27
|
-
Args:
|
28
|
-
model_path: Path to the cloned model directory
|
29
|
-
model_name: The model name to set (e.g., 'llama3.1', 'mistral')
|
30
|
-
|
31
|
-
"""
|
32
|
-
model_py_path = os.path.join(model_path, "1", "model.py")
|
33
|
-
|
34
|
-
if not os.path.exists(model_py_path):
|
35
|
-
logger.warning(f"Model file {model_py_path} not found, skipping model name customization")
|
36
|
-
return
|
37
|
-
|
38
|
-
try:
|
39
|
-
# Read the model.py file
|
40
|
-
with open(model_py_path, 'r') as file:
|
41
|
-
content = file.read()
|
42
|
-
if model_name:
|
43
|
-
# Replace the default model name in the load_model method
|
44
|
-
content = content.replace(
|
45
|
-
'self.model = os.environ.get("OLLAMA_MODEL_NAME", \'llama3.2\')',
|
46
|
-
f'self.model = os.environ.get("OLLAMA_MODEL_NAME", \'{model_name}\')',
|
47
|
-
)
|
48
|
-
|
49
|
-
if port:
|
50
|
-
# Replace the default port variable in the model.py file
|
51
|
-
content = content.replace("PORT = '23333'", f"PORT = '{port}'")
|
52
|
-
|
53
|
-
if context_length:
|
54
|
-
# Replace the default context length variable in the model.py file
|
55
|
-
content = content.replace(
|
56
|
-
"context_length = '8192'", f"context_length = '{context_length}'"
|
57
|
-
)
|
58
|
-
|
59
|
-
# Write the modified content back to model.py
|
60
|
-
with open(model_py_path, 'w') as file:
|
61
|
-
file.write(content)
|
62
|
-
|
63
|
-
except Exception as e:
|
64
|
-
logger.error(f"Failed to customize Ollama model name in {model_py_path}: {e}")
|
65
|
-
raise
|
66
|
-
|
67
|
-
|
68
30
|
@cli.group(
|
69
31
|
['model'], context_settings={'max_content_width': shutil.get_terminal_size().columns - 10}
|
70
32
|
)
|
@@ -125,11 +87,11 @@ def init(
|
|
125
87
|
):
|
126
88
|
"""Initialize a new model directory structure.
|
127
89
|
|
128
|
-
Creates the following structure in the specified directory
|
129
|
-
├── 1
|
130
|
-
│ └── model.py
|
131
|
-
├── requirements.txt
|
132
|
-
└── config.yaml
|
90
|
+
Creates the following structure in the specified directory:\n
|
91
|
+
├── 1/\n
|
92
|
+
│ └── model.py\n
|
93
|
+
├── requirements.txt\n
|
94
|
+
└── config.yaml\n
|
133
95
|
|
134
96
|
If --github-repo is provided, the entire repository contents will be copied to the target
|
135
97
|
directory instead of using default templates. The --github-pat option can be used for authentication
|
@@ -137,13 +99,6 @@ def init(
|
|
137
99
|
branch to clone from.
|
138
100
|
|
139
101
|
MODEL_PATH: Path where to create the model directory structure. If not specified, the current directory is used by default.
|
140
|
-
model_type_id: Type of model to initialize. Options are 'mcp' for MCPModelClass or 'openai' for OpenAIModelClass.
|
141
|
-
github_pat: GitHub Personal Access Token for cloning private repositories.
|
142
|
-
github_url: GitHub repository URL or "user/repo" format or the github folder URL to clone a model files from. If provided, the entire contents of repo/folder will be copied to the target directory instead of using default templates.
|
143
|
-
toolkit: Toolkit to use for model initialization. Currently supports 'ollama'.
|
144
|
-
model_name: Model name to configure when using --toolkit. For ollama toolkit, this sets the Ollama model to use (e.g., 'llama3.1', 'mistral', etc.).
|
145
|
-
port: Port to run the Ollama server on. Defaults to 23333.
|
146
|
-
context_length: Context length for the Ollama model. Defaults to 8192.
|
147
102
|
"""
|
148
103
|
# Resolve the absolute path
|
149
104
|
model_path = os.path.abspath(model_path)
|
@@ -171,6 +126,11 @@ def init(
|
|
171
126
|
|
172
127
|
# --toolkit option
|
173
128
|
if toolkit == 'ollama':
|
129
|
+
if not check_ollama_installed():
|
130
|
+
logger.error(
|
131
|
+
"Ollama is not installed. Please install it from `https://ollama.com/` to use the Ollama toolkit."
|
132
|
+
)
|
133
|
+
raise click.Abort()
|
174
134
|
github_url = DEFAULT_OLLAMA_MODEL_REPO
|
175
135
|
branch = DEFAULT_OLLAMA_MODEL_REPO_BRANCH
|
176
136
|
|
@@ -251,11 +211,12 @@ def init(
|
|
251
211
|
if (model_name or port or context_length) and (toolkit == 'ollama'):
|
252
212
|
customize_ollama_model(model_path, model_name, port, context_length)
|
253
213
|
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
214
|
+
if github_url:
|
215
|
+
logger.info("Model initialization complete with GitHub repository")
|
216
|
+
logger.info("Next steps:")
|
217
|
+
logger.info("1. Review the model configuration")
|
218
|
+
logger.info("2. Install any required dependencies manually")
|
219
|
+
logger.info("3. Test the model locally using 'clarifai model local-test'")
|
259
220
|
|
260
221
|
# Fall back to template-based initialization if no GitHub repo or if GitHub repo failed
|
261
222
|
if not github_url:
|
@@ -620,7 +581,7 @@ def local_runner(ctx, model_path, pool_size):
|
|
620
581
|
compute_cluster = user.compute_cluster(compute_cluster_id)
|
621
582
|
if compute_cluster.cluster_type != 'local-dev':
|
622
583
|
raise ValueError(
|
623
|
-
f"Compute cluster {user_id}/{compute_cluster_id} is not a
|
584
|
+
f"Compute cluster {user_id}/{compute_cluster_id} is not a compute cluster of type 'local-dev'. Please use a compute cluster of type 'local-dev'."
|
624
585
|
)
|
625
586
|
try:
|
626
587
|
compute_cluster_id = ctx.obj.current.compute_cluster_id
|
@@ -630,7 +591,7 @@ def local_runner(ctx, model_path, pool_size):
|
|
630
591
|
except ValueError:
|
631
592
|
raise
|
632
593
|
except Exception as e:
|
633
|
-
logger.
|
594
|
+
logger.warning(f"Failed to get compute cluster with ID '{compute_cluster_id}':\n{e}")
|
634
595
|
y = input(
|
635
596
|
f"Compute cluster not found. Do you want to create a new compute cluster {user_id}/{compute_cluster_id}? (y/n): "
|
636
597
|
)
|
@@ -659,7 +620,7 @@ def local_runner(ctx, model_path, pool_size):
|
|
659
620
|
ctx.obj.current.CLARIFAI_NODEPOOL_ID = nodepool.id
|
660
621
|
ctx.obj.to_yaml() # save to yaml file.
|
661
622
|
except Exception as e:
|
662
|
-
logger.
|
623
|
+
logger.warning(f"Failed to get nodepool with ID '{nodepool_id}':\n{e}")
|
663
624
|
y = input(
|
664
625
|
f"Nodepool not found. Do you want to create a new nodepool {user_id}/{compute_cluster_id}/{nodepool_id}? (y/n): "
|
665
626
|
)
|
@@ -687,7 +648,7 @@ def local_runner(ctx, model_path, pool_size):
|
|
687
648
|
ctx.obj.current.CLARIFAI_APP_ID = app.id
|
688
649
|
ctx.obj.to_yaml() # save to yaml file.
|
689
650
|
except Exception as e:
|
690
|
-
logger.
|
651
|
+
logger.warning(f"Failed to get app with ID '{app_id}':\n{e}")
|
691
652
|
y = input(f"App not found. Do you want to create a new app {user_id}/{app_id}? (y/n): ")
|
692
653
|
if y.lower() != 'y':
|
693
654
|
raise click.Abort()
|
@@ -710,7 +671,7 @@ def local_runner(ctx, model_path, pool_size):
|
|
710
671
|
ctx.obj.current.CLARIFAI_MODEL_ID = model.id
|
711
672
|
ctx.obj.to_yaml() # save to yaml file.
|
712
673
|
except Exception as e:
|
713
|
-
logger.
|
674
|
+
logger.warning(f"Failed to get model with ID '{model_id}':\n{e}")
|
714
675
|
y = input(
|
715
676
|
f"Model not found. Do you want to create a new model {user_id}/{app_id}/models/{model_id}? (y/n): "
|
716
677
|
)
|
@@ -730,9 +691,8 @@ def local_runner(ctx, model_path, pool_size):
|
|
730
691
|
# mentions it's a local runner.
|
731
692
|
model_versions = [v for v in model.list_versions()]
|
732
693
|
if len(model_versions) == 0:
|
733
|
-
logger.
|
694
|
+
logger.warning("No model versions found. Creating a new version for local runner.")
|
734
695
|
version = model.create_version(pretrained_model_config={"local_dev": True}).model_version
|
735
|
-
logger.info(f"Created model version {version.id}")
|
736
696
|
else:
|
737
697
|
version = model_versions[0].model_version
|
738
698
|
|
@@ -759,12 +719,16 @@ def local_runner(ctx, model_path, pool_size):
|
|
759
719
|
# ensure the deployment is using the latest version.
|
760
720
|
if runner.worker.model.model_version.id != version.id:
|
761
721
|
nodepool.delete_runners([runner_id])
|
762
|
-
|
722
|
+
logger.warning("Deleted runner that was for an old model version ID.")
|
723
|
+
raise AttributeError(
|
724
|
+
"Runner deleted because it was associated with an outdated model version."
|
725
|
+
)
|
763
726
|
except Exception as e:
|
764
|
-
|
727
|
+
logger.warning(f"Failed to get runner with ID '{runner_id}':\n{e}")
|
728
|
+
raise AttributeError("Runner not found in nodepool.")
|
765
729
|
except AttributeError:
|
766
730
|
logger.info(
|
767
|
-
f"
|
731
|
+
f"Creating the local runner tying this '{user_id}/{app_id}/models/{model.id}' model (version: {version.id}) to the '{user_id}/{compute_cluster_id}/{nodepool_id}' nodepool."
|
768
732
|
)
|
769
733
|
runner = nodepool.create_runner(
|
770
734
|
runner_config={
|
@@ -792,14 +756,17 @@ def local_runner(ctx, model_path, pool_size):
|
|
792
756
|
# ensure the deployment is using the latest version.
|
793
757
|
if deployment.worker.model.model_version.id != version.id:
|
794
758
|
nodepool.delete_deployments([deployment_id])
|
795
|
-
|
759
|
+
logger.warning("Deleted deployment that was for an old model version ID.")
|
760
|
+
raise Exception(
|
761
|
+
"Deployment deleted because it was associated with an outdated model version."
|
762
|
+
)
|
796
763
|
try:
|
797
764
|
deployment_id = ctx.obj.current.deployment_id
|
798
765
|
except AttributeError: # doesn't exist in context but does in API then update the context.
|
799
766
|
ctx.obj.current.CLARIFAI_DEPLOYMENT_ID = deployment.id
|
800
767
|
ctx.obj.to_yaml() # save to yaml file.
|
801
768
|
except Exception as e:
|
802
|
-
logger.
|
769
|
+
logger.warning(f"Failed to get deployment with ID {deployment_id}:\n{e}")
|
803
770
|
y = input(
|
804
771
|
f"Deployment not found. Do you want to create a new deployment {user_id}/{compute_cluster_id}/{nodepool_id}/{deployment_id}? (y/n): "
|
805
772
|
)
|
@@ -830,16 +797,17 @@ def local_runner(ctx, model_path, pool_size):
|
|
830
797
|
logger.info(f"Current deployment_id: {deployment_id}")
|
831
798
|
|
832
799
|
logger.info(
|
833
|
-
f"Full url for the model
|
800
|
+
f"Full url for the model:\n{ctx.obj.current.ui}/users/{user_id}/apps/{app_id}/models/{model.id}/versions/{version.id}"
|
834
801
|
)
|
835
802
|
|
836
803
|
# Now that we have all the context in ctx.obj, we need to update the config.yaml in
|
837
804
|
# the model_path directory with the model object containing user_id, app_id, model_id, version_id
|
838
805
|
config_file = os.path.join(model_path, 'config.yaml')
|
839
806
|
if not os.path.exists(config_file):
|
840
|
-
|
807
|
+
logger.error(
|
841
808
|
f"config.yaml not found in {model_path}. Please ensure you are passing the correct directory."
|
842
809
|
)
|
810
|
+
raise click.Abort()
|
843
811
|
config = ModelBuilder._load_config(config_file)
|
844
812
|
model_type_id = config.get('model', {}).get('model_type_id', DEFAULT_LOCAL_RUNNER_MODEL_TYPE)
|
845
813
|
# The config.yaml doens't match what we created above.
|
@@ -857,6 +825,18 @@ def local_runner(ctx, model_path, pool_size):
|
|
857
825
|
ModelBuilder._save_config(config_file, config)
|
858
826
|
|
859
827
|
builder = ModelBuilder(model_path, download_validation_only=True)
|
828
|
+
if not check_requirements_installed(model_path):
|
829
|
+
logger.error(f"Requirements not installed for model at {model_path}.")
|
830
|
+
raise click.Abort()
|
831
|
+
|
832
|
+
# Post check while running `clarifai model local-runner` we check if the toolkit is ollama
|
833
|
+
if builder.config.get('toolkit', {}).get('provider') == 'ollama':
|
834
|
+
if not check_ollama_installed():
|
835
|
+
logger.error(
|
836
|
+
"Ollama is not installed. Please install it from `https://ollama.com/` to use the Ollama toolkit."
|
837
|
+
)
|
838
|
+
raise click.Abort()
|
839
|
+
|
860
840
|
# don't mock for local runner since you need the dependencies to run the code anyways.
|
861
841
|
method_signatures = builder.get_method_signatures(mocking=False)
|
862
842
|
|
@@ -871,12 +851,15 @@ def local_runner(ctx, model_path, pool_size):
|
|
871
851
|
base_url=ctx.obj.current.api_base,
|
872
852
|
)
|
873
853
|
|
874
|
-
logger.info("""\
|
875
|
-
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
854
|
+
logger.info(f"""\nXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
876
855
|
# About to start up the local runner in this terminal...
|
877
|
-
# Here is a code snippet to call this model once it start from another terminal:
|
856
|
+
# Here is a code snippet to call this model once it start from another terminal:{snippet}
|
857
|
+
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
878
858
|
""")
|
879
|
-
|
859
|
+
|
860
|
+
logger.info(
|
861
|
+
f"Playground: To chat with your model, visit:\n{ctx.obj.current.ui}/playground?model={model.id}__{version.id}&user_id={user_id}&app_id={app_id}"
|
862
|
+
)
|
880
863
|
|
881
864
|
logger.info("Now starting the local runner...")
|
882
865
|
|
clarifai/client/app.py
CHANGED
@@ -445,7 +445,7 @@ class App(Lister, BaseClient):
|
|
445
445
|
response = self._grpc_request(self.STUB.PostModels, request)
|
446
446
|
if response.status.code != status_code_pb2.SUCCESS:
|
447
447
|
raise Exception(response.status)
|
448
|
-
self.logger.info("
|
448
|
+
self.logger.info(f"Model with ID '{model_id}' is created:\n{response.status}")
|
449
449
|
kwargs.update(
|
450
450
|
{
|
451
451
|
'model_id': model_id,
|