clarifai 11.2.3rc6__py3-none-any.whl → 11.2.3rc8__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 CHANGED
@@ -1 +1 @@
1
- __version__ = "11.2.3rc6"
1
+ __version__ = "11.2.3rc8"
clarifai/cli/base.py CHANGED
@@ -1,108 +1,255 @@
1
+ import json
1
2
  import os
3
+ import sys
2
4
 
3
5
  import click
6
+ import yaml
4
7
 
5
- from ..utils.cli import dump_yaml, from_yaml, load_command_modules, set_base_url
8
+ from clarifai.utils.cli import AliasedGroup, TableFormatter, load_command_modules
9
+ from clarifai.utils.config import Config, Context
10
+ from clarifai.utils.constants import DEFAULT_CONFIG
11
+ from clarifai.utils.logging import logger
6
12
 
7
13
 
8
- class CustomMultiGroup(click.Group):
14
+ #@click.group(cls=CustomMultiGroup)
15
+ @click.group(cls=AliasedGroup)
16
+ @click.option('--config', default=DEFAULT_CONFIG)
17
+ @click.pass_context
18
+ def cli(ctx, config):
19
+ """Clarifai CLI"""
20
+ ctx.ensure_object(dict)
21
+ if os.path.exists(config):
22
+ cfg = Config.from_yaml(filename=config)
23
+ ctx.obj = cfg
24
+ else:
25
+ cfg = Config(
26
+ filename=config,
27
+ current_context='default',
28
+ contexts={
29
+ 'default':
30
+ Context(
31
+ 'default',
32
+ CLARIFAI_PAT=os.environ.get('CLARIFAI_PAT', ''),
33
+ CLARIFAI_USER_ID=os.environ.get('CLARIFAI_USER_ID', ''),
34
+ CLARIFAI_API_BASE=os.environ.get('CLARIFAI_API_BASE', 'api.clarifai.com'),
35
+ )
36
+ })
37
+ try:
38
+ cfg.to_yaml(config)
39
+ except Exception:
40
+ logger.warning("Could not write configuration to disk. Could be a read only file system.")
41
+ ctx.obj = cfg # still have the default config even if couldn't write.
9
42
 
10
- def group(self, *args, **kwargs):
11
- """Behaves the same as `click.Group.group()` except if passed
12
- a list of names, all after the first will be aliases for the first.
13
- """
14
43
 
15
- def decorator(f):
16
- aliased_group = []
17
- if isinstance(args[0], list):
18
- # we have a list so create group aliases
19
- _args = [args[0][0]] + list(args[1:])
20
- for alias in args[0][1:]:
21
- grp = super(CustomMultiGroup, self).group(alias, *args[1:], **kwargs)(f)
22
- grp.short_help = "Alias for '{}'".format(_args[0])
23
- aliased_group.append(grp)
24
- else:
25
- _args = args
44
+ @cli.command()
45
+ @click.argument('shell', type=click.Choice(['bash', 'zsh']))
46
+ def shell_completion(shell):
47
+ """Shell completion script"""
48
+ os.system(f"_CLARIFAI_COMPLETE={shell}_source clarifai")
26
49
 
27
- # create the main group
28
- grp = super(CustomMultiGroup, self).group(*_args, **kwargs)(f)
29
50
 
30
- # for all of the aliased groups, share the main group commands
31
- for aliased in aliased_group:
32
- aliased.commands = grp.commands
51
+ @cli.group(['cfg'], cls=AliasedGroup)
52
+ def config():
53
+ """Manage CLI configuration"""
33
54
 
34
- return grp
35
55
 
36
- return decorator
56
+ @config.command(['e'])
57
+ @click.pass_context
58
+ def edit(ctx):
59
+ """Edit the configuration file"""
60
+ os.system(f'{os.environ.get("EDITOR", "vi")} {ctx.obj.filename}')
37
61
 
38
62
 
39
- @click.group(cls=CustomMultiGroup)
63
+ @config.command(['current'])
64
+ @click.option('-o', '--output-format', default='name', type=click.Choice(['name', 'json', 'yaml']))
40
65
  @click.pass_context
