Skip to content

Commit

Permalink
feat: Add template to py sdk create_experiment (#8927)
Browse files Browse the repository at this point in the history
  • Loading branch information
gt2345 authored Mar 20, 2024
1 parent 5ac1b85 commit 4441d6d
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 27 deletions.
66 changes: 46 additions & 20 deletions e2e_tests/tests/test_sdk.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import os
import pathlib
import random
import shutil
import tempfile
import time

import pytest
Expand All @@ -14,20 +13,17 @@


@pytest.mark.e2e_cpu
def test_completed_experiment_and_checkpoint_apis() -> None:
def test_completed_experiment_and_checkpoint_apis(tmp_path: pathlib.Path) -> None:
sess = api_utils.user_session()
detobj = client.Determined._from_session(sess)

with open(conf.fixtures_path("no_op/single-one-short-step.yaml")) as f:
config = util.yaml_safe_load(f)
config["hyperparameters"]["num_validation_metrics"] = 2
# Test the use of the includes parameter, by feeding the model definition file via includes.
emptydir = tempfile.mkdtemp()
try:
model_def = conf.fixtures_path("no_op/model_def.py")
exp = detobj.create_experiment(config, emptydir, includes=[model_def])
finally:
os.rmdir(emptydir)
emptydir = tmp_path
model_def = conf.fixtures_path("no_op/model_def.py")
exp = detobj.create_experiment(config, emptydir, includes=[model_def])
exp = detobj.create_experiment(config, conf.fixtures_path("no_op"))

# Await first trial is safe to call before a trial has started.
Expand Down Expand Up @@ -94,7 +90,7 @@ def test_completed_experiment_and_checkpoint_apis() -> None:


@pytest.mark.e2e_cpu
def test_checkpoint_apis() -> None:
def test_checkpoint_apis(tmp_path: pathlib.Path) -> None:
sess = api_utils.user_session()
detobj = client.Determined._from_session(sess)
with open(conf.fixtures_path("no_op/single-default-ckpt.yaml")) as f:
Expand Down Expand Up @@ -215,16 +211,10 @@ def test_checkpoint_apis() -> None:
assert "workload_sequencer.pkl" not in partially_deleted_checkpoints[0].resources

# Ensure we can download the partially deleted checkpoint.
temp_dir = tempfile.mkdtemp()
try:
downloaded_path = partially_deleted_checkpoints[0].download(
path=os.path.join(temp_dir, "c")
)
files = os.listdir(downloaded_path)
assert "no_op_checkpoint" in files
assert "workload_sequencer.pkl" not in files
finally:
shutil.rmtree(temp_dir, ignore_errors=False)
downloaded_path = partially_deleted_checkpoints[0].download(path=os.path.join(tmp_path, "c"))
files = os.listdir(downloaded_path)
assert "no_op_checkpoint" in files
assert "workload_sequencer.pkl" not in files

# Ensure we can delete a partially deleted checkpoint.
partially_deleted_checkpoints[0].delete()
Expand Down Expand Up @@ -474,3 +464,39 @@ def test_rp_workspace_mapping() -> None:
finally:
for wid in workspace_ids:
bindings.delete_DeleteWorkspace(session=sess, id=wid)


@pytest.mark.e2e_cpu
def test_create_experiment_w_template(tmp_path: pathlib.Path) -> None:
# Create a minimal experiment with a simple template
# Wait until a trial has started to ensure experiment creation has no errors
# Verify that the content in template is indeed applied
sess = api_utils.user_session()
detobj = client.Determined._from_session(sess)
template_name = "test_template"
template_config_key = "description"
template_config_value = "test_sdk_template"
try:
# create template
template_config = conf.load_config(conf.fixtures_path("templates/template.yaml"))
template_config[template_config_key] = template_config_value
tpl = bindings.v1Template(
name=template_name,
config=template_config,
workspaceId=1,
)
tpl_resp = bindings.post_PostTemplate(sess, body=tpl, template_name=tpl.name)
# create experiment with template
with open(conf.fixtures_path("no_op/single-one-short-step.yaml")) as f:
config = util.yaml_safe_load(f)
model_def = conf.fixtures_path("no_op/model_def.py")
exp = detobj.create_experiment(
config, tmp_path, includes=[model_def], template=tpl_resp.template.name
)
exp.await_first_trial()

assert exp.config is not None
assert exp.config[template_config_key] == template_config_value, exp.config

finally:
bindings.delete_DeleteTemplate(sess, templateName=template_name)
20 changes: 15 additions & 5 deletions harness/determined/common/experimental/determined.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ def create_experiment(
config: Union[str, pathlib.Path, Dict],
model_dir: Optional[Union[str, pathlib.Path]] = None,
includes: Optional[Iterable[Union[str, pathlib.Path]]] = None,
parent_id: Optional[int] = None,
project_id: Optional[int] = None,
template: Optional[str] = None,
) -> experiment.Experiment:
"""
Create an experiment with config parameters and model directory. The function
Expand All @@ -134,8 +137,15 @@ def create_experiment(
config(string, pathlib.Path, dictionary): experiment config filename (.yaml)
or a dict.
model_dir(string, optional): directory containing model definition. (default: ``None``)
includes (Iterable[Union[str, pathlib.Path]], optional): Additional files or
directories to include in the model definition. (default: ``None``)
includes(Iterable[Union[str, pathlib.Path]], optional): Additional files or
directories to include in the model definition. (default: ``None``)
parent_id(int, optional): If specified, the created experiment will use the model
definition from the parent experiment. (default: ``None``)
project_id(int, optional): The id of the project this experiment should belong to.
(default: ``None``)
template(string, optional): The name of the template for the experiment.
See :ref:`config-template` for moredetails.
(default: ``None``)
"""
if isinstance(config, str):
with open(config) as f:
Expand Down Expand Up @@ -166,9 +176,9 @@ def create_experiment(
activate=True,
config=config_text,
modelDefinition=model_context,
# TODO: add these as params to create_experiment()
parentId=None,
projectId=None,
parentId=parent_id,
projectId=project_id,
template=template,
)

resp = bindings.post_CreateExperiment(self._session, body=req)
Expand Down
14 changes: 12 additions & 2 deletions harness/determined/experimental/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,19 +168,29 @@ def create_experiment(
config: Union[str, pathlib.Path, Dict],
model_dir: Optional[str] = None,
includes: Optional[Iterable[Union[str, pathlib.Path]]] = None,
parent_id: Optional[int] = None,
project_id: Optional[int] = None,
template: Optional[str] = None,
) -> Experiment:
"""Create an experiment with config parameters and model directory.
Args:
config: Experiment config filename (.yaml) or a dict.
model_dir: Directory containing model definition.
iterables: Additional files or directories to include in the model definition.
includes: Additional files or directories to include in the model definition.
parent_id: If specified, the created experiment will use the model definition
from the parent experiment.
project_id: The id of the project this experiment should belong to.
template: The name of the template for the experiment.
See :ref:`config-template` for more details.
Returns:
An :class:`~determined.experimental.client.Experiment` of the created experiment.
"""
assert _determined is not None
return _determined.create_experiment(config, model_dir, includes)
return _determined.create_experiment(
config, model_dir, includes, parent_id, project_id, template
)


@_require_singleton
Expand Down

0 comments on commit 4441d6d

Please sign in to comment.