Skip to content

[FEAT] add grid-cardinality-and-auto-switch - #128

Open
VincentG1234 wants to merge 3 commits into
openshift-psap:mainfrom
VincentG1234:FEAT/grid-cardinality-auto-switch
Open

[FEAT] add grid-cardinality-and-auto-switch#128
VincentG1234 wants to merge 3 commits into
openshift-psap:mainfrom
VincentG1234:FEAT/grid-cardinality-auto-switch

Conversation

@VincentG1234

@VincentG1234 VincentG1234 commented Mar 13, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR adds grid cardinality calculation and implements smart sampler selection logic to automatically switch between optimization strategies based on the study configuration.

Changes

New: Grid Cardinality Calculator (auto_tune_vllm/utils/grid_cardinality.py)

  • Computes the total number of parameter combinations in the search space
  • Supports all parameter types: ListParameter, RangeParameter, BooleanParameter

Smart Sampler Auto-Switching (auto_tune_vllm/cli/main.py)

Case 1: n_trials >= grid_cardinality

  • Action: Switch to sampler="grid" and set n_trials = cardinality
  • Why: Grid search explores all combinations exhaustively
  • User benefit: No wasted trials on duplicate parameter combinations

Case 2: n_trials <= n_startup_trials

  • Action: Switch to sampler="random" and ignore n_startup_trials
  • Why: TPE's startup phase is meaningless when we can't even complete it
  • User benefit: Immediate optimization without waiting for random startup

CLI Enhancement

  • Grid cardinality is now displayed in the validate command output
  • Clear warning messages inform users when auto-switching occurs

Example Behavior

study_config.yaml with small search space
parameters:
tensor_parallel_size:
type: list
options: [1, 2] # 2 values
dtype:
type: list
options: [float16, bfloat16] # 2 values
→ Grid cardinality = 2 × 2 = 4

  • If user requests --trials 10 (> 4) → Warning: n_trials (10) exceeds grid cardinality (4). Search set to grid mode with n_trials = 4.

  • If user requests --trials 5 with n_startup_trials=10 → Warning: n_trials (5) <= n_startup_trials (10). Search set to random mode; n_startup_trials ignored.

Summary by CodeRabbit

  • New Features
    • Configuration summaries now show "Possible combinations (grid cardinality)" — the total number of parameter combinations.
    • Automatic trial adjustments: if requested trials exceed the grid, the tool switches to grid mode and clamps trial counts with a CLI warning; if trials are too few relative to startup sampling, the sampler auto-switches to random with an explanatory warning.

Signed-off-by: Vincent Gimenes <vincent.gimenes@gmail.com>
Signed-off-by: Vincent Gimenes <vincent.gimenes@gmail.com>
@coderabbitai

coderabbitai Bot commented Mar 21, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Computes the parameter-grid cardinality from a StudyConfig and integrates it into the CLI: the CLI compares requested trials against the grid size, forces grid sampler (or switches to random sampler) and adjusts trial/startup counts accordingly; validate output includes the grid cardinality.

Changes

Cohort / File(s) Summary
Grid Cardinality Utility
auto_tune_vllm/utils/grid_cardinality.py, auto_tune_vllm/utils/__init__.py
Added get_parameter_grid_cardinality() to compute total combinations by counting discrete values per parameter type (ListParameter, EnvironmentParameter, BooleanParameter, RangeParameter), with a max-cap; re-exported from utils.__init__.
CLI Integration
auto_tune_vllm/cli/main.py
Integrated grid cardinality check into run_optimization_sync() to: compute cardinality, force sampler = "grid" and clamp n_trials/n_startup_trials when requested trials >= cardinality, or auto-switch sampler to "random" when startup_trials >= total trials for certain samplers; added cardinality to validate_command() output and removed a redundant total_trials reassignment.

Sequence Diagram(s)

