Skip to content
This repository was archived by the owner on Oct 6, 2025. It is now read-only.

Commit 72cf234

Browse files
committed
Merge branch 'main' into inspect-remote-model
# Conflicts: # commands/inspect.go
2 parents 02a55c0 + f7ab896 commit 72cf234

File tree

338 files changed

+47588
-83
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

338 files changed

+47588
-83
lines changed

commands/compose.go

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ import (
55
"errors"
66
"fmt"
77
"slices"
8-
"strconv"
98
"strings"
109

1110
"github.com/docker/model-cli/desktop"
12-
"github.com/docker/model-cli/pkg/standalone"
11+
"github.com/docker/model-runner/pkg/inference/backends/llamacpp"
12+
"github.com/docker/model-runner/pkg/inference/scheduling"
1313
"github.com/spf13/cobra"
1414
)
1515

@@ -28,6 +28,9 @@ func newComposeCmd() *cobra.Command {
2828

2929
func newUpCommand() *cobra.Command {
3030
var models []string
31+
var ctxSize int64
32+
var rawRuntimeFlags string
33+
var backend string
3134
c := &cobra.Command{
3235
Use: "up",
3336
RunE: func(cmd *cobra.Command, args []string) error {
@@ -37,31 +40,61 @@ func newUpCommand() *cobra.Command {
3740
return err
3841
}
3942

40-
if err := ensureStandaloneRunnerAvailable(cmd.Context(), nil); err != nil {
43+
sendInfo("Initializing model runner...")
44+
if ctxSize != 4096 {
45+
sendInfo(fmt.Sprintf("Setting context size to %d", ctxSize))
46+
}
47+
if rawRuntimeFlags != "" {
48+
sendInfo("Setting raw runtime flags to " + rawRuntimeFlags)
49+
}
50+
51+
kind := modelRunner.EngineKind()
52+
standalone, err := ensureStandaloneRunnerAvailable(cmd.Context(), nil)
53+
if err != nil {
4154
_ = sendErrorf("Failed to initialize standalone model runner: %v", err)
4255
return fmt.Errorf("Failed to initialize standalone model runner: %w", err)
56+
} else if ((kind == desktop.ModelRunnerEngineKindMoby || kind == desktop.ModelRunnerEngineKindCloud) &&
57+
standalone == nil) ||
58+
(standalone != nil && (standalone.gatewayIP == "" || standalone.gatewayPort == 0)) {
59+
return errors.New("unable to determine standalone runner endpoint")
4360
}
4461

4562
if err := downloadModelsOnlyIfNotFound(desktopClient, models); err != nil {
4663
return err
4764
}
4865

49-
if kind := modelRunner.EngineKind(); kind == desktop.ModelRunnerEngineKindDesktop {
50-
// TODO: Get the actual URL from Docker Desktop via some API.
66+
for _, model := range models {
67+
if err := desktopClient.ConfigureBackend(scheduling.ConfigureRequest{
68+
Model: model,
69+
ContextSize: ctxSize,
70+
RawRuntimeFlags: rawRuntimeFlags,
71+
}); err != nil {
72+
configErrFmtString := "failed to configure backend for model %s with context-size %d and runtime-flags %s"
73+
_ = sendErrorf(configErrFmtString+": %v", model, ctxSize, rawRuntimeFlags, err)
74+
return fmt.Errorf(configErrFmtString+": %w", model, ctxSize, rawRuntimeFlags, err)
75+
}
76+
sendInfo("Successfully configured backend for model " + model)
77+
}
78+
79+
switch kind {
80+
case desktop.ModelRunnerEngineKindDesktop:
5181
_ = setenv("URL", "http://model-runner.docker.internal/engines/v1/")
52-
} else if kind == desktop.ModelRunnerEngineKindMobyManual {
82+
case desktop.ModelRunnerEngineKindMobyManual:
5383
_ = setenv("URL", modelRunner.URL("/engines/v1/"))
54-
} else if kind == desktop.ModelRunnerEngineKindMoby {
55-
// TODO: Use more robust detection in Moby-like environments.
56-
_ = setenv("URL", "http://host.docker.internal:"+strconv.Itoa(standalone.DefaultControllerPortMoby)+"/engines/v1/")
57-
} else if kind == desktop.ModelRunnerEngineKindCloud {
58-
// TODO: Use more robust detection in Cloud environments.
59-
_ = setenv("URL", "http://host.docker.internal:"+strconv.Itoa(standalone.DefaultControllerPortCloud)+"/engines/v1/")
84+
case desktop.ModelRunnerEngineKindCloud:
85+
fallthrough
86+
case desktop.ModelRunnerEngineKindMoby:
87+
_ = setenv("URL", fmt.Sprintf("http://%s:%d/engines/v1", standalone.gatewayIP, standalone.gatewayPort))
88+
default:
89+
return fmt.Errorf("unhandled engine kind: %v", kind)
6090
}
6191
return nil
6292
},
6393
}
6494
c.Flags().StringArrayVar(&models, "model", nil, "model to use")
95+
c.Flags().Int64Var(&ctxSize, "context-size", -1, "context size for the model")
96+
c.Flags().StringVar(&rawRuntimeFlags, "runtime-flags", "", "raw runtime flags to pass to the inference engine")
97+
c.Flags().StringVar(&backend, "backend", llamacpp.Name, "inference backend to use")
6598
return c
6699
}
67100

commands/inspect.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@ func newInspectCmd() *cobra.Command {
2626
return nil
2727
},
2828
RunE: func(cmd *cobra.Command, args []string) error {
29+
if _, err := ensureStandaloneRunnerAvailable(cmd.Context(), cmd); err != nil {
30+
return fmt.Errorf("unable to initialize standalone model runner: %w", err)
31+
}
2932
if openai && remote {
3033
return fmt.Errorf("--openai and --remote flags are not compatible")
3134
}
32-
if err := ensureStandaloneRunnerAvailable(cmd.Context(), cmd); err != nil {
33-
return fmt.Errorf("unable to initialize standalone model runner: %w", err)
34-
}
3535
inspectedModel, err := inspectModel(args, openai, remote, desktopClient)
3636
if err != nil {
3737
return err

commands/install-runner.go

Lines changed: 60 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"os"
88
"time"
99

10+
"github.com/docker/docker/api/types/container"
1011
"github.com/docker/model-cli/commands/completion"
1112
"github.com/docker/model-cli/desktop"
1213
gpupkg "github.com/docker/model-cli/pkg/gpu"
@@ -42,21 +43,49 @@ func waitForStandaloneRunnerAfterInstall(ctx context.Context) error {
4243
return errors.New("standalone model runner took too long to initialize")
4344
}
4445

46+
// standaloneRunner encodes the standalone runner configuration, if one exists.
47+
type standaloneRunner struct {
48+
// hostPort is the port that the runner is listening to on the host.
49+
hostPort uint16
50+
// gatewayIP is the gateway IP address that the runner is listening on.
51+
gatewayIP string
52+
// gatewayPort is the gateway port that the runner is listening on.
53+
gatewayPort uint16
54+
}
55+
56+
// inspectStandaloneRunner inspects a standalone runner container and extracts
57+
// its configuration.
58+
func inspectStandaloneRunner(container container.Summary) *standaloneRunner {
59+
result := &standaloneRunner{}
60+
for _, port := range container.Ports {
61+
if port.IP == "127.0.0.1" {
62+
result.hostPort = port.PublicPort
63+
} else {
64+
// We don't really have a good way of knowing what the gateway IP
65+
// address is, but in the standard standalone configuration we only
66+
// bind to two interfaces: 127.0.0.1 and the gateway interface.
67+
result.gatewayIP = port.IP
68+
result.gatewayPort = port.PublicPort
69+
}
70+
}
71+
return result
72+
}
73+
4574
// ensureStandaloneRunnerAvailable is a utility function that other commands can
4675
// use to initialize a default standalone model runner. It is a no-op in
4776
// unsupported contexts or if automatic installs have been disabled.
48-
func ensureStandaloneRunnerAvailable(ctx context.Context, printer standalone.StatusPrinter) error {
77+
func ensureStandaloneRunnerAvailable(ctx context.Context, printer standalone.StatusPrinter) (*standaloneRunner, error) {
4978
// If we're not in a supported model runner context, then don't do anything.
5079
engineKind := modelRunner.EngineKind()
5180
standaloneSupported := engineKind == desktop.ModelRunnerEngineKindMoby ||
5281
engineKind == desktop.ModelRunnerEngineKindCloud
5382
if !standaloneSupported {
54-
return nil
83+
return nil, nil
5584
}
5685

5786
// If automatic installation has been disabled, then don't do anything.
5887
if os.Getenv("MODEL_RUNNER_NO_AUTO_INSTALL") != "" {
59-
return nil
88+
return nil, nil
6089
}
6190

6291
// Ensure that the output printer is non-nil.
@@ -67,32 +96,32 @@ func ensureStandaloneRunnerAvailable(ctx context.Context, printer standalone.Sta
6796
// Create a Docker client for the active context.
6897
dockerClient, err := desktop.DockerClientForContext(dockerCLI, dockerCLI.CurrentContext())
6998
if err != nil {
70-
return fmt.Errorf("failed to create Docker client: %w", err)
99+
return nil, fmt.Errorf("failed to create Docker client: %w", err)
71100
}
72101

73102
// Check if a model runner container exists.
74-
container, _, err := standalone.FindControllerContainer(ctx, dockerClient)
103+
containerID, _, container, err := standalone.FindControllerContainer(ctx, dockerClient)
75104
if err != nil {
76-
return fmt.Errorf("unable to identify existing standalone model runner: %w", err)
77-
} else if container != "" {
78-
return nil
105+
return nil, fmt.Errorf("unable to identify existing standalone model runner: %w", err)
106+
} else if containerID != "" {
107+
return inspectStandaloneRunner(container), nil
79108
}
80109

81110
// Automatically determine GPU support.
82111
gpu, err := gpupkg.ProbeGPUSupport(ctx, dockerClient)
83112
if err != nil {
84-
return fmt.Errorf("unable to probe GPU support: %w", err)
113+
return nil, fmt.Errorf("unable to probe GPU support: %w", err)
85114
}
86115

87116
// Ensure that we have an up-to-date copy of the image.
88117
if err := standalone.EnsureControllerImage(ctx, dockerClient, gpu, printer); err != nil {
89-
return fmt.Errorf("unable to pull latest standalone model runner image: %w", err)
118+
return nil, fmt.Errorf("unable to pull latest standalone model runner image: %w", err)
90119
}
91120

92121
// Ensure that we have a model storage volume.
93122
modelStorageVolume, err := standalone.EnsureModelStorageVolume(ctx, dockerClient, printer)
94123
if err != nil {
95-
return fmt.Errorf("unable to initialize standalone model storage: %w", err)
124+
return nil, fmt.Errorf("unable to initialize standalone model storage: %w", err)
96125
}
97126

98127
// Create the model runner container.
@@ -101,11 +130,28 @@ func ensureStandaloneRunnerAvailable(ctx context.Context, printer standalone.Sta
101130
port = standalone.DefaultControllerPortCloud
102131
}
103132
if err := standalone.CreateControllerContainer(ctx, dockerClient, port, false, gpu, modelStorageVolume, printer); err != nil {
104-
return fmt.Errorf("unable to initialize standalone model runner container: %w", err)
133+
return nil, fmt.Errorf("unable to initialize standalone model runner container: %w", err)
105134
}
106135

107136
// Poll until we get a response from the model runner.
108-
return waitForStandaloneRunnerAfterInstall(ctx)
137+
if err := waitForStandaloneRunnerAfterInstall(ctx); err != nil {
138+
return nil, err
139+
}
140+
141+
// Find the runner container.
142+
//
143+
// TODO: We should actually find this before calling
144+
// waitForStandaloneRunnerAfterInstall (or have CreateControllerContainer
145+
// return the container information), and probably pass the target
146+
// information info waitForStandaloneRunnerAfterInstall, but let's wait
147+
// until we do listener port customization / detection in the next PR.
148+
containerID, _, container, err = standalone.FindControllerContainer(ctx, dockerClient)
149+
if err != nil {
150+
return nil, fmt.Errorf("unable to identify existing standalone model runner: %w", err)
151+
} else if containerID == "" {
152+
return nil, errors.New("standalone model runner not found after installation")
153+
}
154+
return inspectStandaloneRunner(container), nil
109155
}
110156

111157
func newInstallRunner() *cobra.Command {
@@ -149,7 +195,7 @@ func newInstallRunner() *cobra.Command {
149195
}
150196

151197
// Check if an active model runner container already exists.
152-
if ctrID, ctrName, err := standalone.FindControllerContainer(cmd.Context(), dockerClient); err != nil {
198+
if ctrID, ctrName, _, err := standalone.FindControllerContainer(cmd.Context(), dockerClient); err != nil {
153199
return err
154200
} else if ctrID != "" {
155201
if ctrName != "" {

commands/list.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func newListCmd() *cobra.Command {
3030
if !jsonFormat && !openai && !quiet {
3131
standaloneInstallPrinter = cmd
3232
}
33-
if err := ensureStandaloneRunnerAvailable(cmd.Context(), standaloneInstallPrinter); err != nil {
33+
if _, err := ensureStandaloneRunnerAvailable(cmd.Context(), standaloneInstallPrinter); err != nil {
3434
return fmt.Errorf("unable to initialize standalone model runner: %w", err)
3535
}
3636
models, err := listModels(openai, desktopClient, quiet, jsonFormat)

commands/logs.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func newLogsCmd() *cobra.Command {
4444
if err != nil {
4545
return fmt.Errorf("failed to create Docker client: %w", err)
4646
}
47-
ctrID, _, err := standalone.FindControllerContainer(cmd.Context(), dockerClient)
47+
ctrID, _, _, err := standalone.FindControllerContainer(cmd.Context(), dockerClient)
4848
if err != nil {
4949
return fmt.Errorf("unable to identify Model Runner container: %w", err)
5050
} else if ctrID == "" {

commands/pull.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ func newPullCmd() *cobra.Command {
2323
return nil
2424
},
2525
RunE: func(cmd *cobra.Command, args []string) error {
26-
if err := ensureStandaloneRunnerAvailable(cmd.Context(), cmd); err != nil {
26+
if _, err := ensureStandaloneRunnerAvailable(cmd.Context(), cmd); err != nil {
2727
return fmt.Errorf("unable to initialize standalone model runner: %w", err)
2828
}
2929
return pullModel(cmd, desktopClient, args[0])

commands/push.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ func newPushCmd() *cobra.Command {
2323
return nil
2424
},
2525
RunE: func(cmd *cobra.Command, args []string) error {
26-
if err := ensureStandaloneRunnerAvailable(cmd.Context(), cmd); err != nil {
26+
if _, err := ensureStandaloneRunnerAvailable(cmd.Context(), cmd); err != nil {
2727
return fmt.Errorf("unable to initialize standalone model runner: %w", err)
2828
}
2929
return pushModel(cmd, desktopClient, args[0])

commands/rm.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func newRemoveCmd() *cobra.Command {
2424
return nil
2525
},
2626
RunE: func(cmd *cobra.Command, args []string) error {
27-
if err := ensureStandaloneRunnerAvailable(cmd.Context(), cmd); err != nil {
27+
if _, err := ensureStandaloneRunnerAvailable(cmd.Context(), cmd); err != nil {
2828
return fmt.Errorf("unable to initialize standalone model runner: %w", err)
2929
}
3030
response, err := desktopClient.Remove(args, force)

commands/run.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ func newRunCmd() *cobra.Command {
3333
}
3434
}
3535

36-
if err := ensureStandaloneRunnerAvailable(cmd.Context(), cmd); err != nil {
36+
if _, err := ensureStandaloneRunnerAvailable(cmd.Context(), cmd); err != nil {
3737
return fmt.Errorf("unable to initialize standalone model runner: %w", err)
3838
}
3939

commands/status.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ func newStatusCmd() *cobra.Command {
1515
Use: "status",
1616
Short: "Check if the Docker Model Runner is running",
1717
RunE: func(cmd *cobra.Command, args []string) error {
18-
if err := ensureStandaloneRunnerAvailable(cmd.Context(), cmd); err != nil {
18+
if _, err := ensureStandaloneRunnerAvailable(cmd.Context(), cmd); err != nil {
1919
return fmt.Errorf("unable to initialize standalone model runner: %w", err)
2020
}
2121
status := desktopClient.Status()

0 commit comments

Comments
 (0)