clarifai 11.6.4rc2__py3-none-any.whl → 11.6.6__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 +119 -118
- clarifai/cli/model.py +116 -86
- 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/model_client.py +20 -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 +23 -1
- clarifai/runners/utils/model_utils.py +4 -4
- clarifai/runners/utils/url_fetcher.py +51 -12
- clarifai/utils/cli.py +148 -13
- clarifai/utils/constants.py +5 -0
- clarifai/utils/misc.py +47 -0
- {clarifai-11.6.4rc2.dist-info → clarifai-11.6.6.dist-info}/METADATA +2 -2
- clarifai-11.6.6.dist-info/RECORD +127 -0
- {clarifai-11.6.4rc2.dist-info → clarifai-11.6.6.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.6.dist-info}/entry_points.txt +0 -0
- {clarifai-11.6.4rc2.dist-info → clarifai-11.6.6.dist-info}/licenses/LICENSE +0 -0
- {clarifai-11.6.4rc2.dist-info → clarifai-11.6.6.dist-info}/top_level.txt +0 -0
clarifai/cli/model.py
CHANGED
@@ -5,7 +5,13 @@ 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
|
+
parse_requirements,
|
13
|
+
validate_context,
|
14
|
+
)
|
9
15
|
from clarifai.utils.constants import (
|
10
16
|
DEFAULT_LOCAL_RUNNER_APP_ID,
|
11
17
|
DEFAULT_LOCAL_RUNNER_COMPUTE_CLUSTER_CONFIG,
|
@@ -22,49 +28,6 @@ from clarifai.utils.logging import logger
|
|
22
28
|
from clarifai.utils.misc import GitHubDownloader, clone_github_repo, format_github_repo_url
|
23
29
|
|
24
30
|
|
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
31
|
@cli.group(
|
69
32
|
['model'], context_settings={'max_content_width': shutil.get_terminal_size().columns - 10}
|
70
33
|
)
|
@@ -121,15 +84,22 @@ def model():
|
|
121
84
|
required=False,
|
122
85
|
)
|
123
86
|
def init(
|
124
|
-
model_path,
|
87
|
+
model_path,
|
88
|
+
model_type_id,
|
89
|
+
github_pat,
|
90
|
+
github_url,
|
91
|
+
toolkit,
|
92
|
+
model_name,
|
93
|
+
port,
|
94
|
+
context_length,
|
125
95
|
):
|
126
96
|
"""Initialize a new model directory structure.
|
127
97
|
|
128
|
-
Creates the following structure in the specified directory
|
129
|
-
├── 1
|
130
|
-
│ └── model.py
|
131
|
-
├── requirements.txt
|
132
|
-
└── config.yaml
|
98
|
+
Creates the following structure in the specified directory:\n
|
99
|
+
├── 1/\n
|
100
|
+
│ └── model.py\n
|
101
|
+
├── requirements.txt\n
|
102
|
+
└── config.yaml\n
|
133
103
|
|
134
104
|
If --github-repo is provided, the entire repository contents will be copied to the target
|
135
105
|
directory instead of using default templates. The --github-pat option can be used for authentication
|
@@ -137,13 +107,13 @@ def init(
|
|
137
107
|
branch to clone from.
|
138
108
|
|
139
109
|
MODEL_PATH: Path where to create the model directory structure. If not specified, the current directory is used by default.
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
110
|
+
MODEL_TYPE_ID: Type of model to create. If not specified, defaults to "text-to-text" for text models.
|
111
|
+
GITHUB_PAT: GitHub Personal Access Token for authentication when cloning private repositories.
|
112
|
+
GITHUB_URL: GitHub repository URL or "repo" format to clone a repository from. If provided, the entire repository contents will be copied to the target directory instead of using default templates.
|
113
|
+
TOOLKIT: Toolkit to use for model initialization. Currently supports "ollama".
|
114
|
+
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.).
|
115
|
+
PORT: Port to run the Ollama server on. Defaults to 23333.
|
116
|
+
CONTEXT_LENGTH: Context length for the Ollama model. Defaults to 8192.
|
147
117
|
"""
|
148
118
|
# Resolve the absolute path
|
149
119
|
model_path = os.path.abspath(model_path)
|
@@ -171,6 +141,11 @@ def init(
|
|
171
141
|
|
172
142
|
# --toolkit option
|
173
143
|
if toolkit == 'ollama':
|
144
|
+
if not check_ollama_installed():
|
145
|
+
logger.error(
|
146
|
+
"Ollama is not installed. Please install it from `https://ollama.com/` to use the Ollama toolkit."
|
147
|
+
)
|
148
|
+
raise click.Abort()
|
174
149
|
github_url = DEFAULT_OLLAMA_MODEL_REPO
|
175
150
|
branch = DEFAULT_OLLAMA_MODEL_REPO_BRANCH
|
176
151
|
|
@@ -251,11 +226,12 @@ def init(
|
|
251
226
|
if (model_name or port or context_length) and (toolkit == 'ollama'):
|
252
227
|
customize_ollama_model(model_path, model_name, port, context_length)
|
253
228
|
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
229
|
+
if github_url:
|
230
|
+
logger.info("Model initialization complete with GitHub repository")
|
231
|
+
logger.info("Next steps:")
|
232
|
+
logger.info("1. Review the model configuration")
|
233
|
+
logger.info("2. Install any required dependencies manually")
|
234
|
+
logger.info("3. Test the model locally using 'clarifai model local-test'")
|
259
235
|
|
260
236
|
# Fall back to template-based initialization if no GitHub repo or if GitHub repo failed
|
261
237
|
if not github_url:
|
@@ -548,8 +524,13 @@ def run_locally(model_path, port, mode, keep_env, keep_image, skip_dockerfile=Fa
|
|
548
524
|
show_default=True,
|
549
525
|
help="The number of threads to use. On community plan, the compute time allocation is drained at a rate proportional to the number of threads.",
|
550
526
|
) # pylint: disable=range-builtin-not-iterating
|
527
|
+
@click.option(
|
528
|
+
'--verbose',
|
529
|
+
is_flag=True,
|
530
|
+
help='Show detailed logs including Ollama server output. By default, Ollama logs are suppressed.',
|
531
|
+
)
|
551
532
|
@click.pass_context
|
552
|
-
def local_runner(ctx, model_path, pool_size):
|
533
|
+
def local_runner(ctx, model_path, pool_size, verbose):
|
553
534
|
"""Run the model as a local runner to help debug your model connected to the API or to
|
554
535
|
leverage local compute resources manually. This relies on many variables being present in the env
|
555
536
|
of the currently selected context. If they are not present then default values will be used to
|
@@ -591,7 +572,23 @@ def local_runner(ctx, model_path, pool_size):
|
|
591
572
|
from clarifai.runners.server import serve
|
592
573
|
|
593
574
|
validate_context(ctx)
|
594
|
-
|
575
|
+
builder = ModelBuilder(model_path, download_validation_only=True)
|
576
|
+
logger.info("> Checking local runner requirements...")
|
577
|
+
if not check_requirements_installed(model_path):
|
578
|
+
logger.error(f"Requirements not installed for model at {model_path}.")
|
579
|
+
raise click.Abort()
|
580
|
+
|
581
|
+
# Post check while running `clarifai model local-runner` we check if the toolkit is ollama
|
582
|
+
dependencies = parse_requirements(model_path)
|
583
|
+
if "ollama" in dependencies or builder.config.get('toolkit', {}).get('provider') == 'ollama':
|
584
|
+
logger.info("Verifying Ollama installation...")
|
585
|
+
if not check_ollama_installed():
|
586
|
+
logger.error(
|
587
|
+
"Ollama application is not installed. Please install it from `https://ollama.com/` to use the Ollama toolkit."
|
588
|
+
)
|
589
|
+
raise click.Abort()
|
590
|
+
|
591
|
+
logger.info("> Verifying local runner setup...")
|
595
592
|
logger.info(f"Current context: {ctx.obj.current.name}")
|
596
593
|
user_id = ctx.obj.current.user_id
|
597
594
|
logger.info(f"Current user_id: {user_id}")
|
@@ -620,7 +617,7 @@ def local_runner(ctx, model_path, pool_size):
|
|
620
617
|
compute_cluster = user.compute_cluster(compute_cluster_id)
|
621
618
|
if compute_cluster.cluster_type != 'local-dev':
|
622
619
|
raise ValueError(
|
623
|
-
f"Compute cluster {user_id}/{compute_cluster_id} is not a
|
620
|
+
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
621
|
)
|
625
622
|
try:
|
626
623
|
compute_cluster_id = ctx.obj.current.compute_cluster_id
|
@@ -630,7 +627,7 @@ def local_runner(ctx, model_path, pool_size):
|
|
630
627
|
except ValueError:
|
631
628
|
raise
|
632
629
|
except Exception as e:
|
633
|
-
logger.
|
630
|
+
logger.warning(f"Failed to get compute cluster with ID '{compute_cluster_id}':\n{e}")
|
634
631
|
y = input(
|
635
632
|
f"Compute cluster not found. Do you want to create a new compute cluster {user_id}/{compute_cluster_id}? (y/n): "
|
636
633
|
)
|
@@ -659,7 +656,7 @@ def local_runner(ctx, model_path, pool_size):
|
|
659
656
|
ctx.obj.current.CLARIFAI_NODEPOOL_ID = nodepool.id
|
660
657
|
ctx.obj.to_yaml() # save to yaml file.
|
661
658
|
except Exception as e:
|
662
|
-
logger.
|
659
|
+
logger.warning(f"Failed to get nodepool with ID '{nodepool_id}':\n{e}")
|
663
660
|
y = input(
|
664
661
|
f"Nodepool not found. Do you want to create a new nodepool {user_id}/{compute_cluster_id}/{nodepool_id}? (y/n): "
|
665
662
|
)
|
@@ -687,7 +684,7 @@ def local_runner(ctx, model_path, pool_size):
|
|
687
684
|
ctx.obj.current.CLARIFAI_APP_ID = app.id
|
688
685
|
ctx.obj.to_yaml() # save to yaml file.
|
689
686
|
except Exception as e:
|
690
|
-
logger.
|
687
|
+
logger.warning(f"Failed to get app with ID '{app_id}':\n{e}")
|
691
688
|
y = input(f"App not found. Do you want to create a new app {user_id}/{app_id}? (y/n): ")
|
692
689
|
if y.lower() != 'y':
|
693
690
|
raise click.Abort()
|
@@ -710,7 +707,7 @@ def local_runner(ctx, model_path, pool_size):
|
|
710
707
|
ctx.obj.current.CLARIFAI_MODEL_ID = model.id
|
711
708
|
ctx.obj.to_yaml() # save to yaml file.
|
712
709
|
except Exception as e:
|
713
|
-
logger.
|
710
|
+
logger.warning(f"Failed to get model with ID '{model_id}':\n{e}")
|
714
711
|
y = input(
|
715
712
|
f"Model not found. Do you want to create a new model {user_id}/{app_id}/models/{model_id}? (y/n): "
|
716
713
|
)
|
@@ -730,11 +727,14 @@ def local_runner(ctx, model_path, pool_size):
|
|
730
727
|
# mentions it's a local runner.
|
731
728
|
model_versions = [v for v in model.list_versions()]
|
732
729
|
if len(model_versions) == 0:
|
733
|
-
logger.
|
730
|
+
logger.warning("No model versions found. Creating a new version for local runner.")
|
734
731
|
version = model.create_version(pretrained_model_config={"local_dev": True}).model_version
|
735
|
-
|
732
|
+
ctx.obj.current.CLARIFAI_MODEL_VERSION_ID = version.id
|
733
|
+
ctx.obj.to_yaml()
|
736
734
|
else:
|
737
735
|
version = model_versions[0].model_version
|
736
|
+
ctx.obj.current.CLARIFAI_MODEL_VERSION_ID = version.id
|
737
|
+
ctx.obj.to_yaml() # save to yaml file.
|
738
738
|
|
739
739
|
logger.info(f"Current model version {version.id}")
|
740
740
|
|
@@ -759,12 +759,16 @@ def local_runner(ctx, model_path, pool_size):
|
|
759
759
|
# ensure the deployment is using the latest version.
|
760
760
|
if runner.worker.model.model_version.id != version.id:
|
761
761
|
nodepool.delete_runners([runner_id])
|
762
|
-
|
762
|
+
logger.warning("Deleted runner that was for an old model version ID.")
|
763
|
+
raise AttributeError(
|
764
|
+
"Runner deleted because it was associated with an outdated model version."
|
765
|
+
)
|
763
766
|
except Exception as e:
|
764
|
-
|
767
|
+
logger.warning(f"Failed to get runner with ID '{runner_id}':\n{e}")
|
768
|
+
raise AttributeError("Runner not found in nodepool.")
|
765
769
|
except AttributeError:
|
766
770
|
logger.info(
|
767
|
-
f"
|
771
|
+
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
772
|
)
|
769
773
|
runner = nodepool.create_runner(
|
770
774
|
runner_config={
|
@@ -792,14 +796,17 @@ def local_runner(ctx, model_path, pool_size):
|
|
792
796
|
# ensure the deployment is using the latest version.
|
793
797
|
if deployment.worker.model.model_version.id != version.id:
|
794
798
|
nodepool.delete_deployments([deployment_id])
|
795
|
-
|
799
|
+
logger.warning("Deleted deployment that was for an old model version ID.")
|
800
|
+
raise Exception(
|
801
|
+
"Deployment deleted because it was associated with an outdated model version."
|
802
|
+
)
|
796
803
|
try:
|
797
804
|
deployment_id = ctx.obj.current.deployment_id
|
798
805
|
except AttributeError: # doesn't exist in context but does in API then update the context.
|
799
806
|
ctx.obj.current.CLARIFAI_DEPLOYMENT_ID = deployment.id
|
800
807
|
ctx.obj.to_yaml() # save to yaml file.
|
801
808
|
except Exception as e:
|
802
|
-
logger.
|
809
|
+
logger.warning(f"Failed to get deployment with ID {deployment_id}:\n{e}")
|
803
810
|
y = input(
|
804
811
|
f"Deployment not found. Do you want to create a new deployment {user_id}/{compute_cluster_id}/{nodepool_id}/{deployment_id}? (y/n): "
|
805
812
|
)
|
@@ -829,17 +836,14 @@ def local_runner(ctx, model_path, pool_size):
|
|
829
836
|
|
830
837
|
logger.info(f"Current deployment_id: {deployment_id}")
|
831
838
|
|
832
|
-
logger.info(
|
833
|
-
f"Full url for the model: {ctx.obj.current.ui}/users/{user_id}/apps/{app_id}/models/{model.id}/versions/{version.id}"
|
834
|
-
)
|
835
|
-
|
836
839
|
# Now that we have all the context in ctx.obj, we need to update the config.yaml in
|
837
840
|
# the model_path directory with the model object containing user_id, app_id, model_id, version_id
|
838
841
|
config_file = os.path.join(model_path, 'config.yaml')
|
839
842
|
if not os.path.exists(config_file):
|
840
|
-
|
843
|
+
logger.error(
|
841
844
|
f"config.yaml not found in {model_path}. Please ensure you are passing the correct directory."
|
842
845
|
)
|
846
|
+
raise click.Abort()
|
843
847
|
config = ModelBuilder._load_config(config_file)
|
844
848
|
model_type_id = config.get('model', {}).get('model_type_id', DEFAULT_LOCAL_RUNNER_MODEL_TYPE)
|
845
849
|
# The config.yaml doens't match what we created above.
|
@@ -857,6 +861,28 @@ def local_runner(ctx, model_path, pool_size):
|
|
857
861
|
ModelBuilder._save_config(config_file, config)
|
858
862
|
|
859
863
|
builder = ModelBuilder(model_path, download_validation_only=True)
|
864
|
+
if not check_requirements_installed(model_path):
|
865
|
+
logger.error(f"Requirements not installed for model at {model_path}.")
|
866
|
+
raise click.Abort()
|
867
|
+
|
868
|
+
# Post check while running `clarifai model local-runner` we check if the toolkit is ollama
|
869
|
+
if builder.config.get('toolkit', {}).get('provider') == 'ollama':
|
870
|
+
if not check_ollama_installed():
|
871
|
+
logger.error(
|
872
|
+
"Ollama is not installed. Please install it from `https://ollama.com/` to use the Ollama toolkit."
|
873
|
+
)
|
874
|
+
raise click.Abort()
|
875
|
+
|
876
|
+
try:
|
877
|
+
logger.info("Customizing Ollama model with provided parameters...")
|
878
|
+
customize_ollama_model(
|
879
|
+
model_path=model_path,
|
880
|
+
verbose=True if verbose else False,
|
881
|
+
)
|
882
|
+
except Exception as e:
|
883
|
+
logger.error(f"Failed to customize Ollama model: {e}")
|
884
|
+
raise click.Abort()
|
885
|
+
|
860
886
|
# don't mock for local runner since you need the dependencies to run the code anyways.
|
861
887
|
method_signatures = builder.get_method_signatures(mocking=False)
|
862
888
|
|
@@ -871,14 +897,17 @@ def local_runner(ctx, model_path, pool_size):
|
|
871
897
|
base_url=ctx.obj.current.api_base,
|
872
898
|
)
|
873
899
|
|
874
|
-
logger.info("""\
|
875
|
-
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
900
|
+
logger.info(f"""\nXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
876
901
|
# 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:
|
902
|
+
# Here is a code snippet to call this model once it start from another terminal:{snippet}
|
903
|
+
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
878
904
|
""")
|
879
|
-
logger.info(snippet)
|
880
905
|
|
881
|
-
logger.info(
|
906
|
+
logger.info(
|
907
|
+
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}"
|
908
|
+
)
|
909
|
+
|
910
|
+
logger.info("✅ Starting local runner...")
|
882
911
|
|
883
912
|
# This reads the config.yaml from the model_path so we alter it above first.
|
884
913
|
serve(
|
@@ -891,6 +920,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
|
891
920
|
runner_id=runner_id,
|
892
921
|
base_url=ctx.obj.current.api_base,
|
893
922
|
pat=ctx.obj.current.pat,
|
923
|
+
context=ctx.obj.current,
|
894
924
|
)
|
895
925
|
|
896
926
|
|
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,
|
clarifai/client/auth/helper.py
CHANGED
@@ -2,6 +2,7 @@ import os
|
|
2
2
|
import urllib.request
|
3
3
|
from typing import Any, Dict
|
4
4
|
|
5
|
+
import grpc
|
5
6
|
from clarifai_grpc.channel.clarifai_channel import ClarifaiChannel
|
6
7
|
from clarifai_grpc.grpc.api import resources_pb2, service_pb2_grpc
|
7
8
|
|
@@ -289,7 +290,11 @@ class ClarifaiAuthHelper:
|
|
289
290
|
)
|
290
291
|
|
291
292
|
def get_stub(self) -> service_pb2_grpc.V2Stub:
|
292
|
-
|
293
|
+
stub, channel = self.get_stub_and_channel()
|
294
|
+
return stub
|
295
|
+
|
296
|
+
def get_stub_and_channel(self) -> tuple[service_pb2_grpc.V2Stub, grpc.Channel]:
|
297
|
+
"""Get the API gRPC stub and channel based on the API endpoint base.
|
293
298
|
|
294
299
|
Returns:
|
295
300
|
stub: The service_pb2_grpc.V2Stub stub for the API.
|
@@ -310,7 +315,7 @@ class ClarifaiAuthHelper:
|
|
310
315
|
port = 80
|
311
316
|
channel = ClarifaiChannel.get_insecure_grpc_channel(base=host, port=port)
|
312
317
|
stub = service_pb2_grpc.V2Stub(channel)
|
313
|
-
return stub
|
318
|
+
return stub, channel
|
314
319
|
|
315
320
|
def get_async_stub(self) -> service_pb2_grpc.V2Stub:
|
316
321
|
"""Get the API gRPC async stub using the right channel based on the API endpoint base.
|
clarifai/client/base.py
CHANGED
@@ -11,7 +11,7 @@ from clarifai.client.auth.helper import ClarifaiAuthHelper
|
|
11
11
|
from clarifai.constants.base import COMPUTE_ORCHESTRATION_RESOURCES
|
12
12
|
from clarifai.errors import ApiError, UserError
|
13
13
|
from clarifai.utils.constants import CLARIFAI_PAT_ENV_VAR, CLARIFAI_SESSION_TOKEN_ENV_VAR
|
14
|
-
from clarifai.utils.misc import
|
14
|
+
from clarifai.utils.misc import get_from_dict_env_or_config
|
15
15
|
|
16
16
|
|
17
17
|
class BaseClient:
|
@@ -39,15 +39,42 @@ class BaseClient:
|
|
39
39
|
def __init__(self, **kwargs):
|
40
40
|
token, pat = "", ""
|
41
41
|
try:
|
42
|
-
pat =
|
42
|
+
pat = get_from_dict_env_or_config(key="pat", env_key=CLARIFAI_PAT_ENV_VAR, **kwargs)
|
43
43
|
except UserError:
|
44
|
-
|
45
|
-
|
46
|
-
|
44
|
+
try:
|
45
|
+
token = get_from_dict_env_or_config(
|
46
|
+
key="token", env_key=CLARIFAI_SESSION_TOKEN_ENV_VAR, **kwargs
|
47
|
+
)
|
48
|
+
except UserError:
|
49
|
+
pass
|
47
50
|
finally:
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
+
if not (token or pat):
|
52
|
+
raise UserError(
|
53
|
+
"Authentication Required. Please authenticate in one of the following ways:\n\n"
|
54
|
+
"- Pass your Personal Access Token ('pat') or session token ('token') as arguments to your function.\n"
|
55
|
+
"- Set the CLARIFAI_PAT or CLARIFAI_SESSION_TOKEN environment variables in your environment.\n"
|
56
|
+
"- Run `clarifai login` in your terminal to configure CLI authentication."
|
57
|
+
)
|
58
|
+
|
59
|
+
# Also try to get user_id and base from CLI config if not provided
|
60
|
+
if not kwargs.get('user_id'):
|
61
|
+
try:
|
62
|
+
user_id = get_from_dict_env_or_config(
|
63
|
+
key="user_id", env_key="CLARIFAI_USER_ID", **kwargs
|
64
|
+
)
|
65
|
+
kwargs['user_id'] = user_id
|
66
|
+
except UserError:
|
67
|
+
pass # user_id is optional for some use cases
|
68
|
+
|
69
|
+
if not kwargs.get('base'):
|
70
|
+
try:
|
71
|
+
base = get_from_dict_env_or_config(
|
72
|
+
key="base", env_key="CLARIFAI_API_BASE", **kwargs
|
73
|
+
)
|
74
|
+
kwargs['base'] = base
|
75
|
+
except UserError:
|
76
|
+
pass # base has a default value
|
77
|
+
|
51
78
|
kwargs.update({'token': token, 'pat': pat})
|
52
79
|
|
53
80
|
self.auth_helper = ClarifaiAuthHelper(**kwargs, validate=False)
|
@@ -165,7 +165,7 @@ class ComputeCluster(Lister, BaseClient):
|
|
165
165
|
response = self._grpc_request(self.STUB.PostNodepools, request)
|
166
166
|
if response.status.code != status_code_pb2.SUCCESS:
|
167
167
|
raise Exception(response.status)
|
168
|
-
self.logger.info("
|
168
|
+
self.logger.info(f"Nodepool with ID '{nodepool_id}' is created:\n{response.status}")
|
169
169
|
|
170
170
|
dict_response = MessageToDict(response.nodepools[0], preserving_proto_field_name=True)
|
171
171
|
kwargs = self.process_response_keys(dict_response, 'nodepool')
|
clarifai/client/model.py
CHANGED
@@ -445,7 +445,9 @@ class Model(Lister, BaseClient):
|
|
445
445
|
response = self._grpc_request(self.STUB.PostModelVersions, 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(
|
449
|
+
f"Model Version with ID '{response.model.model_version.id}' is created:\n{response.status}"
|
450
|
+
)
|
449
451
|
|
450
452
|
kwargs.update({'app_id': self.app_id, 'user_id': self.user_id})
|
451
453
|
dict_response = MessageToDict(response, preserving_proto_field_name=True)
|
clarifai/client/model_client.py
CHANGED
@@ -76,7 +76,22 @@ class ModelClient:
|
|
76
76
|
def __getattr__(self, name):
|
77
77
|
if not self._defined:
|
78
78
|
self.fetch()
|
79
|
-
|
79
|
+
try:
|
80
|
+
return self.__getattribute__(name)
|
81
|
+
except AttributeError as e:
|
82
|
+
# Provide helpful error message with available methods
|
83
|
+
available_methods = []
|
84
|
+
if self._method_signatures:
|
85
|
+
available_methods = list(self._method_signatures.keys())
|
86
|
+
|
87
|
+
error_msg = f"'{self.__class__.__name__}' object has no attribute '{name}'"
|
88
|
+
|
89
|
+
if available_methods:
|
90
|
+
error_msg += f". Available methods: {available_methods}"
|
91
|
+
raise AttributeError(error_msg) from e
|
92
|
+
else:
|
93
|
+
error_msg += ". This model is a non-pythonic model. Please use the old inference methods i.e. predict_by_url, predict_by_bytes, etc."
|
94
|
+
raise Exception(error_msg) from e
|
80
95
|
|
81
96
|
def _fetch_signatures(self):
|
82
97
|
'''
|
@@ -148,6 +163,10 @@ class ModelClient:
|
|
148
163
|
self._define_compatability_functions()
|
149
164
|
return
|
150
165
|
if response.status.code != status_code_pb2.SUCCESS:
|
166
|
+
if response.outputs[0].status.description.startswith("cannot identify image file"):
|
167
|
+
raise Exception(
|
168
|
+
"Failed to fetch method signatures from model and backup method. This model is a non-pythonic model. Please use the old inference methods i.e. predict_by_url, predict_by_bytes, etc."
|
169
|
+
)
|
151
170
|
raise Exception(f"Model failed with response {response!r}")
|
152
171
|
self._method_signatures = signatures_from_json(response.outputs[0].data.text.raw)
|
153
172
|
|
clarifai/client/nodepool.py
CHANGED
@@ -195,7 +195,9 @@ class Nodepool(Lister, BaseClient):
|
|
195
195
|
response = self._grpc_request(self.STUB.PostDeployments, request)
|
196
196
|
if response.status.code != status_code_pb2.SUCCESS:
|
197
197
|
raise Exception(response.status)
|
198
|
-
self.logger.info(
|
198
|
+
self.logger.info(
|
199
|
+
f"Deployment with ID '{response.deployments[0].id}' is created:\n{response.status}"
|
200
|
+
)
|
199
201
|
|
200
202
|
dict_response = MessageToDict(
|
201
203
|
response.deployments[0], preserving_proto_field_name=True, use_integers_for_enums=True
|
@@ -324,7 +326,7 @@ class Nodepool(Lister, BaseClient):
|
|
324
326
|
if response.status.code != status_code_pb2.SUCCESS:
|
325
327
|
raise Exception(response.status)
|
326
328
|
self.logger.info(
|
327
|
-
"
|
329
|
+
f"Runner with ID '{response.runners[0].id}' is created:\n{response.status}"
|
328
330
|
)
|
329
331
|
|
330
332
|
dict_response = MessageToDict(response.runners[0], preserving_proto_field_name=True)
|
clarifai/client/user.py
CHANGED
@@ -177,7 +177,7 @@ class User(Lister, BaseClient):
|
|
177
177
|
response = self._grpc_request(self.STUB.PostApps, request)
|
178
178
|
if response.status.code != status_code_pb2.SUCCESS:
|
179
179
|
raise Exception(response.status)
|
180
|
-
self.logger.info("
|
180
|
+
self.logger.info(f"App with ID '{app_id}' is created:\n{response.status}")
|
181
181
|
return App.from_auth_helper(auth=self.auth_helper, app_id=app_id)
|
182
182
|
|
183
183
|
def _process_compute_cluster_config(
|
@@ -255,7 +255,9 @@ class User(Lister, BaseClient):
|
|
255
255
|
response = self._grpc_request(self.STUB.PostComputeClusters, request)
|
256
256
|
if response.status.code != status_code_pb2.SUCCESS:
|
257
257
|
raise Exception(response.status)
|
258
|
-
self.logger.info(
|
258
|
+
self.logger.info(
|
259
|
+
f"Compute Cluster with ID '{compute_cluster_id}' is created:\n{response.status}"
|
260
|
+
)
|
259
261
|
return ComputeCluster.from_auth_helper(
|
260
262
|
auth=self.auth_helper, compute_cluster_id=compute_cluster_id
|
261
263
|
)
|