[Frontend] Only show the summary line of config docstrings in `--help` (#57357)

Signed-off-by: Harry Mellor <19981378+hmellor@users.noreply.github.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

Harry Mellor committed Sep 17, 2026 at 13:53 UTC 0ef8366ba39fc38b88c60b17ee2ddf05aa8a7596
2 files changed +35 -7
tests/utils_/test_argparse_utils.py
+17
@@ -524,3 +524,20 @@ def test_flat_product():
524 (3, 4, "a", 5, 6),
525 (3, 4, "b", 5, 6),
526 ]
527 +
528 +
529 +def test_group_description_is_summary_only():
530 + """Group descriptions are config docstrings, too long for the terminal."""
531 + parser = FlexibleArgumentParser()
532 + group = parser.add_argument_group(
533 + title="MyConfig",
534 + description="Summary line.\n\nDetails which only belong in the docs.",
535 + )
536 + group.add_argument("--my-arg")
537 +
538 + assert "Summary line." in parser.format_help()
539 + assert "only belong in the docs" not in parser.format_help()
540 +
541 + parser._search_keyword = "myconfig"
542 + assert "Summary line." in parser.format_help()
543 + assert "only belong in the docs" not in parser.format_help()
vllm/utils/argparse_utils.py
+18 -7
@@ -93,6 +93,11 @@ def human_readable_int_or_auto(value: str) -> int:
93 return human_readable_int(value)
94
95
96 +def summary_line(description: str | None) -> str:
97 + """Return the first paragraph of a config docstring as a single line."""
98 + return " ".join((description or "").split("\n\n", 1)[0].split())
99 +
100 +
101 class SortedHelpFormatter(ArgumentDefaultsHelpFormatter, RawDescriptionHelpFormatter):
102 """SortedHelpFormatter that sorts arguments by their option strings."""
103
@@ -203,7 +208,7 @@ class FlexibleArgumentParser(ArgumentParser):
208 for group in self._action_groups:
209 if group.title and group.title.lower() == search_keyword:
210 formatter.start_section(group.title)
206 - formatter.add_text(group.description)
211 + formatter.add_text(summary_line(group.description))
212 formatter.add_arguments(group._group_actions)
213 formatter.end_section()
214 formatter.add_text(self._json_tip)
@@ -242,12 +247,18 @@ class FlexibleArgumentParser(ArgumentParser):
247 # positionals, optionals and user-defined groups
248 formatter.start_section("Config Groups")
249 config_groups = ""
245 - for group in self._action_groups:
246 - if not group._group_actions:
247 - continue
248 - title = group.title
249 - description = group.description or ""
250 - config_groups += f"{title: <24}{description}\n"
250 + groups = [g for g in self._action_groups if g._group_actions]
251 + titles = [g.title or "" for g in groups]
252 + title_width = max((len(title) for title in titles), default=0) + 1
253 + width = max(formatter._width - formatter._current_indent, title_width + 20)
254 + for title, group in zip(titles, groups):
255 + lines = textwrap.wrap(
256 + summary_line(group.description),
257 + width,
258 + initial_indent=f"{title: <{title_width}}",
259 + subsequent_indent=" " * title_width,
260 + )
261 + config_groups += ("\n".join(lines) or title) + "\n"
262 formatter.add_text(config_groups)
263 formatter.end_section()
264