diff --git a/python/pyproject.toml b/python/pyproject.toml index ce4d87ff3..bfe0dd649 100755 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -89,7 +89,7 @@ diffusion = [ "imageio==2.36.0", "imageio-ffmpeg==0.5.1", "moviepy>=2.0.0", - "opencv-python==4.10.0.84", + "opencv-python-headless==4.10.0.84", "remote-pdb", "st_attn ==0.0.7", "vsa==0.0.4", diff --git a/python/sglang/multimodal_gen/configs/sample/sampling_params.py b/python/sglang/multimodal_gen/configs/sample/sampling_params.py index 2adc7c94f..4d538a93f 100644 --- a/python/sglang/multimodal_gen/configs/sample/sampling_params.py +++ b/python/sglang/multimodal_gen/configs/sample/sampling_params.py @@ -16,6 +16,7 @@ from dataclasses import dataclass from enum import Enum, auto from typing import Any +from sglang.multimodal_gen import envs from sglang.multimodal_gen.runtime.utils.logging_utils import init_logger from sglang.multimodal_gen.utils import StoreBoolean @@ -207,6 +208,10 @@ class SamplingParams: if env_steps is not None and self.num_inference_steps is not None: self.num_inference_steps = int(env_steps) + # Auto-enable stage logging if dump path is provided + if self.perf_dump_path: + envs.SGLANG_DIFFUSION_STAGE_LOGGING = True + def _validate(self): """ check if the sampling params is correct by itself diff --git a/python/sglang/multimodal_gen/runtime/entrypoints/cli/generate.py b/python/sglang/multimodal_gen/runtime/entrypoints/cli/generate.py index 42c4489f5..0aad34db2 100644 --- a/python/sglang/multimodal_gen/runtime/entrypoints/cli/generate.py +++ b/python/sglang/multimodal_gen/runtime/entrypoints/cli/generate.py @@ -8,7 +8,6 @@ import dataclasses import os from typing import cast -import sglang.multimodal_gen.envs as envs from sglang.multimodal_gen import DiffGenerator from sglang.multimodal_gen.configs.sample.sampling_params import SamplingParams from sglang.multimodal_gen.runtime.entrypoints.cli.cli_types import CLISubcommand @@ -89,11 +88,6 @@ def generate_cmd(args: argparse.Namespace): """The entry point for the generate command.""" args.request_id = "mocked_fake_id_for_offline_generate" - # Auto-enable stage logging if dump path is provided - if args.perf_dump_path: - os.environ["SGLANG_DIFFUSION_STAGE_LOGGING"] = "True" - envs.SGLANG_DIFFUSION_STAGE_LOGGING = True - server_args = ServerArgs.from_cli_args(args) sampling_params_kwargs = SamplingParams.get_cli_args(args) generator = DiffGenerator.from_pretrained( diff --git a/python/sglang/multimodal_gen/runtime/managers/gpu_worker.py b/python/sglang/multimodal_gen/runtime/managers/gpu_worker.py index f6905d137..a656c03ec 100644 --- a/python/sglang/multimodal_gen/runtime/managers/gpu_worker.py +++ b/python/sglang/multimodal_gen/runtime/managers/gpu_worker.py @@ -26,7 +26,10 @@ from sglang.multimodal_gen.runtime.utils.logging_utils import ( globally_suppress_loggers, init_logger, ) -from sglang.multimodal_gen.runtime.utils.perf_logger import PerformanceLogger +from sglang.multimodal_gen.runtime.utils.perf_logger import ( + PerformanceLogger, + StageProfiler, +) logger = init_logger(__name__) @@ -108,7 +111,7 @@ class GPUWorker: if output_batch.timings: duration_ms = (time.monotonic() - start_time) * 1000 output_batch.timings.total_duration_ms = duration_ms - if req.perf_dump_path is not None: + if StageProfiler.metrics_enabled(): PerformanceLogger.log_request_summary(timings=output_batch.timings) except Exception as e: logger.error( diff --git a/python/sglang/multimodal_gen/test/run_suite.py b/python/sglang/multimodal_gen/test/run_suite.py index 35fea064f..9f47799cd 100644 --- a/python/sglang/multimodal_gen/test/run_suite.py +++ b/python/sglang/multimodal_gen/test/run_suite.py @@ -77,14 +77,45 @@ def parse_args(): def collect_test_items(files, filter_expr=None): - """Collect test item node IDs from the given files using pytest --collect-only.""" + """Collect test item node IDs from the given files using pytest --collect-only. + + Raises: + RuntimeError: If pytest collection fails due to errors (e.g., syntax errors, + import errors, or other collection failures). + """ cmd = [sys.executable, "-m", "pytest", "--collect-only", "-q"] if filter_expr: cmd.extend(["-k", filter_expr]) cmd.extend(files) + logger.info(f"Collecting tests with command: {' '.join(cmd)}") result = subprocess.run(cmd, capture_output=True, text=True) + # Check for collection errors + # pytest exit codes: + # 0: success + # 1: tests collected but some had errors during collection + # 2: test execution interrupted + # 3: internal error + # 4: command line usage error + # 5: no tests collected (may be expected with filters) + if result.returncode not in (0, 5): + error_msg = ( + f"pytest --collect-only failed with exit code {result.returncode}\n" + f"Command: {' '.join(cmd)}\n" + ) + if result.stderr: + error_msg += f"stderr:\n{result.stderr}\n" + if result.stdout: + error_msg += f"stdout:\n{result.stdout}\n" + logger.error(error_msg) + raise RuntimeError(error_msg) + + if result.returncode == 5: + logger.info( + "No tests were collected (exit code 5). This may be expected with filters." + ) + # Parse the output to extract test node IDs # pytest -q outputs lines like: test_file.py::TestClass::test_method[param] test_items = [] @@ -97,6 +128,7 @@ def collect_test_items(files, filter_expr=None): if "::" in test_id: test_items.append(test_id) + logger.info(f"Collected {len(test_items)} test items") return test_items