[build-system] requires = [ "setuptools>=77.0.3,<81.0.0", "wheel", "setuptools-scm>=8.0", ] build-backend = "setuptools.build_meta" [project] name = "vllm-omni" dynamic = ["version", "dependencies"] description = "A framework for efficient model inference with omni-modality models" readme = "README.md" requires-python = ">=3.10,<3.14" license = "Apache-2.0" authors = [ {name = "vLLM-Omni Team"} ] keywords = ["vllm", "multimodal", "diffusion", "transformer", "inference", "serving"] classifiers = [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "Intended Audience :: Science/Research", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Topic :: Scientific/Engineering :: Artificial Intelligence", "Topic :: Software Development :: Libraries :: Python Modules", ] # Dependencies are now managed dynamically via setup.py based on detected hardware platform. # This allows automatic installation of the correct platform-specific dependencies (CUDA/ROCm/CPU/XPU/NPU) # without requiring extras like [cuda]. See requirements/ directory for platform-specific dependencies. [project.optional-dependencies] dev = [ "pytest==9.1.1", "pytest-asyncio==1.4.0", "pytest-cov==7.1.0", "pytest-mock==3.15.1", "pytest-shard==0.1.2", "pytest-xdist==3.8.0", "websockets==16.1", "pytest-subtests==0.15.0", "filelock>=3.16.1,<4", "datasets==3.6.0", "mypy==1.11.1", "pre-commit==4.0.1", "openai-whisper==20250625", "psutil==7.2.2", "soundfile==0.14.0", "imageio[ffmpeg]==2.37.4", "opencv-python==5.0.0.93", # 0.3.12 includes acknowledged TCP writes (Mooncake #2850): completion # must mean the receive buffer is ready before zero-copy consumers read it. "mooncake-transfer-engine-cuda13==0.3.12.post1", "av==18.0.0; python_version >= '3.11'", # for ComfyUI tests "av==17.1.0; python_version < '3.11'", # last av release that supports Python 3.10 "tomli==2.4.1; python_version < '3.11'", # tomllib backport used by tests/helpers/mark.py "openpyxl==3.1.5", # for nightly CI "pyttsx3==2.99", "opencc==1.4.1", "mistune==3.3.4", # for example tests "torchmetrics==1.9.0", # for accuracy similarity metrics "ray[default]==2.56.1", # for RL test "jiwer==4.0.0", "zhon==2.1.1", "zhconv==1.4.3", "funasr==1.3.29", "lpips==0.1.4", # for quantization fp8 "orjson==3.11.9", # to make v1/embeddings API fast "voxcpm==2.0.3", # for VoxCPM2 path-locating in tests "torchdiffeq==0.2.5", # for covo_audio Test "FlagEmbedding==1.4.0", # for hunyuan_image3 tests # Provides top-level cosyvoice2; do not co-install stepaudio2-minicpmo, # whose top-level stepaudio2 package conflicts with this distribution. "step-audio2==1.0.0", # Step-Audio2 / MiniCPM-o 4.5 Token2Wav (flashcosyvoice / hyperpyyaml) ] demo = [ "gradio>=6.7.0", "opencv-python>=4.12.0.88", # cli/stream_client frame reading "requests>=2.28.0", # cli/stream_client HTTP "cn2an>=0.5.22", # Chinese number normalization for TTS (e.g. "1次" -> "一次") ] forced-aligner = [ "qwen-asr>=0.0.6", # faithful Japanese/Korean word segmentation for the TTS forced aligner ] indextts2 = [ "fugashi>=1.2.0", "unidic-lite>=1.0.0", "wetext>=0.0.9; sys_platform != 'linux'", "WeTextProcessing; sys_platform == 'linux'", ] # Local-test-only extras local = [ "FlagEmbedding", ] # LongCat-Video-Avatar A2V/AI2V runtime dependencies for vocal # separation and loudness normalization. longcat-video-avatar = [ "audio-separator==0.44.2", "pyloudnorm==0.1.1", "soundfile>=0.13.1", ] # Optional Blackwell-only fused-bias FP8 GEMM; package is `quack-kernels` (imported # as `quack`), not the unrelated `quack`. See docs/user_guide/quantization/fp8.md. quack = [ "quack-kernels>=0.3.11", ] # Optional Blackwell-native FlashAttention-4 backend. Keep this opt-in because # the CuTe/CUTLASS dependency is CUDA 13 and Blackwell specific. fa4 = [ "flash-attn-4[cu13]==4.0.0b18", ] # FastVideo VSA kernels for the supported Linux/Python 3.12 wheel environment. vsa = [ "fastvideo-kernel==0.3.4", ] docs = [ "mkdocs>=1.5.0", "mkdocs-api-autonav", "mkdocs-material", "mkdocstrings-python", "mkdocs-gen-files", "mkdocs-awesome-nav", "mkdocs-redirects", "mkdocs-glightbox", "mkdocs-git-revision-date-localized-plugin", "mkdocs-minify-plugin", "regex", "ruff", "pydantic", ] [project.urls] Homepage = "https://github.com/vllm-project/vllm-omni" Repository = "https://github.com/vllm-project/vllm-omni" Documentation = "https://vllm-omni.readthedocs.io" "Bug Tracker" = "https://github.com/vllm-project/vllm-omni/issues" [project.scripts] vllm-omni = "vllm_omni.entrypoints.cli.main:main" # Register vllm-omni's model registrations on every vllm subprocess. vllm # auto-loads anything advertised under `vllm.general_plugins` in its own # `load_general_plugins()`, so worker subprocesses spawned by vllm (which # only import vllm, not vllm_omni) will still pick up the omni archs. [project.entry-points."vllm.general_plugins"] vllm_omni_register_models = "vllm_omni.engine.arg_utils:register_omni_models_to_vllm" [tool.setuptools] include-package-data = false [tool.setuptools.packages.find] where = ["."] include = ["vllm_omni*"] [tool.setuptools.package-data] "vllm_omni" = [ "_version.py", "py.typed", "deploy/*.md", "deploy/*.yaml", "diffusion/distributed/csrc/*.cu", "diffusion/distributed/csrc/*.hpp", "model_executor/models/covo_audio/speaker_prompt/*.npy", "model_executor/models/step_audio2/assets/*.wav", "transformers_utils/chat_templates/*.jinja", ] [tool.setuptools_scm] # no extra settings needed, presence enables setuptools-scm [tool.ruff] line-length = 120 exclude = [ ".eggs", ".git", ".hg", ".mypy_cache", ".tox", ".venv", "build", "dist", "vllm_omni.egg-info", ] [tool.ruff.lint] select = [ "E", # pycodestyle errors "W", # pycodestyle warnings "F", # pyflakes "I", # isort (handled separately, but included for compatibility) "N", # pep8-naming "UP", # pyupgrade "TID251", # flake8-tidy-imports.banned-api "TC004", # flake8-type-checking: runtime-used imports ] ignore = [ "E203", # whitespace before ':' (conflicts with black) # W503 is not needed in ruff as it's compatible with black by default "N801", # class names should use CapWords convention "N802", # function name should follow snake_case "N806", # variable in function should follow snake_case "N812", # lowercase imported as non-lowercase: functional as F ] [tool.ruff.lint.per-file-ignores] "examples/**" = ["E501"] # Allow long lines in examples "tests/**" = ["E501"] # Allow long lines in tests # MiniCPM-o reference modeling code vendored from upstream HF/transformers/MiniCPM-o. # These files keep upstream conventions (star imports, long lines, math-symbol # argument names) so they stay easy to diff against upstream releases. "vllm_omni/model_executor/models/minicpmo_4_5/minicpmo_4_5_omni_llm.py" = ["E402", "E501", "F403", "F405", "N803"] # NemotronVoiceChat inference modules vendored from NVIDIA-NeMo/Speech (branch # nemotron-labs-voicechat). Numerics-bearing code is kept byte-close to # upstream to stay diffable and parity-safe, so upstream style (long lines, # legacy typing, whitespace, unused-import shims) is exempted. TID251 and the # F-correctness rules still apply. "vllm_omni/model_executor/models/nemotron_voicechat/nemo_vendored/**" = ["E501", "E721", "E741", "F401", "F841", "I001", "N803", "N814", "UP006", "UP007", "UP008", "UP011", "UP032", "UP035", "W291", "W293"] "vllm_omni/experimental/fullduplex/joyvl/decision/prompts.py" = ["E501"] # System/summarizer prompts are long prose lines # Kandinsky 6 keeps native/BigVGAN names (T/H/W, `l`) and NVIDIA vocoder # docstring length so the port stays diffable against the source modules. "vllm_omni/diffusion/models/kandinsky6/kandinsky6_transformer.py" = ["N803", "E741"] "vllm_omni/diffusion/models/kandinsky6/pipeline_kandinsky6.py" = ["N803"] "vllm_omni/diffusion/models/kandinsky6/modeling_kandinsky6_audio.py" = ["E501", "E741", "N803", "UP008"] [tool.ruff.lint.flake8-tidy-imports.banned-api] "librosa".msg = "The librosa module is banned, use vllm.multimodal helpers instead" "torch.cuda.max_memory_allocated".msg = "Use torch.accelerator.max_memory_allocated" "torch.cuda.reset_peak_memory_stats".msg = "Use torch.accelerator.reset_peak_memory_stats" "torch.cuda.device_count".msg = "Use torch.accelerator.device_count" "torch.cuda.current_device".msg = "Use torch.accelerator.current_device_index" "torch.cuda.empty_cache".msg = "Use torch.accelerator.empty_cache" "torch.cuda.synchronize".msg = "Use torch.accelerator.synchronize" [tool.mypy] python_version = "3.12" # Align with vLLM: silent follow for library code; missing third-party stubs # are ignored everywhere (including tests). tests/ still get # --follow-imports skip from tools/pre_commit/mypy.py. plugins = ["pydantic.mypy"] ignore_missing_imports = true check_untyped_defs = true follow_imports = "silent" [tool.pytest.ini_options] asyncio_mode = "auto" testpaths = ["tests"] python_files = ["test_*.py", "*_test.py"] python_classes = ["Test*"] python_functions = ["test_*"] addopts = [ "--strict-markers", "--strict-config", "--dist=loadgroup" ] markers = [ # ci/cd required — tag with [ci-level] for tests.helpers.mark.get_level_markers(). "core_model: [ci-level] L1&L2 tests (run in each PR)", "advanced_model: [ci-level] L3 level tests (run on each merge)", "full_model: [ci-level] L4 level tests (run nightly)", "local_model: [ci-level] tests (run locally)", # function module markers "diffusion: Diffusion model tests", "omni: Omni model tests", "tts: TTS model tests", "cache: Cache backend tests", "parallel: Parallelism/distributed tests", "sp: Sequence parallelism tests", "example: Doc example code tests", "nvidia_only: Tests that require NVIDIA CUDA and must not run on ROCm", # platform markers # Tag with [hardware-platform] for tests.helpers.mark.get_supported_platforms(). # Add [gpu] on accelerator platforms that should also get pytest.mark.gpu. # cpu/gpu are pytest marks; hardware_test(res=...) rejects them as keys. "cpu: [hardware-platform] Tests that run on CPU", "gpu: [hardware-platform] Tests that run on GPU (auto-added)", "cuda: [hardware-platform] [gpu] Tests that run on CUDA (auto-added)", "rocm: [hardware-platform] [gpu] Tests that run on AMD/ROCm (auto-added)", "xpu: [hardware-platform] [gpu] Tests that run on XPU (auto-added)", "npu: [hardware-platform] Tests that run on NPU/Ascend (auto-added)", "musa: [hardware-platform] [gpu] Tests that run on MUSA/Moore Threads (auto-added)", # specified computation resources marks (auto-added) # [hardware-resource] + [cuda]/[rocm]/[xpu]/[npu]/[musa] for hardware_test(res=...). # Do not put [gpu] on SKU lines: that would make gpu a res key. "H100: [hardware-resource] [cuda] Tests that require H100 GPU", "H800: [hardware-resource] [cuda] Tests that require H800 GPU", "H200: [hardware-resource] [cuda] Tests that require H200 GPU", "L4: [hardware-resource] [cuda] Tests that require L4 GPU", "B200: [hardware-resource] [cuda] Tests that require B200 GPU", "MI325: [hardware-resource] [rocm] Tests that require MI325 GPU (AMD/ROCm)", "B60: [hardware-resource] [xpu] Tests that require Intel Arc Pro B60 XPU", "S5000: [hardware-resource] [musa] Tests that require S5000 GPU (Moore Threads/MUSA)", "A2: [hardware-resource] [npu] Tests that require A2 NPU", "A3: [hardware-resource] [npu] Tests that require A3 NPU", "A5: [hardware-resource] [npu] Tests that require A5 NPU", "310P: [hardware-resource] [npu] Tests that require 310P NPU", # Tag with [hardware-cards] for tests.helpers.mark.get_supported_card_counts(). "cards_1: [hardware-cards] Tests that require 1 accelerator card", "cards_2: [hardware-cards] Tests that require 2 accelerator cards", "cards_3: [hardware-cards] Tests that require 3 accelerator cards", "cards_4: [hardware-cards] Tests that require 4 accelerator cards", "cards_5: [hardware-cards] Tests that require 5 accelerator cards", "cards_6: [hardware-cards] Tests that require 6 accelerator cards", "cards_7: [hardware-cards] Tests that require 7 accelerator cards", "cards_8: [hardware-cards] Tests that require 8 accelerator cards", # more detailed markers "sp: Sequence parallelism tests (multi-GPU)", "slow: [ci-level] Slow tests (may skip in quick CI)", "benchmark: Benchmark tests", "xdist: xdist-parallelizable tests", ] filterwarnings = [ "ignore:.*does not have '__test__' attribute.*:UserWarning", "ignore:.*does not have '__bases__' attribute.*:UserWarning", ] [tool.coverage.run] core = "sysmon" source = ["vllm_omni"] # Online-serving tests launch the server via subprocess.Popen and stop it with # SIGTERM. pytest-cov no longer instruments subprocesses implicitly, and a # SIGTERM-ed process discards its data, so without patch/sigterm a coverage run # over an online test measures only the pytest parent. patch = ["subprocess"] concurrency = ["multiprocessing", "thread"] sigterm = true [tool.coverage.report] show_missing = true skip_covered = true [tool.typos.default] extend-ignore-identifiers-re = [ # Canonical PyTorch CUDA device property. "^shared_memory_per_block_optin$", ".*_thw", ".*thw", "ein", ".*arange", ".*MoBA", ".*temperal_downsample", ".*temperal_upsample", ".*_nd", ".*nd$", ".*EmbedND$", ".*nothink.*", ".*NOTHINK.*", ".*nin.*", ".*[Oo]no_[Aa]nna.*", ".*cann.*", ".*[Nn][Dd]3.*", ".*updator.*", "byt5.*", # NemotronVoiceChat vendored triton kernel: dout/DOUT abbreviate d_out # (output feature dim), not "doubt". ".*dout.*", ".*DOUT.*", # Kandinsky nabla threshold argument (`thr`), not the word "the". "^thr$", ] extend-ignore-re = [ "\\.\\.\\.n,d->\\.\\.\\.nd", # setuptools-scm / git-describe local versions, e.g. 0.26.1.dev14+gae6577ea "\\+g[0-9a-f]{7,}", ] [tool.typos.default.extend-words] ue = "ue" # Einstein-summation index tuple for head/expert/dimension axes. hed = "hed" semantics = "semantics" fullset = "fullset" Vai = "Vai" tockens = "tockens" CANN = "CANN" # Step-Audio reasoning parser streams `` tokens split across chunks # (e.g. ""). The fragment "thi" appears literally in its # parser logic and tests and is not a typo of "the"/"this". thi = "thi" ND = "ND" byt5 = "byt5" # "seeked" is the standard HTML media element DOM event name (fires when a # seek completes), used by the word-timestamps Gradio demo. Not a typo. seeked = "seeked" # Ryan Leary: author credited in the NemotronVoiceChat vendored NeMo # features.py copyright header. A surname, not a typo of "leery". Leary = "Leary" # IndexTTS 2.5 language codes and speech-emotion-recognition event token. fo = "fo" ba = "ba" SER = "SER" # NumPy ndarray.flags.writeable (canonical flag name, not "writable"). writeable = "writeable" # ARPAbet phoneme symbol (Fish Speech phoneme-control token example, e.g. # "IY0"), not a typo of "IT". IY = "IY" # "convnet" abbreviates convolutional network. It appears in the vendored Fish # Speech DAC codec identifiers (convnet_type, transconvnet_type) and is not a # typo of "convent". convnet = "convnet" # Upstream Kandinsky system prompt. "promt" and "scren" are part of the # conditioning text and must not be corrected. thr = "thr" promt = "promt" scren = "scren"