41
- def cli(ctx):
42
- """Clarifai CLI"""
43
- ctx.ensure_object(dict)
44
- config_path = 'config.yaml'
45
- if os.path.exists(config_path):
46
- ctx.obj = from_yaml(config_path)
66
+ def current_context(ctx, output_format):
67
+ """Get the current context"""
68
+ if output_format == 'name':
69
+ print(ctx.obj.current_context)
47
70
  else:
48
- ctx.obj = {}
71
+ if output_format == 'json':
72
+ print(json.dumps(ctx.obj.contexts[ctx.obj.current_context].to_serializable_dict()))
73
+ else:
74
+ print(yaml.safe_dump(ctx.obj.contexts[ctx.obj.current_context].to_serializable_dict()))
49
75
 
50
76
 
51
- @cli.command()
52
- @click.option('--config', type=click.Path(), required=False, help='Path to the config file')
77
+ @config.command(['list', 'ls'])
53
78
  @click.option(
54
- '-e',
55
- '--env',
56
- required=False,
57
- help='Environment to use, choose from prod, staging and dev',
58
- type=click.Choice(['prod', 'staging', 'dev']))
79
+ '-o', '--output-format', default='wide', type=click.Choice(['wide', 'name', 'json', 'yaml']))
80
+ @click.pass_context
81
+ def get_contexts(ctx, output_format):
82
+ """Get all contexts"""
83
+ if output_format == 'wide':
84
+ formatter = TableFormatter(custom_columns={
85
+ '': lambda c: '*' if c.name == ctx.obj.current_context else '',
86
+ 'NAME': lambda c: c.name,
87
+ 'USER_ID': lambda c: c.user_id,
88
+ 'API_BASE': lambda c: c.api_base,
89
+ 'PAT': lambda c: pat_display(c.pat),
90
+ })
91
+ print(formatter.format(ctx.obj.contexts.values(), fmt="plain"))
92
+ elif output_format == 'name':
93
+ print('\n'.join(ctx.obj.contexts))
94
+ elif output_format in ('json', 'yaml'):
95
+ dicts = [v.__dict__ for c, v in ctx.obj.contexts.items()]
96
+ for d in dicts:
97
+ d.pop('pat')
98
+ if output_format == 'json':
99
+ print(json.dumps(dicts))
100
+ elif output_format == 'yaml':
101
+ print(yaml.safe_dump(dicts))
102
+
103
+
104
+ @config.command(['use'])
105
+ @click.argument('context-name', type=str)
106
+ @click.pass_context
107
+ def use_context(ctx, context_name):
108
+ """Set the current context"""
109
+ if context_name not in ctx.obj.contexts:
110
+ raise click.UsageError('Context not found')
111
+ ctx.obj.current_context = context_name
112
+ ctx.obj.to_yaml()
113
+ print(f'Set {context_name} as the current context')
114
+
115
+
116
+ @config.command(['cat'])
117
+ @click.option('-o', '--output-format', default='yaml', type=click.Choice(['yaml', 'json']))
118
+ @click.pass_obj
119
+ def dump(ctx_obj, output_format):
120
+ """Dump the configuration to stdout"""
121
+ if output_format == 'yaml':
122
+ yaml.safe_dump(ctx_obj.to_dict(), sys.stdout)
123
+ else:
124
+ json.dump(ctx_obj.to_dict(), sys.stdout, indent=2)
125
+
126
+
127
+ @cli.command()
128
+ @click.argument('api_url', default="https://api.clarifai.com")
59
129
  @click.option('--user_id', required=False, help='User ID')
60
130
  @click.pass_context
61
- def login(ctx, config, env, user_id):
131
+ def login(ctx, api_url, user_id):
62
132
  """Login command to set PAT and other configurations."""
63
133
 
64
- if config and os.path.exists(config):
65
- ctx.obj = from_yaml(config)
134
+ name = input('context name (default: "default"): ')
135
+ user_id = user_id if user_id is not None else input('user id: ')
136
+ pat = input_or_default(
137
+ 'personal access token value (default: "ENVVAR" to get our of env var rather than config): ',
138
+ 'ENVVAR')
66
139
 
