Skip to content

[#10710][feat] Make explicit CLI flags take precedence over --config / --extra_llm_api_options YAML - #14812

Merged
marinayanov merged 3 commits into
NVIDIA:mainfrom
nv-auto-deploy:myanov/cli-over-yaml
Jun 7, 2026
Merged

[#10710][feat] Make explicit CLI flags take precedence over --config / --extra_llm_api_options YAML#14812
marinayanov merged 3 commits into
NVIDIA:mainfrom
nv-auto-deploy:myanov/cli-over-yaml

Conversation

@marinayanov

@marinayanov marinayanov commented Jun 1, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • Documentation
    • Updated CLI/YAML override behavior documentation: explicit CLI flags now take precedence over YAML configuration values. Unset CLI flags fall back to YAML settings, then to defaults for trtllm-serve, trtllm-eval, and trtllm-bench commands.
    • Updated TensorRT-LLM Release 1.2 release notes to reflect the revised precedence rules.

Description

Title
[#10710][feat] Make explicit CLI flags take precedence over --config / --extra_llm_api_options YAML
Body

@coderabbitai summary

Description

Today, --config / --extra_llm_api_options YAML values silently override
explicit CLI flags in trtllm-serve, trtllm-eval, and trtllm-bench.
For example, trtllm-serve <model> --tensor_parallel_size 4 --config foo.yaml
with tensor_parallel_size: 8 in foo.yaml runs at TP=8. This is
unconventional and inconsistent with AutoDeploy's documented
CLI > YAML > defaults. See #10710.
This PR flips the precedence to explicit CLI > YAML > defaults, using
click.Context.get_parameter_source() to detect which flags the user
typed. Un-set CLI flags still fall back to YAML.
Backward-compatible: programmatic callers of
update_llm_args_with_extra_dict (Triton backend, LLM API, third-party)
that don't pass the new explicit_cli_keys argument keep today's
behavior.

Why this is the right direction, briefly:

  • In-repo precedent. AutoDeploy's config system already documents
    exactly this order — see docs/source/features/auto_deploy/advanced/expert_configurations.md:
    "CLI Arguments (highest priority) > YAML Configs > Default Settings (lowest priority)."
    This PR brings the rest of the CLI surface in line.
  • Conventional behavior. kubectl, Helm, Hydra, Pydantic Settings,
    and ~every argparse-based Python CLI implement CLI > config-file > defaults.
    The current "YAML > CLI" is the surprise.
  • PR [TRTLLM-10845][feat] Add dynamic llmapi defaults system #11035 acknowledged the gap. That PR added a value-based mitigation in trtllm-serve's is_non_default_or_required, and the
    reviewers explicitly flagged the remaining limitation:
    "CLI params can make this a bit tricky, since you need to
    distinguish between a CLI param being explicitly set vs. defaulting
    to a value."
    This PR closes that gap with
    click.Context.get_parameter_source().

Test Coverage

tests/unittest/llmapi/test_llm_args.py:

  • New: TestExplicitCliKeysPrecedence, TestEvalTranslationMap,
    TestBenchTranslationMap — cover precedence, deep-merges, build_config
    tiered rule, and per-tool Click-flag → LlmArgs translations.
  • Existing TestTelemetryConfigPrecedence and
    TestPyTorchBackendModelDefaults pass unchanged (back-compat).

tests/unittest/llmapi/apps/_test_trtllm_serve_duplicated_args.py:

  • flipped — --tp_size 1 plus YAML tensor_parallel_size: 99; server
    starting at TP=1 is the assertion that CLI wins.

pytest tests/unittest/llmapi/test_llm_args.py -q

PR Checklist

Please review the following before submitting your PR:

  • PR description clearly explains what and why. If using CodeRabbit's summary, please make sure it makes sense.

  • PR Follows TRT-LLM CODING GUIDELINES to the best of your knowledge.

  • Test cases are provided for new code paths (see test instructions)

  • If PR introduces API changes, an appropriate PR label is added - either api-compatible or api-breaking. For api-breaking, include BREAKING in the PR title.

  • Any new dependencies have been scanned for license and vulnerabilities

  • CODEOWNERS updated if ownership changes

  • Documentation updated as needed

  • Update tava architecture diagram if there is a significant design change in PR.

  • The reviewers assigned automatically/manually are appropriate for the PR.

  • [v ] Please check this after reviewing the above items as appropriate for this PR.

GitHub Bot Help

To see a list of available CI bot commands, please comment /bot help.

@coderabbitai

coderabbitai Bot commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This pull request implements CLI-over-YAML precedence enforcement across TensorRT-LLM serve, eval, and benchmark commands. It adds parameter tracking to identify explicitly set command-line flags, updates configuration merging logic to preserve CLI values during deep-merge of nested configs, and integrates this mechanism into all affected commands with consistent help text updates and comprehensive test coverage.

Changes

CLI Precedence Implementation

Layer / File(s) Summary
CLI parameter tracking utility
tensorrt_llm/commands/utils.py
New collect_explicit_cli_keys() helper inspects Click context to identify parameters provided on the command line, with support for excluding meta-options and translating parameter names to downstream field names.
Core LLM args merge and override logic
tensorrt_llm/llmapi/llm_args.py
update_llm_args_with_extra_dict() and update_llm_args_with_extra_options() now accept explicit_cli_keys to enforce CLI-over-YAML precedence during deep merge of nested configs (KV cache, telemetry, build config), while preventing claimed YAML keys from overriding explicit CLI values.
Serve command CLI precedence integration
tensorrt_llm/commands/serve.py, tests/unittest/llmapi/apps/_test_trtllm_serve_duplicated_args.py
is_non_default_or_required() and get_llm_args() signatures updated to accept explicit_cli_keys for filtering parameters. Integration in serve(), serve_encoder(), and disaggregated_mpi_worker() tracks CLI keys and passes them through config merging; help text clarifies precedence. Test fixture demonstrates CLI value winning over YAML.
Eval command CLI precedence integration
tensorrt_llm/commands/eval.py
Parameter translation mapping _CLICK_TO_LLM_ARG enables Click option tracking; main() collects explicit keys and passes them to update_llm_args_with_extra_options() for YAML merge precedence. Help text updated.
Benchmark infrastructure and CLI precedence integration
tensorrt_llm/bench/benchmark/__init__.py, low_latency.py, throughput.py, tensorrt_llm/bench/dataclasses/configuration.py
Benchmark-specific _BENCH_CLICK_TO_LLM_ARG mapping (excluding beam_width); RuntimeConfig adds explicit_cli_keys field; both latency and throughput benchmarks populate exec_settings["explicit_cli_keys"] before config construction.
Documentation and test validation
docs/source/commands/trtllm-serve/trtllm-serve.rst, docs/source/release-notes.md, tests/unittest/llmapi/test_llm_args.py
User docs and release notes updated to describe CLI-over-YAML precedence. Test suite adds legacy back-compat coverage, explicit key precedence test class, Click parameter translation validation, and updated serve defaults filtering assertions.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 37.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: making explicit CLI flags take precedence over YAML config values in trtllm tools, which is the core objective of the PR.
Description check ✅ Passed The PR description includes a comprehensive explanation of the problem, the solution using click.Context.get_parameter_source(), test coverage details (test files and test classes added), and a completed PR checklist. It meets the required template structure and provides sufficient context for understanding the changes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

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

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

🧹 Nitpick comments (2)
tensorrt_llm/bench/dataclasses/configuration.py (1)

5-5: 💤 Low value

Consider using PEP 585 built-in generic set instead of typing.Set.

Same as the comment in __init__.py: for Python 3.10+, prefer set[str] over Set[str] as per coding guidelines. However, this file already uses Dict, List, etc., from typing, so the current change is consistent with the existing style.

♻️ Proposed refactor to use built-in generic
-from typing import Any, Dict, List, Literal, Optional, Set, Union
+from typing import Any, Dict, List, Literal, Optional, Union

Then update line 39:

-    explicit_cli_keys: Optional[Set[str]] = None
+    explicit_cli_keys: Optional[set[str]] = None

As per coding guidelines: "Prefer built-in types list, dict, tuple over legacy typing.List, typing.Dict, typing.Tuple" (applies to set as well).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tensorrt_llm/bench/dataclasses/configuration.py` at line 5, Replace
typing.Set with the PEP 585 built-in generic set: remove Set from the import
list on the top import line and change any type annotations that use typing.Set
(the Set[...] occurrence referenced around the current line 39) to use the
built-in set[...] form; keep other typing imports (Dict, List, etc.) unchanged
to preserve file style.
tensorrt_llm/bench/benchmark/__init__.py (1)

3-3: 💤 Low value

Consider using PEP 585 built-in generic set instead of typing.Set.

The coding guidelines state: "Prefer built-in types list, dict, tuple over legacy typing.List, typing.Dict, typing.Tuple". For Python 3.10+, you can use set[str] directly instead of Set[str].

However, the existing code in this file uses Dict, Optional, etc., from typing, so this change would be consistent with the current style but not with the guideline preference.

♻️ Proposed refactor to use built-in generic
-from typing import Callable, Dict, Optional, Set
+from typing import Callable, Dict, Optional

Then update line 31:

-def collect_explicit_cli_keys() -> Set[str]:
+def collect_explicit_cli_keys() -> set[str]:

As per coding guidelines: "Prefer built-in types list, dict, tuple over legacy typing.List, typing.Dict, typing.Tuple; use | syntax instead of typing.Union" (applies to set as well in Python 3.10+).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tensorrt_llm/bench/benchmark/__init__.py` at line 3, The import currently
pulls Set from typing ("from typing import Callable, Dict, Optional, Set");
replace usage of typing.Set with the PEP 585 built-in generic by removing Set
from the typing import and using the built-in "set" in type annotations (e.g.,
change any "Set[str]" to "set[str]"); update the import line to "from typing
import Callable, Dict, Optional" (or prefer "dict" and "Optional" changes
separately) and adjust any annotations elsewhere in this module (e.g., the
annotation referenced around the existing use on/near line 31) to use the
built-in set generic.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tensorrt_llm/commands/serve.py`:
- Around line 28-29: The import set_spawn_proxy_process_ipc_hmac_key is unused
and causes autoflake/pre-commit failures; update the import statement in
serve.py to remove that symbol so only LlmLauncherEnvs is imported from
tensorrt_llm.executor.utils (i.e., change the from ... import line to import
LlmLauncherEnvs only).

---

Nitpick comments:
In `@tensorrt_llm/bench/benchmark/__init__.py`:
- Line 3: The import currently pulls Set from typing ("from typing import
Callable, Dict, Optional, Set"); replace usage of typing.Set with the PEP 585
built-in generic by removing Set from the typing import and using the built-in
"set" in type annotations (e.g., change any "Set[str]" to "set[str]"); update
the import line to "from typing import Callable, Dict, Optional" (or prefer
"dict" and "Optional" changes separately) and adjust any annotations elsewhere
in this module (e.g., the annotation referenced around the existing use on/near
line 31) to use the built-in set generic.

In `@tensorrt_llm/bench/dataclasses/configuration.py`:
- Line 5: Replace typing.Set with the PEP 585 built-in generic set: remove Set
from the import list on the top import line and change any type annotations that
use typing.Set (the Set[...] occurrence referenced around the current line 39)
to use the built-in set[...] form; keep other typing imports (Dict, List, etc.)
unchanged to preserve file style.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 8da6af56-6405-4faa-966d-70336b3aa1b2

📥 Commits

Reviewing files that changed from the base of the PR and between 35cce74 and 67b9960.

📒 Files selected for processing (12)
  • docs/source/commands/trtllm-serve/trtllm-serve.rst
  • docs/source/release-notes.md
  • tensorrt_llm/bench/benchmark/__init__.py
  • tensorrt_llm/bench/benchmark/low_latency.py
  • tensorrt_llm/bench/benchmark/throughput.py
  • tensorrt_llm/bench/dataclasses/configuration.py
  • tensorrt_llm/commands/eval.py
  • tensorrt_llm/commands/serve.py
  • tensorrt_llm/commands/utils.py
  • tensorrt_llm/llmapi/llm_args.py
  • tests/unittest/llmapi/apps/_test_trtllm_serve_duplicated_args.py
  • tests/unittest/llmapi/test_llm_args.py

Comment thread tensorrt_llm/commands/serve.py Outdated
Ensure explicitly provided CLI flags take precedence over config YAML values across the command entry points, with shared tracking of explicit keys and focused coverage for precedence behavior.

Signed-off-by: marinayanov <256585945+marinayanov@users.noreply.github.com>
@marinayanov
marinayanov force-pushed the myanov/cli-over-yaml branch from 67b9960 to 85f1e74 Compare June 1, 2026 12:07
@marinayanov

Copy link
Copy Markdown
Collaborator Author

/bot run

1 similar comment
@marinayanov

Copy link
Copy Markdown
Collaborator Author

/bot run

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #51386 [ run ] triggered by Bot. Commit: 85f1e74 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #51386 [ run ] completed with state SUCCESS. Commit: 85f1e74
/LLM/main/L0_MergeRequest_PR pipeline #40796 completed with status: 'SUCCESS'
Pipeline passed with automatic retried tests. Check the rerun report for details.

CI Report

Link to invocation

…m_args extra-dict

Address review (Devin): in `disaggregated_mpi_worker`, the previous
commits passed `explicit_cli_keys=set(server_cfg.other_args)` to BOTH
`get_llm_args` AND `update_llm_args_with_extra_dict`. The first call is
correct (bypasses the value-based filter for default-valued disagg-YAML
fields like `tensor_parallel_size: 1`). The second was wrong: in this
path `llm_args_extra_dict` is just the catch-all for kwargs that didn't
match `get_llm_args`'s named signature (`quant_config`, `lora_config`,
`pytorch_backend_config`, `decoding_config`, ...), not a separate YAML
being overridden. Passing the explicit set tripped the merge function's
"drop YAML keys claimed by explicit CLI" filter at `llm_args.py:4640-4644`
and silently dropped every catch-all kwarg.

This regressed disagg serving for any config that uses kwargs outside
`get_llm_args`'s named params — i.e. most realistic disagg configs.

Refactor: extract `_build_llm_args_from_disagg_server_cfg(other_args)` in
`serve.py` and use it from both call sites in `disaggregated_mpi_worker`
(the client-mode and leader-mode branches). The helper passes
`explicit_cli_keys` only to `get_llm_args` and not to the merge step,
with a docstring explaining why. The leader branch's `llm_args` was
unused on `main` (never passed to `_launch_disaggregated_leader`); a
TODO comment is added to clarify but the call is kept symmetric with
the client branch for safety.

Tests: add `TestDisaggLauncherKwargsPreservation` with two cases:
- `test_extra_kwargs_survive` — a `quant_config` and `lora_config` from
  `server_cfg.other_args` must reach the final llm_args. Fails on the
  buggy state, passes after the fix.
- `test_default_valued_named_params_survive` — pre-existing-bug
  regression guard for `tensor_parallel_size: 1` (the original
  motivation for adding `explicit_cli_keys` to `get_llm_args`).

`pytest tests/unittest/llmapi/test_llm_args.py -q`: 128 passed, 3 skipped
(skips are pre-existing).

Signed-off-by: marinayanov <256585945+marinayanov@users.noreply.github.com>
@marinayanov

Copy link
Copy Markdown
Collaborator Author

/bot run

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #51662 [ run ] triggered by Bot. Commit: 69ef3e8 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #51662 [ run ] completed with state SUCCESS. Commit: 69ef3e8
/LLM/main/L0_MergeRequest_PR pipeline #41044 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

Comment thread tensorrt_llm/llmapi/llm_args.py Outdated

@venkywonka venkywonka left a comment

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.

lgtm, thanks!

…L value

Address review (JunyiXu-nv): since flipping precedence to "CLI > YAML"
may break workflows that relied on YAML overriding CLI, emit a warning
when an explicit CLI flag actually overrides a value set in the YAML
config.

Warnings are added at the two override sites in
update_llm_args_with_extra_dict, each guarded so it fires only on a
genuine override (CLI value differs from the YAML value it replaces):

1. The "drop YAML keys claimed by explicit CLI flags" step -- covers
   top-level YAML scalars (e.g. `tensor_parallel_size: N`,
   `max_batch_size: N`). These keys are applied via the bulk dict merge,
   so the drop step is the only per-key processing point for them.
2. The build_config dual-location loop -- covers the nested
   `build_config:` block form (e.g. `build_config: {max_batch_size: N}`),
   which the top-level drop step does not see. This is the path the
   reviewer commented on. The pre-existing "set to X from explicit CLI
   flag" info log is kept for the non-override case (warn on override,
   info otherwise -- never both).

Identical values, and CLI flags absent from the YAML, stay silent. The
disagg launcher path does not pass explicit_cli_keys to the merge step,
so it produces no spurious warnings.

Signed-off-by: marinayanov <256585945+marinayanov@users.noreply.github.com>
@marinayanov

Copy link
Copy Markdown
Collaborator Author

/bot run

@marinayanov
marinayanov enabled auto-merge (squash) June 3, 2026 23:12
@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #51916 [ run ] triggered by Bot. Commit: 749037d Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #51916 [ run ] completed with state FAILURE. Commit: 749037d
/LLM/main/L0_MergeRequest_PR pipeline #41270 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

Link to invocation

@marinayanov

Copy link
Copy Markdown
Collaborator Author

/bot run

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #51995 [ run ] triggered by Bot. Commit: 749037d Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #51995 [ run ] completed with state FAILURE. Commit: 749037d
/LLM/main/L0_MergeRequest_PR pipeline #41339 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

Link to invocation

@marinayanov

Copy link
Copy Markdown
Collaborator Author

/bot run

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #52046 [ run ] triggered by Bot. Commit: 749037d Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #52046 [ run ] completed with state SUCCESS. Commit: 749037d
/LLM/main/L0_MergeRequest_PR pipeline #41380 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

@marinayanov

Copy link
Copy Markdown
Collaborator Author

/bot run

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #52077 [ run ] triggered by Bot. Commit: 749037d Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #52077 [ run ] completed with state SUCCESS. Commit: 749037d
/LLM/main/L0_MergeRequest_PR pipeline #41408 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

Link to invocation

@marinayanov

Copy link
Copy Markdown
Collaborator Author

/bot run

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #52104 [ run ] triggered by Bot. Commit: 749037d Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #52104 [ run ] completed with state SUCCESS. Commit: 749037d
/LLM/main/L0_MergeRequest_PR pipeline #41433 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

@marinayanov

Copy link
Copy Markdown
Collaborator Author

/bot run

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #52585 [ run ] triggered by Bot. Commit: 749037d Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #52585 [ run ] completed with state SUCCESS. Commit: 749037d
/LLM/main/L0_MergeRequest_PR pipeline #41867 completed with status: 'SUCCESS'

CI Report

Link to invocation

@marinayanov
marinayanov merged commit dcd4e90 into NVIDIA:main Jun 7, 2026
8 checks passed
2ez4bz pushed a commit to 2ez4bz/TensorRT-LLM that referenced this pull request Jun 8, 2026
…onfig / --extra_llm_api_options YAML (NVIDIA#14812)

Signed-off-by: marinayanov <256585945+marinayanov@users.noreply.github.com>
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.

4 participants