Skip to content

Commit 8babe24

Browse files
authored
Merge pull request #770 from doringeman/uninstall-runner-for-deferred-backends
feat(backends): add Uninstall method to Backend interface and uninstall-backend endpoint
2 parents 36e01bc + 72809c5 commit 8babe24

16 files changed

Lines changed: 193 additions & 4 deletions

File tree

cmd/cli/commands/uninstall-runner.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,21 @@ import (
1414
type cleanupOptions struct {
1515
models bool
1616
removeImages bool
17+
backend string
1718
}
1819

1920
// runUninstallOrStop is shared logic for uninstall-runner and stop-runner commands
2021
func runUninstallOrStop(cmd *cobra.Command, opts cleanupOptions) error {
22+
// Deferred backend uninstall is handled via the running model runner API
23+
// and works in any context (Desktop, Moby, etc.), so handle it first.
24+
if opts.backend != "" {
25+
if err := desktopClient.UninstallBackend(opts.backend); err != nil {
26+
return fmt.Errorf("failed to uninstall %s backend: %w", opts.backend, err)
27+
}
28+
cmd.Printf("Uninstalled %s backend\n", opts.backend)
29+
return nil
30+
}
31+
2132
// Ensure that we're running in a supported model runner context.
2233
if kind := modelRunner.EngineKind(); kind == types.ModelRunnerEngineKindDesktop {
2334
if desktop.IsDesktopWSLContext(cmd.Context(), dockerCLI) {
@@ -62,18 +73,21 @@ func runUninstallOrStop(cmd *cobra.Command, opts cleanupOptions) error {
6273

6374
func newUninstallRunner() *cobra.Command {
6475
var models, images bool
76+
var backend string
6577
c := &cobra.Command{
6678
Use: "uninstall-runner",
6779
Short: "Uninstall Docker Model Runner (Docker Engine only)",
6880
RunE: func(cmd *cobra.Command, args []string) error {
6981
return runUninstallOrStop(cmd, cleanupOptions{
7082
models: models,
7183
removeImages: images,
84+
backend: backend,
7285
})
7386
},
7487
ValidArgsFunction: completion.NoComplete,
7588
}
7689
c.Flags().BoolVar(&models, "models", false, "Remove model storage volume")
7790
c.Flags().BoolVar(&images, "images", false, "Remove "+standalone.ControllerImage+" images")
91+
c.Flags().StringVar(&backend, "backend", "", "Uninstall a deferred backend (e.g. vllm, diffusers)")
7892
return c
7993
}

cmd/cli/desktop/desktop.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -895,6 +895,30 @@ func (c *Client) InstallBackend(backend string) error {
895895
return nil
896896
}
897897

898+
// UninstallBackend removes a backend's local installation via the model runner API.
899+
func (c *Client) UninstallBackend(backend string) error {
900+
uninstallPath := inference.InferencePrefix + "/uninstall-backend"
901+
jsonData, err := json.Marshal(struct {
902+
Backend string `json:"backend"`
903+
}{Backend: backend})
904+
if err != nil {
905+
return fmt.Errorf("error marshaling request: %w", err)
906+
}
907+
908+
resp, err := c.doRequest(http.MethodPost, uninstallPath, bytes.NewReader(jsonData))
909+
if err != nil {
910+
return c.handleQueryError(err, uninstallPath)
911+
}
912+
defer resp.Body.Close()
913+
914+
if resp.StatusCode != http.StatusOK {
915+
body, _ := io.ReadAll(resp.Body)
916+
return fmt.Errorf("uninstall backend failed with status %s: %s", resp.Status, string(body))
917+
}
918+
919+
return nil
920+
}
921+
898922
func (c *Client) ConfigureBackend(request scheduling.ConfigureRequest) error {
899923
configureBackendPath := inference.InferencePrefix + "/_configure"
900924
jsonData, err := json.Marshal(request)

cmd/cli/docs/reference/docker_model_uninstall-runner.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,15 @@ usage: docker model uninstall-runner
55
pname: docker model
66
plink: docker_model.yaml
77
options:
8+
- option: backend
9+
value_type: string
10+
description: Uninstall a deferred backend (e.g. vllm, diffusers)
11+
deprecated: false
12+
hidden: false
13+
experimental: false
14+
experimentalcli: false
15+
kubernetes: false
16+
swarm: false
817
- option: images
918
value_type: bool
1019
default_value: "false"

cmd/cli/docs/reference/model_uninstall-runner.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@ Uninstall Docker Model Runner (Docker Engine only)
55

66
### Options
77

8-
| Name | Type | Default | Description |
9-
|:-----------|:-------|:--------|:----------------------------------|
10-
| `--images` | `bool` | | Remove docker/model-runner images |
11-
| `--models` | `bool` | | Remove model storage volume |
8+
| Name | Type | Default | Description |
9+
|:------------|:---------|:--------|:----------------------------------------------------|
10+
| `--backend` | `string` | | Uninstall a deferred backend (e.g. vllm, diffusers) |
11+
| `--images` | `bool` | | Remove docker/model-runner images |
12+
| `--models` | `bool` | | Remove model storage volume |
1213

1314

1415
<!---MARKER_GEN_END-->

pkg/inference/backend.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,10 @@ type Backend interface {
314314
// instead load only the specified model. Backends should still respond to
315315
// OpenAI API requests for other models with a 421 error code.
316316
Run(ctx context.Context, socket, model string, modelRef string, mode BackendMode, config *BackendConfiguration) error
317+
// Uninstall removes backend-specific local installations (e.g. files
318+
// downloaded to ~/.docker/model-runner/). Backends with nothing to clean
319+
// up should return nil.
320+
Uninstall() error
317321
// Status returns a description of the backend's state.
318322
Status() string
319323
// GetDiskUsage returns the disk usage of the backend.

pkg/inference/backends/diffusers/diffusers.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,16 @@ func (d *diffusers) Run(ctx context.Context, socket, model string, modelRef stri
264264
}
265265

266266
// Status implements inference.Backend.Status.
267+
// Uninstall implements inference.Backend.Uninstall.
268+
func (d *diffusers) Uninstall() error {
269+
if err := os.RemoveAll(d.installDir); err != nil {
270+
return fmt.Errorf("failed to remove diffusers install directory: %w", err)
271+
}
272+
d.pythonPath = ""
273+
d.status = inference.FormatNotInstalled("")
274+
return nil
275+
}
276+
267277
func (d *diffusers) Status() string {
268278
return d.status
269279
}

pkg/inference/backends/llamacpp/llamacpp.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,11 @@ func (l *llamaCpp) Run(ctx context.Context, socket, model string, _ string, mode
183183
})
184184
}
185185

186+
// Uninstall implements inference.Backend.Uninstall.
187+
func (l *llamaCpp) Uninstall() error {
188+
return nil
189+
}
190+
186191
func (l *llamaCpp) Status() string {
187192
return l.status
188193
}

pkg/inference/backends/mlx/mlx.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,11 @@ func (m *mlx) Run(ctx context.Context, socket, model string, modelRef string, mo
147147
})
148148
}
149149

150+
// Uninstall implements inference.Backend.Uninstall.
151+
func (m *mlx) Uninstall() error {
152+
return nil
153+
}
154+
150155
func (m *mlx) Status() string {
151156
return m.status
152157
}

pkg/inference/backends/sglang/sglang.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,11 @@ func (s *sglang) Run(ctx context.Context, socket, model string, modelRef string,
176176
})
177177
}
178178

179+
// Uninstall implements inference.Backend.Uninstall.
180+
func (s *sglang) Uninstall() error {
181+
return nil
182+
}
183+
179184
func (s *sglang) Status() string {
180185
return s.status
181186
}

pkg/inference/backends/vllm/vllm.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,11 @@ func (v *vLLM) Run(ctx context.Context, socket, model string, modelRef string, m
187187
})
188188
}
189189

190+
// Uninstall implements inference.Backend.Uninstall.
191+
func (v *vLLM) Uninstall() error {
192+
return nil
193+
}
194+
190195
func (v *vLLM) Status() string {
191196
return v.status
192197
}

0 commit comments

Comments
 (0)