67
- if 'pat' in ctx.obj:
68
- os.environ["CLARIFAI_PAT"] = ctx.obj['pat']
69
- click.echo("Loaded PAT from config file.")
70
- elif 'CLARIFAI_PAT' in os.environ:
71
- ctx.obj['pat'] = os.environ["CLARIFAI_PAT"]
72
- click.echo("Loaded PAT from environment variable.")
73
- else:
74
- _pat = click.prompt(
75
- "Get your PAT from https://clarifai.com/settings/security and pass it here", type=str)
76
- os.environ["CLARIFAI_PAT"] = _pat
77
- ctx.obj['pat'] = _pat
78
- click.echo("PAT saved successfully.")
79
-
80
- if user_id:
81
- ctx.obj['user_id'] = user_id
82
- os.environ["CLARIFAI_USER_ID"] = ctx.obj['user_id']
83
- elif 'user_id' in ctx.obj:
84
- ctx.obj['user_id'] = ctx.obj.get('user_id', "")
85
- os.environ["CLARIFAI_USER_ID"] = ctx.obj['user_id']
86
- elif 'CLARIFAI_USER_ID' in os.environ:
87
- ctx.obj['user_id'] = os.environ["CLARIFAI_USER_ID"]
88
- else:
89
- user_id = click.prompt("Pass the User ID here", type=str)
90
- os.environ["CLARIFAI_USER_ID"] = user_id
91
- ctx.obj['user_id'] = user_id
92
- click.echo("User ID saved successfully.")
93
-
94
- if env:
95
- ctx.obj['env'] = env
96
- ctx.obj['base_url'] = set_base_url(env)
97
- os.environ["CLARIFAI_API_BASE"] = ctx.obj['base_url']
98
- elif 'env' in ctx.obj:
99
- ctx.obj['env'] = ctx.obj.get('env', "prod")
100
- ctx.obj['base_url'] = set_base_url(ctx.obj['env'])
101
- os.environ["CLARIFAI_API_BASE"] = ctx.obj['base_url']
102
- elif 'CLARIFAI_API_BASE' in os.environ:
103
- ctx.obj['base_url'] = os.environ["CLARIFAI_API_BASE"]
104
-
105
- dump_yaml(ctx.obj, 'config.yaml')
140
+ context = Context(
141
+ name,
142
+ CLARIFAI_API_BASE=api_url,
143
+ CLARIFAI_USER_ID=user_id,
144
+ CLARIFAI_PAT=pat,
145
+ )
146
+
147
+ if context.name == '':
148
+ context.name = 'default'
149
+
150
+ ctx.obj.contexts[context.name] = context
151
+ ctx.obj.current_context = context.name
152
+
153
+ ctx.obj.to_yaml()
154
+
155
+
156
+ @cli.group(cls=AliasedGroup)
157
+ def context():
158
+ """Manage contexts"""
159
+
160
+
161
+ def pat_display(pat):
162
+ return pat[:5] + "****"
163
+
164
+
165
+ @context.command(['ls'])
166
+ @click.pass_context
167
+ def list(ctx):
168
+ """List available contexts"""
169
+ formatter = TableFormatter(custom_columns={
170
+ '': lambda c: '*' if c.name == ctx.obj.current_context else '',
171
+ 'NAME': lambda c: c.name,
172
+ 'USER_ID': lambda c: c.user_id,
173
+ 'API_BASE': lambda c: c.api_base,
174
+ 'PAT': lambda c: pat_display(c.pat)
175
+ })
176
+ print(formatter.format(ctx.obj.contexts.values(), fmt="plain"))
177
+
178
+
179
+ def input_or_default(prompt, default):
180
+ value = input(prompt)
181
+ return value if value else default
182
+
183
+
184
+ @context.command()
185
+ @click.argument('name')
186
+ @click.option('--user-id', required=False, help='User ID')
187
+ @click.option('--base-url', required=False, help='Base URL')
188
+ @click.option('--pat', required=False, help='Personal access token')
189
+ @click.pass_context
190
+ def create(
191
+ ctx,
192
+ name,
193
+ user_id=None,
194
+ base_url=None,
195
+ pat=None,
196
+ ):
197
+ """Create a new context"""
198
+ if name in ctx.obj.contexts:
199
+ print(f'{name} already exists')
200
+ exit(1)
201
+ if not user_id:
202
+ user_id = input('user id: ')
203
+ if not base_url:
204
+ base_url = input_or_default('base url (default: https://api.clarifai.com): ',
205
+ 'https://api.clarifai.com')
206
+ if not pat:
207
+ pat = input_or_default(
208
+ 'personal access token value (default: "ENVVAR" to get our of env var rather than config): ',
209
+ 'ENVVAR')
210
+
211
+ context = Context(name, CLARIFAI_USER_ID=user_id, CLARIFAI_API_BASE=base_url, CLARIFAI_PAT=pat)
212
+ ctx.obj.contexts[context.name] = context
213
+ ctx.obj.to_yaml()
214
+
215
+
216
+ # write a click command to delete a context
217
+ @context.command(['rm'])
218
+ @click.argument('name')
219
+ @click.pass_context
220
+ def delete(ctx, name):
221
+ """Delete a context"""
222
+ if name not in ctx.obj.contexts:
223
+ print(f'{name} is not a valid context')
224
+ exit(1)
225
+ ctx.obj.contexts.pop(name)
226
+ ctx.obj.to_yaml()
227
+ print(f'{name} deleted')
228
+
229
+
230
+ @context.command()
231
+ @click.argument('name', type=str)
232
+ @click.pass_context
233
+ def use(ctx, name):
234
+ """Set the current context"""
235
+ if name not in ctx.obj.contexts:
236
+ raise click.UsageError('Context not found')
237
+ ctx.obj.current_context = name
238
+ ctx.obj.to_yaml()
239
+ print(f'Set {name} as the current context')
240
+
241
+
242
+ @cli.command()
243
+ @click.argument('script', type=str)
244
+ @click.option('--context', type=str, help='Context to use')
245
+ @click.pass_context
246
+ def run(ctx, script, context=None):
247
+ """Execute a script with the current context's environment"""
248
+ context = ctx.obj.current if not context else context
249
+ cmd = f'CLARIFAI_USER_ID={context.user_id} CLARIFAI_API_BASE={context.base_url} CLARIFAI_PAT={context.pat} '
250
+ cmd += ' '.join([f'{k}={v}' for k, v in context.env.items()])
251
+ cmd += f' {script}'
252
+ os.system(cmd)
106
253
 
