Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cli support for delete and restore + docs #367

Merged
merged 6 commits into from Aug 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
53 changes: 51 additions & 2 deletions docs/source/cli.rst
Expand Up @@ -21,7 +21,7 @@ and list experiments, and download artifacts.
Commands:
azureml Serve models on Azure ML.
download Download the artifact at the specified DBFS or S3 URI.
experiments Run and list experiments.
experiments Manage experiments.
pyfunc Serve Python models locally.
run Run an MLflow project from the given URI.
sagemaker Serve models on Amazon SageMaker.
Expand Down Expand Up @@ -49,7 +49,56 @@ specified.
Experiments
-----------

Subcommands to create and list experiments.
Subcommands to manage experiments.


Create
~~~~~~

Subcommand to create a new experiment. The command has required argument for experiment name.
Additionally, users can provide an artifact location using ``-l`` or ``--artifact-location``
option. If not provided, backend store will pick default location. Backend store will generate a
unique ID for each experiment.

All artifacts generated by runs related to this experiment will be stored under artifact location,
organized under specific run_uuid sub-directories.

Implementation of experiment and metadata store is dependent on backend storage. ``FileStore``
creates a folder for each experiment ID and stores metadata in ``meta.yaml``. Runs are stored as
subfolders.


List
~~~~

Lists all experiments managed by backend store. Command takes an optional ``--view`` or ``-v``
argument. Valid arguments are ``active_only`` (default), ``deleted_only``, or ``all``.


Delete
~~~~~~

Marks an active experiment for deletion. This also applies to experiment's metadata, runs and
associated data, and artifacts if they are store in default location. Use ``list`` command to view
artifact location. Command takes a required argument for experiment ID. Command will thrown
an error if experiment is not found or already marked for deletion.

Experiments marked for deletion can be restored using ``restore`` command, unless they are
permanently deleted.

Specific implementation of deletion is dependent on backend stores. ``FileStore`` moves
experiments marked for deletion under a ``.trash`` folder under the main folder used to
instantiate ``FileStore``. Experiments marked for deletion can be permanently deleted by clearing
the ``.trash`` folder. It is recommended to use a ``cron`` job or an alternate workflow mechanism
to clear ``.trash`` folder.


Restore
~~~~~~~

Restore a deleted experiment. This also applies to experiment's metadata, runs and associated data.
Command takes a required argument for experiment ID. Command will throw an error if experiment is
already active, cannot be found, or permanently deleted.


Python Function
Expand Down
22 changes: 22 additions & 0 deletions mlflow/entities/view_type.py
@@ -1,3 +1,25 @@
class ViewType(object):
"""Enum to qualify `ListExperiments` API query for requested experiment types."""
ACTIVE_ONLY, DELETED_ONLY, ALL = range(1, 4)
_VIEW_TO_STRING = {
ACTIVE_ONLY: "active_only",
DELETED_ONLY: "deleted_only",
ALL: "all",
}
_STRING_TO_VIEW = {value: key for key, value in _VIEW_TO_STRING.items()}

@staticmethod
def from_string(view_str):
if view_str not in ViewType._STRING_TO_VIEW:
raise Exception(
"Could not get valid view type corresponding to string %s. "
"Valid view types are %s" % (view_str, list(ViewType._STRING_TO_VIEW.keys())))
return ViewType._STRING_TO_VIEW[view_str]

@staticmethod
def to_string(view_type):
if view_type not in ViewType._VIEW_TO_STRING:
raise Exception(
"Could not get valid view type corresponding to string %s. "
"Valid view types are %s" % (view_type, list(ViewType._VIEW_TO_STRING.keys())))
return ViewType._VIEW_TO_STRING[view_type]
34 changes: 32 additions & 2 deletions mlflow/experiments.py
Expand Up @@ -6,6 +6,7 @@
from tabulate import tabulate

from mlflow.data import is_uri
from mlflow.entities import ViewType
from mlflow.tracking import _get_store


Expand Down Expand Up @@ -33,12 +34,41 @@ def create(experiment_name, artifact_location):


@commands.command("list")
def list_experiments():
@click.option("--view", "-v", default="active_only",
help="Select view type for list experiments. Valid view types are "
"'active_only' (default), 'deleted_only', and 'all'.")
def list_experiments(view):
"""
List all experiments in the configured tracking server.
"""
store = _get_store()
experiments = store.list_experiments()
view_type = ViewType.from_string(view) if view else ViewType.ACTIVE_ONLY
experiments = store.list_experiments(view_type)
table = [[exp.experiment_id, exp.name, exp.artifact_location if is_uri(exp.artifact_location)
else os.path.abspath(exp.artifact_location)] for exp in experiments]
print(tabulate(sorted(table), headers=["Experiment Id", "Name", "Artifact Location"]))


@commands.command("delete")
@click.argument("experiment_id")
def delete_experiment(experiment_id):
"""
Marks experiment for deletion. This command will error out if experiment does not exist or
is already marked. Experiments marked this way can be restored with restore_experiment,
or permanently deleted based on the backend store (refer to docs for details).
"""
store = _get_store()
store.delete_experiment(experiment_id)
print("Experiment with id %s has been deleted." % str(experiment_id))


@commands.command("restore")
@click.argument("experiment_id")
def restore_experiment(experiment_id):
"""
Restore a deleted experiment.
This command will error out if experiment is already active or has been permanently deleted.
"""
store = _get_store()
store.restore_experiment(experiment_id)
print("Experiment with id %s has been restored." % str(experiment_id))