Skip to content
This repository was archived by the owner on Aug 11, 2020. It is now read-only.

Commit f5e060d

Browse files
BartoszCkikossak
authored andcommitted
Add new hyperparameters commands - createAndStart, delete, details, start
1 parent 20f5ef2 commit f5e060d

File tree

5 files changed

+517
-49
lines changed

5 files changed

+517
-49
lines changed

paperspace/cli/hyperparameters.py

Lines changed: 107 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import functools
2+
13
import click
24

35
from paperspace import client, config
@@ -12,55 +14,62 @@ def hyperparameters_group():
1214
pass
1315

1416

17+
def common_hyperparameter_create_options(f):
18+
options = [
19+
click.option(
20+
"--name",
21+
"name",
22+
required=True,
23+
),
24+
click.option(
25+
"--projectId",
26+
"projectHandle",
27+
required=True,
28+
),
29+
click.option(
30+
"--tuningCommand",
31+
"tuningCommand",
32+
required=True,
33+
),
34+
click.option(
35+
"--workerContainer",
36+
"workerContainer",
37+
required=True,
38+
),
39+
click.option(
40+
"--workerMachineType",
41+
"workerMachineType",
42+
required=True,
43+
),
44+
click.option(
45+
"--workerCommand",
46+
"workerCommand",
47+
required=True,
48+
),
49+
click.option(
50+
"--workerCount",
51+
"workerCount",
52+
required=True,
53+
type=int,
54+
),
55+
click.option(
56+
"--serverRegistryUsername",
57+
"hyperparameterServerRegistryUsername",
58+
),
59+
click.option(
60+
"--serverRegistryPassword",
61+
"hyperparameterServerRegistryPassword",
62+
),
63+
click.option(
64+
"--serverContainerUser",
65+
"hyperparameterServerContainerUser",
66+
),
67+
]
68+
return functools.reduce(lambda x, opt: opt(x), reversed(options), f)
69+
70+
1571
@hyperparameters_group.command("create", help="Create hyperparameter")
16-
@click.option(
17-
"--name",
18-
"name",
19-
required=True,
20-
)
21-
@click.option(
22-
"--projectId",
23-
"projectHandle",
24-
required=True,
25-
)
26-
@click.option(
27-
"--tuningCommand",
28-
"tuningCommand",
29-
required=True,
30-
)
31-
@click.option(
32-
"--workerContainer",
33-
"workerContainer",
34-
required=True,
35-
)
36-
@click.option(
37-
"--workerMachineType",
38-
"workerMachineType",
39-
required=True,
40-
)
41-
@click.option(
42-
"--workerCommand",
43-
"workerCommand",
44-
required=True,
45-
)
46-
@click.option(
47-
"--workerCount",
48-
"workerCount",
49-
required=True,
50-
type=int,
51-
)
52-
@click.option(
53-
"--serverRegistryUsername",
54-
"hyperparameterServerRegistryUsername",
55-
)
56-
@click.option(
57-
"--serverRegistryPassword",
58-
"hyperparameterServerRegistryPassword",
59-
)
60-
@click.option(
61-
"--serverContainerUser",
62-
"hyperparameterServerContainerUser",
63-
)
72+
@common_hyperparameter_create_options
6473
@common.api_key_option
6574
def create_hyperparameter(api_key, **hyperparameter):
6675
common.del_if_value_is_none(hyperparameter)
@@ -69,9 +78,59 @@ def create_hyperparameter(api_key, **hyperparameter):
6978
command.execute(hyperparameter)
7079

7180