107
254
 
108
255
  # Import the CLI commands to register them
@@ -1,51 +1,61 @@
1
1
  import click
2
+
2
3
  from clarifai.cli.base import cli
3
- from clarifai.client.user import User
4
- from clarifai.utils.cli import display_co_resources
4
+ from clarifai.utils.cli import AliasedGroup, display_co_resources, validate_context
5
5
 
6
6
 
7
- @cli.group(['computecluster', 'cc'])
7
+ @cli.group(['computecluster', 'cc'], cls=AliasedGroup)
8
8
  def computecluster():
9
9
  """Manage Compute Clusters: create, delete, list"""
10
- pass
11
10
 
12
11
 
13
- @computecluster.command()
12
+ @computecluster.command(['c'])
13
+ @click.argument('compute_cluster_id')
14
14
  @click.option(
15
15
  '--config',
16
16
  type=click.Path(exists=True),
17
17
  required=True,
18
18
  help='Path to the compute cluster config file.')
19
- @click.option(
20
- '-cc_id',
21
- '--compute_cluster_id',
22
- required=False,
23
- help='New Compute Cluster ID for the compute cluster to create.')
24
19
  @click.pass_context
25
- def create(ctx, config, compute_cluster_id):
20
+ def create(ctx, compute_cluster_id, config):
26
21
  """Create a new Compute Cluster with the given config file."""
27
- user = User(user_id=ctx.obj['user_id'], pat=ctx.obj['pat'], base_url=ctx.obj['base_url'])
22
+ from clarifai.client.user import User
23
+ validate_context(ctx)
24
+ user = User(
25
+ user_id=ctx.obj.current.user_id, pat=ctx.obj.current.pat, base_url=ctx.obj.current.api_base)
28
26
  if compute_cluster_id:
29
27
  user.create_compute_cluster(config, compute_cluster_id=compute_cluster_id)
30
28
  else:
31
29
  user.create_compute_cluster(config)
32
30
 
33
31
 
34
- @computecluster.command()
32
+ @computecluster.command(['ls'])
35
33
  @click.option('--page_no', required=False, help='Page number to list.', default=1)
36
34
  @click.option('--per_page', required=False, help='Number of items per page.', default=16)
37
35
  @click.pass_context
38
36
  def list(ctx, page_no, per_page):
39
37
  """List all compute clusters for the user."""
