Skip to content

Commit e5954a3

Browse files
author
Andrey Cheptsov
committed
Improve endpoint preset apply output
1 parent ce01650 commit e5954a3

5 files changed

Lines changed: 25 additions & 13 deletions

File tree

mkdocs/docs/concepts/endpoints.md

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,19 @@ To deploy a preset as a service, pass the endpoint configuration to the `dstack
117117

118118
```shell
119119
$ dstack endpoint preset apply -f endpoint.dstack.yml
120+
Preset Qwen/Qwen2.5-7B-Instruct (recipe=8f3a12c4)
121+
122+
# BACKEND RESOURCES INSTANCE TYPE PRICE
123+
1 runpod (CA-MTL-1) cpu=9 mem=50GB disk=200GB NVIDIA RTX A5000 $0.27
124+
gpu=A5000:24GB:1
125+
2 runpod (CA-MTL-1) cpu=9 mem=50GB disk=200GB NVIDIA RTX A5000 $0.27
126+
gpu=A5000:24GB:1 (spot)
127+
3 runpod (US-IL-1) cpu=12 mem=25GB disk=200GB NVIDIA RTX A5000 $0.27
128+
gpu=A5000:24GB:1
129+
...
130+
Shown 3 of 4 offers, $0.27max
131+
132+
Submit the run qwen25-7b? [y/n]: y
120133
```
121134

122135
</div>
@@ -132,7 +145,7 @@ You can delete a specific recipe or the entire preset.
132145
<div class="termy">
133146

134147
```shell
135-
dstack endpoint preset delete --recipe 8f3a12c4
148+
$ dstack endpoint preset delete --recipe 8f3a12c4
136149
```
137150

138151
</div>
@@ -142,7 +155,7 @@ To delete the entire preset and all its recipes, pass the base model:
142155
<div class="termy">
143156

144157
```shell
145-
dstack endpoint preset delete Qwen/Qwen2.5-7B-Instruct
158+
$ dstack endpoint preset delete Qwen/Qwen2.5-7B-Instruct
146159
```
147160

148161
</div>

src/dstack/_internal/cli/services/configurators/run.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ def apply_prepared_configuration(
158158
prepared: PreparedRunConfiguration[RunConfigurationT],
159159
command_args: argparse.Namespace,
160160
configurator_args: argparse.Namespace,
161+
plan_properties: Optional[Dict[str, str]] = None,
161162
):
162163
conf = prepared.configuration
163164
repo = prepared.repo
@@ -173,6 +174,7 @@ def apply_prepared_configuration(
173174
max_offers=configurator_args.max_offers,
174175
no_fleets=no_fleets,
175176
verbose=command_args.verbose,
177+
extra_properties=plan_properties,
176178
)
177179

178180
confirm_message = "Submit a new run?"

src/dstack/_internal/cli/services/endpoint_preset_apply.py

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,13 @@
22
from dataclasses import dataclass
33
from typing import Optional
44

5-
from rich.table import Table
5+
from rich.markup import escape
66

77
from dstack._internal.cli.services.configurators.run import (
88
PreparedRunConfiguration,
99
ServiceConfigurator,
1010
)
1111
from dstack._internal.cli.services.endpoint_presets import EndpointPresetStore
12-
from dstack._internal.cli.utils.common import console
1312
from dstack._internal.core.errors import CLIError
1413
from dstack._internal.core.models.configurations import ServiceConfiguration
1514
from dstack._internal.core.models.endpoint_presets import EndpointPresetRecipe
@@ -56,11 +55,11 @@ def apply_endpoint_preset(
5655
configurator=configurator,
5756
service_args=service_args,
5857
)
59-
_print_selected_recipe(selected.recipe)
6058
configurator.apply_prepared_configuration(
6159
prepared=selected.prepared,
6260
command_args=command_args,
6361
configurator_args=service_args,
62+
plan_properties={"Preset": _format_selected_recipe(selected.recipe)},
6463
)
6564

6665

@@ -137,11 +136,5 @@ def _has_available_offers(plan: RunPlan) -> bool:
137136
)
138137

139138

140-
def _print_selected_recipe(recipe: EndpointPresetRecipe) -> None:
141-
table = Table(box=None, show_header=False)
142-
table.add_column(no_wrap=True)
143-
table.add_column()
144-
table.add_row("[bold]Preset[/]", recipe.base)
145-
table.add_row("[bold]Recipe[/]", recipe.id)
146-
console.print(table)
147-
console.print()
139+
def _format_selected_recipe(recipe: EndpointPresetRecipe) -> str:
140+
return f"{escape(recipe.base)} ([secondary]recipe={escape(recipe.id)}[/])"

src/dstack/_internal/cli/utils/run.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ def print_run_plan(
100100
no_fleets: bool = False,
101101
verbose: bool = False,
102102
show_offer_fleet_hint: bool = False,
103+
extra_properties: Optional[Dict[str, str]] = None,
103104
):
104105
run_spec = run_plan.get_effective_run_spec()
105106
job_plan = run_plan.job_plans[0]
@@ -170,6 +171,8 @@ def th(s: str) -> str:
170171
props.add_row(th("Inactivity duration"), inactivity_duration)
171172
if verbose or run_spec.configuration.reservation:
172173
props.add_row(th("Reservation"), run_spec.configuration.reservation or "no")
174+
for key, value in (extra_properties or {}).items():
175+
props.add_row(th(key), value)
173176

174177
offers = Table(box=None, expand=shutil.get_terminal_size(fallback=(120, 40)).columns <= 110)
175178
offers.add_column("#")

src/tests/_internal/cli/services/test_endpoint_preset_apply.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ def test_applies_the_selected_prepared_plan(self, monkeypatch):
132132
prepared=prepared,
133133
command_args=command_args,
134134
configurator_args=configurator.get_parser.return_value.parse_args.return_value,
135+
plan_properties={"Preset": "Qwen/Qwen3.5-27B ([secondary]recipe=8f3a12c4[/])"},
135136
)
136137

137138

0 commit comments

Comments
 (0)