# SPDX-License-Identifier: Apache-2.0 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project import logging import sys from argparse import SUPPRESS, HelpFormatter from pathlib import Path from typing import Literal from unittest.mock import MagicMock, patch ROOT_DIR = Path(__file__).parent.parent.parent.parent ARGPARSE_DOC_DIR = ROOT_DIR / "docs/argparse" sys.path.insert(0, str(ROOT_DIR)) sys.modules["aiohttp"] = MagicMock() sys.modules["blake3"] = MagicMock() sys.modules["vllm._C"] = MagicMock() from vllm.engine.arg_utils import AsyncEngineArgs, EngineArgs # noqa: E402 from vllm.utils import FlexibleArgumentParser # noqa: E402 logger = logging.getLogger("mkdocs") class MarkdownFormatter(HelpFormatter): """Custom formatter that generates markdown for argument groups.""" def __init__(self, prog): super().__init__(prog, max_help_position=float('inf'), width=float('inf')) self._markdown_output = [] def start_section(self, heading): if heading not in {"positional arguments", "options"}: self._markdown_output.append(f"\n### {heading}\n\n") def end_section(self): pass def add_text(self, text): if text: self._markdown_output.append(f"{text.strip()}\n\n") def add_usage(self, usage, actions, groups, prefix=None): pass def add_arguments(self, actions): for action in actions: option_strings = f'`{"`, `".join(action.option_strings)}`' self._markdown_output.append(f"#### {option_strings}\n\n") if choices := action.choices: choices = f'`{"`, `".join(str(c) for c in choices)}`' self._markdown_output.append( f"Possible choices: {choices}\n\n") self._markdown_output.append(f"{action.help}\n\n") if (default := action.default) != SUPPRESS: self._markdown_output.append(f"Default: `{default}`\n\n") def format_help(self): """Return the formatted help as markdown.""" return "".join(self._markdown_output) def create_parser(cls, **kwargs) -> FlexibleArgumentParser: """Create a parser for the given class with markdown formatting. Args: cls: The class to create a parser for **kwargs: Additional keyword arguments to pass to `cls.add_cli_args`. Returns: FlexibleArgumentParser: A parser with markdown formatting for the class. """ parser = FlexibleArgumentParser() parser.formatter_class = MarkdownFormatter with patch("vllm.config.DeviceConfig.__post_init__"): return cls.add_cli_args(parser, **kwargs) def on_startup(command: Literal["build", "gh-deploy", "serve"], dirty: bool): logger.info("Generating argparse documentation") logger.debug("Root directory: %s", ROOT_DIR.resolve()) logger.debug("Output directory: %s", ARGPARSE_DOC_DIR.resolve()) # Create the ARGPARSE_DOC_DIR if it doesn't exist if not ARGPARSE_DOC_DIR.exists(): ARGPARSE_DOC_DIR.mkdir(parents=True) # Create parsers to document parsers = { "engine_args": create_parser(EngineArgs), "async_engine_args": create_parser(AsyncEngineArgs, async_args_only=True), } # Generate documentation for each parser for stem, parser in parsers.items(): doc_path = ARGPARSE_DOC_DIR / f"{stem}.md" with open(doc_path, "w") as f: f.write(parser.format_help()) logger.info("Argparse generated: %s", doc_path.relative_to(ROOT_DIR))