exp: Generate a human-readable name beforehand.

- Add `get_random_exp_name` to utils.
Generates a name (`f"{adjective}-{noun}"`) by randomly chosing pairs of adjetive, noun.
Recieves `scm` and `baseline_rev` and retries the random choice until a non-existing ref is found.

Closes https://github.com/iterative/dvc/issues/8650
This commit is contained in:
David de la Iglesia Castro
2022-12-09 10:32:38 +01:00
parent 334f297ad3
commit bb7512687c
6 changed files with 67 additions and 24 deletions
+9 -18
View File
@@ -32,7 +32,7 @@ from .refs import (
ExpRefInfo,
)
from .stash import ExpStashEntry
from .utils import exp_refs_by_rev, unlocked_repo
from .utils import check_ref_format, exp_refs_by_rev, unlocked_repo
logger = logging.getLogger(__name__)
@@ -236,17 +236,6 @@ class Experiments:
"\tdvc exp branch <exp> <branch>\n"
)
def _validate_new_ref(self, exp_ref: ExpRefInfo):
from .utils import check_ref_format
if not exp_ref.name:
return
check_ref_format(self.scm, exp_ref)
if self.scm.get_ref(str(exp_ref)):
raise ExperimentExistsError(exp_ref.name)
def new(
self,
queue: BaseStashQueue,
@@ -265,13 +254,15 @@ class Experiments:
name = kwargs.get("name", None)
baseline_sha = kwargs.get("baseline_rev") or self.repo.scm.get_rev()
exp_ref = ExpRefInfo(baseline_sha=baseline_sha, name=name)
try:
self._validate_new_ref(exp_ref)
except ExperimentExistsError as err:
if not (kwargs.get("force", False) or kwargs.get("reset", False)):
raise err
if name:
exp_ref = ExpRefInfo(baseline_sha=baseline_sha, name=name)
check_ref_format(self.scm, exp_ref)
force = kwargs.get("force", False)
reset = kwargs.get("reset", False)
if self.scm.get_ref(str(exp_ref)) and not (force or reset):
raise ExperimentExistsError(exp_ref.name)
return queue.put(*args, **kwargs)
def _resume_checkpoint(
+11 -4
View File
@@ -30,7 +30,13 @@ from ..executor.base import BaseExecutor, ExecutorResult
from ..executor.local import WorkspaceExecutor
from ..refs import ExpRefInfo
from ..stash import ExpStash, ExpStashEntry
from ..utils import EXEC_PID_DIR, EXEC_TMP_DIR, exp_refs_by_rev, get_exp_rwlock
from ..utils import (
EXEC_PID_DIR,
EXEC_TMP_DIR,
exp_refs_by_rev,
get_exp_rwlock,
get_random_exp_name,
)
from .utils import get_remote_executor_refs
if TYPE_CHECKING:
@@ -281,7 +287,7 @@ class BaseStashQueue(ABC):
output.
"""
def _stash_exp(
def _stash_exp( # noqa: C901
self,
*args,
params: Optional[Dict[str, List[str]]] = None,
@@ -399,8 +405,9 @@ class BaseStashQueue(ABC):
run_env = {
DVC_EXP_BASELINE_REV: baseline_rev,
}
if name:
run_env[DVC_EXP_NAME] = name
if not name:
name = get_random_exp_name(self.scm, baseline_rev)
run_env[DVC_EXP_NAME] = name
if resume_rev:
run_env[DVCLIVE_RESUME] = "1"
self._pack_args(*args, run_env=run_env, **kwargs)
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -684,7 +684,7 @@ def test_experiments_workspace_not_log_exception(caplog, dvc, scm):
assert not caplog.text
def test_run_env(tmp_dir, dvc, scm):
def test_run_env(tmp_dir, dvc, scm, mocker):
dump_run_env = dedent(
"""\
import os
@@ -703,7 +703,7 @@ def test_run_env(tmp_dir, dvc, scm):
)
dvc.experiments.run()
assert (tmp_dir / "DVC_EXP_BASELINE_REV").read_text().strip() == baseline
assert (tmp_dir / "DVC_EXP_NAME").read_text().strip() == ""
assert (tmp_dir / "DVC_EXP_NAME").read_text().strip() != ""
dvc.experiments.run(name="foo")
assert (tmp_dir / "DVC_EXP_BASELINE_REV").read_text().strip() == baseline
+1
View File
@@ -220,6 +220,7 @@ def test_show_failed_experiment(tmp_dir, scm, dvc, failed_exp_stage):
"msg": "Experiment run failed.",
"type": "",
},
"name": ANY,
}
}
+29
View File
@@ -0,0 +1,29 @@
from funcy import first
def test_generate_random_exp_name(tmp_dir, dvc, scm, exp_stage, mocker):
mocker.patch(
"dvc.repo.experiments.utils.random.choice",
side_effect=[
0,
0,
0,
0,
1,
1,
0,
0,
],
)
ref = first(dvc.experiments.run(exp_stage.addressing, params=["foo=1"]))
assert dvc.experiments.get_exact_name([ref])[ref] == "0-0"
# Causes 1 retry
ref = first(dvc.experiments.run(exp_stage.addressing, params=["foo=2"]))
assert dvc.experiments.get_exact_name([ref])[ref] == "1-1"
tmp_dir.scm_gen({"foo": "bar"}, commit="foo")
# Can use same name because of different baseline_rev
ref = first(dvc.experiments.run(exp_stage.addressing, params=["foo=1"]))
assert dvc.experiments.get_exact_name([ref])[ref] == "0-0"