From 184d6df1bcd22cb3dab1fd2624c3dbfa6fcd5ea4 Mon Sep 17 00:00:00 2001 From: LordMathis Date: Mon, 22 Sep 2025 21:25:50 +0200 Subject: [PATCH] Fix vllm command parsing --- pkg/backends/parser.go | 29 +++++++++++++++++++++++------ pkg/backends/vllm/vllm_test.go | 17 +++++++++++------ 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/pkg/backends/parser.go b/pkg/backends/parser.go index 89ad46e..df585c9 100644 --- a/pkg/backends/parser.go +++ b/pkg/backends/parser.go @@ -17,8 +17,8 @@ func ParseCommand(command string, executableNames []string, subcommandNames []st return fmt.Errorf("command cannot be empty") } - // Extract arguments - args, err := extractArgs(command, executableNames, subcommandNames) + // Extract arguments and positional model + args, modelFromPositional, err := extractArgs(command, executableNames, subcommandNames) if err != nil { return err } @@ -29,6 +29,13 @@ func ParseCommand(command string, executableNames []string, subcommandNames []st return err } + // If we found a positional model and no --model flag was provided, set the model + if modelFromPositional != "" { + if _, hasModelFlag := options["model"]; !hasModelFlag { + options["model"] = modelFromPositional + } + } + // Convert to target struct via JSON jsonData, err := json.Marshal(options) if err != nil { @@ -51,15 +58,16 @@ func normalizeCommand(command string) string { } // extractArgs extracts arguments from command, removing executable and subcommands -func extractArgs(command string, executableNames []string, subcommandNames []string) ([]string, error) { +// Returns: args, modelFromPositional, error +func extractArgs(command string, executableNames []string, subcommandNames []string) ([]string, string, error) { // Check for unterminated quotes if strings.Count(command, `"`)%2 != 0 || strings.Count(command, `'`)%2 != 0 { - return nil, fmt.Errorf("unterminated quoted string") + return nil, "", fmt.Errorf("unterminated quoted string") } tokens := strings.Fields(command) if len(tokens) == 0 { - return nil, fmt.Errorf("no tokens found") + return nil, "", fmt.Errorf("no tokens found") } // Skip executable @@ -104,7 +112,16 @@ func extractArgs(command string, executableNames []string, subcommandNames []str } } - return tokens[start:], nil + args := tokens[start:] + + // Extract first positional argument (model) if present and not a flag + var modelFromPositional string + if len(args) > 0 && !strings.HasPrefix(args[0], "-") { + modelFromPositional = args[0] + args = args[1:] // Remove the model from args to process remaining flags + } + + return args, modelFromPositional, nil } // parseFlags parses command line flags into a map diff --git a/pkg/backends/vllm/vllm_test.go b/pkg/backends/vllm/vllm_test.go index db5a295..ea13496 100644 --- a/pkg/backends/vllm/vllm_test.go +++ b/pkg/backends/vllm/vllm_test.go @@ -14,17 +14,22 @@ func TestParseVllmCommand(t *testing.T) { }{ { name: "basic vllm serve command", - command: "vllm serve --model microsoft/DialoGPT-medium", + command: "vllm serve microsoft/DialoGPT-medium", expectErr: false, }, { name: "serve only command", - command: "serve --model microsoft/DialoGPT-medium", + command: "serve microsoft/DialoGPT-medium", expectErr: false, }, { - name: "args only", - command: "--model microsoft/DialoGPT-medium --tensor-parallel-size 2", + name: "positional model with flags", + command: "vllm serve microsoft/DialoGPT-medium --tensor-parallel-size 2", + expectErr: false, + }, + { + name: "model with path", + command: "vllm serve /path/to/model --gpu-memory-utilization 0.8", expectErr: false, }, { @@ -34,7 +39,7 @@ func TestParseVllmCommand(t *testing.T) { }, { name: "unterminated quote", - command: `vllm serve --model "unterminated`, + command: `vllm serve "unterminated`, expectErr: true, }, } @@ -63,7 +68,7 @@ func TestParseVllmCommand(t *testing.T) { } func TestParseVllmCommandValues(t *testing.T) { - command := "vllm serve --model test-model --tensor-parallel-size 4 --gpu-memory-utilization 0.8 --enable-log-outputs" + command := "vllm serve test-model --tensor-parallel-size 4 --gpu-memory-utilization 0.8 --enable-log-outputs" result, err := vllm.ParseVllmCommand(command) if err != nil {