40
- user = User(user_id=ctx.obj['user_id'], pat=ctx.obj['pat'], base_url=ctx.obj['base_url'])
38
+ from clarifai.client.user import User
39
+ validate_context(ctx)
40
+ user = User(
41
+ user_id=ctx.obj.current.user_id, pat=ctx.obj.current.pat, base_url=ctx.obj.current.api_base)
41
42
  response = user.list_compute_clusters(page_no, per_page)
42
- display_co_resources(response, "Compute Cluster")
43
+ display_co_resources(
44
+ response,
45
+ custom_columns={
46
+ 'ID': lambda c: c.id,
47
+ 'USER_ID': lambda c: c.user_id,
48
+ 'DESCRIPTION': lambda c: c.description,
49
+ })
43
50
 
44
51
 
45
- @computecluster.command()
46
- @click.option('-cc_id', '--compute_cluster_id', help='Compute Cluster ID of the user to delete.')
52
+ @computecluster.command(['rm'])
53
+ @click.argument('compute_cluster_id')
47
54
  @click.pass_context
48
55
  def delete(ctx, compute_cluster_id):
49
56
  """Deletes a compute cluster for the user."""
50
- user = User(user_id=ctx.obj['user_id'], pat=ctx.obj['pat'], base_url=ctx.obj['base_url'])
57
+ from clarifai.client.user import User
58
+ validate_context(ctx)
59
+ user = User(
60
+ user_id=ctx.obj.current.user_id, pat=ctx.obj.current.pat, base_url=ctx.obj.current.api_base)
51
61
  user.delete_compute_clusters([compute_cluster_id])
@@ -1,84 +1,112 @@
1
1
  import click
2
+
2
3
  from clarifai.cli.base import cli
3
- from clarifai.client.nodepool import Nodepool
4
- from clarifai.utils.cli import display_co_resources, from_yaml
4
+ from clarifai.utils.cli import AliasedGroup, display_co_resources, from_yaml, validate_context
5
5
 
6
6
 
7
- @cli.group(['deployment', 'dpl'])
7
+ @cli.group(['deployment', 'dp'], cls=AliasedGroup)
8
8
  def deployment():
9
9
  """Manage Deployments: create, delete, list"""
10
- pass
11
10
 
12
11
 
13
- @deployment.command()
14
- @click.option(
15
- '-np_id',
16
- '--nodepool_id',
17
- required=False,
18
- help='Nodepool ID for the Nodepool to interact with.')
12
+ @deployment.command(['c'])
13
+ @click.argument('nodepool_id')
14
+ @click.argument('deployment_id')
19
15
  @click.option(
20
16
  '--config',
21
17
  type=click.Path(exists=True),
22
18
  required=True,
23
19
  help='Path to the deployment config file.')
24
- @click.option(
25
- '-dpl_id',
26
- '--deployment_id',
27
- required=False,
28
- help='New deployment ID for the deployment to create.')
29
20
  @click.pass_context
30
- def create(ctx, nodepool_id, config, deployment_id):
21
+ def create(ctx, nodepool_id, deployment_id, config):
31
22
  """Create a new Deployment with the given config file."""
23
+
24
+ from clarifai.client.nodepool import Nodepool
25
+ validate_context(ctx)
32
26
  if not nodepool_id:
33
27
  deployment_config = from_yaml(config)
34
28
  nodepool_id = deployment_config['deployment']['nodepools'][0]['id']
35
29
 
36
30
  nodepool = Nodepool(
37
31
  nodepool_id=nodepool_id,
38
- user_id=ctx.obj['user_id'],
39
- pat=ctx.obj['pat'],
40
- base_url=ctx.obj['base_url'])
32
+ user_id=ctx.obj.current.user_id,
33
+ pat=ctx.obj.current.pat,
34
+ base_url=ctx.obj.current.api_base)
41
35
  if deployment_id:
42
36
  nodepool.create_deployment(config, deployment_id=deployment_id)
43
37
  else:
44
38
  nodepool.create_deployment(config)
45
39
 
46
40
 
47
- @deployment.command()
48
- @click.option(
49
- '-np_id',
50
- '--nodepool_id',
51
- required=True,
52
- help='Nodepool ID for the Nodepool to interact with.')
41
+ @deployment.command(['ls'])
42
+ @click.argument('nodepool_id', default="")
53
43
  @click.option('--page_no', required=False, help='Page number to list.', default=1)
