Skip to content

chore: allow cli to pick model from model list - #1114

Closed
mainred wants to merge 5 commits into
masterfrom
mainred/fix-overwrite-model-config
Closed

mainred wants to merge 5 commits into
masterfrom
mainred/fix-overwrite-model-config

Conversation

@mainred

@mainred mainred commented Nov 10, 2025 •

Copy link
Copy Markdown
Collaborator

When the CLI user define model list, and specify the model flag, holmesgpt will be overwrite the existing model with empty ones if the other llm configurations are not present in the config.
We allow the user to specify the model only when there's no api_key defined the configuration file.

Test

The model_list.yaml contains

azure/gpt-4.1:
  api_key: "***"
  model: azure/gpt-4.1
  api_base: https://**.openai.azure.com/
  api_version: 2025-01-01-preview
azure/gpt-5:
  api_key: "****"
  model: azure/gpt-5
  api_base: https://**.openai.azure.com/
  api_version: 2025-01-01-preview

config.yaml contains

model: "azure/gpt-4.1"
 poetry run holmes ask "what pods are running?"
Loaded models: ['azure/gpt-4.1', 'azure/gpt-5']
✅ Toolset docker/core
✅ Toolset kubernetes/core
✅ Toolset aks/core
Using 28 datasources (toolsets). To refresh: use flag `--refresh-toolsets`
NO ENABLED LOGGING TOOLSET
Using selected model: azure/gpt-4.1
Using model: azure/gpt-4.1 (1,047,576 total tokens, 32,768 output tokens)
Welcome to HolmesGPT: Type '/exit' to exit, '/help' for commands.
User: what pods are running?

Thinking...

The AI requested 1 tool call(s).
Running tool #1 kubectl_get_by_kind_in_cluster: kubectl get -A --show-labels -o wide pod
  Finished #1 in 0.30s, output length: 59,202 characters (163 lines) - /show 1 to view contents
... ...

same case when I use poetry run holmes ask "what pods are running?" --model=azure/gpt-4.1

@coderabbitai

coderabbitai Bot commented Nov 10, 2025 •

Copy link
Copy Markdown
Contributor

Walkthrough

LLM model initialization now avoids overwriting existing model entries when config omits an api_key; it only creates/overwrites from config if the model is missing or an api_key is provided. Added sentry_sdk and EXTRA_HEADERS imports and explanatory comments; tests for these behaviors were added.

Changes

Cohort / File(s) Summary
Core LLM Model Logic
holmes/core/llm.py
Added sentry_sdk and EXTRA_HEADERS imports; changed _init_models to conditionally avoid overwriting existing model entries when config omits api_key; create/update from config when the model is absent or an api_key is provided; added explanatory comments.
LLMModelRegistry Tests
tests/core/test_llm_model_registry.py
New test suite for _init_models covering: overwrite when config includes api_key, preserve when config omits api_key, create when model is absent (with and without api_key); uses temporary YAML model-list files, patches MODEL_LIST_FILE_LOCATION, mocks DAL and config, and asserts ModelEntry fields (including SecretStr).

Sequence Diagram(s)

sequenceDiagram
    participant Init as Model Init
    participant File as YAML File
    participant Config as Config
    participant Registry as Model Registry

    Init->>File: Read model list / lookup model
    File-->>Init: entryFound / notFound

    alt entryFound AND no api_key in Config
        Init->>Registry: Keep existing entry (no override)
        Registry-->>Init: existing entry retained
    else entryMissing OR api_key provided in Config
        Init->>Config: Load model values from config
        Config-->>Init: model config (model, name, base_url, api_key, ...)
        Init->>Registry: Create or update entry with config values
        Registry-->>Init: entry created/updated
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20–25 minutes

  • Inspect conditional branches in holmes/core/llm.py::_init_models (existing+no key, existing+key, missing).
  • Verify import additions (sentry_sdk, EXTRA_HEADERS) and comment accuracy.
  • Review tests/core/test_llm_model_registry.py for correct setup, patching of MODEL_LIST_FILE_LOCATION, mocks, and assertions (notably SecretStr handling).

