Skip to content

Commit b330b1c

Browse files
committed
Add --detach flag to docker model run command
So we can load models in the background without interaction Signed-off-by: Eric Curtin <eric.curtin@docker.com>
1 parent 38a800e commit b330b1c

4 files changed

Lines changed: 101 additions & 10 deletions

File tree

cmd/cli/commands/run.go

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@ func newRunCmd() *cobra.Command {
307307
var backend string
308308
var ignoreRuntimeMemoryCheck bool
309309
var colorMode string
310+
var detach bool
310311

311312
const cmdArgs = "MODEL [PROMPT]"
312313
c := &cobra.Command{
@@ -341,17 +342,20 @@ func newRunCmd() *cobra.Command {
341342
prompt = strings.Join(args[1:], " ")
342343
}
343344

344-
fi, err := os.Stdin.Stat()
345-
if err == nil && (fi.Mode()&os.ModeCharDevice) == 0 {
346-
// Read all from stdin
347-
reader := bufio.NewReader(os.Stdin)
348-
input, err := io.ReadAll(reader)
349-
if err == nil {
350-
if prompt != "" {
351-
prompt += "\n\n"
345+
// Only read from stdin if not in detach mode
346+
if !detach {
347+
fi, err := os.Stdin.Stat()
348+
if err == nil && (fi.Mode()&os.ModeCharDevice) == 0 {
349+
// Read all from stdin
350+
reader := bufio.NewReader(os.Stdin)
351+
input, err := io.ReadAll(reader)
352+
if err == nil {
353+
if prompt != "" {
354+
prompt += "\n\n"
355+
}
356+
357+
prompt += string(input)
352358
}
353-
354-
prompt += string(input)
355359
}
356360
}
357361

@@ -381,6 +385,21 @@ func newRunCmd() *cobra.Command {
381385
}
382386
}
383387

388+
// Handle --detach flag: just load the model without interaction
389+
if detach {
390+
// Make a minimal request to load the model into memory
391+
err := desktopClient.Chat(backend, model, "", apiKey, func(content string) {
392+
// Silently discard output in detach mode
393+
}, false)
394+
if err != nil {
395+
return handleClientError(err, "Failed to load model")
396+
}
397+
if debug {
398+
cmd.Printf("Model %s loaded successfully\n", model)
399+
}
400+
return nil
401+
}
402+
384403
if prompt != "" {
385404
if err := chatWithMarkdown(cmd, desktopClient, backend, model, prompt, apiKey); err != nil {
386405
return handleClientError(err, "Failed to generate a response")
@@ -439,6 +458,7 @@ func newRunCmd() *cobra.Command {
439458
c.Flags().MarkHidden("backend")
440459
c.Flags().BoolVar(&ignoreRuntimeMemoryCheck, "ignore-runtime-memory-check", false, "Do not block pull if estimated runtime memory for model exceeds system resources.")
441460
c.Flags().StringVar(&colorMode, "color", "auto", "Use colored output (auto|yes|no)")
461+
c.Flags().BoolVarP(&detach, "detach", "d", false, "Load the model in the background without interaction")
442462

443463
return c
444464
}

cmd/cli/commands/run_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,3 +113,46 @@ func TestReadMultilineInputUnclosed(t *testing.T) {
113113
t.Errorf("readMultilineInput() error should mention unclosed multiline input, got: %v", err)
114114
}
115115
}
116+
117+
func TestRunCmdDetachFlag(t *testing.T) {
118+
// Create the run command
119+
cmd := newRunCmd()
120+
121+
// Verify the --detach flag exists
122+
detachFlag := cmd.Flags().Lookup("detach")
123+
if detachFlag == nil {
124+
t.Fatal("--detach flag not found")
125+
}
126+
127+
// Verify the shorthand flag exists
128+
detachFlagShort := cmd.Flags().ShorthandLookup("d")
129+
if detachFlagShort == nil {
130+
t.Fatal("-d shorthand flag not found")
131+
}
132+
133+
// Verify the default value is false
134+
if detachFlag.DefValue != "false" {
135+
t.Errorf("Expected default detach value to be 'false', got '%s'", detachFlag.DefValue)
136+
}
137+
138+
// Verify the flag type
139+
if detachFlag.Value.Type() != "bool" {
140+
t.Errorf("Expected detach flag type to be 'bool', got '%s'", detachFlag.Value.Type())
141+
}
142+
143+
// Test setting the flag value
144+
err := cmd.Flags().Set("detach", "true")
145+
if err != nil {
146+
t.Errorf("Failed to set detach flag: %v", err)
147+
}
148+
149+
// Verify the value was set
150+
detachValue, err := cmd.Flags().GetBool("detach")
151+
if err != nil {
152+
t.Errorf("Failed to get detach flag value: %v", err)
153+
}
154+
155+
if !detachValue {
156+
t.Errorf("Expected detach flag value to be true, got false")
157+
}
158+
}

cmd/cli/docs/reference/docker_model_run.yaml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,17 @@ options:
3939
experimentalcli: false
4040
kubernetes: false
4141
swarm: false
42+
- option: detach
43+
shorthand: d
44+
value_type: bool
45+
default_value: "false"
46+
description: Load the model in the background without interaction
47+
deprecated: false
48+
hidden: false
49+
experimental: false
50+
experimentalcli: false
51+
kubernetes: false
52+
swarm: false
4253
- option: ignore-runtime-memory-check
4354
value_type: bool
4455
default_value: "false"
@@ -78,6 +89,14 @@ examples: |-
7889
> /bye
7990
Chat session ended.
8091
```
92+
93+
### Pre-load a model
94+
95+
```console
96+
docker model run --detach ai/smollm2
97+
```
98+
99+
This loads the model into memory without interaction, ensuring maximum performance for subsequent requests.
81100
deprecated: false
82101
hidden: false
83102
experimental: false

cmd/cli/docs/reference/model_run.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Run a model and interact with it using a submitted prompt or chat mode
99
|:--------------------------------|:---------|:--------|:----------------------------------------------------------------------------------|
1010
| `--color` | `string` | `auto` | Use colored output (auto\|yes\|no) |
1111
| `--debug` | `bool` | | Enable debug logging |
12+
| `-d`, `--detach` | `bool` | | Load the model in the background without interaction |
1213
| `--ignore-runtime-memory-check` | `bool` | | Do not block pull if estimated runtime memory for model exceeds system resources. |
1314

1415

@@ -51,3 +52,11 @@ Hi there! It's SmolLM, AI assistant. How can I help you today?
5152
> /bye
5253
Chat session ended.
5354
```
55+
56+
### Pre-load a model
57+
58+
```console
59+
docker model run --detach ai/smollm2
60+
```
61+
62+
This loads the model into memory without interaction, ensuring maximum performance for subsequent requests.

0 commit comments

Comments
 (0)