From 78572c189d6f808e56aa620ddc281ac905d63e28 Mon Sep 17 00:00:00 2001 From: JunyiXu-nv <219237550+JunyiXu-nv@users.noreply.github.com> Date: Mon, 2 Nov 2026 06:11:53 +0000 Subject: [PATCH 1/2] [TRTLLM-17557][fix] Make the configuration-database CLI test runnable test_database_yaml_config_serve_cli runs the real launch_server with a mocked LLM and server, but the fakes predate two launch_server behaviors: the serving-frontend count now defaults to more than one, so launch_server tried to spawn attached frontend processes by re-executing the test's own command line and crashed reading the mocked executor's IPC directory, and _apply_fastapi_middlewares reads the server's .app, which the mock server lacked. Pin --num_serve_frontends 1 in the test's CLI argv and give the mock server a real FastAPI app. Stop collecting examples/configs/curated/eplb/ as serving configs: those files are MoE expert-placement tables that the Qwen3.8 max-throughput configs reference through moe_config.load_balancer, so they can neither validate as TorchLlmArgs nor start trtllm-serve on their own (lookup.yaml is excluded from collection for the same reason). Add the three examples/configs/curated/lookup.yaml entries that test_all_configs_have_lookup_entry still requires: the Hopper Marlin NVFP4 Nemotron recipe and the two Qwen3.5 GB300 agentic disaggregated configs, and regenerate docs/source/_static/config_db.json from the lookup files as the other lookup changes do. Signed-off-by: JunyiXu-nv <219237550+JunyiXu-nv@users.noreply.github.com> --- docs/source/_static/config_db.json | 12 ++++++++++++ examples/configs/curated/lookup.yaml | 17 +++++++++++++++++ tests/unittest/llmapi/test_config_database.py | 16 +++++++++++++++- 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/docs/source/_static/config_db.json b/docs/source/_static/config_db.json index 8f9f4ebec38e..29dd33a51cc1 100644 --- a/docs/source/_static/config_db.json +++ b/docs/source/_static/config_db.json @@ -24,6 +24,18 @@ "model_url": "https://huggingface.co/nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B-NVFP4", "scenario": "Max Throughput" }, + { + "command": "trtllm-serve nvidia/NVIDIA-Nemotron-3-Super-120B-A12B-NVFP4 --config ${TRTLLM_DIR}/examples/configs/curated/nemotron-super-marlin.yaml", + "config_filename": "nemotron-super-marlin.yaml", + "config_github_url": "https://github.com/NVIDIA/TensorRT-LLM/blob/main/examples/configs/curated/nemotron-super-marlin.yaml", + "config_path": "examples/configs/curated/nemotron-super-marlin.yaml", + "config_raw_url": "https://raw.githubusercontent.com/NVIDIA/TensorRT-LLM/main/examples/configs/curated/nemotron-super-marlin.yaml", + "gpu_compatibility": "H100, H200", + "model": "nvidia/NVIDIA-Nemotron-3-Super-120B-A12B-NVFP4", + "model_display_name": "Nemotron v3 Super (NVFP4)", + "model_url": "https://huggingface.co/nvidia/NVIDIA-Nemotron-3-Super-120B-A12B-NVFP4", + "scenario": "NVFP4 on Hopper (Marlin)" + }, { "command": "trtllm-serve Qwen/Qwen3-Next-80B-A3B-Thinking --config ${TRTLLM_DIR}/examples/configs/curated/qwen3-next.yaml", "config_filename": "qwen3-next.yaml", diff --git a/examples/configs/curated/lookup.yaml b/examples/configs/curated/lookup.yaml index da0789bc22e5..0cf8431c105e 100644 --- a/examples/configs/curated/lookup.yaml +++ b/examples/configs/curated/lookup.yaml @@ -9,6 +9,11 @@ config_path: examples/configs/curated/nemotron-3-ultra-throughput.yaml scenario: Max Throughput gpu_compatibility: "B200, B300, GB200, GB300, H100, H200" +- model: nvidia/NVIDIA-Nemotron-3-Super-120B-A12B-NVFP4 + arch: NemotronHForCausalLM + config_path: examples/configs/curated/nemotron-super-marlin.yaml + scenario: NVFP4 on Hopper (Marlin) + gpu_compatibility: "H100, H200" - model: Qwen/Qwen3-Next-80B-A3B-Thinking arch: Qwen3NextForCausalLM config_path: examples/configs/curated/qwen3-next.yaml @@ -56,6 +61,18 @@ config_path: examples/configs/curated/qwen3.5.yaml scenario: Max Throughput gpu_compatibility: "B200, B300, GB200, GB300" +- model: nvidia/Qwen3.5-397B-A17B-NVFP4-V2 + arch: Qwen3_5MoeForCausalLM + config_path: examples/configs/curated/qwen3.5-gb300-agentic-prefill.yaml + scenario: Agentic Disaggregated Prefill + gpu_compatibility: "GB300" + disagg: true +- model: nvidia/Qwen3.5-397B-A17B-NVFP4-V2 + arch: Qwen3_5MoeForCausalLM + config_path: examples/configs/curated/qwen3.5-gb300-agentic-decode.yaml + scenario: Agentic Disaggregated Decode + gpu_compatibility: "GB300" + disagg: true - model: Qwen/Qwen3-30B-A3B arch: Qwen3MoeForCausalLM config_path: examples/configs/curated/qwen3.yaml diff --git a/tests/unittest/llmapi/test_config_database.py b/tests/unittest/llmapi/test_config_database.py index b443c231e15e..5c4d73c6d68b 100644 --- a/tests/unittest/llmapi/test_config_database.py +++ b/tests/unittest/llmapi/test_config_database.py @@ -45,7 +45,14 @@ CURATED_DIR = CONFIG_ROOT / "curated" DATABASE_DIR = CONFIG_ROOT / "database" -CURATED_CONFIGS = collect_yaml_files(CURATED_DIR, "**/*.yaml", exclude_names={"lookup.yaml"}) +# curated/eplb/ holds MoE expert-placement tables that curated configs reference through +# moe_config.load_balancer; like lookup.yaml they are not standalone serving configs. +CURATED_EPLB_DIR = CURATED_DIR / "eplb" +CURATED_CONFIGS = [ + path + for path in collect_yaml_files(CURATED_DIR, "**/*.yaml", exclude_names={"lookup.yaml"}) + if CURATED_EPLB_DIR not in path.parents +] DATABASE_CONFIGS = collect_yaml_files(DATABASE_DIR, "**/*.yaml", exclude_names={"lookup.yaml"}) ALL_CONFIGS = sorted(CURATED_CONFIGS + DATABASE_CONFIGS) ALL_LOOKUP_PATHS = sorted((DATABASE_DIR / "lookup.yaml", CURATED_DIR / "lookup.yaml")) @@ -207,6 +214,11 @@ def _serve_cli_args(config_path: Path, port: int = 17999): str(config_path), "--port", str(port), + # With more than one frontend, launch_server spawns attached frontend + # processes by re-executing sys.argv (here: the pytest command line); + # a single frontend keeps the real launch_server in-process. + "--num_serve_frontends", + "1", ] @@ -218,6 +230,8 @@ class _MockOpenAIServer: def __init__(self, generator, model, **kwargs): self.generator = generator self.model = model + # launch_server registers --middleware objects on the server's app. + self.app = FastAPI() def __call__(self, host, port, sockets=None): return _noop_serve(host, port, sockets) From 9f3d439b484ab61879e091c47881bb6480f18382 Mon Sep 17 00:00:00 2001 From: JunyiXu-nv <219237550+JunyiXu-nv@users.noreply.github.com> Date: Mon, 2 Nov 2026 20:03:42 +0000 Subject: [PATCH 2/2] [None][test] Note that the config-database CLI test covers one frontend only Passing --num_serve_frontends skips the default frontend-count resolution a plain trtllm-serve --config run goes through. Signed-off-by: JunyiXu-nv <219237550+JunyiXu-nv@users.noreply.github.com> --- tests/unittest/llmapi/test_config_database.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/unittest/llmapi/test_config_database.py b/tests/unittest/llmapi/test_config_database.py index 5c4d73c6d68b..33dc9011af9f 100644 --- a/tests/unittest/llmapi/test_config_database.py +++ b/tests/unittest/llmapi/test_config_database.py @@ -216,7 +216,9 @@ def _serve_cli_args(config_path: Path, port: int = 17999): str(port), # With more than one frontend, launch_server spawns attached frontend # processes by re-executing sys.argv (here: the pytest command line); - # a single frontend keeps the real launch_server in-process. + # a single frontend keeps the real launch_server in-process. Passing + # the flag skips the default frontend-count resolution, so this test + # covers the single-frontend path only. "--num_serve_frontends", "1", ]