sequenceDiagram
    participant CLI
    participant Loader as StudyConfig Loader
    participant Grid as grid_cardinality.get_parameter_grid_cardinality
    participant Optim as OptimizerRunner

    CLI->>Loader: load StudyConfig (path or object)
    CLI->>Grid: compute cardinality(config)
    Grid-->>CLI: cardinality (int)
    CLI->>CLI: compare requested_trials vs cardinality
    alt requested >= cardinality
        CLI->>CLI: set sampler = "grid", clamp n_trials, adjust n_startup_trials
    else requested < cardinality and startup >= total_trials and sampler in (tpe,gp,botorch)
        CLI->>CLI: set sampler = "random", clamp n_startup_trials
    end
    CLI->>Optim: run_optimization_sync(config, n_trials, sampler)
    Optim-->>CLI: progress / results
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 I hopped through configs bright and merry,
Counting combos — many, few, or scary.
If trials outrun the grid I see,
I'll switch the sampler, tidy and free,
And nibble warnings with a grateful cherry. 🍒

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title '[FEAT] add grid-cardinality-and-auto-switch' accurately describes the main changes: adding grid cardinality computation and implementing automatic sampler switching logic.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
auto_tune_vllm/cli/main.py (1)

21-21: Consider importing from the package's public API.

The function is re-exported in auto_tune_vllm/utils/__init__.py. Importing from the package (from ..utils import get_parameter_grid_cardinality) would be more consistent with the established pattern.

Suggested change
-from ..utils.grid_cardinality import get_parameter_grid_cardinality
+from ..utils import get_parameter_grid_cardinality
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@auto_tune_vllm/cli/main.py` at line 21, The import in main.py currently pulls
get_parameter_grid_cardinality from the internal module path; update the import
to use the package's public API by importing get_parameter_grid_cardinality from
..utils (i.e., replace the current from ..utils.grid_cardinality import
get_parameter_grid_cardinality with from ..utils import
get_parameter_grid_cardinality) so it uses the re-export in utils/__init__.py
and follows the project's import convention.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@auto_tune_vllm/cli/main.py`:
- Around line 373-387: Update the sampler selection logic in main.py around
total_trials/n_trials so it handles both auto-switch cases: (A) change the
current boundary check from ">" to ">=" when comparing total_trials to
cardinality and set config.optimization.sampler = "grid", adjust
config.optimization.n_trials, n_startup_trials, n_trials, and total_trials and
emit the console.print as done now (use symbols total_trials, n_trials,
cardinality, config.optimization.sampler, config.optimization.n_trials,
config.optimization.n_startup_trials, console.print,
get_parameter_grid_cardinality to find the block); (B) add the missing branch
that checks if n_trials <= config.optimization.n_startup_trials and in that case
set config.optimization.sampler = "random", set config.optimization.n_trials =
n_trials (or leave unchanged), ensure n_startup_trials is <= n_trials (e.g.,
reduce n_startup_trials to max(0, n_trials - 1)), update total_trials
accordingly, and emit a console.print explaining the auto-switch to random to
prevent TPE startup from consuming all trials. Ensure both branches are mutually
exclusive (check grid first then startup case).

In `@auto_tune_vllm/utils/grid_cardinality.py`:
- Around line 25-37: The float-range branch in grid_cardinality.py miscomputes
step counts due to floating-point truncation and mishandles step=None; update
the calculation in the RangeParameter float branch to compute n_steps robustly
(e.g., n_steps = int(round((max_val - min_val) / step)) + 1) and clamp to
_MAX_GRID_SIZE, and if step is None for a float RangeParameter treat the
cardinality as effectively large by returning _MAX_GRID_SIZE (instead of
defaulting step=1). Reference the RangeParameter float branch variables min_val,
max_val, step and the cap constant _MAX_GRID_SIZE when making the change.
- Around line 38-41: The function that computes grid cardinality (e.g.,
get_cardinality or similar) currently returns 0 for unhandled parameter types,
which will zero out total cardinality; change the default behavior to return 1
(neutral for multiplication) instead of 0 for unknown parameter types, and
optionally emit a warning or raise a ValueError if you prefer strict validation;
ensure the branch with BooleanParameter still returns 2 and update the default
return from 0 to 1 so unrecognized parameters do not silently zero the grid.

---