Suggested reviewers

  • moshemorad

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 77.78% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description check ✅ Passed The description clearly explains the bug fix: preventing model configuration overwrites when CLI users specify a model flag without corresponding LLM configurations.
Title check ✅ Passed The title focuses on allowing the CLI to pick a model from the model list, which is a key aspect of the change. However, the main objective involves preventing unintended overwrites of model configurations when both a model list and --model flag are supplied. The title captures only part of the intent.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch mainred/fix-overwrite-model-config

Tip

📝 Customizable high-level summaries are now available!

You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.

  • Provide custom instructions to shape the summary (bullet lists, tables, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example:

"Create a concise high-level summary as a bullet-point list. Then include a Markdown table showing lines added and removed by each contributing author."

Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later.


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: 2

🧹 Nitpick comments (1)
tests/core/test_llm_model_registry.py (1)

22-27: Consider using pytest's tmp_path fixture for automatic cleanup.

The current implementation creates temp files with delete=False but never cleans them up, which can lead to disk space accumulation over many test runs.

Consider refactoring to use pytest's built-in tmp_path fixture:

-    def create_temp_model_file(self, model_data: dict) -> str:
+    def create_temp_model_file(self, model_data: dict, tmp_path) -> str:
         """Create a temporary model list file for testing."""
-        temp_file = tempfile.NamedTemporaryFile(mode='w', suffix='.yaml', delete=False)
-        yaml.dump(model_data, temp_file)
-        temp_file.flush()
-        return temp_file.name
+        temp_file = tmp_path / "model_list.yaml"
+        temp_file.write_text(yaml.dump(model_data))
+        return str(temp_file)

Then update each test method signature to accept tmp_path and pass it to the helper:

def test_init_models_existing_model_with_api_key_overwrites(self, tmp_path):
    # ...
    temp_file = self.create_temp_model_file(model_data, tmp_path)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b5a039f and cd5d976.

📒 Files selected for processing (2)
  • holmes/core/llm.py (3 hunks)
  • tests/core/test_llm_model_registry.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Use Ruff for formatting and linting (configured in pyproject.toml) for all Python code
Type hints are required; code should pass mypy (configured in pyproject.toml)
ALWAYS place Python imports at the top of the file, not inside functions or methods

Files:

  • tests/core/test_llm_model_registry.py
  • holmes/core/llm.py
tests/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Only use pytest markers that are defined in pyproject.toml; never introduce undefined markers/tags

Files:

  • tests/core/test_llm_model_registry.py
tests/**

📄 CodeRabbit inference engine (CLAUDE.md)

Test files should mirror the source structure under tests/

Files:

  • tests/core/test_llm_model_registry.py
🧠 Learnings (1)
📚 Learning: 2025-07-08T08:45:41.069Z
Learnt from: nherment
Repo: robusta-dev/holmesgpt PR: 610
File: .github/workflows/llm-evaluation.yaml:39-42
Timestamp: 2025-07-08T08:45:41.069Z
Learning: The robusta-dev/holmesgpt codebase has comprehensive existing validation for Azure environment variables (AZURE_API_BASE, AZURE_API_KEY, AZURE_API_VERSION) and MODEL in tests/llm/utils/classifiers.py, tests/llm/conftest.py, and holmes/core/llm.py. Don't suggest adding redundant validation logic.

Applied to files:

  • tests/core/test_llm_model_registry.py
  • holmes/core/llm.py
🧬 Code graph analysis (1)
tests/core/test_llm_model_registry.py (2)
holmes/config.py (1)
  • Config (46-521)
holmes/core/llm.py (3)
  • LLMModelRegistry (520-716)
  • ModelEntry (65-86)
  • models (672-673)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: llm_evals
  • GitHub Check: Pre-commit checks
  • GitHub Check: build
🔇 Additional comments (2)
holmes/core/llm.py (1)

9-9: LGTM - imports are properly used.

Both imports are used in the file and correctly placed at the top per coding guidelines.

Also applies to: 21-21

tests/core/test_llm_model_registry.py (1)

29-168: Excellent test coverage of the new conditional loading logic.

The four test methods comprehensively validate all scenarios:

  • Overwriting existing models when api_key is provided
  • Preserving existing models when api_key is not provided
  • Creating new model entries for non-existent models (both with and without api_key)

The tests correctly use SecretStr for API key comparisons and properly mock dependencies.

Comment thread holmes/core/llm.py Outdated
Comment thread tests/core/test_llm_model_registry.py Outdated

@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 (2)
tests/core/test_llm_model_registry.py (2)

28-61: LGTM!

Test correctly verifies that when api_key is provided in config, the existing model entry is completely overwritten. The assertions properly validate all fields including the SecretStr type for api_key.

Per coding guidelines, consider adding return type annotation:

-    def test_init_models_existing_model_with_api_key_overwrites(self):
+    def test_init_models_existing_model_with_api_key_overwrites(self) -> None:

63-157: Excellent test coverage!

These three test methods comprehensively cover the critical scenarios:

  1. Preserve behavior: When an existing model entry exists and no api_key is provided, the original entry is correctly preserved (including checking api_base from YAML rather than base_url).
  2. Create with api_key: New model entries are created when the model doesn't exist in the file, with all fields properly set.
  3. Create without api_key: New model entries are created even without an api_key when the model doesn't exist, correctly validating that api_key is None.

The test logic aligns perfectly with the _init_models behavior: if not existing_model or self.config.api_key:.

Per coding guidelines, consider adding return type annotations to these test methods:

-    def test_init_models_existing_model_without_api_key_preserves(self):
+    def test_init_models_existing_model_without_api_key_preserves(self) -> None:
-    def test_init_models_nonexistent_model_creates_new_entry(self):
+    def test_init_models_nonexistent_model_creates_new_entry(self) -> None:
-    def test_init_models_nonexistent_model_without_api_key_still_creates(self):
+    def test_init_models_nonexistent_model_without_api_key_still_creates(self) -> None:
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cd5d976 and c2f7177.

📒 Files selected for processing (1)
  • tests/core/test_llm_model_registry.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Use Ruff for formatting and linting (configured in pyproject.toml) for all Python code
Type hints are required; code should pass mypy (configured in pyproject.toml)
ALWAYS place Python imports at the top of the file, not inside functions or methods

Files:

  • tests/core/test_llm_model_registry.py
tests/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Only use pytest markers that are defined in pyproject.toml; never introduce undefined markers/tags

Files:

  • tests/core/test_llm_model_registry.py
tests/**

📄 CodeRabbit inference engine (CLAUDE.md)

Test files should mirror the source structure under tests/

Files:

  • tests/core/test_llm_model_registry.py
🧠 Learnings (1)
📚 Learning: 2025-07-08T08:45:41.069Z
Learnt from: nherment
Repo: robusta-dev/holmesgpt PR: 610
File: .github/workflows/llm-evaluation.yaml:39-42
Timestamp: 2025-07-08T08:45:41.069Z
Learning: The robusta-dev/holmesgpt codebase has comprehensive existing validation for Azure environment variables (AZURE_API_BASE, AZURE_API_KEY, AZURE_API_VERSION) and MODEL in tests/llm/utils/classifiers.py, tests/llm/conftest.py, and holmes/core/llm.py. Don't suggest adding redundant validation logic.

Applied to files:

  • tests/core/test_llm_model_registry.py
🧬 Code graph analysis (1)
tests/core/test_llm_model_registry.py (2)
holmes/config.py (1)
  • Config (46-521)
holmes/core/llm.py (2)
  • LLMModelRegistry (520-716)
  • models (672-673)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Pre-commit checks
  • GitHub Check: llm_evals
  • GitHub Check: build
🔇 Additional comments (2)
tests/core/test_llm_model_registry.py (2)

1-9: LGTM!

Imports are correctly placed at the top of the file and include all necessary modules for the test suite.


12-13: LGTM!

Clear class definition with appropriate docstring describing test focus.

Comment thread tests/core/test_llm_model_registry.py Outdated
@mainred mainred changed the title allow cli pick model from model list allow cli to pick model from model list Nov 11, 2025
Comment thread holmes/core/llm.py
existing_model = self._llms.get(self.config.model)
# When self.config.api_key and self.config.model are both set, we assume the user wants to override the
# model entry from the model list file.
if not existing_model or self.config.api_key:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thinking here loudly, I think that this is very confusing, in which cases the user wants to override the api key of the models.

Also, if he would like to override it he can't just set the value in the model list? we already have couple of places (toolset for example) that we are allowing those kind od override and it is complexing the code very much.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I just want to make it safe when both model and api_key are specified in the configuration file(~/.homes/config), we pick the configuration file instead of from the model list.
I agree too much check makes the code complicated. I think we can allow the user either to specify the model config in either model list or configuration file, and in cli when model list is defined, he can specify which model to use through model flag.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

This merge the cli and server behavior when model list is defined.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The thing that confuse me in that case is what happen if you set all the params like base_url in the model list and not in the config. It will override it?

I think it is very cumbersome. you either set all in the model list or set all in the config. In that case if the user set only the api key we will also overrider other params imlicitly and im not sure that this is the right behivour.

Are you sure that this is what we want to do?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

If the user set all in the model list, how will he select which model to use through CLI?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looks im missing something. In the suggested implementation we are overriding the model with the api_key, how this is connected to selecting the right model though cli?

@Avi-Robusta has an open pr that still need tests here: https://github.com/HolmesGPT/holmesgpt/pull/1096/files#diff-008177b02b41ee19dca44738e38891469986b5f51dfd58bc1b2ae22231471679R550-R556

In that pr you can select models from the model list and use them.
We still need to add tests + docs for this flow.

Can you help me understand what im missing in your suggested pr?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I think #1096 addresses the same issue as I want to in this PR. Since the PR is opened for review, let's focus #1096 instead.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

The user scenario is the user specify the model list and select the model from CLL.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Gotcha, thanks @mainred !

@mainred

mainred commented Nov 13, 2025

Copy link
Copy Markdown
Collaborator Author

@moshemorad May I get a second review on this one?

@github-actions

Copy link
Copy Markdown
Contributor

Results of HolmesGPT evals

  • ask_holmes: 31/36 test cases were successful, 3 regressions, 1 setup failures
Test suite Test case Status
ask 01_how_many_pods ✅
ask 02_what_is_wrong_with_pod ✅
ask 04_related_k8s_events ✅
ask 05_image_version ✅
ask 09_crashpod ✅
ask 10_image_pull_backoff ✅
ask 110_k8s_events_image_pull ✅
ask 11_init_containers ✅
ask 13a_pending_node_selector_basic ✅
ask 14_pending_resources ✅
ask 15_failed_readiness_probe ✅
ask 17_oom_kill ✅
ask 18_oom_kill_from_issues_history ✅
ask 19_detect_missing_app_details ✅
ask 20_long_log_file_search ✅
ask 24_misconfigured_pvc ✅
ask 24a_misconfigured_pvc_basic ✅
ask 28_permissions_error 🚧
ask 39_failed_toolset ✅
ask 41_setup_argo ✅
ask 42_dns_issues_steps_new_tools ⚠️
ask 43_current_datetime_from_prompt ✅
ask 45_fetch_deployment_logs_simple ✅
ask 51_logs_summarize_errors ✅
ask 53_logs_find_term ✅
ask 54_not_truncated_when_getting_pods ✅
ask 59_label_based_counting ✅
ask 60_count_less_than ✅
ask 61_exact_match_counting ✅
ask 63_fetch_error_logs_no_errors ✅
ask 79_configmap_mount_issue ✅
ask 83_secret_not_found ✅
ask 86_configmap_like_but_secret ✅
ask 93_calling_datadog[0] ❌
ask 93_calling_datadog[1] ❌
ask 93_calling_datadog[2] ❌

Legend

  • ✅ the test was successful
  • :minus: the test was skipped
  • ⚠️ the test failed but is known to be flaky or known to fail
  • 🚧 the test had a setup failure (not a code regression)
  • 🔧 the test failed due to mock data issues (not a code regression)
  • 🚫 the test was throttled by API rate limits/overload
  • ❌ the test failed and should be fixed before merging the PR

@mainred mainred changed the title allow cli to pick model from model list chore: allow cli to pick model from model list Nov 17, 2025
@mainred

mainred commented Nov 18, 2025

Copy link
Copy Markdown
Collaborator Author

Duplicate of #1096

@mainred mainred marked this as a duplicate of #1096 Nov 18, 2025
@mainred mainred closed this Nov 18, 2025
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