Skip to content

Commit

Permalink
added module interface (#150)
Browse files Browse the repository at this point in the history
  • Loading branch information
sainivedh authored Aug 24, 2023
1 parent 17b821e commit 1b5a7b9
Show file tree
Hide file tree
Showing 12 changed files with 615 additions and 246 deletions.
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,3 +134,23 @@ all_workflow = app.list_workflow()
# List all workflow in community filtered by description
all_face_community_workflows = App().list_workflows(filter_by={"query": "face"}, only_in_app=False) # Get all face related workflows
```

## Interacting with Modules

```python
# Note: CLARIFAI_PAT must be set as env variable.
from clarifai.client.app import App
app = App(user_id="user_id", app_id="app_id")

# create a new module
module = app.create_module(module_id="module_id", description="module_description")

# List all modules in an app
all_modules = app.list_modules()

# List all module versions
all_module_versions = module.list_versions()

# Delete a module
app.delete_module(module_id="module_id")
```
185 changes: 176 additions & 9 deletions clarifai/client/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,19 @@
from clarifai.client.input import Inputs
from clarifai.client.lister import Lister
from clarifai.client.model import Model
from clarifai.client.module import Module
from clarifai.client.workflow import Workflow
from clarifai.errors import UserError
from clarifai.urls.helper import ClarifaiUrlHelper
from clarifai.utils.logging import get_logger


class App(Lister, BaseClient):
"""
App is a class that provides access to Clarifai API endpoints related to App information.
Inherits from BaseClient for authentication purposes.
"""
"""App is a class that provides access to Clarifai API endpoints related to App information."""

def __init__(self, url_init: str = "", app_id: str = "", **kwargs):
"""Initializes an App object.
Args:
url_init (str): The URL to initialize the app object.
app_id (str): The App ID for the App to interact with.
Expand All @@ -43,6 +42,7 @@ def __init__(self, url_init: str = "", app_id: str = "", **kwargs):

def list_datasets(self) -> List[Dataset]:
"""Lists all the datasets for the app.
Returns:
List[Dataset]: A list of Dataset objects for the datasets in the app.
Expand All @@ -65,10 +65,12 @@ def list_datasets(self) -> List[Dataset]:
return [Dataset(**dataset_info) for dataset_info in all_datasets_info]

def list_models(self, filter_by: Dict[str, Any] = {}, only_in_app: bool = True) -> List[Model]:
"""Lists all the models for the app.
"""Lists all the available models for the user.
Args:
filter_by (dict): A dictionary of filters to apply to the list of models.
only_in_app (bool): If True, only return models that are in the app.
Returns:
List[Model]: A list of Model objects for the models in the app.
Expand All @@ -95,11 +97,12 @@ def list_models(self, filter_by: Dict[str, Any] = {}, only_in_app: bool = True)

def list_workflows(self, filter_by: Dict[str, Any] = {},
only_in_app: bool = True) -> List[Workflow]:
"""
Lists all the workflows for the app.
"""Lists all the available workflows for the user.
Args:
filter_by (dict): A dictionary of filters to apply to the list of workflows.
only_in_app (bool): If True, only return workflows that are in the app.
Returns:
List[Workflow]: A list of Workflow objects for the workflows in the app.
Expand All @@ -122,17 +125,74 @@ def list_workflows(self, filter_by: Dict[str, Any] = {},

return [Workflow(**workflow_info) for workflow_info in all_workflows_info]

def list_concepts(self):
def list_modules(self, filter_by: Dict[str, Any] = {}, only_in_app: bool = True) -> List[Module]:
"""Lists all the available modules for the user.
Args:
filter_by (dict): A dictionary of filters to apply to the list of modules.
only_in_app (bool): If True, only return modules that are in the app.
Returns:
List[Module]: A list of Module objects for the modules in the app.
Example:
>>> from clarifai.client.app import App
>>> app = App(app_id="app_id", user_id="user_id")
>>> all_modules = app.list_modules()
"""
Lists all the concepts for the app.
request_data = dict(user_app_id=self.user_app_id, per_page=self.default_page_size, **filter_by)
all_modules_info = list(
self.list_all_pages_generator(self.STUB.ListModules, service_pb2.ListModulesRequest,
request_data))

filtered_modules_info = []
for module_info in all_modules_info:
if only_in_app:
if module_info['app_id'] != self.id:
continue
filtered_modules_info.append(module_info)

return [Module(**module_info) for module_info in filtered_modules_info]

def list_installed_module_versions(self, filter_by: Dict[str, Any] = {}) -> List[Module]:
"""Lists all installed module versions in the app.
Args:
filter_by (dict): A dictionary of filters to apply to the list of installed module versions.
Returns:
List[Module]: A list of Module objects for the installed module versions in the app.
Example:
>>> from clarifai.client.app import App
>>> app = App(app_id="app_id", user_id="user_id")
>>> all_installed_module_versions = app.list_installed_module_versions()
"""
request_data = dict(user_app_id=self.user_app_id, per_page=self.default_page_size, **filter_by)
all_imv_infos = list(
self.list_all_pages_generator(self.STUB.ListInstalledModuleVersions,
service_pb2.ListInstalledModuleVersionsRequest,
request_data))
for imv_info in all_imv_infos:
del imv_info['deploy_url']
del imv_info['installed_module_version_id'] # TODO: remove this after the backend fix

return [
Module(module_id=imv_info['module_version']['module_id'], **imv_info)
for imv_info in all_imv_infos
]

def list_concepts(self):
"""Lists all the concepts for the app."""
pass # TODO

def create_dataset(self, dataset_id: str, **kwargs) -> Dataset:
"""Creates a dataset for the app.
Args:
dataset_id (str): The dataset ID for the dataset to create.
**kwargs: Additional keyword arguments to be passed to the Dataset.
Returns:
Dataset: A Dataset object for the specified dataset ID.
Expand All @@ -153,9 +213,11 @@ def create_dataset(self, dataset_id: str, **kwargs) -> Dataset:

def create_model(self, model_id: str, **kwargs) -> Model:
"""Creates a model for the app.
Args:
model_id (str): The model ID for the model to create.
**kwargs: Additional keyword arguments to be passed to the Model.
Returns:
Model: A Model object for the specified model ID.
Expand All @@ -176,9 +238,11 @@ def create_model(self, model_id: str, **kwargs) -> Model:

def create_workflow(self, workflow_id: str, **kwargs) -> Workflow:
"""Creates a workflow for the app.
Args:
workflow_id (str): The workflow ID for the workflow to create.
**kwargs: Additional keyword arguments to be passed to the workflow.
Returns:
Workflow: A Workflow object for the specified workflow ID.
Expand All @@ -197,10 +261,40 @@ def create_workflow(self, workflow_id: str, **kwargs) -> Workflow:

return Workflow(workflow_id=workflow_id, **kwargs)

def create_module(self, module_id: str, description: str, **kwargs) -> Module:
"""Creates a module for the app.
Args:
module_id (str): The module ID for the module to create.
description (str): The description of the module to create.
**kwargs: Additional keyword arguments to be passed to the module.
Returns:
Module: A Module object for the specified module ID.
Example:
>>> from clarifai.client.app import App
>>> app = App(app_id="app_id", user_id="user_id")
>>> module = app.create_module(module_id="module_id")
"""
request = service_pb2.PostModulesRequest(
user_app_id=self.user_app_id,
modules=[resources_pb2.Module(id=module_id, description=description, **kwargs)])
response = self._grpc_request(self.STUB.PostModules, request)

if response.status.code != status_code_pb2.SUCCESS:
raise Exception(response.status)
self.logger.info("\nModule created\n%s", response.status)
kwargs.update({'app_id': self.id, 'user_id': self.user_id})

return Module(module_id=module_id, **kwargs)

def dataset(self, dataset_id: str, **kwargs) -> Dataset:
"""Returns a Dataset object for the existing dataset ID.
Args:
dataset_id (str): The dataset ID for the dataset to interact with.
Returns:
Dataset: A Dataset object for the existing dataset ID.
Expand All @@ -211,6 +305,7 @@ def dataset(self, dataset_id: str, **kwargs) -> Dataset:
"""
request = service_pb2.GetDatasetRequest(user_app_id=self.user_app_id, dataset_id=dataset_id)
response = self._grpc_request(self.STUB.GetDataset, request)

if response.status.code != status_code_pb2.SUCCESS:
raise Exception(response.status)
dict_response = MessageToDict(response, preserving_proto_field_name=True)
Expand All @@ -221,9 +316,11 @@ def dataset(self, dataset_id: str, **kwargs) -> Dataset:

def model(self, model_id: str, model_version_id: str = "", **kwargs) -> Model:
"""Returns a Model object for the existing model ID.
Args:
model_id (str): The model ID for the model to interact with.
model_version_id (str): The model version ID for the model version to interact with.
Returns:
Model: A Model object for the existing model ID.
Expand All @@ -235,6 +332,7 @@ def model(self, model_id: str, model_version_id: str = "", **kwargs) -> Model:
request = service_pb2.GetModelRequest(
user_app_id=self.user_app_id, model_id=model_id, version_id=model_version_id)
response = self._grpc_request(self.STUB.GetModel, request)

if response.status.code != status_code_pb2.SUCCESS:
raise Exception(response.status)
dict_response = MessageToDict(response, preserving_proto_field_name=True)
Expand All @@ -243,8 +341,10 @@ def model(self, model_id: str, model_version_id: str = "", **kwargs) -> Model:

def workflow(self, workflow_id: str, **kwargs) -> Workflow:
"""Returns a workflow object for the existing workflow ID.
Args:
workflow_id (str): The workflow ID for the workflow to interact with.
Returns:
Workflow: A Workflow object for the existing workflow ID.
Expand All @@ -255,6 +355,7 @@ def workflow(self, workflow_id: str, **kwargs) -> Workflow:
"""
request = service_pb2.GetWorkflowRequest(user_app_id=self.user_app_id, workflow_id=workflow_id)
response = self._grpc_request(self.STUB.GetWorkflow, request)

if response.status.code != status_code_pb2.SUCCESS:
raise Exception(response.status)
dict_response = MessageToDict(response, preserving_proto_field_name=True)
Expand All @@ -263,47 +364,113 @@ def workflow(self, workflow_id: str, **kwargs) -> Workflow:

return Workflow(**kwargs)

def module(self, module_id: str, module_version_id: str = "", **kwargs) -> Module:
"""Returns a Module object for the existing module ID.
Args:
module_id (str): The module ID for the module to interact with.
module_version_id (str): The module version ID for the module version to interact with.
Returns:
Module: A Module object for the existing module ID.
Example:
>>> from clarifai.client.app import App
>>> app = App(app_id="app_id", user_id="user_id")
>>> module = app.module(module_id="module_id", module_version_id="module_version_id")
"""
request = service_pb2.GetModuleRequest(
user_app_id=self.user_app_id, module_id=module_id, version_id=module_version_id)
response = self._grpc_request(self.STUB.GetModule, request)

if response.status.code != status_code_pb2.SUCCESS:
raise Exception(response.status)
dict_response = MessageToDict(response, preserving_proto_field_name=True)
kwargs = self.process_response_keys(dict_response['module'], 'module')

return Module(**kwargs)

def inputs(self,):
"""Returns an Input object.
Returns:
Inputs: An input object.
"""
return Inputs(self.user_id, self.id)

def delete_dataset(self, dataset_id: str) -> None:
"""Deletes an dataset for the user.
Args:
dataset_id (str): The dataset ID for the app to delete.
Example:
>>> from clarifai.client.app import App
>>> app = App(app_id="app_id", user_id="user_id")
>>> app.delete_dataset(dataset_id="dataset_id")
"""
request = service_pb2.DeleteDatasetsRequest(
user_app_id=self.user_app_id, dataset_ids=[dataset_id])
response = self._grpc_request(self.STUB.DeleteDatasets, request)

if response.status.code != status_code_pb2.SUCCESS:
raise Exception(response.status)
self.logger.info("\nDataset Deleted\n%s", response.status)

def delete_model(self, model_id: str) -> None:
"""Deletes an model for the user.
Args:
model_id (str): The model ID for the app to delete.
Example:
>>> from clarifai.client.app import App
>>> app = App(app_id="app_id", user_id="user_id")
>>> app.delete_model(model_id="model_id")
"""
request = service_pb2.DeleteModelsRequest(user_app_id=self.user_app_id, ids=[model_id])
response = self._grpc_request(self.STUB.DeleteModels, request)

if response.status.code != status_code_pb2.SUCCESS:
raise Exception(response.status)
self.logger.info("\nModel Deleted\n%s", response.status)

def delete_workflow(self, workflow_id: str) -> None:
"""Deletes an workflow for the user.
Args:
workflow_id (str): The workflow ID for the app to delete.
Example:
>>> from clarifai.client.app import App
>>> app = App(app_id="app_id", user_id="user_id")
>>> app.delete_workflow(workflow_id="workflow_id")
"""
request = service_pb2.DeleteWorkflowsRequest(user_app_id=self.user_app_id, ids=[workflow_id])
response = self._grpc_request(self.STUB.DeleteWorkflows, request)

if response.status.code != status_code_pb2.SUCCESS:
raise Exception(response.status)
self.logger.info("\nWorkflow Deleted\n%s", response.status)

def delete_module(self, module_id: str) -> None:
"""Deletes an module for the user.
Args:
module_id (str): The module ID for the app to delete.
Example:
>>> from clarifai.client.app import App
>>> app = App(app_id="app_id", user_id="user_id")
>>> app.delete_module(module_id="module_id")
"""
request = service_pb2.DeleteModulesRequest(user_app_id=self.user_app_id, ids=[module_id])
response = self._grpc_request(self.STUB.DeleteModules, request)

if response.status.code != status_code_pb2.SUCCESS:
raise Exception(response.status)
self.logger.info("\nModule Deleted\n%s", response.status)

def __getattr__(self, name):
return getattr(self.app_info, name)

Expand Down
Loading

0 comments on commit 1b5a7b9

Please sign in to comment.