81+
@hyperparameters_group.command("createAndStart", help="Create hyperparameter")
82+
@common_hyperparameter_create_options
83+
@common.api_key_option
84+
def create_and_start_hyperparameter(api_key, **hyperparameter):
85+
common.del_if_value_is_none(hyperparameter)
86+
hyperparameters_api = client.API(config.CONFIG_EXPERIMENTS_HOST, api_key=api_key)
87+
command = hyperparameters_commands.CreateAndStartHyperparameterCommand(api=hyperparameters_api)
88+
command.execute(hyperparameter)
89+
90+
7291
@hyperparameters_group.command("list", help="List hyperparameters")
7392
@common.api_key_option
7493
def create_hyperparameter(api_key):
7594
hyperparameters_api = client.API(config.CONFIG_EXPERIMENTS_HOST, api_key=api_key)
7695
command = hyperparameters_commands.ListHyperparametersCommand(api=hyperparameters_api)
7796
command.execute()
97+
98+
99+
# TODO: 'unhidden' command and test it when api is updated to support deleting hyperparameters
100+
@hyperparameters_group.command("delete", help="Delete hyperparameter", hidden=True)
101+
@click.option(
102+
"--id",
103+
"id_",
104+
required=True,
105+
)
106+
@common.api_key_option
107+
def delete_hyperparameter(api_key, id_):
108+
hyperparameters_api = client.API(config.CONFIG_EXPERIMENTS_HOST, api_key=api_key)
109+
command = hyperparameters_commands.DeleteHyperparameterCommand(api=hyperparameters_api)
110+
command.execute(id_)
111+
112+
113+
@hyperparameters_group.command("details", help="Show details of hyperparameter")
114+
@click.option(
115+
"--id",
116+
"id_",
117+
required=True,
118+
)
119+
@common.api_key_option
120+
def get_hyperparameter_details(api_key, id_):
121+
hyperparameters_api = client.API(config.CONFIG_EXPERIMENTS_HOST, api_key=api_key)
122+
command = hyperparameters_commands.HyperparameterDetailsCommand(api=hyperparameters_api)
123+
command.execute(id_)
124+
125+
126+
@hyperparameters_group.command("start", help="Start hyperparameter tuning")
127+
@click.option(
128+
"--id",
129+
"id_",
130+
required=True,
131+
)
132+
@common.api_key_option
133+
def get_hyperparameter_details(api_key, id_):
134+
hyperparameters_api = client.API(config.CONFIG_EXPERIMENTS_HOST, api_key=api_key)
135+
command = hyperparameters_commands.HyperparameterStartCommand(api=hyperparameters_api)
136+
command.execute(id_)

paperspace/client.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,12 @@ def get(self, url, json=None, params=None):
5454
logger.debug("Response status code: {}".format(response.status_code))
5555
logger.debug("Response content: {}".format(response.content))
5656
return response
57+
58+
def delete(self, url, json=None, params=None):
59+
path = self.get_path(url)
60+
response = requests.delete(path, params=params, headers=self.headers, json=json)
61+
logger.debug("DELETE request sent to: {} \n\theaders: {}\n\tjson: {}\n\tparams: {}"
62+
.format(response.url, self.headers, json, params))
63+
logger.debug("Response status code: {}".format(response.status_code))
64+
logger.debug("Response content: {}".format(response.content))
65+
return response

paperspace/commands/hyperparameters.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import terminaltables
2+
13
from paperspace.commands import common
24

35

@@ -27,6 +29,14 @@ def execute(self, hyperparameter):
2729
"Unknown error while creating hyperparameter")
2830

2931

32+
class CreateAndStartHyperparameterCommand(HyperparametersCommandBase):
33+
def execute(self, hyperparameter):
34+
response = self.api.post("/hyperopt/create_and_start/", json=hyperparameter)
35+
self._log_message(response,
36+
"Hyperparameter created with ID: {handle} and started",
37+
"Unknown error while creating hyperparameter")
38+
39+
3040
class ListHyperparametersCommand(common.ListCommand):
3141
@property
3242
def request_url(self):
@@ -49,3 +59,58 @@ def _get_objects(self, response, kwargs):
4959
def _get_request_params(self, kwargs):
5060
params = {"limit": -1}
5161
return params
62+
63+
64+
class DeleteHyperparameterCommand(HyperparametersCommandBase):
65+
def execute(self, id_):
66+
url = "/hyperopt/{}/".format(id_)
67+
response = self.api.delete(url)
68+
self._log_message(response,
69+
"Hyperparameter deleted",
70+
"Unknown error while deleting hyperparameter")
71+
72+
73+
class HyperparameterDetailsCommand(HyperparametersCommandBase):
74+
def execute(self, id_):
75+
url = "/hyperopt/{}/".format(id_)
76+
response = self.api.get(url)
77+
78+
try:
79+
data = response.json()
80+
if not response.ok:
81+
self.logger.log_error_response(data)
82+
return
83+
84+
table = self.make_details_table(data)
85+
except (ValueError, KeyError) as e:
86+
self.logger.error("Error while parsing response data: {}".format(e))
87+
else:
88+
self.logger.log(table)
89+
90+
@staticmethod
91+
def make_details_table(obj):
92+
data = (
93+
("ID", obj["data"].get("handle")),
94+
("Name", obj["data"]["templateHistory"]["params"].get("name")),
95+
("Ports", obj["data"]["templateHistory"]["params"].get("ports")),
96+
("Project ID", obj["data"]["templateHistory"]["params"].get("project_handle")),
97+
("Tuning command", obj["data"]["templateHistory"]["params"].get("tuning_command")),
98+
("Worker command", obj["data"]["templateHistory"]["params"].get("worker_command")),
99+
("Worker container", obj["data"]["templateHistory"]["params"].get("worker_container")),
100+
("Worker count", obj["data"]["templateHistory"]["params"].get("worker_count")),
101+
("Worker machine type", obj["data"]["templateHistory"]["params"].get("worker_machine_type")),
102+
("Worker use dockerfile", obj["data"]["templateHistory"]["params"].get("worker_use_dockerfile")),
103+
("Workspace URL", obj["data"]["templateHistory"]["params"].get("workspaceUrl")),
104+
)
105+
ascii_table = terminaltables.AsciiTable(data)
106+
table_string = ascii_table.table
107+
return table_string
108+
109+
110+
class HyperparameterStartCommand(HyperparametersCommandBase):
111+
def execute(self, id_):
112+
url = "/hyperopt/{}/start/".format(id_)
113+
response = self.api.put(url)
114+
self._log_message(response,
115+
"Hyperparameter tuning started",
116+
"Unknown error while starting hyperparameter tuning")

tests/example_responses.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3293,3 +3293,49 @@
32933293
"totalItems": 15
32943294
}
32953295
}
3296+
3297+
HYPERPARAMETERS_DETAILS_RESPONSE_JSON = {
3298+
"data": {
3299+
"dtCreated": "2019-05-13T10:57:32.828135+00:00",
3300+
"dtDeleted": None,
3301+
"dtFinished": None,
3302+
"dtModified": "2019-05-13T10:57:32.828135+00:00",
3303+
"dtProvisioningFinished": None,
3304+
"dtProvisioningStarted": None,
3305+
"dtStarted": None,
3306+
"dtTeardownFinished": None,
3307+
"dtTeardownStarted": None,
3308+
"experimentError": None,
3309+
"experimentTemplateHistoryId": 45973,
3310+
"experimentTemplateId": 8,
3311+
"experimentTypeId": 4,
3312+
"handle": "ess6t3fjs2hb1g",
3313+
"id": 45966,
3314+
"projectHandle": "pr4yxj956",
3315+
"projectId": 14898,
3316+
"started_by_user_id": 199654,
3317+
"state": 1,
3318+
"templateHistory": {
3319+
"dtCreated": "2019-05-13T10:57:31.592657+00:00",
3320+
"dtDeleted": None,
3321+
"experimentTemplateId": 8,
3322+
"id": 45973,
3323+
"params": {
3324+
"is_preemptible": False,
3325+
"name": "some_name",
3326+
"ports": 5000,
3327+
"project_handle": "pr4yxj956",
3328+
"tuning_command": "some command",
3329+
"worker_command": "some worker command",
3330+
"worker_container": "some_container",
3331+
"worker_count": 1,
3332+
"worker_machine_type": "k80",
3333+
"worker_use_dockerfile": False,
3334+
"workspaceUrl": "none"
3335+
},
3336+
"triggerEvent": None,
3337+
"triggerEventId": None
3338+
}
3339+
},
3340+
"message": "success"
3341+
}

0 commit comments

Comments
 (0)