Nitpick comments:
In `@auto_tune_vllm/cli/main.py`:
- Line 21: The import in main.py currently pulls get_parameter_grid_cardinality
from the internal module path; update the import to use the package's public API
by importing get_parameter_grid_cardinality from ..utils (i.e., replace the
current from ..utils.grid_cardinality import get_parameter_grid_cardinality with
from ..utils import get_parameter_grid_cardinality) so it uses the re-export in
utils/__init__.py and follows the project's import convention.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 925ceea8-d974-4c8d-aa34-39d29bf442d7

📥 Commits

Reviewing files that changed from the base of the PR and between acff360 and 3e8d3e5.

📒 Files selected for processing (3)
  • auto_tune_vllm/cli/main.py
  • auto_tune_vllm/utils/__init__.py
  • auto_tune_vllm/utils/grid_cardinality.py

Comment thread auto_tune_vllm/cli/main.py
Comment thread auto_tune_vllm/utils/grid_cardinality.py
Comment thread auto_tune_vllm/utils/grid_cardinality.py
Signed-off-by: Vincent Gimenes <vincent.gimenes@gmail.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
auto_tune_vllm/cli/main.py (1)

389-405: Inconsistency: local n_trials not updated in Case 2.

In Case 1 (line 382), the local n_trials variable is reassigned to cardinality. In Case 2, only config.optimization.n_trials is updated, but the local n_trials variable (which may be None) is not reassigned. This value is later passed to controller.run_optimization(n_trials, ...) on line 430.

If run_optimization treats None differently from an explicit integer, the behavior may be inconsistent between the two cases. Consider updating n_trials for symmetry:

Proposed fix for consistency
     config.optimization.sampler = "random"