54
44
  @click.option('--per_page', required=False, help='Number of items per page.', default=16)
55
45
  @click.pass_context
56
46
  def list(ctx, nodepool_id, page_no, per_page):
57
47
  """List all deployments for the nodepool."""
48
+ from clarifai.client.compute_cluster import ComputeCluster
49
+ from clarifai.client.nodepool import Nodepool
50
+ from clarifai.client.user import User
58
51
 
59
- nodepool = Nodepool(
60
- nodepool_id=nodepool_id,
61
- user_id=ctx.obj['user_id'],
62
- pat=ctx.obj['pat'],
63
- base_url=ctx.obj['base_url'])
64
- response = nodepool.list_deployments(page_no=page_no, per_page=per_page)
65
- display_co_resources(response, "Deployment")
52
+ validate_context(ctx)
53
+ if nodepool_id:
54
+ nodepool = Nodepool(
55
+ nodepool_id=nodepool_id,
56
+ user_id=ctx.obj.current.user_id,
57
+ pat=ctx.obj.current.pat,
58
+ base_url=ctx.obj.current.api_base)
59
+ response = nodepool.list_deployments(page_no=page_no, per_page=per_page)
60
+ else:
61
+ user = User(
62
+ user_id=ctx.obj.current.user_id,
63
+ pat=ctx.obj.current.pat,
64
+ base_url=ctx.obj.current.api_base)
65
+ ccs = user.list_compute_clusters(page_no, per_page)
66
+ nps = []
67
+ for cc in ccs:
68
+ compute_cluster = ComputeCluster(
69
+ compute_cluster_id=cc.id,
70
+ user_id=ctx.obj.current.user_id,
71
+ pat=ctx.obj.current.pat,
72
+ base_url=ctx.obj.current.api_base)
73
+ nps.extend([i for i in compute_cluster.list_nodepools(page_no, per_page)])
74
+ response = []
75
+ for np in nps:
76
+ nodepool = Nodepool(
77
+ nodepool_id=np.id,
78
+ user_id=ctx.obj.current.user_id,
79
+ pat=ctx.obj.current.pat,
80
+ base_url=ctx.obj.current.api_base)
81
+ response.extend([i for i in nodepool.list_deployments(page_no=page_no, per_page=per_page)])
66
82
 
83
+ display_co_resources(
84
+ response,
85
+ custom_columns={
86
+ 'ID': lambda c: c.id,
87
+ 'USER_ID': lambda c: c.user_id,
88
+ 'COMPUTE_CLUSTER_ID': lambda c: c.nodepools[0].compute_cluster.id,
89
+ 'NODEPOOL_ID': lambda c: c.nodepools[0].id,
90
+ 'MODEL_USER_ID': lambda c: c.worker.model.user_id,
91
+ 'MODEL_APP_ID': lambda c: c.worker.model.app_id,
92
+ 'MODEL_ID': lambda c: c.worker.model.id,
93
+ 'MODEL_VERSION_ID': lambda c: c.worker.model.model_version.id,
94
+ 'DESCRIPTION': lambda c: c.description,
95
+ })
67
96
 
68
- @deployment.command()
69
- @click.option(
70
- '-np_id',
71
- '--nodepool_id',
72
- required=True,
73
- help='Nodepool ID for the Nodepool to interact with.')
74
- @click.option('-dpl_id', '--deployment_id', help='Deployment ID of the nodepool to delete.')
97
+
98
+ @deployment.command(['rm'])
99
+ @click.argument('nodepool_id')
100
+ @click.argument('deployment_id')
75
101
  @click.pass_context
76
102
  def delete(ctx, nodepool_id, deployment_id):
77
103
  """Deletes a deployment for the nodepool."""
104
+ from clarifai.client.nodepool import Nodepool
78
105
 
106
+ validate_context(ctx)
79
107
  nodepool = Nodepool(
80
108
  nodepool_id=nodepool_id,
81
- user_id=ctx.obj['user_id'],
82
- pat=ctx.obj['pat'],
83
- base_url=ctx.obj['base_url'])
109
+ user_id=ctx.obj.current.user_id,
110
+ pat=ctx.obj.current.pat,
111
+ base_url=ctx.obj.current.api_base)
84
112
  nodepool.delete_deployments([deployment_id])
clarifai/cli/model.py CHANGED
@@ -5,7 +5,7 @@ from clarifai.cli.base import cli
5
5
 
6
6
  @cli.group(['model'])
7
7
  def model():
8
- """Manage models: upload, test locally, run locally, predict, and more"""
8
+ """Manage models: upload, test, local dev, predict, etc"""
9
9
 
10
10
 
11
11
  @model.command()
@@ -121,11 +121,14 @@ def signatures(model_path, out_path):
121
121
  help=
122
122
  'Keep the Docker image after testing the model locally (applicable for container mode). Defaults to False.'
123
123
  )
124
- def test_locally(model_path, keep_env=False, keep_image=False, mode='env'):
125
- """Test model locally.
126
-
127
- MODEL_PATH: Path to the model directory. If not specified, the current directory is used by default.
128
- """
124
+ @click.option(
125
+ '--skip_dockerfile',
126
+ is_flag=True,
127
+ help=
128
+ 'Flag to skip generating a dockerfile so that you can manually edit an already created dockerfile. Apply for `--mode conatainer`.',
129
+ )
130
+ def test_locally(model_path, keep_env=False, keep_image=False, mode='env', skip_dockerfile=False):
131
+ """Test model locally."""
129
132
  try:
130
133
  from clarifai.runners.models import model_run_locally
131
134
  if mode == 'env' and keep_image:
@@ -139,7 +142,11 @@ def test_locally(model_path, keep_env=False, keep_image=False, mode='env'):
139
142
  elif mode == "container":
140
143
  click.echo("Testing model locally inside a container...")
141
144
  model_run_locally.main(
142
- model_path, inside_container=True, run_model_server=False, keep_image=keep_image)
145
+ model_path,
146
+ inside_container=True,
147
+ run_model_server=False,
148
+ keep_image=keep_image,
149
+ skip_dockerfile=skip_dockerfile)
143
150
  click.echo("Model tested successfully.")
144
151
  except Exception as e:
145
152
  click.echo(f"Failed to test model locally: {e}", err=True)
@@ -179,11 +186,14 @@ def test_locally(model_path, keep_env=False, keep_image=False, mode='env'):
179
186
  help=
180
187
  'Keep the Docker image after testing the model locally (applicable for container mode). Defaults to False.'
181
188
  )
182
- def run_locally(model_path, port, mode, keep_env, keep_image):
183
- """Run the model locally and start a gRPC server to serve the model.
184
-
185
- MODEL_PATH: Path to the model directory. If not specified, the current directory is used by default.
186
- """
189
+ @click.option(
190
+ '--skip_dockerfile',
191
+ is_flag=True,
192
+ help=
193
+ 'Flag to skip generating a dockerfile so that you can manually edit an already created dockerfile. Apply for `--mode conatainer`.',
194
+ )
195
+ def run_locally(model_path, port, mode, keep_env, keep_image, skip_dockerfile=False):
196
+ """Run the model locally and start a gRPC server to serve the model."""
187
197
  try:
188
198
  from clarifai.runners.models import model_run_locally
189
199
  if mode == 'env' and keep_image:
@@ -201,7 +211,8 @@ def run_locally(model_path, port, mode, keep_env, keep_image):
201
211
  inside_container=True,
202
212
  run_model_server=True,
203
213
  port=port,
204
- keep_image=keep_image)
214
+ keep_image=keep_image,
215
+ skip_dockerfile=skip_dockerfile)
205
216
  click.echo(f"Model server started locally from {model_path} in {mode} mode.")
206
217
  except Exception as e:
207
218
  click.echo(f"Failed to starts model server locally: {e}", err=True)
@@ -255,7 +266,8 @@ def predict(ctx, config, model_id, user_id, app_id, model_url, file_path, url, b
255
266
  import json
256
267
 
257
268
  from clarifai.client.model import Model
258
- from clarifai.utils.cli import from_yaml
269
+ from clarifai.utils.cli import from_yaml, validate_context
270
+ validate_context(ctx)
259
271
  if config:
260
272
  config = from_yaml(config)
261
273
  model_id, user_id, app_id, model_url, file_path, url, bytes, input_type, compute_cluster_id, nodepool_id, deployment_id, inference_params, output_config = (