-    config.optimization.n_trials = total_trials
+    n_trials = total_trials
+    config.optimization.n_trials = n_trials
     config.optimization.n_startup_trials = min(
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@auto_tune_vllm/cli/main.py` around lines 389 - 405, The local n_trials
variable is not updated in the branch that auto-switches sampler to "random",
causing inconsistent behavior when calling controller.run_optimization(n_trials,
...); update the local n_trials to match the new config by assigning n_trials =
config.optimization.n_trials after you set config.optimization.n_trials so the
value passed to controller.run_optimization is consistent with the config (refer
to config.optimization.n_trials, config.optimization.sampler, and
controller.run_optimization).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@auto_tune_vllm/cli/main.py`:
- Around line 373-405: The current logic treats a grid cardinality of 0 as
valid, causing total_trials >= cardinality to force grid mode with n_trials=0;
update the check around get_parameter_grid_cardinality(config) so that if
cardinality == 0 you raise or console.error a clear configuration error
(mentioning ListParameter/EnvironmentParameter empty options) and abort early
instead of switching to grid mode. Specifically, in the block using total_trials
and cardinality, add a guard: if cardinality == 0, log/raise an error describing
the empty options issue (or set a fallback behavior), and do not set
config.optimization.sampler = "grid" or overwrite n_trials; reference
get_parameter_grid_cardinality, total_trials, and config.optimization.n_trials
when implementing the guard.

---

Nitpick comments:
In `@auto_tune_vllm/cli/main.py`:
- Around line 389-405: The local n_trials variable is not updated in the branch
that auto-switches sampler to "random", causing inconsistent behavior when
calling controller.run_optimization(n_trials, ...); update the local n_trials to
match the new config by assigning n_trials = config.optimization.n_trials after
you set config.optimization.n_trials so the value passed to
controller.run_optimization is consistent with the config (refer to
config.optimization.n_trials, config.optimization.sampler, and
controller.run_optimization).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f7e32139-2fb7-4e71-9940-64de88363c63

📥 Commits

Reviewing files that changed from the base of the PR and between 3e8d3e5 and 213675f.

📒 Files selected for processing (2)
  • auto_tune_vllm/cli/main.py
  • auto_tune_vllm/utils/grid_cardinality.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • auto_tune_vllm/utils/grid_cardinality.py

Comment on lines +373 to +405
total_trials = n_trials or config.optimization.n_trials
cardinality = get_parameter_grid_cardinality(config)
if total_trials >= cardinality:
requested = total_trials
config.optimization.sampler = "grid"
config.optimization.n_trials = cardinality
config.optimization.n_startup_trials = min(
config.optimization.n_startup_trials, max(0, cardinality - 1)
)
n_trials = cardinality
total_trials = cardinality
console.print(
f"[yellow]n_trials ({requested}) meets or exceeds grid cardinality "
f"({cardinality}). "
"Search set to grid mode with n_trials = cardinality.[/yellow]"
)
elif (
config.optimization.sampler.lower() in ("tpe", "gp", "botorch")
and total_trials <= config.optimization.n_startup_trials
):
startup_before = config.optimization.n_startup_trials
prev_sampler = config.optimization.sampler
config.optimization.sampler = "random"
config.optimization.n_trials = total_trials
config.optimization.n_startup_trials = min(
startup_before, max(0, total_trials - 1)
)
console.print(
f"[yellow]Auto-switched sampler from '{prev_sampler}' to 'random': "
f"n_trials ({total_trials}) is <= n_startup_trials ({startup_before}), "
"so startup sampling would consume the full trial budget. "
f"n_startup_trials is now {config.optimization.n_startup_trials}.[/yellow]"
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify what get_parameter_grid_cardinality returns for empty/disabled parameters
ast-grep --pattern $'def get_parameter_grid_cardinality($$$) {
  $$$
}'

Repository: openshift-psap/auto-tuning-vllm

Length of output: 57


🏁 Script executed:

#!/bin/bash
# Find where get_parameter_grid_cardinality is defined
rg -n "def get_parameter_grid_cardinality" --type py

Repository: openshift-psap/auto-tuning-vllm

Length of output: 154


🏁 Script executed:

#!/bin/bash
# Also check imports in main.py to understand where this function comes from
head -50 auto_tune_vllm/cli/main.py | grep -E "^(from|import)" || true
rg "get_parameter_grid_cardinality" auto_tune_vllm/cli/main.py | head -5

Repository: openshift-psap/auto-tuning-vllm

Length of output: 903


🏁 Script executed:

#!/bin/bash
# Search for any validation or checks around parameter grid cardinality
rg -B 5 -A 10 "get_parameter_grid_cardinality" auto_tune_vllm/cli/main.py

Repository: openshift-psap/auto-tuning-vllm

Length of output: 1894


🏁 Script executed:

#!/bin/bash
# Examine the get_parameter_grid_cardinality function
cat -n auto_tune_vllm/utils/grid_cardinality.py | head -100

Repository: openshift-psap/auto-tuning-vllm

Length of output: 2461


🏁 Script executed:

#!/bin/bash
# Check the full file to understand the function
wc -l auto_tune_vllm/utils/grid_cardinality.py

Repository: openshift-psap/auto-tuning-vllm

Length of output: 118


🏁 Script executed:

#!/bin/bash
# Get the specific function and context
sed -n '40,80p' auto_tune_vllm/utils/grid_cardinality.py

Repository: openshift-psap/auto-tuning-vllm

Length of output: 807


🏁 Script executed:

#!/bin/bash
# Check what happens with parameters that have 0 options or values
# Look at the _count_parameter_values function and its return values
grep -A 5 "def _count_parameter_values" auto_tune_vllm/utils/grid_cardinality.py

Repository: openshift-psap/auto-tuning-vllm

Length of output: 391


🏁 Script executed:

#!/bin/bash
# Check if any parameter configuration can result in 0 values returned from _count_parameter_values
# Examine the function logic more carefully
sed -n '21,43p' auto_tune_vllm/utils/grid_cardinality.py

Repository: openshift-psap/auto-tuning-vllm

Length of output: 1004


🏁 Script executed:

#!/bin/bash
# Check if parameters can have empty options and what validation exists
# Look for ListParameter and EnvironmentParameter definitions
rg -A 10 "class ListParameter" auto_tune_vllm/core/parameters.py

Repository: openshift-psap/auto-tuning-vllm

Length of output: 393


🏁 Script executed:

#!/bin/bash
# Check for validation in the StudyConfig or parameter loading
rg -B 5 -A 5 "options" auto_tune_vllm/core/parameters.py | head -50

Repository: openshift-psap/auto-tuning-vllm

Length of output: 828


🏁 Script executed:

#!/bin/bash
# Check if there's any validation when parameters are loaded
rg "from_file\|validate" auto_tune_vllm/core/config.py | head -20

Repository: openshift-psap/auto-tuning-vllm

Length of output: 57


🏁 Script executed:

#!/bin/bash
# Check if there's validation preventing empty options in the parameter classes
rg -B 5 -A 15 "class ParameterConfig" auto_tune_vllm/core/parameters.py | head -60

Repository: openshift-psap/auto-tuning-vllm

Length of output: 589


🏁 Script executed:

#!/bin/bash
# Look for field validators or constraints on options
rg "validator\|Field\|constraints" auto_tune_vllm/core/parameters.py

Repository: openshift-psap/auto-tuning-vllm

Length of output: 57


🏁 Script executed:

#!/bin/bash
# Check if options can be empty by looking at test files or examples
fd "test" --type f --name "*parameter*" | head -5

Repository: openshift-psap/auto-tuning-vllm

Length of output: 325


🏁 Script executed:

#!/bin/bash
# Look for test files that might show parameter configurations
find . -type f -name "test_*.py" -o -name "*_test.py" | grep -i param | head -5

Repository: openshift-psap/auto-tuning-vllm

Length of output: 57


🏁 Script executed:

#!/bin/bash
# Search for example configs or test data
find . -type f -name "*.yaml" -o -name "*.yml" | head -10

Repository: openshift-psap/auto-tuning-vllm

Length of output: 487


🏁 Script executed:

#!/bin/bash
# Check if there's a pydantic validator on the options field
rg -B 2 -A 2 "options.*=" auto_tune_vllm/core/parameters.py

Repository: openshift-psap/auto-tuning-vllm

Length of output: 57


🏁 Script executed:

#!/bin/bash
# Look at an example config to understand realistic parameter configurations
cat examples/study_config_minimal.yaml

Repository: openshift-psap/auto-tuning-vllm

Length of output: 1375


🏁 Script executed:

#!/bin/bash
# Check what happens if there are no enabled parameters
rg -B 3 -A 8 "for param_config in config.parameters" auto_tune_vllm/utils/grid_cardinality.py

Repository: openshift-psap/auto-tuning-vllm

Length of output: 368


🏁 Script executed:

#!/bin/bash
# Verify the actual scenario: what if a ListParameter has empty options?
# Look for any validation when loading configs
cat auto_tune_vllm/core/config.py | head -100

Repository: openshift-psap/auto-tuning-vllm

Length of output: 3254


🏁 Script executed:

#!/bin/bash
# Check if there's any validation preventing empty options lists in parameter definitions
rg -C 10 "class ListParameter\|class EnvironmentParameter" auto_tune_vllm/core/parameters.py

Repository: openshift-psap/auto-tuning-vllm

Length of output: 57


🏁 Script executed:

#!/bin/bash
# Check the StudyConfig.from_file method for validation
rg -A 30 "def from_file" auto_tune_vllm/core/config.py

Repository: openshift-psap/auto-tuning-vllm

Length of output: 1170


🏁 Script executed:

#!/bin/bash
# Check for any validation in the ConfigValidator class
rg -A 50 "class ConfigValidator" auto_tune_vllm/core/config.py | head -80

Repository: openshift-psap/auto-tuning-vllm

Length of output: 1860


🏁 Script executed:

#!/bin/bash
# Look for validation of parameters section in ConfigValidator
rg -B 5 -A 15 "def.*validate.*parameter\|validate.*options" auto_tune_vllm/core/config.py

Repository: openshift-psap/auto-tuning-vllm

Length of output: 57


🏁 Script executed:

#!/bin/bash
# Check if pydantic models have field validators
grep -r "field_validator\|@validator" auto_tune_vllm/core/parameters.py

Repository: openshift-psap/auto-tuning-vllm

Length of output: 57


🏁 Script executed:

#!/bin/bash
# Look at the full parameters.py file structure for validation
wc -l auto_tune_vllm/core/parameters.py

Repository: openshift-psap/auto-tuning-vllm

Length of output: 111


🏁 Script executed:

#!/bin/bash
# Check if there's a __post_init__ or validation in ParameterConfig subclasses
rg -B 2 -A 5 "__post_init__\|model_validate\|validate" auto_tune_vllm/core/parameters.py

Repository: openshift-psap/auto-tuning-vllm

Length of output: 57


🏁 Script executed:

#!/bin/bash
# Check if parameters can actually have empty options by looking at actual schema usage
cat auto_tune_vllm/schemas/vllm_defaults/v0_10_0.yaml | head -100

Repository: openshift-psap/auto-tuning-vllm

Length of output: 2088


🏁 Script executed:

#!/bin/bash
# Look at the full parameters.py to see if there's any validation
cat -n auto_tune_vllm/core/parameters.py

Repository: openshift-psap/auto-tuning-vllm

Length of output: 3003


🏁 Script executed:

#!/bin/bash
# Check test files to see if cardinality == 0 is tested or handled
find . -type f -name "test_*.py" -o -name "*_test.py" | xargs rg -l "cardinality\|grid" 2>/dev/null | head -5

Repository: openshift-psap/auto-tuning-vllm

Length of output: 57


🏁 Script executed:

#!/bin/bash
# Look for any test that checks grid cardinality
rg "get_parameter_grid_cardinality" --type py | grep -i test

Repository: openshift-psap/auto-tuning-vllm

Length of output: 57


🏁 Script executed:

#!/bin/bash
# Check if there's any validation when Optuna creates search space
rg -B 5 -A 15 "create_search_space\|_create_search_space" auto_tune_vllm/core/study_controller.py | head -50

Repository: openshift-psap/auto-tuning-vllm

Length of output: 57


🏁 Script executed:

#!/bin/bash
# Check if empty options would cause errors earlier in the pipeline
rg "suggest_categorical" auto_tune_vllm/core/study_controller.py

Repository: openshift-psap/auto-tuning-vllm

Length of output: 57


🏁 Script executed:

#!/bin/bash
# Verify the actual context around line 375 in main.py to see if there's any prior validation
sed -n '360,380p' auto_tune_vllm/cli/main.py

Repository: openshift-psap/auto-tuning-vllm

Length of output: 803


🏁 Script executed:

#!/bin/bash
# Check if there's any validation in the ConfigValidator._validate_config method
rg -A 50 "def _validate_config" auto_tune_vllm/core/config.py | head -80

Repository: openshift-psap/auto-tuning-vllm

Length of output: 2234


🏁 Script executed:

#!/bin/bash
# Verify if parameters are validated before being used
rg -B 5 -A 15 "parameters.*=" auto_tune_vllm/core/config.py | grep -A 10 "parameters:"

Repository: openshift-psap/auto-tuning-vllm

Length of output: 1115


🏁 Script executed:

#!/bin/bash
# Check what happens if we have zero enabled parameters - does cardinality stay at 1?
# Verify the logic in grid_cardinality.py more carefully
cat -n auto_tune_vllm/utils/grid_cardinality.py | sed -n '46,61p'

Repository: openshift-psap/auto-tuning-vllm

Length of output: 772


🏁 Script executed:

#!/bin/bash
# Check if Optuna would fail earlier with empty options
rg -B 5 -A 10 "suggest_categorical" auto_tune_vllm/ | head -30

Repository: openshift-psap/auto-tuning-vllm

Length of output: 1848


🏁 Script executed:

#!/bin/bash
# Check _build_parameter_config to see if it validates non-empty options for ListParameter
rg -A 30 "_build_parameter_config" auto_tune_vllm/core/config.py | head -50

Repository: openshift-psap/auto-tuning-vllm

Length of output: 2133


🏁 Script executed:

#!/bin/bash
# Get the rest of _build_parameter_config
rg -A 60 "def _build_parameter_config" auto_tune_vllm/core/config.py | tail -40

Repository: openshift-psap/auto-tuning-vllm

Length of output: 1234


🏁 Script executed:

#!/bin/bash
# Also check _infer_parameter_type to understand how ListParameter is created
rg -B 5 -A 30 "_infer_parameter_type" auto_tune_vllm/core/config.py

Repository: openshift-psap/auto-tuning-vllm

Length of output: 2570


Guard against zero cardinality from empty parameter options.

If a ListParameter or EnvironmentParameter is configured with an empty options list, get_parameter_grid_cardinality() returns 0. The condition total_trials >= cardinality (line 375) then always evaluates to true, forcing grid mode with n_trials = 0, which runs no trials and produces no results. While rare, this edge case is possible because validation does not prevent empty options lists.

Add a guard to catch this configuration error early:

Proposed fix
 total_trials = n_trials or config.optimization.n_trials
 cardinality = get_parameter_grid_cardinality(config)
+if cardinality == 0:
+    console.print(
+        "[bold red]Error: Grid cardinality is 0 (empty parameter options or no enabled parameters).[/bold red]"
+    )
+    raise typer.Exit(1)
 if total_trials >= cardinality:
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
total_trials = n_trials or config.optimization.n_trials
cardinality = get_parameter_grid_cardinality(config)
if total_trials >= cardinality:
requested = total_trials
config.optimization.sampler = "grid"
config.optimization.n_trials = cardinality
config.optimization.n_startup_trials = min(
config.optimization.n_startup_trials, max(0, cardinality - 1)
)
n_trials = cardinality
total_trials = cardinality
console.print(
f"[yellow]n_trials ({requested}) meets or exceeds grid cardinality "
f"({cardinality}). "
"Search set to grid mode with n_trials = cardinality.[/yellow]"
)
elif (
config.optimization.sampler.lower() in ("tpe", "gp", "botorch")
and total_trials <= config.optimization.n_startup_trials
):
startup_before = config.optimization.n_startup_trials
prev_sampler = config.optimization.sampler
config.optimization.sampler = "random"
config.optimization.n_trials = total_trials
config.optimization.n_startup_trials = min(
startup_before, max(0, total_trials - 1)
)
console.print(
f"[yellow]Auto-switched sampler from '{prev_sampler}' to 'random': "
f"n_trials ({total_trials}) is <= n_startup_trials ({startup_before}), "
"so startup sampling would consume the full trial budget. "
f"n_startup_trials is now {config.optimization.n_startup_trials}.[/yellow]"
)
total_trials = n_trials or config.optimization.n_trials
cardinality = get_parameter_grid_cardinality(config)
if cardinality == 0:
console.print(
"[bold red]Error: Grid cardinality is 0 (empty parameter options or no enabled parameters).[/bold red]"
)
raise typer.Exit(1)
if total_trials >= cardinality:
requested = total_trials
config.optimization.sampler = "grid"
config.optimization.n_trials = cardinality
config.optimization.n_startup_trials = min(
config.optimization.n_startup_trials, max(0, cardinality - 1)
)
n_trials = cardinality
total_trials = cardinality
console.print(
f"[yellow]n_trials ({requested}) meets or exceeds grid cardinality "
f"({cardinality}). "
"Search set to grid mode with n_trials = cardinality.[/yellow]"
)
elif (
config.optimization.sampler.lower() in ("tpe", "gp", "botorch")
and total_trials <= config.optimization.n_startup_trials
):
startup_before = config.optimization.n_startup_trials
prev_sampler = config.optimization.sampler
config.optimization.sampler = "random"
config.optimization.n_trials = total_trials
config.optimization.n_startup_trials = min(
startup_before, max(0, total_trials - 1)
)
console.print(
f"[yellow]Auto-switched sampler from '{prev_sampler}' to 'random': "
f"n_trials ({total_trials}) is <= n_startup_trials ({startup_before}), "
"so startup sampling would consume the full trial budget. "
f"n_startup_trials is now {config.optimization.n_startup_trials}.[/yellow]"
)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@auto_tune_vllm/cli/main.py` around lines 373 - 405, The current logic treats
a grid cardinality of 0 as valid, causing total_trials >= cardinality to force
grid mode with n_trials=0; update the check around
get_parameter_grid_cardinality(config) so that if cardinality == 0 you raise or
console.error a clear configuration error (mentioning
ListParameter/EnvironmentParameter empty options) and abort early instead of
switching to grid mode. Specifically, in the block using total_trials and
cardinality, add a guard: if cardinality == 0, log/raise an error describing the
empty options issue (or set a fallback behavior), and do not set
config.optimization.sampler = "grid" or overwrite n_trials; reference
get_parameter_grid_cardinality, total_trials, and config.optimization.n_trials
when implementing the guard.

@aas008
aas008 requested review from aas008 and thameem-abbas April 6, 2026 13:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants