[Chore] Bump Python version and apply formatting changes for v0.12 release (#126)
Signed-off-by: DarkLight1337 <tlleungac@connect.ust.hk>
This commit is contained in:
1 parent
31fedcfa2b
commit
c091a03d82
61 files changed
+534
-553
No files matched your search
@@ -23,7 +23,7 @@ repos:
|
||||
- id: ruff-format
|
||||
|
||||
- repo: https://github.com/crate-ci/typos
|
||||
rev: v1.35.5
|
||||
rev: v1.38.1
|
||||
hooks:
|
||||
- id: typos
|
||||
# only for staged files
|
||||
|
||||
@@ -201,7 +201,7 @@ omni = Omni(
|
||||
|
||||
You can customize the configuration by modifying the `cache_config` dictionary to use only specific methods (e.g., DBCache only, DBCache + SCM, etc.) based on your quality and speed requirements.
|
||||
|
||||
To test another model, you can modify `--model` with the target model identifier like `Tongyi-MAI/Z-Image-Turbo` and update `cache_confg` according the model architecture (e.g., number of transformer blocks).
|
||||
To test another model, you can modify `--model` with the target model identifier like `Tongyi-MAI/Z-Image-Turbo` and update `cache_config` according the model architecture (e.g., number of transformer blocks).
|
||||
|
||||
|
||||
## Additional Resources
|
||||
|
||||
@@ -6,7 +6,7 @@ with the correct prompt format on Qwen2.5-Omni
|
||||
"""
|
||||
|
||||
import os
|
||||
from typing import NamedTuple, Optional
|
||||
from typing import NamedTuple
|
||||
|
||||
import librosa
|
||||
import numpy as np
|
||||
@@ -58,9 +58,9 @@ def get_text_query(question: str = None) -> QueryResult:
|
||||
|
||||
|
||||
def get_mixed_modalities_query(
|
||||
video_path: Optional[str] = None,
|
||||
image_path: Optional[str] = None,
|
||||
audio_path: Optional[str] = None,
|
||||
video_path: str | None = None,
|
||||
image_path: str | None = None,
|
||||
audio_path: str | None = None,
|
||||
num_frames: int = 16,
|
||||
sampling_rate: int = 16000,
|
||||
) -> QueryResult:
|
||||
@@ -114,7 +114,7 @@ def get_mixed_modalities_query(
|
||||
|
||||
|
||||
def get_use_audio_in_video_query(
|
||||
video_path: Optional[str] = None, num_frames: int = 16, sampling_rate: int = 16000
|
||||
video_path: str | None = None, num_frames: int = 16, sampling_rate: int = 16000
|
||||
) -> QueryResult:
|
||||
question = "Describe the content of the video, then convert what the baby say into text."
|
||||
prompt = (
|
||||
@@ -151,7 +151,7 @@ def get_use_audio_in_video_query(
|
||||
)
|
||||
|
||||
|
||||
def get_multi_audios_query(audio_path: Optional[str] = None, sampling_rate: int = 16000) -> QueryResult:
|
||||
def get_multi_audios_query(audio_path: str | None = None, sampling_rate: int = 16000) -> QueryResult:
|
||||
question = "Are these two audio clips the same?"
|
||||
prompt = (
|
||||
f"<|im_start|>system\n{default_system}<|im_end|>\n"
|
||||
@@ -190,7 +190,7 @@ def get_multi_audios_query(audio_path: Optional[str] = None, sampling_rate: int
|
||||
)
|
||||
|
||||
|
||||
def get_image_query(question: str = None, image_path: Optional[str] = None) -> QueryResult:
|
||||
def get_image_query(question: str = None, image_path: str | None = None) -> QueryResult:
|
||||
if question is None:
|
||||
question = "What is the content of this image?"
|
||||
prompt = (
|
||||
@@ -219,7 +219,7 @@ def get_image_query(question: str = None, image_path: Optional[str] = None) -> Q
|
||||
)
|
||||
|
||||
|
||||
def get_video_query(question: str = None, video_path: Optional[str] = None, num_frames: int = 16) -> QueryResult:
|
||||
def get_video_query(question: str = None, video_path: str | None = None, num_frames: int = 16) -> QueryResult:
|
||||
if question is None:
|
||||
question = "Why is this video funny?"
|
||||
prompt = (
|
||||
@@ -247,7 +247,7 @@ def get_video_query(question: str = None, video_path: Optional[str] = None, num_
|
||||
)
|
||||
|
||||
|
||||
def get_audio_query(question: str = None, audio_path: Optional[str] = None, sampling_rate: int = 16000) -> QueryResult:
|
||||
def get_audio_query(question: str = None, audio_path: str | None = None, sampling_rate: int = 16000) -> QueryResult:
|
||||
if question is None:
|
||||
question = "What is the content of this audio?"
|
||||
prompt = (
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
from typing import Optional
|
||||
|
||||
|
||||
def extract_prompt(line: str) -> Optional[str]:
|
||||
def extract_prompt(line: str) -> str | None:
|
||||
# Extract the content between the first '|' and the second '|'
|
||||
i = line.find("|")
|
||||
if i == -1:
|
||||
|
||||
@@ -6,7 +6,7 @@ with the correct prompt format on Qwen3-Omni (thinker only).
|
||||
"""
|
||||
|
||||
import os
|
||||
from typing import NamedTuple, Optional
|
||||
from typing import NamedTuple
|
||||
|
||||
import librosa
|
||||
import numpy as np
|
||||
@@ -57,7 +57,7 @@ def get_text_query(question: str = None) -> QueryResult:
|
||||
)
|
||||
|
||||
|
||||
def get_video_query(question: str = None, video_path: Optional[str] = None, num_frames: int = 16) -> QueryResult:
|
||||
def get_video_query(question: str = None, video_path: str | None = None, num_frames: int = 16) -> QueryResult:
|
||||
if question is None:
|
||||
question = "Why is this video funny?"
|
||||
prompt = (
|
||||
@@ -85,7 +85,7 @@ def get_video_query(question: str = None, video_path: Optional[str] = None, num_
|
||||
)
|
||||
|
||||
|
||||
def get_image_query(question: str = None, image_path: Optional[str] = None) -> QueryResult:
|
||||
def get_image_query(question: str = None, image_path: str | None = None) -> QueryResult:
|
||||
if question is None:
|
||||
question = "What is the content of this image?"
|
||||
prompt = (
|
||||
@@ -114,7 +114,7 @@ def get_image_query(question: str = None, image_path: Optional[str] = None) -> Q
|
||||
)
|
||||
|
||||
|
||||
def get_audio_query(question: str = None, audio_path: Optional[str] = None, sampling_rate: int = 16000) -> QueryResult:
|
||||
def get_audio_query(question: str = None, audio_path: str | None = None, sampling_rate: int = 16000) -> QueryResult:
|
||||
if question is None:
|
||||
question = "What is the content of this audio?"
|
||||
prompt = (
|
||||
|
||||
@@ -5,7 +5,7 @@ import signal
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from types import SimpleNamespace
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
|
||||
import gradio as gr
|
||||
import numpy as np
|
||||
@@ -175,16 +175,16 @@ def create_prompt_args(base_args: argparse.Namespace) -> SimpleNamespace:
|
||||
|
||||
|
||||
def process_audio_file(
|
||||
audio_file: Optional[Any],
|
||||
) -> Optional[tuple[np.ndarray, int]]:
|
||||
audio_file: Any | None,
|
||||
) -> tuple[np.ndarray, int] | None:
|
||||
"""Normalize Gradio audio input to (np.ndarray, sample_rate)."""
|
||||
if audio_file is None:
|
||||
return None
|
||||
|
||||
sample_rate: Optional[int] = None
|
||||
audio_np: Optional[np.ndarray] = None
|
||||
sample_rate: int | None = None
|
||||
audio_np: np.ndarray | None = None
|
||||
|
||||
def _load_from_path(path_str: str) -> Optional[tuple[np.ndarray, int]]:
|
||||
def _load_from_path(path_str: str) -> tuple[np.ndarray, int] | None:
|
||||
if not path_str:
|
||||
return None
|
||||
path = Path(path_str)
|
||||
@@ -237,7 +237,7 @@ def process_audio_file(
|
||||
return audio_np.astype(np.float32), sample_rate
|
||||
|
||||
|
||||
def process_image_file(image_file: Optional[Image.Image]) -> Optional[Image.Image]:
|
||||
def process_image_file(image_file: Image.Image | None) -> Image.Image | None:
|
||||
"""Process image file from Gradio input.
|
||||
|
||||
Returns:
|
||||
@@ -252,10 +252,10 @@ def process_image_file(image_file: Optional[Image.Image]) -> Optional[Image.Imag
|
||||
|
||||
|
||||
def process_video_file(
|
||||
video_file: Optional[str],
|
||||
video_file: str | None,
|
||||
enable_audio_in_video: bool = False,
|
||||
max_frames: int = 32,
|
||||
) -> Optional[tuple[np.ndarray, dict[str, Any], Optional[tuple[np.ndarray, int]]]]:
|
||||
) -> tuple[np.ndarray, dict[str, Any], tuple[np.ndarray, int] | None] | None:
|
||||
"""Process video file and optionally extract audio track."""
|
||||
if video_file is None:
|
||||
return None
|
||||
@@ -272,7 +272,7 @@ def process_video_file(
|
||||
print(f"Failed to decode video {video_path}: {exc}")
|
||||
return None
|
||||
|
||||
audio_tuple: Optional[tuple[np.ndarray, int]] = None
|
||||
audio_tuple: tuple[np.ndarray, int] | None = None
|
||||
if enable_audio_in_video:
|
||||
try:
|
||||
import librosa # type: ignore import
|
||||
@@ -290,9 +290,9 @@ async def run_inference_async_omni(
|
||||
sampling_params: list[SamplingParams],
|
||||
prompt_args_template: SimpleNamespace,
|
||||
user_prompt: str,
|
||||
audio_file: Optional[tuple[str, tuple[int, np.ndarray]]] = None,
|
||||
image_file: Optional[Image.Image] = None,
|
||||
video_file: Optional[str] = None,
|
||||
audio_file: tuple[str, tuple[int, np.ndarray]] | None = None,
|
||||
image_file: Image.Image | None = None,
|
||||
video_file: str | None = None,
|
||||
use_audio_in_video: bool = False,
|
||||
):
|
||||
"""Run inference using AsyncOmni directly with multimodal support."""
|
||||
@@ -420,9 +420,9 @@ def build_interface(
|
||||
|
||||
async def run_inference(
|
||||
user_prompt: str,
|
||||
audio_file: Optional[tuple[str, tuple[int, np.ndarray]]],
|
||||
image_file: Optional[Image.Image],
|
||||
video_file: Optional[str],
|
||||
audio_file: tuple[str, tuple[int, np.ndarray]] | None,
|
||||
image_file: Image.Image | None,
|
||||
video_file: str | None,
|
||||
use_audio_in_video: bool,
|
||||
):
|
||||
return await run_inference_async_omni(
|
||||
|
||||
+10
-11
@@ -1,6 +1,5 @@
|
||||
import base64
|
||||
import os
|
||||
from typing import Optional
|
||||
|
||||
import requests
|
||||
from openai import OpenAI
|
||||
@@ -38,7 +37,7 @@ def encode_base64_content_from_file(file_path: str) -> str:
|
||||
return result
|
||||
|
||||
|
||||
def get_video_url_from_path(video_path: Optional[str]) -> str:
|
||||
def get_video_url_from_path(video_path: str | None) -> str:
|
||||
"""Convert a video path (local file or URL) to a video URL format for the API.
|
||||
|
||||
If video_path is None or empty, returns the default URL.
|
||||
@@ -77,7 +76,7 @@ def get_video_url_from_path(video_path: Optional[str]) -> str:
|
||||
return f"data:{mime_type};base64,{video_base64}"
|
||||
|
||||
|
||||
def get_image_url_from_path(image_path: Optional[str]) -> str:
|
||||
def get_image_url_from_path(image_path: str | None) -> str:
|
||||
"""Convert an image path (local file or URL) to an image URL format for the API.
|
||||
|
||||
If image_path is None or empty, returns the default URL.
|
||||
@@ -114,7 +113,7 @@ def get_image_url_from_path(image_path: Optional[str]) -> str:
|
||||
return f"data:{mime_type};base64,{image_base64}"
|
||||
|
||||
|
||||
def get_audio_url_from_path(audio_path: Optional[str]) -> str:
|
||||
def get_audio_url_from_path(audio_path: str | None) -> str:
|
||||
"""Convert an audio path (local file or URL) to an audio URL format for the API.
|
||||
|
||||
If audio_path is None or empty, returns the default URL.
|
||||
@@ -169,7 +168,7 @@ def get_system_prompt():
|
||||
}
|
||||
|
||||
|
||||
def get_text_query(custom_prompt: Optional[str] = None):
|
||||
def get_text_query(custom_prompt: str | None = None):
|
||||
question = (
|
||||
custom_prompt or "Explain the system architecture for a scalable audio generation pipeline. Answer in 15 words."
|
||||
)
|
||||
@@ -186,10 +185,10 @@ def get_text_query(custom_prompt: Optional[str] = None):
|
||||
|
||||
|
||||
def get_mixed_modalities_query(
|
||||
video_path: Optional[str] = None,
|
||||
image_path: Optional[str] = None,
|
||||
audio_path: Optional[str] = None,
|
||||
custom_prompt: Optional[str] = None,
|
||||
video_path: str | None = None,
|
||||
image_path: str | None = None,
|
||||
audio_path: str | None = None,
|
||||
custom_prompt: str | None = None,
|
||||
):
|
||||
question = (
|
||||
custom_prompt or "What is recited in the audio? What is the content of this image? Why is this video funny?"
|
||||
@@ -222,7 +221,7 @@ def get_mixed_modalities_query(
|
||||
return prompt
|
||||
|
||||
|
||||
def get_use_audio_in_video_query(video_path: Optional[str] = None, custom_prompt: Optional[str] = None):
|
||||
def get_use_audio_in_video_query(video_path: str | None = None, custom_prompt: str | None = None):
|
||||
question = custom_prompt or "Describe the content of the video, then convert what the baby say into text."
|
||||
video_url = get_video_url_from_path(video_path)
|
||||
|
||||
@@ -246,7 +245,7 @@ def get_use_audio_in_video_query(video_path: Optional[str] = None, custom_prompt
|
||||
return prompt
|
||||
|
||||
|
||||
def get_multi_audios_query(audio_path: Optional[str] = None, custom_prompt: Optional[str] = None):
|
||||
def get_multi_audios_query(audio_path: str | None = None, custom_prompt: str | None = None):
|
||||
question = custom_prompt or "Are these two audio clips the same?"
|
||||
audio_url = get_audio_url_from_path(audio_path)
|
||||
prompt = {
|
||||
|
||||
@@ -5,7 +5,7 @@ import signal
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from types import SimpleNamespace
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
|
||||
import gradio as gr
|
||||
import numpy as np
|
||||
@@ -178,16 +178,16 @@ def create_prompt_args(base_args: argparse.Namespace) -> SimpleNamespace:
|
||||
|
||||
|
||||
def process_audio_file(
|
||||
audio_file: Optional[Any],
|
||||
) -> Optional[tuple[np.ndarray, int]]:
|
||||
audio_file: Any | None,
|
||||
) -> tuple[np.ndarray, int] | None:
|
||||
"""Normalize Gradio audio input to (np.ndarray, sample_rate)."""
|
||||
if audio_file is None:
|
||||
return None
|
||||
|
||||
sample_rate: Optional[int] = None
|
||||
audio_np: Optional[np.ndarray] = None
|
||||
sample_rate: int | None = None
|
||||
audio_np: np.ndarray | None = None
|
||||
|
||||
def _load_from_path(path_str: str) -> Optional[tuple[np.ndarray, int]]:
|
||||
def _load_from_path(path_str: str) -> tuple[np.ndarray, int] | None:
|
||||
if not path_str:
|
||||
return None
|
||||
path = Path(path_str)
|
||||
@@ -240,7 +240,7 @@ def process_audio_file(
|
||||
return audio_np.astype(np.float32), sample_rate
|
||||
|
||||
|
||||
def process_image_file(image_file: Optional[Image.Image]) -> Optional[Image.Image]:
|
||||
def process_image_file(image_file: Image.Image | None) -> Image.Image | None:
|
||||
"""Process image file from Gradio input.
|
||||
|
||||
Returns:
|
||||
@@ -255,10 +255,10 @@ def process_image_file(image_file: Optional[Image.Image]) -> Optional[Image.Imag
|
||||
|
||||
|
||||
def process_video_file(
|
||||
video_file: Optional[str],
|
||||
video_file: str | None,
|
||||
enable_audio_in_video: bool = False,
|
||||
max_frames: int = 32,
|
||||
) -> Optional[tuple[np.ndarray, dict[str, Any], Optional[tuple[np.ndarray, int]]]]:
|
||||
) -> tuple[np.ndarray, dict[str, Any], tuple[np.ndarray, int] | None] | None:
|
||||
"""Process video file and optionally extract audio track."""
|
||||
if video_file is None:
|
||||
return None
|
||||
@@ -275,7 +275,7 @@ def process_video_file(
|
||||
print(f"Failed to decode video {video_path}: {exc}")
|
||||
return None
|
||||
|
||||
audio_tuple: Optional[tuple[np.ndarray, int]] = None
|
||||
audio_tuple: tuple[np.ndarray, int] | None = None
|
||||
if enable_audio_in_video:
|
||||
try:
|
||||
import librosa # type: ignore import
|
||||
@@ -293,9 +293,9 @@ async def run_inference_async_omni(
|
||||
sampling_params: list[SamplingParams],
|
||||
prompt_args_template: SimpleNamespace,
|
||||
user_prompt: str,
|
||||
audio_file: Optional[tuple[str, tuple[int, np.ndarray]]] = None,
|
||||
image_file: Optional[Image.Image] = None,
|
||||
video_file: Optional[str] = None,
|
||||
audio_file: tuple[str, tuple[int, np.ndarray]] | None = None,
|
||||
image_file: Image.Image | None = None,
|
||||
video_file: str | None = None,
|
||||
use_audio_in_video: bool = False,
|
||||
):
|
||||
"""Run inference using AsyncOmni directly with multimodal support."""
|
||||
@@ -426,9 +426,9 @@ def build_interface(
|
||||
|
||||
async def run_inference(
|
||||
user_prompt: str,
|
||||
audio_file: Optional[tuple[str, tuple[int, np.ndarray]]],
|
||||
image_file: Optional[Image.Image],
|
||||
video_file: Optional[str],
|
||||
audio_file: tuple[str, tuple[int, np.ndarray]] | None,
|
||||
image_file: Image.Image | None,
|
||||
video_file: str | None,
|
||||
use_audio_in_video: bool,
|
||||
):
|
||||
return await run_inference_async_omni(
|
||||
|
||||
+8
-8
@@ -1,6 +1,6 @@
|
||||
import base64
|
||||
import os
|
||||
from typing import NamedTuple, Optional
|
||||
from typing import NamedTuple
|
||||
|
||||
import requests
|
||||
from openai import OpenAI
|
||||
@@ -43,7 +43,7 @@ def encode_base64_content_from_file(file_path: str) -> str:
|
||||
return result
|
||||
|
||||
|
||||
def get_video_url_from_path(video_path: Optional[str]) -> str:
|
||||
def get_video_url_from_path(video_path: str | None) -> str:
|
||||
"""Convert a video path (local file or URL) to a video URL format for the API.
|
||||
|
||||
If video_path is None or empty, returns the default URL.
|
||||
@@ -82,7 +82,7 @@ def get_video_url_from_path(video_path: Optional[str]) -> str:
|
||||
return f"data:{mime_type};base64,{video_base64}"
|
||||
|
||||
|
||||
def get_image_url_from_path(image_path: Optional[str]) -> str:
|
||||
def get_image_url_from_path(image_path: str | None) -> str:
|
||||
"""Convert an image path (local file or URL) to an image URL format for the API.
|
||||
|
||||
If image_path is None or empty, returns the default URL.
|
||||
@@ -119,7 +119,7 @@ def get_image_url_from_path(image_path: Optional[str]) -> str:
|
||||
return f"data:{mime_type};base64,{image_base64}"
|
||||
|
||||
|
||||
def get_audio_url_from_path(audio_path: Optional[str]) -> str:
|
||||
def get_audio_url_from_path(audio_path: str | None) -> str:
|
||||
"""Convert an audio path (local file or URL) to an audio URL format for the API.
|
||||
|
||||
If audio_path is None or empty, returns the default URL.
|
||||
@@ -174,7 +174,7 @@ def get_system_prompt():
|
||||
}
|
||||
|
||||
|
||||
def get_text_query(custom_prompt: Optional[str] = None):
|
||||
def get_text_query(custom_prompt: str | None = None):
|
||||
question = (
|
||||
custom_prompt or "Explain the system architecture for a scalable audio generation pipeline. Answer in 15 words."
|
||||
)
|
||||
@@ -197,7 +197,7 @@ default_system = (
|
||||
)
|
||||
|
||||
|
||||
def get_video_query(video_path: Optional[str] = None, custom_prompt: Optional[str] = None):
|
||||
def get_video_query(video_path: str | None = None, custom_prompt: str | None = None):
|
||||
question = custom_prompt or "Why is this video funny?"
|
||||
video_url = get_video_url_from_path(video_path)
|
||||
prompt = {
|
||||
@@ -216,7 +216,7 @@ def get_video_query(video_path: Optional[str] = None, custom_prompt: Optional[st
|
||||
return prompt
|
||||
|
||||
|
||||
def get_image_query(image_path: Optional[str] = None, custom_prompt: Optional[str] = None):
|
||||
def get_image_query(image_path: str | None = None, custom_prompt: str | None = None):
|
||||
question = custom_prompt or "What is the content of this image?"
|
||||
image_url = get_image_url_from_path(image_path)
|
||||
prompt = {
|
||||
@@ -235,7 +235,7 @@ def get_image_query(image_path: Optional[str] = None, custom_prompt: Optional[st
|
||||
return prompt
|
||||
|
||||
|
||||
def get_audio_query(audio_path: Optional[str] = None, custom_prompt: Optional[str] = None):
|
||||
def get_audio_query(audio_path: str | None = None, custom_prompt: str | None = None):
|
||||
question = custom_prompt or "What is the content of this audio?"
|
||||
audio_url = get_audio_url_from_path(audio_path)
|
||||
prompt = {
|
||||
|
||||
+5
-8
@@ -7,7 +7,7 @@ name = "vllm-omni"
|
||||
version = "0.11.0rc1"
|
||||
description = "A framework for efficient model inference with omni-modality models"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.9,<3.14" # Align with vLLM v0.11 supported Python versions
|
||||
requires-python = ">=3.10,<3.14"
|
||||
license = {text = "Apache-2.0"}
|
||||
authors = [
|
||||
{name = "vLLM-Omni Team"}
|
||||
@@ -18,11 +18,10 @@ classifiers = [
|
||||
"Intended Audience :: Developers",
|
||||
"Intended Audience :: Science/Research",
|
||||
"License :: OSI Approved :: Apache Software License",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"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",
|
||||
]
|
||||
@@ -48,10 +47,8 @@ dev = [
|
||||
"pytest>=7.0.0",
|
||||
"pytest-asyncio>=0.21.0",
|
||||
"pytest-cov>=4.0.0",
|
||||
"black>=23.0.0",
|
||||
"isort>=5.12.0",
|
||||
"mypy>=1.0.0",
|
||||
"pre-commit>=3.0.0",
|
||||
"mypy==1.11.1",
|
||||
"pre-commit==4.0.1",
|
||||
]
|
||||
|
||||
docs = [
|
||||
@@ -65,8 +62,8 @@ docs = [
|
||||
"mkdocs-git-revision-date-localized-plugin",
|
||||
"mkdocs-minify-plugin",
|
||||
"regex",
|
||||
"ruff",
|
||||
"pydantic",
|
||||
"black>=23.0.0",
|
||||
]
|
||||
|
||||
|
||||
|
||||
+13
-13
@@ -1,7 +1,7 @@
|
||||
import json
|
||||
import warnings
|
||||
from importlib.util import find_spec
|
||||
from typing import Any, Literal, Optional
|
||||
from typing import Any, Literal
|
||||
|
||||
import torch
|
||||
import vllm.envs as envs
|
||||
@@ -65,8 +65,8 @@ class OmniModelConfig(ModelConfig):
|
||||
stage_id: int = 0
|
||||
model_stage: str = "thinker"
|
||||
model_arch: str = "Qwen2_5OmniForConditionalGeneration"
|
||||
engine_output_type: Optional[str] = None
|
||||
hf_config_name: Optional[str] = None
|
||||
engine_output_type: str | None = None
|
||||
hf_config_name: str | None = None
|
||||
|
||||
@property
|
||||
def registry(self):
|
||||
@@ -87,16 +87,16 @@ class OmniModelConfig(ModelConfig):
|
||||
def __post_init__(
|
||||
self,
|
||||
# Multimodal config init vars
|
||||
limit_mm_per_prompt: Optional[dict[str, int]],
|
||||
media_io_kwargs: Optional[dict[str, dict[str, Any]]],
|
||||
mm_processor_kwargs: Optional[dict[str, Any]],
|
||||
mm_processor_cache_gb: Optional[float],
|
||||
mm_processor_cache_type: Optional[MMCacheType],
|
||||
mm_shm_cache_max_object_size_mb: Optional[int],
|
||||
mm_encoder_tp_mode: Optional[MMEncoderTPMode],
|
||||
interleave_mm_strings: Optional[bool],
|
||||
skip_mm_profiling: Optional[bool],
|
||||
video_pruning_rate: Optional[float],
|
||||
limit_mm_per_prompt: dict[str, int] | None,
|
||||
media_io_kwargs: dict[str, dict[str, Any]] | None,
|
||||
mm_processor_kwargs: dict[str, Any] | None,
|
||||
mm_processor_cache_gb: float | None,
|
||||
mm_processor_cache_type: MMCacheType | None,
|
||||
mm_shm_cache_max_object_size_mb: int | None,
|
||||
mm_encoder_tp_mode: MMEncoderTPMode | None,
|
||||
interleave_mm_strings: bool | None,
|
||||
skip_mm_profiling: bool | None,
|
||||
video_pruning_rate: float | None,
|
||||
) -> None:
|
||||
# Set the default seed to 0 in V1.
|
||||
if envs.VLLM_USE_V1 and self.seed is None:
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import time
|
||||
from collections import defaultdict
|
||||
from typing import Optional
|
||||
|
||||
from vllm.v1.core.kv_cache_manager import KVCacheBlocks
|
||||
from vllm.v1.core.sched.request_queue import create_request_queue
|
||||
@@ -170,7 +169,7 @@ class OmniGenerationScheduler(VLLMScheduler):
|
||||
kv_connector_output = model_runner_output.kv_connector_output
|
||||
|
||||
outputs: dict[int, list[EngineCoreOutput]] = defaultdict(list)
|
||||
spec_decoding_stats: Optional[SpecDecodingStats] = None
|
||||
spec_decoding_stats: SpecDecodingStats | None = None
|
||||
kv_connector_stats = kv_connector_output.kv_connector_stats if kv_connector_output else None
|
||||
|
||||
# NOTE(woosuk): As len(num_scheduled_tokens) can be up to 1K or more,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional
|
||||
|
||||
from vllm.v1.core.sched.output import NewRequestData
|
||||
from vllm.v1.request import Request
|
||||
@@ -21,9 +20,9 @@ class OmniNewRequestData(NewRequestData):
|
||||
"""
|
||||
|
||||
# Optional serialized prompt embeddings
|
||||
prompt_embeds: Optional[PromptEmbedsPayload] = None
|
||||
prompt_embeds: PromptEmbedsPayload | None = None
|
||||
# Optional serialized additional information
|
||||
additional_information: Optional[AdditionalInformationPayload] = None
|
||||
additional_information: AdditionalInformationPayload | None = None
|
||||
|
||||
@classmethod
|
||||
def from_request(
|
||||
|
||||
+4
-3
@@ -7,7 +7,8 @@ This module provides a CacheDiTBackend class to enable cache-dit acceleration on
|
||||
pipelines in vllm-omni, supporting both single and dual-transformer architectures.
|
||||
"""
|
||||
|
||||
from typing import Any, Callable, Optional
|
||||
from collections.abc import Callable
|
||||
from typing import Any, Optional
|
||||
|
||||
from vllm.logger import init_logger
|
||||
|
||||
@@ -311,8 +312,8 @@ class CacheDiTBackend(CacheBackend):
|
||||
super().__init__(config)
|
||||
|
||||
# Cache-dit specific attributes
|
||||
self._refresh_func: Optional[Callable[[Any, int, bool], None]] = None
|
||||
self._last_num_inference_steps: Optional[int] = None
|
||||
self._refresh_func: Callable[[Any, int, bool], None] | None = None
|
||||
self._last_num_inference_steps: int | None = None
|
||||
|
||||
def enable(self, pipeline: Any) -> None:
|
||||
"""Enable cache-dit on the pipeline if configured.
|
||||
|
||||
+1
-2
@@ -2,7 +2,6 @@
|
||||
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional
|
||||
|
||||
# Model-specific polynomial coefficients for rescaling L1 distances
|
||||
# These coefficients account for model-specific characteristics in how embeddings change
|
||||
@@ -51,7 +50,7 @@ class TeaCacheConfig:
|
||||
"""
|
||||
|
||||
rel_l1_thresh: float = 0.2
|
||||
coefficients: Optional[list[float]] = None
|
||||
coefficients: list[float] | None = None
|
||||
model_type: str = "QwenImagePipeline"
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
|
||||
+3
-2
@@ -13,8 +13,9 @@ all model-specific information needed for generic caching, including preprocessi
|
||||
transformer execution, and postprocessing logic.
|
||||
"""
|
||||
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, Callable, Union
|
||||
from typing import Any
|
||||
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
@@ -146,7 +147,7 @@ def extract_qwen_context(
|
||||
hidden_states: torch.Tensor,
|
||||
encoder_hidden_states: torch.Tensor,
|
||||
encoder_hidden_states_mask: torch.Tensor,
|
||||
timestep: Union[torch.Tensor, float, int],
|
||||
timestep: torch.Tensor | float | int,
|
||||
img_shapes: torch.Tensor,
|
||||
txt_seq_lens: torch.Tensor,
|
||||
guidance: torch.Tensor | None = None,
|
||||
|
||||
+3
-5
@@ -7,8 +7,6 @@ TeaCache state management.
|
||||
This module manages the state for TeaCache hooks across diffusion timesteps.
|
||||
"""
|
||||
|
||||
from typing import Optional
|
||||
|
||||
import torch
|
||||
|
||||
|
||||
@@ -27,9 +25,9 @@ class TeaCacheState:
|
||||
|
||||
# Caching state
|
||||
self.accumulated_rel_l1_distance = 0.0
|
||||
self.previous_modulated_input: Optional[torch.Tensor] = None
|
||||
self.previous_residual: Optional[torch.Tensor] = None
|
||||
self.previous_residual_encoder: Optional[torch.Tensor] = None
|
||||
self.previous_modulated_input: torch.Tensor | None = None
|
||||
self.previous_residual: torch.Tensor | None = None
|
||||
self.previous_residual_encoder: torch.Tensor | None = None
|
||||
|
||||
def reset(self) -> None:
|
||||
"""Reset all state variables for a new inference run."""
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
import enum
|
||||
import os
|
||||
import random
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass, field, fields
|
||||
from typing import Any, Callable
|
||||
from typing import Any
|
||||
|
||||
import torch
|
||||
from vllm.logger import init_logger
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, Callable
|
||||
from typing import Any
|
||||
|
||||
import torch.nn as nn
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import logging
|
||||
import math
|
||||
import os
|
||||
from collections.abc import Iterable
|
||||
from typing import Any, Optional, Union
|
||||
from typing import Any
|
||||
|
||||
import numpy as np
|
||||
import torch
|
||||
@@ -75,10 +75,10 @@ def calculate_shift(
|
||||
|
||||
def retrieve_timesteps(
|
||||
scheduler,
|
||||
num_inference_steps: Optional[int] = None,
|
||||
device: Optional[Union[str, torch.device]] = None,
|
||||
timesteps: Optional[list[int]] = None,
|
||||
sigmas: Optional[list[float]] = None,
|
||||
num_inference_steps: int | None = None,
|
||||
device: str | torch.device | None = None,
|
||||
timesteps: list[int] | None = None,
|
||||
sigmas: list[float] | None = None,
|
||||
**kwargs,
|
||||
) -> tuple[torch.Tensor, int]:
|
||||
r"""
|
||||
@@ -186,7 +186,7 @@ def get_timestep_embedding(
|
||||
|
||||
def apply_rotary_emb_qwen(
|
||||
x: torch.Tensor,
|
||||
freqs_cis: Union[torch.Tensor, tuple[torch.Tensor]],
|
||||
freqs_cis: torch.Tensor | tuple[torch.Tensor],
|
||||
use_real: bool = True,
|
||||
use_real_unbind_dim: int = -1,
|
||||
) -> tuple[torch.Tensor, torch.Tensor]:
|
||||
@@ -359,8 +359,8 @@ class QwenImagePipeline(
|
||||
|
||||
def _get_qwen_prompt_embeds(
|
||||
self,
|
||||
prompt: Union[str, list[str]] = None,
|
||||
dtype: Optional[torch.dtype] = None,
|
||||
prompt: str | list[str] = None,
|
||||
dtype: torch.dtype | None = None,
|
||||
):
|
||||
dtype = dtype or self.text_encoder.dtype
|
||||
|
||||
@@ -400,10 +400,10 @@ class QwenImagePipeline(
|
||||
|
||||
def encode_prompt(
|
||||
self,
|
||||
prompt: Union[str, list[str]],
|
||||
prompt: str | list[str],
|
||||
num_images_per_prompt: int = 1,
|
||||
prompt_embeds: Optional[torch.Tensor] = None,
|
||||
prompt_embeds_mask: Optional[torch.Tensor] = None,
|
||||
prompt_embeds: torch.Tensor | None = None,
|
||||
prompt_embeds_mask: torch.Tensor | None = None,
|
||||
max_sequence_length: int = 1024,
|
||||
):
|
||||
r"""
|
||||
@@ -601,23 +601,23 @@ class QwenImagePipeline(
|
||||
def forward(
|
||||
self,
|
||||
req: OmniDiffusionRequest,
|
||||
prompt: Union[str, list[str]] = "",
|
||||
negative_prompt: Union[str, list[str]] = "",
|
||||
prompt: str | list[str] = "",
|
||||
negative_prompt: str | list[str] = "",
|
||||
true_cfg_scale: float = 4.0,
|
||||
height: int | None = None,
|
||||
width: int | None = None,
|
||||
num_inference_steps: int = 50,
|
||||
sigmas: Optional[list[float]] = None,
|
||||
sigmas: list[float] | None = None,
|
||||
guidance_scale: float = 1.0,
|
||||
num_images_per_prompt: int = 1,
|
||||
generator: Optional[Union[torch.Generator, list[torch.Generator]]] = None,
|
||||
latents: Optional[torch.Tensor] = None,
|
||||
prompt_embeds: Optional[torch.Tensor] = None,
|
||||
prompt_embeds_mask: Optional[torch.Tensor] = None,
|
||||
negative_prompt_embeds: Optional[torch.Tensor] = None,
|
||||
negative_prompt_embeds_mask: Optional[torch.Tensor] = None,
|
||||
output_type: Optional[str] = "pil",
|
||||
attention_kwargs: Optional[dict[str, Any]] = None,
|
||||
generator: torch.Generator | list[torch.Generator] | None = None,
|
||||
latents: torch.Tensor | None = None,
|
||||
prompt_embeds: torch.Tensor | None = None,
|
||||
prompt_embeds_mask: torch.Tensor | None = None,
|
||||
negative_prompt_embeds: torch.Tensor | None = None,
|
||||
negative_prompt_embeds_mask: torch.Tensor | None = None,
|
||||
output_type: str | None = "pil",
|
||||
attention_kwargs: dict[str, Any] | None = None,
|
||||
callback_on_step_end_tensor_inputs: list[str] = ["latents"],
|
||||
max_sequence_length: int = 512,
|
||||
) -> DiffusionOutput:
|
||||
|
||||
@@ -7,7 +7,7 @@ import logging
|
||||
import math
|
||||
import os
|
||||
from collections.abc import Iterable
|
||||
from typing import Any, Optional, Union
|
||||
from typing import Any
|
||||
|
||||
import numpy as np
|
||||
import PIL.Image
|
||||
@@ -134,10 +134,10 @@ def calculate_dimensions(target_area: float, ratio: float):
|
||||
|
||||
def retrieve_timesteps(
|
||||
scheduler,
|
||||
num_inference_steps: Optional[int] = None,
|
||||
device: Optional[Union[str, torch.device]] = None,
|
||||
timesteps: Optional[list[int]] = None,
|
||||
sigmas: Optional[list[float]] = None,
|
||||
num_inference_steps: int | None = None,
|
||||
device: str | torch.device | None = None,
|
||||
timesteps: list[int] | None = None,
|
||||
sigmas: list[float] | None = None,
|
||||
**kwargs,
|
||||
) -> tuple[torch.Tensor, int]:
|
||||
r"""
|
||||
@@ -173,7 +173,7 @@ def retrieve_timesteps(
|
||||
|
||||
|
||||
def retrieve_latents(
|
||||
encoder_output: torch.Tensor, generator: Optional[torch.Generator] = None, sample_mode: str = "argmax"
|
||||
encoder_output: torch.Tensor, generator: torch.Generator | None = None, sample_mode: str = "argmax"
|
||||
):
|
||||
"""Retrieve latents from VAE encoder output."""
|
||||
if hasattr(encoder_output, "latent_dist"):
|
||||
@@ -305,9 +305,9 @@ class QwenImageEditPipeline(
|
||||
|
||||
def _get_qwen_prompt_embeds(
|
||||
self,
|
||||
prompt: Union[str, list[str]] = None,
|
||||
image: Optional[torch.Tensor] = None,
|
||||
dtype: Optional[torch.dtype] = None,
|
||||
prompt: str | list[str] = None,
|
||||
image: torch.Tensor | None = None,
|
||||
dtype: torch.dtype | None = None,
|
||||
):
|
||||
dtype = dtype or self.text_encoder.dtype
|
||||
|
||||
@@ -350,9 +350,9 @@ class QwenImageEditPipeline(
|
||||
|
||||
def _get_qwen_prompt_embeds(
|
||||
self,
|
||||
prompt: Union[str, list[str]] = None,
|
||||
image: Optional[Union[PIL.Image.Image, torch.Tensor]] = None,
|
||||
dtype: Optional[torch.dtype] = None,
|
||||
prompt: str | list[str] = None,
|
||||
image: PIL.Image.Image | torch.Tensor | None = None,
|
||||
dtype: torch.dtype | None = None,
|
||||
):
|
||||
"""Get prompt embeddings with image support for editing."""
|
||||
dtype = dtype or self.text_encoder.dtype
|
||||
@@ -397,11 +397,11 @@ class QwenImageEditPipeline(
|
||||
|
||||
def encode_prompt(
|
||||
self,
|
||||
prompt: Union[str, list[str]],
|
||||
image: Optional[torch.Tensor] = None,
|
||||
prompt: str | list[str],
|
||||
image: torch.Tensor | None = None,
|
||||
num_images_per_prompt: int = 1,
|
||||
prompt_embeds: Optional[torch.Tensor] = None,
|
||||
prompt_embeds_mask: Optional[torch.Tensor] = None,
|
||||
prompt_embeds: torch.Tensor | None = None,
|
||||
prompt_embeds_mask: torch.Tensor | None = None,
|
||||
max_sequence_length: int = 1024,
|
||||
):
|
||||
r"""
|
||||
@@ -638,24 +638,24 @@ class QwenImageEditPipeline(
|
||||
def forward(
|
||||
self,
|
||||
req: OmniDiffusionRequest,
|
||||
prompt: Union[str, list[str]] = "",
|
||||
negative_prompt: Union[str, list[str]] = "",
|
||||
image: Optional[Union[PIL.Image.Image, torch.Tensor]] = None,
|
||||
prompt: str | list[str] = "",
|
||||
negative_prompt: str | list[str] = "",
|
||||
image: PIL.Image.Image | torch.Tensor | None = None,
|
||||
true_cfg_scale: float = 4.0,
|
||||
height: int | None = None,
|
||||
width: int | None = None,
|
||||
num_inference_steps: int = 50,
|
||||
sigmas: Optional[list[float]] = None,
|
||||
sigmas: list[float] | None = None,
|
||||
guidance_scale: float = 1.0,
|
||||
num_images_per_prompt: int = 1,
|
||||
generator: Optional[Union[torch.Generator, list[torch.Generator]]] = None,
|
||||
latents: Optional[torch.Tensor] = None,
|
||||
prompt_embeds: Optional[torch.Tensor] = None,
|
||||
prompt_embeds_mask: Optional[torch.Tensor] = None,
|
||||
negative_prompt_embeds: Optional[torch.Tensor] = None,
|
||||
negative_prompt_embeds_mask: Optional[torch.Tensor] = None,
|
||||
output_type: Optional[str] = "pil",
|
||||
attention_kwargs: Optional[dict[str, Any]] = None,
|
||||
generator: torch.Generator | list[torch.Generator] | None = None,
|
||||
latents: torch.Tensor | None = None,
|
||||
prompt_embeds: torch.Tensor | None = None,
|
||||
prompt_embeds_mask: torch.Tensor | None = None,
|
||||
negative_prompt_embeds: torch.Tensor | None = None,
|
||||
negative_prompt_embeds_mask: torch.Tensor | None = None,
|
||||
output_type: str | None = "pil",
|
||||
attention_kwargs: dict[str, Any] | None = None,
|
||||
callback_on_step_end_tensor_inputs: list[str] = ["latents"],
|
||||
max_sequence_length: int = 512,
|
||||
) -> DiffusionOutput:
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
import functools
|
||||
from collections.abc import Iterable
|
||||
from typing import Any, Optional, Union
|
||||
from typing import Any
|
||||
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
@@ -26,7 +26,7 @@ logger = init_logger(__name__)
|
||||
|
||||
def apply_rotary_emb_qwen(
|
||||
x: torch.Tensor,
|
||||
freqs_cis: Union[torch.Tensor, tuple[torch.Tensor]],
|
||||
freqs_cis: torch.Tensor | tuple[torch.Tensor],
|
||||
use_real: bool = True,
|
||||
use_real_unbind_dim: int = -1,
|
||||
) -> tuple[torch.Tensor, torch.Tensor]:
|
||||
@@ -393,8 +393,8 @@ class QwenImageTransformerBlock(nn.Module):
|
||||
encoder_hidden_states: torch.Tensor,
|
||||
encoder_hidden_states_mask: torch.Tensor,
|
||||
temb: torch.Tensor,
|
||||
image_rotary_emb: Optional[tuple[torch.Tensor, torch.Tensor]] = None,
|
||||
joint_attention_kwargs: Optional[dict[str, Any]] = None,
|
||||
image_rotary_emb: tuple[torch.Tensor, torch.Tensor] | None = None,
|
||||
joint_attention_kwargs: dict[str, Any] | None = None,
|
||||
) -> tuple[torch.Tensor, torch.Tensor]:
|
||||
# Get modulation parameters for both streams
|
||||
img_mod_params = self.img_mod(temb) # [B, 6*dim]
|
||||
@@ -490,7 +490,7 @@ class QwenImageTransformer2DModel(nn.Module):
|
||||
od_config: OmniDiffusionConfig,
|
||||
patch_size: int = 2,
|
||||
in_channels: int = 64,
|
||||
out_channels: Optional[int] = 16,
|
||||
out_channels: int | None = 16,
|
||||
num_layers: int = 60,
|
||||
attention_head_dim: int = 128,
|
||||
num_attention_heads: int = 24,
|
||||
@@ -537,12 +537,12 @@ class QwenImageTransformer2DModel(nn.Module):
|
||||
encoder_hidden_states: torch.Tensor = None,
|
||||
encoder_hidden_states_mask: torch.Tensor = None,
|
||||
timestep: torch.LongTensor = None,
|
||||
img_shapes: Optional[list[tuple[int, int, int]]] = None,
|
||||
txt_seq_lens: Optional[list[int]] = None,
|
||||
img_shapes: list[tuple[int, int, int]] | None = None,
|
||||
txt_seq_lens: list[int] | None = None,
|
||||
guidance: torch.Tensor = None, # TODO: this should probably be removed
|
||||
attention_kwargs: Optional[dict[str, Any]] = None,
|
||||
attention_kwargs: dict[str, Any] | None = None,
|
||||
return_dict: bool = True,
|
||||
) -> Union[torch.Tensor, Transformer2DModelOutput]:
|
||||
) -> torch.Tensor | Transformer2DModelOutput:
|
||||
"""
|
||||
The [`QwenTransformer2DModel`] forward method.
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
import math
|
||||
from collections.abc import Iterable
|
||||
from typing import Any, Optional, Union
|
||||
from typing import Any
|
||||
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
@@ -127,7 +127,7 @@ class WanRotaryPosEmbed(nn.Module):
|
||||
class WanImageEmbedding(nn.Module):
|
||||
"""Image embedding module for I2V tasks."""
|
||||
|
||||
def __init__(self, in_features: int, out_features: int, pos_embed_seq_len: Optional[int] = None):
|
||||
def __init__(self, in_features: int, out_features: int, pos_embed_seq_len: int | None = None):
|
||||
super().__init__()
|
||||
|
||||
self.norm1 = FP32LayerNorm(in_features)
|
||||
@@ -159,8 +159,8 @@ class WanTimeTextImageEmbedding(nn.Module):
|
||||
time_freq_dim: int,
|
||||
time_proj_dim: int,
|
||||
text_embed_dim: int,
|
||||
image_embed_dim: Optional[int] = None,
|
||||
pos_embed_seq_len: Optional[int] = None,
|
||||
image_embed_dim: int | None = None,
|
||||
pos_embed_seq_len: int | None = None,
|
||||
):
|
||||
super().__init__()
|
||||
|
||||
@@ -178,9 +178,9 @@ class WanTimeTextImageEmbedding(nn.Module):
|
||||
self,
|
||||
timestep: torch.Tensor,
|
||||
encoder_hidden_states: torch.Tensor,
|
||||
encoder_hidden_states_image: Optional[torch.Tensor] = None,
|
||||
timestep_seq_len: Optional[int] = None,
|
||||
) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor, Optional[torch.Tensor]]:
|
||||
encoder_hidden_states_image: torch.Tensor | None = None,
|
||||
timestep_seq_len: int | None = None,
|
||||
) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor, torch.Tensor | None]:
|
||||
timestep = self.timesteps_proj(timestep)
|
||||
if timestep_seq_len is not None:
|
||||
timestep = timestep.unflatten(0, (-1, timestep_seq_len))
|
||||
@@ -250,7 +250,7 @@ class WanSelfAttention(nn.Module):
|
||||
def forward(
|
||||
self,
|
||||
hidden_states: torch.Tensor,
|
||||
rotary_emb: Optional[tuple[torch.Tensor, torch.Tensor]] = None,
|
||||
rotary_emb: tuple[torch.Tensor, torch.Tensor] | None = None,
|
||||
) -> torch.Tensor:
|
||||
# Fused QKV projection
|
||||
qkv, _ = self.to_qkv(hidden_states)
|
||||
@@ -296,7 +296,7 @@ class WanCrossAttention(nn.Module):
|
||||
head_dim: int,
|
||||
eps: float = 1e-5,
|
||||
dropout: float = 0.0,
|
||||
added_kv_proj_dim: Optional[int] = None,
|
||||
added_kv_proj_dim: int | None = None,
|
||||
):
|
||||
super().__init__()
|
||||
|
||||
@@ -413,7 +413,7 @@ class WanTransformerBlock(nn.Module):
|
||||
ffn_dim: int,
|
||||
num_heads: int,
|
||||
eps: float = 1e-6,
|
||||
added_kv_proj_dim: Optional[int] = None,
|
||||
added_kv_proj_dim: int | None = None,
|
||||
cross_attn_norm: bool = False,
|
||||
):
|
||||
super().__init__()
|
||||
@@ -528,10 +528,10 @@ class WanTransformer3DModel(nn.Module):
|
||||
num_layers: int = 40,
|
||||
cross_attn_norm: bool = True,
|
||||
eps: float = 1e-6,
|
||||
image_dim: Optional[int] = None,
|
||||
added_kv_proj_dim: Optional[int] = None,
|
||||
image_dim: int | None = None,
|
||||
added_kv_proj_dim: int | None = None,
|
||||
rope_max_seq_len: int = 1024,
|
||||
pos_embed_seq_len: Optional[int] = None,
|
||||
pos_embed_seq_len: int | None = None,
|
||||
):
|
||||
super().__init__()
|
||||
|
||||
@@ -598,10 +598,10 @@ class WanTransformer3DModel(nn.Module):
|
||||
hidden_states: torch.Tensor,
|
||||
timestep: torch.LongTensor,
|
||||
encoder_hidden_states: torch.Tensor,
|
||||
encoder_hidden_states_image: Optional[torch.Tensor] = None,
|
||||
encoder_hidden_states_image: torch.Tensor | None = None,
|
||||
return_dict: bool = True,
|
||||
attention_kwargs: Optional[dict[str, Any]] = None,
|
||||
) -> Union[torch.Tensor, Transformer2DModelOutput]:
|
||||
attention_kwargs: dict[str, Any] | None = None,
|
||||
) -> torch.Tensor | Transformer2DModelOutput:
|
||||
batch_size, num_channels, num_frames, height, width = hidden_states.shape
|
||||
p_t, p_h, p_w = self.config.patch_size
|
||||
post_patch_num_frames = num_frames // p_t
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
import inspect
|
||||
import json
|
||||
import os
|
||||
from collections.abc import Iterable
|
||||
from typing import Any, Callable
|
||||
from collections.abc import Callable, Iterable
|
||||
from typing import Any
|
||||
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
import math
|
||||
from collections.abc import Iterable
|
||||
from typing import Optional
|
||||
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
@@ -232,7 +231,7 @@ class ZImageTransformerBlock(nn.Module):
|
||||
x: torch.Tensor,
|
||||
attn_mask: torch.Tensor,
|
||||
freqs_cis: torch.Tensor,
|
||||
adaln_input: Optional[torch.Tensor] = None,
|
||||
adaln_input: torch.Tensor | None = None,
|
||||
):
|
||||
if self.modulation:
|
||||
assert adaln_input is not None
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
# and vllm_omni.entrypoints.omni_llm.py
|
||||
|
||||
import time
|
||||
from typing import Any, Callable, Optional
|
||||
from collections.abc import Callable
|
||||
from typing import Any
|
||||
|
||||
from .utils.logging import get_connector_logger
|
||||
|
||||
@@ -90,7 +91,7 @@ def try_recv_via_connector(
|
||||
task: dict[str, Any],
|
||||
connectors: dict[Any, Any],
|
||||
stage_id: int,
|
||||
) -> tuple[Any, Optional[dict[str, Any]]]:
|
||||
) -> tuple[Any, dict[str, Any] | None]:
|
||||
"""
|
||||
Attempts to resolve input data from either connector or IPC.
|
||||
Returns (engine_inputs, rx_metrics) or (None, None) if failed/skipped.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
|
||||
from ..utils.logging import get_connector_logger
|
||||
|
||||
@@ -15,7 +15,7 @@ class OmniConnectorBase(ABC):
|
||||
@abstractmethod
|
||||
def put(
|
||||
self, from_stage: str, to_stage: str, request_id: str, data: Any
|
||||
) -> tuple[bool, int, Optional[dict[str, Any]]]:
|
||||
) -> tuple[bool, int, dict[str, Any] | None]:
|
||||
"""Store Python object, internal serialization handled by connector.
|
||||
|
||||
Args:
|
||||
@@ -32,8 +32,8 @@ class OmniConnectorBase(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def get(
|
||||
self, from_stage: str, to_stage: str, request_id: str, metadata: Optional[dict[str, Any]] = None
|
||||
) -> Optional[tuple[Any, int]]:
|
||||
self, from_stage: str, to_stage: str, request_id: str, metadata: dict[str, Any] | None = None
|
||||
) -> tuple[Any, int] | None:
|
||||
"""Retrieve Python object and payload size (bytes).
|
||||
|
||||
Args:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
||||
|
||||
import time
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
|
||||
from ..utils.logging import get_connector_logger
|
||||
from .base import OmniConnectorBase
|
||||
@@ -36,8 +36,8 @@ class MooncakeConnector(OmniConnectorBase):
|
||||
self.proto = config.get("proto", "tcp")
|
||||
self.rdma = config.get("rdma", "")
|
||||
|
||||
self.store: Optional[MooncakeDistributedStore] = None
|
||||
self.pin: Optional[ReplicateConfig] = None
|
||||
self.store: MooncakeDistributedStore | None = None
|
||||
self.pin: ReplicateConfig | None = None
|
||||
|
||||
self._metrics = {
|
||||
"puts": 0,
|
||||
@@ -74,7 +74,7 @@ class MooncakeConnector(OmniConnectorBase):
|
||||
|
||||
def put(
|
||||
self, from_stage: str, to_stage: str, request_id: str, data: Any
|
||||
) -> tuple[bool, int, Optional[dict[str, Any]]]:
|
||||
) -> tuple[bool, int, dict[str, Any] | None]:
|
||||
if not self.store:
|
||||
logger.error("Store not initialized")
|
||||
return False, 0, None
|
||||
@@ -102,8 +102,8 @@ class MooncakeConnector(OmniConnectorBase):
|
||||
return False, 0, None
|
||||
|
||||
def get(
|
||||
self, from_stage: str, to_stage: str, request_id: str, metadata: Optional[dict[str, Any]] = None
|
||||
) -> Optional[tuple[Any, int]]:
|
||||
self, from_stage: str, to_stage: str, request_id: str, metadata: dict[str, Any] | None = None
|
||||
) -> tuple[Any, int] | None:
|
||||
if not self.store:
|
||||
logger.error("Store not initialized")
|
||||
return None
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
||||
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
|
||||
from vllm_omni.entrypoints.stage_utils import shm_read_bytes, shm_write_bytes
|
||||
|
||||
@@ -31,7 +31,7 @@ class SharedMemoryConnector(OmniConnectorBase):
|
||||
|
||||
def put(
|
||||
self, from_stage: str, to_stage: str, request_id: str, data: Any
|
||||
) -> tuple[bool, int, Optional[dict[str, Any]]]:
|
||||
) -> tuple[bool, int, dict[str, Any] | None]:
|
||||
try:
|
||||
# Always serialize first to check size (and for SHM writing)
|
||||
# Note: For extremely large objects in "inline" mode (e.g. Ray),
|
||||
@@ -63,8 +63,8 @@ class SharedMemoryConnector(OmniConnectorBase):
|
||||
return False, 0, None
|
||||
|
||||
def get(
|
||||
self, from_stage: str, to_stage: str, request_id: str, metadata: Optional[dict[str, Any]] = None
|
||||
) -> Optional[tuple[Any, int]]:
|
||||
self, from_stage: str, to_stage: str, request_id: str, metadata: dict[str, Any] | None = None
|
||||
) -> tuple[Any, int] | None:
|
||||
if not metadata:
|
||||
logger.error(f"SharedMemoryConnector get called without metadata for req {request_id}")
|
||||
return None
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
|
||||
from .logging import get_connector_logger
|
||||
|
||||
@@ -28,9 +28,9 @@ class OmniTransferConfig:
|
||||
|
||||
# Direct mapping: (from_stage, to_stage) -> connector
|
||||
connectors: dict[tuple[str, str], ConnectorSpec] = field(default_factory=dict)
|
||||
default_connector: Optional[ConnectorSpec] = None
|
||||
default_connector: ConnectorSpec | None = None
|
||||
|
||||
def get_connector_for_edge(self, from_stage: str, to_stage: str) -> Optional[ConnectorSpec]:
|
||||
def get_connector_for_edge(self, from_stage: str, to_stage: str) -> ConnectorSpec | None:
|
||||
"""Get connector spec for a specific edge."""
|
||||
edge_key = (from_stage, to_stage)
|
||||
return self.connectors.get(edge_key, self.default_connector)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING, Any, Optional, Union
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from ..factory import OmniConnectorFactory
|
||||
from .config import ConnectorSpec, OmniTransferConfig
|
||||
@@ -21,8 +21,8 @@ logger = get_connector_logger(__name__)
|
||||
|
||||
|
||||
def initialize_connectors_from_config(
|
||||
config_path: Optional[Union[str, Path]] = None, default_shm_threshold: int = 65536
|
||||
) -> tuple[Optional[OmniTransferConfig], dict[tuple[str, str], OmniConnectorBase]]:
|
||||
config_path: str | Path | None = None, default_shm_threshold: int = 65536
|
||||
) -> tuple[OmniTransferConfig | None, dict[tuple[str, str], OmniConnectorBase]]:
|
||||
"""
|
||||
Initialize connectors from configuration file.
|
||||
|
||||
@@ -64,9 +64,7 @@ def create_connectors_from_config(
|
||||
return connectors
|
||||
|
||||
|
||||
def get_connectors_config_for_stage(
|
||||
transfer_config: Optional[OmniTransferConfig], stage_id: Union[str, int]
|
||||
) -> dict[str, Any]:
|
||||
def get_connectors_config_for_stage(transfer_config: OmniTransferConfig | None, stage_id: str | int) -> dict[str, Any]:
|
||||
"""
|
||||
Extract connector configurations relevant for a specific stage worker.
|
||||
|
||||
@@ -98,10 +96,10 @@ def get_connectors_config_for_stage(
|
||||
|
||||
|
||||
def load_omni_transfer_config(
|
||||
config_path: Optional[Union[str, Path]] = None,
|
||||
config_dict: Optional[dict[str, Any]] = None,
|
||||
config_path: str | Path | None = None,
|
||||
config_dict: dict[str, Any] | None = None,
|
||||
default_shm_threshold: int = 65536,
|
||||
) -> Optional[OmniTransferConfig]:
|
||||
) -> OmniTransferConfig | None:
|
||||
"""Load OmniTransferConfig from file or dict."""
|
||||
if config_path is None and config_dict is None:
|
||||
# Even if no config provided, we might want to return a default config with SHM connectors
|
||||
@@ -239,8 +237,8 @@ def load_omni_transfer_config(
|
||||
|
||||
|
||||
def initialize_orchestrator_connectors(
|
||||
config_path: Optional[str], worker_backend: Optional[str] = "multi_process", shm_threshold_bytes: int = 65536
|
||||
) -> tuple[Optional[OmniTransferConfig], dict[tuple[str, str], OmniConnectorBase]]:
|
||||
config_path: str | None, worker_backend: str | None = "multi_process", shm_threshold_bytes: int = 65536
|
||||
) -> tuple[OmniTransferConfig | None, dict[tuple[str, str], OmniConnectorBase]]:
|
||||
"""Initialize connectors shared at orchestrator level.
|
||||
Args:
|
||||
config_path: The path to the configuration file.
|
||||
@@ -259,7 +257,7 @@ def initialize_orchestrator_connectors(
|
||||
|
||||
|
||||
def get_stage_connector_config(
|
||||
transfer_config: Optional[OmniTransferConfig],
|
||||
transfer_config: OmniTransferConfig | None,
|
||||
stage_id: int,
|
||||
) -> dict[str, Any]:
|
||||
"""Return the serialized connector config payload for a specific stage."""
|
||||
@@ -280,7 +278,7 @@ def get_stage_connector_config(
|
||||
def build_stage_connectors(
|
||||
stage_id: int,
|
||||
connectors_config: dict[str, Any],
|
||||
) -> Optional[dict[tuple[str, str], Any]]:
|
||||
) -> dict[tuple[str, str], Any] | None:
|
||||
"""Instantiate OmniConnectors for a stage based on config."""
|
||||
if not connectors_config:
|
||||
return {}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import logging
|
||||
import os
|
||||
from contextlib import contextmanager
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
|
||||
import torch
|
||||
|
||||
@@ -96,7 +96,7 @@ def get_ray_queue_class():
|
||||
return lambda: RayQueue(maxsize=0)
|
||||
|
||||
|
||||
def initialize_ray_cluster(address: Optional[str] = None):
|
||||
def initialize_ray_cluster(address: str | None = None):
|
||||
if not RAY_AVAILABLE:
|
||||
logger.warning("Ray is not available, skipping initialization.")
|
||||
return
|
||||
@@ -107,9 +107,7 @@ def initialize_ray_cluster(address: Optional[str] = None):
|
||||
ray.init(address=address, ignore_reinit_error=True, runtime_env=runtime_env)
|
||||
|
||||
|
||||
def create_placement_group(
|
||||
number_of_stages: int, address: Optional[str] = None, strategy: str = "PACK"
|
||||
) -> PlacementGroup:
|
||||
def create_placement_group(number_of_stages: int, address: str | None = None, strategy: str = "PACK") -> PlacementGroup:
|
||||
"""Create a placement group for the given number of stages.
|
||||
Args:
|
||||
number_of_stages: The number of stages to create the placement group for.
|
||||
|
||||
@@ -4,7 +4,7 @@ Engine components for vLLM-Omni.
|
||||
|
||||
import time
|
||||
from collections.abc import Mapping
|
||||
from typing import Any, Optional, Union
|
||||
from typing import Any
|
||||
|
||||
import msgspec
|
||||
import torch
|
||||
@@ -42,12 +42,12 @@ class AdditionalInformationEntry(msgspec.Struct):
|
||||
"""
|
||||
|
||||
# Tensor form
|
||||
tensor_data: Optional[bytes] = None
|
||||
tensor_shape: Optional[list[int]] = None
|
||||
tensor_dtype: Optional[str] = None
|
||||
tensor_data: bytes | None = None
|
||||
tensor_shape: list[int] | None = None
|
||||
tensor_dtype: str | None = None
|
||||
|
||||
# List form
|
||||
list_data: Optional[list[Any]] = None
|
||||
list_data: list[Any] | None = None
|
||||
|
||||
|
||||
class AdditionalInformationPayload(msgspec.Struct):
|
||||
@@ -74,9 +74,9 @@ class OmniEngineCoreRequest(EngineCoreRequest):
|
||||
"""
|
||||
|
||||
# Optional prompt embeddings (direct-transfer version)
|
||||
prompt_embeds: Optional[PromptEmbedsPayload] = None
|
||||
prompt_embeds: PromptEmbedsPayload | None = None
|
||||
# Optional additional information dictionary (serialized)
|
||||
additional_information: Optional[AdditionalInformationPayload] = None
|
||||
additional_information: AdditionalInformationPayload | None = None
|
||||
|
||||
|
||||
class OmniEngineCoreOutput(
|
||||
@@ -88,17 +88,17 @@ class OmniEngineCoreOutput(
|
||||
request_id: str
|
||||
new_token_ids: list[int]
|
||||
|
||||
new_logprobs: Optional[LogprobsLists] = None
|
||||
new_prompt_logprobs_tensors: Optional[LogprobsTensors] = None
|
||||
new_logprobs: LogprobsLists | None = None
|
||||
new_prompt_logprobs_tensors: LogprobsTensors | None = None
|
||||
|
||||
pooling_output: Optional[dict[str, torch.Tensor]] = None
|
||||
pooling_output: dict[str, torch.Tensor] | None = None
|
||||
|
||||
finish_reason: Optional[FinishReason] = None
|
||||
stop_reason: Union[int, str, None] = None
|
||||
events: Optional[list[EngineCoreEvent]] = None
|
||||
kv_transfer_params: Optional[dict[str, Any]] = None
|
||||
finish_reason: FinishReason | None = None
|
||||
stop_reason: int | str | None = None
|
||||
events: list[EngineCoreEvent] | None = None
|
||||
kv_transfer_params: dict[str, Any] | None = None
|
||||
|
||||
trace_headers: Optional[Mapping[str, str]] = None
|
||||
trace_headers: Mapping[str, str] | None = None
|
||||
# The number of tokens with prefix cache hits.
|
||||
num_cached_tokens: int = 0
|
||||
|
||||
@@ -120,18 +120,18 @@ class OmniEngineCoreOutputs(
|
||||
|
||||
# [num_reqs]
|
||||
outputs: list[OmniEngineCoreOutput] = []
|
||||
scheduler_stats: Optional[SchedulerStats] = None
|
||||
scheduler_stats: SchedulerStats | None = None
|
||||
timestamp: float = 0.0
|
||||
|
||||
utility_output: Optional[UtilityOutput] = None
|
||||
finished_requests: Optional[set[str]] = None
|
||||
utility_output: UtilityOutput | None = None
|
||||
finished_requests: set[str] | None = None
|
||||
|
||||
# In DP case, used to signal that the current wave of requests
|
||||
# has finished and the engines are paused.
|
||||
wave_complete: Optional[int] = None
|
||||
wave_complete: int | None = None
|
||||
# In DP case, used to signal that a request was received for an
|
||||
# "old" wave, so the next wave needs to be started in other engines.
|
||||
start_wave: Optional[int] = None
|
||||
start_wave: int | None = None
|
||||
|
||||
def __post_init__(self):
|
||||
if self.timestamp == 0.0:
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional
|
||||
|
||||
from transformers.models.qwen3_omni_moe.configuration_qwen3_omni_moe import Qwen3OmniMoeTextConfig
|
||||
from vllm.engine.arg_utils import EngineArgs
|
||||
@@ -30,8 +29,8 @@ class OmniEngineArgs(EngineArgs):
|
||||
stage_id: int = 0
|
||||
model_stage: str = "thinker"
|
||||
model_arch: str = "Qwen2_5OmniForConditionalGeneration"
|
||||
engine_output_type: Optional[str] = None
|
||||
hf_config_name: Optional[str] = None
|
||||
engine_output_type: str | None = None
|
||||
hf_config_name: str | None = None
|
||||
|
||||
def draw_hf_text_config(self, config_dict: dict) -> Qwen3OmniMoeTextConfig:
|
||||
# transformers' get_text_config method is used to get the text config from thinker_config.
|
||||
@@ -91,8 +90,8 @@ class AsyncOmniEngineArgs(AsyncEngineArgs):
|
||||
stage_id: int = 0
|
||||
model_stage: str = "thinker"
|
||||
model_arch: str = "Qwen2_5OmniForConditionalGeneration"
|
||||
engine_output_type: Optional[str] = None
|
||||
hf_config_name: Optional[str] = None
|
||||
engine_output_type: str | None = None
|
||||
hf_config_name: str | None = None
|
||||
|
||||
def draw_hf_text_config(self, config_dict: dict) -> Qwen3OmniMoeTextConfig:
|
||||
# transformers' get_text_config method is used to get the text config from thinker_config.
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from ast import Dict
|
||||
from typing import Any, Callable, Optional, Union
|
||||
from collections.abc import Callable
|
||||
from typing import Any
|
||||
|
||||
import torch
|
||||
from vllm.logger import init_logger
|
||||
@@ -33,18 +34,18 @@ class OmniRequestState(RequestState):
|
||||
**kwargs,
|
||||
):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.mm_type: Optional[str] = None
|
||||
self.mm_accumulated: Optional[Dict[str, Any]] = None
|
||||
self.mm_type: str | None = None
|
||||
self.mm_accumulated: Dict[str, Any] | None = None
|
||||
|
||||
@classmethod
|
||||
def from_new_request(
|
||||
cls,
|
||||
tokenizer: AnyTokenizer,
|
||||
request: EngineCoreRequest,
|
||||
prompt: Optional[str],
|
||||
parent_req: Optional[ParentRequest],
|
||||
prompt: str | None,
|
||||
parent_req: ParentRequest | None,
|
||||
request_index: int,
|
||||
queue: Optional[Any],
|
||||
queue: Any | None,
|
||||
log_stats: bool,
|
||||
) -> "OmniRequestState":
|
||||
if sampling_params := request.sampling_params:
|
||||
@@ -93,7 +94,7 @@ class OmniRequestState(RequestState):
|
||||
log_stats=log_stats,
|
||||
)
|
||||
|
||||
def add_multimodal_tensor(self, payload: Optional[Any], mm_type: Optional[str]) -> None:
|
||||
def add_multimodal_tensor(self, payload: Any | None, mm_type: str | None) -> None:
|
||||
if payload is None:
|
||||
return
|
||||
try:
|
||||
@@ -167,11 +168,11 @@ class OmniRequestState(RequestState):
|
||||
def make_request_output(
|
||||
self,
|
||||
new_token_ids: list[int],
|
||||
pooling_output: Optional[torch.Tensor],
|
||||
finish_reason: Optional[FinishReason],
|
||||
stop_reason: Optional[Union[int, str]],
|
||||
kv_transfer_params: Optional[dict[str, Any]] = None,
|
||||
) -> Optional[Union[OmniRequestOutput, PoolingRequestOutput]]:
|
||||
pooling_output: torch.Tensor | None,
|
||||
finish_reason: FinishReason | None,
|
||||
stop_reason: int | str | None,
|
||||
kv_transfer_params: dict[str, Any] | None = None,
|
||||
) -> OmniRequestOutput | PoolingRequestOutput | None:
|
||||
"""Create a request output from generation results.
|
||||
|
||||
Creates a RequestOutput or PoolingRequestOutput from the generated
|
||||
@@ -210,8 +211,8 @@ class OmniRequestState(RequestState):
|
||||
def _new_completion_output(
|
||||
self,
|
||||
token_ids: list[int],
|
||||
finish_reason: Optional[FinishReason],
|
||||
stop_reason: Optional[Union[int, str]],
|
||||
finish_reason: FinishReason | None,
|
||||
stop_reason: int | str | None,
|
||||
) -> Any:
|
||||
# Reuse base text/logprobs logic, then annotate with pooling_result.
|
||||
base_output = super()._new_completion_output(token_ids, finish_reason, stop_reason)
|
||||
@@ -248,7 +249,7 @@ class MultimodalOutputProcessor(VLLMOutputProcessor):
|
||||
self,
|
||||
tokenizer: AnyTokenizer,
|
||||
log_stats: bool,
|
||||
engine_core_output_type: Optional[str] = None,
|
||||
engine_core_output_type: str | None = None,
|
||||
):
|
||||
"""Initialize the multimodal output processor.
|
||||
|
||||
@@ -281,10 +282,10 @@ class MultimodalOutputProcessor(VLLMOutputProcessor):
|
||||
def add_request(
|
||||
self,
|
||||
request: EngineCoreRequest,
|
||||
prompt: Optional[str],
|
||||
parent_req: Optional[ParentRequest] = None,
|
||||
prompt: str | None,
|
||||
parent_req: ParentRequest | None = None,
|
||||
request_index: int = 0,
|
||||
queue: Optional[RequestOutputCollector] = None,
|
||||
queue: RequestOutputCollector | None = None,
|
||||
) -> None:
|
||||
"""Add a new request to be processed.
|
||||
|
||||
@@ -322,8 +323,8 @@ class MultimodalOutputProcessor(VLLMOutputProcessor):
|
||||
def process_outputs(
|
||||
self,
|
||||
engine_core_outputs: list[EngineCoreOutput],
|
||||
engine_core_timestamp: Optional[float] = None,
|
||||
iteration_stats: Optional[IterationStats] = None,
|
||||
engine_core_timestamp: float | None = None,
|
||||
iteration_stats: IterationStats | None = None,
|
||||
) -> OutputProcessorOutput:
|
||||
"""Process engine core outputs into request outputs.
|
||||
|
||||
@@ -524,7 +525,7 @@ class MultimodalOutputProcessor(VLLMOutputProcessor):
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def _extract_from_multimodal_outputs(self, eco: EngineCoreOutput, keys: tuple[str, ...]) -> Optional[torch.Tensor]:
|
||||
def _extract_from_multimodal_outputs(self, eco: EngineCoreOutput, keys: tuple[str, ...]) -> torch.Tensor | None:
|
||||
mm = getattr(eco, "multimodal_outputs", None)
|
||||
if not isinstance(mm, dict):
|
||||
return None
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import time
|
||||
from collections.abc import Mapping
|
||||
from typing import Any, Optional, Union
|
||||
from typing import Any
|
||||
|
||||
import torch
|
||||
from vllm.config import VllmConfig
|
||||
@@ -90,14 +90,14 @@ class OmniProcessor(Processor):
|
||||
self,
|
||||
request_id: str,
|
||||
prompt: PromptType,
|
||||
params: Union[SamplingParams, PoolingParams],
|
||||
arrival_time: Optional[float] = None,
|
||||
lora_request: Optional[LoRARequest] = None,
|
||||
tokenization_kwargs: Optional[dict[str, Any]] = None,
|
||||
trace_headers: Optional[Mapping[str, str]] = None,
|
||||
params: SamplingParams | PoolingParams,
|
||||
arrival_time: float | None = None,
|
||||
lora_request: LoRARequest | None = None,
|
||||
tokenization_kwargs: dict[str, Any] | None = None,
|
||||
trace_headers: Mapping[str, str] | None = None,
|
||||
priority: int = 0,
|
||||
data_parallel_rank: Optional[int] = None,
|
||||
) -> tuple[Optional[str], OmniEngineCoreRequest]:
|
||||
data_parallel_rank: int | None = None,
|
||||
) -> tuple[str | None, OmniEngineCoreRequest]:
|
||||
"""Process input prompt into an engine core request.
|
||||
|
||||
Converts a prompt (text, tokens, or multimodal) into an
|
||||
@@ -185,7 +185,7 @@ class OmniProcessor(Processor):
|
||||
# discriminated unions of TypedDicts, because of how it handles
|
||||
# inheritance of TypedDict. If we explicitly extract the items we want
|
||||
# we can avoid type errors from using `dict.get` later in the method.
|
||||
prompt_str: Optional[str] = None if decoder_inputs["type"] == "embeds" else decoder_inputs.get("prompt")
|
||||
prompt_str: str | None = None if decoder_inputs["type"] == "embeds" else decoder_inputs.get("prompt")
|
||||
prompt_token_ids = decoder_inputs["prompt_token_ids"] if decoder_inputs["type"] != "embeds" else None
|
||||
prompt_embeds = decoder_inputs["prompt_embeds"] if decoder_inputs["type"] == "embeds" else None
|
||||
|
||||
@@ -205,7 +205,7 @@ class OmniProcessor(Processor):
|
||||
pooling_params = params.clone()
|
||||
|
||||
# Multimodal related.
|
||||
mm_features: Optional[list[MultiModalFeatureSpec]] = None
|
||||
mm_features: list[MultiModalFeatureSpec] | None = None
|
||||
|
||||
if decoder_inputs["type"] == "multimodal":
|
||||
decoder_mm_inputs = decoder_inputs["mm_kwargs"]
|
||||
@@ -230,8 +230,8 @@ class OmniProcessor(Processor):
|
||||
|
||||
# Serialize prompt_embeds and additional_information if provided
|
||||
# (direct-transfer path)
|
||||
prompt_embeds_payload: Optional[PromptEmbedsPayload] = None
|
||||
additional_information_payload: Optional[AdditionalInformationPayload] = None
|
||||
prompt_embeds_payload: PromptEmbedsPayload | None = None
|
||||
additional_information_payload: AdditionalInformationPayload | None = None
|
||||
if "prompt_embeds" in decoder_inputs: # type: ignore[operator]
|
||||
pe: torch.Tensor = decoder_inputs["prompt_embeds"] # type: ignore[index]
|
||||
if pe.ndim != 2:
|
||||
|
||||
@@ -6,7 +6,7 @@ import time
|
||||
from argparse import Namespace
|
||||
from collections.abc import AsyncGenerator, Iterable, Mapping, Sequence
|
||||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||
from typing import Any, Optional, Union
|
||||
from typing import Any
|
||||
|
||||
import torch
|
||||
|
||||
@@ -261,11 +261,11 @@ class AsyncOmni(EngineClient):
|
||||
self,
|
||||
prompt: PromptType,
|
||||
request_id: str,
|
||||
sampling_params_list: Optional[Union[SamplingParams, Sequence[SamplingParams]]] = None,
|
||||
lora_request: Optional[LoRARequest] = None,
|
||||
trace_headers: Optional[Mapping[str, str]] = None,
|
||||
sampling_params_list: SamplingParams | Sequence[SamplingParams] | None = None,
|
||||
lora_request: LoRARequest | None = None,
|
||||
trace_headers: Mapping[str, str] | None = None,
|
||||
priority: int = 0,
|
||||
data_parallel_rank: Optional[int] = None,
|
||||
data_parallel_rank: int | None = None,
|
||||
) -> AsyncGenerator[OmniRequestOutput, None]:
|
||||
"""Generate outputs for the given prompt asynchronously.
|
||||
|
||||
@@ -577,7 +577,7 @@ class AsyncOmni(EngineClient):
|
||||
def dead_error(self) -> BaseException:
|
||||
return EngineDeadError()
|
||||
|
||||
async def abort(self, request_id: Union[str, Iterable[str]]) -> None:
|
||||
async def abort(self, request_id: str | Iterable[str]) -> None:
|
||||
pass
|
||||
|
||||
async def get_vllm_config(self) -> VllmConfig:
|
||||
@@ -620,13 +620,13 @@ class AsyncOmni(EngineClient):
|
||||
async def reset_mm_cache(self) -> None:
|
||||
pass
|
||||
|
||||
async def reset_prefix_cache(self, device: Optional[Device] = None) -> None:
|
||||
async def reset_prefix_cache(self, device: Device | None = None) -> None:
|
||||
pass
|
||||
|
||||
async def sleep(self, level: int = 1) -> None:
|
||||
pass
|
||||
|
||||
async def wake_up(self, tags: Optional[list[str]] = None) -> None:
|
||||
async def wake_up(self, tags: list[str] | None = None) -> None:
|
||||
pass
|
||||
|
||||
async def is_sleeping(self) -> bool:
|
||||
@@ -689,8 +689,8 @@ class AsyncOmniStageLLM(AsyncLLM):
|
||||
use_cached_outputs: bool = False,
|
||||
log_requests: bool = True,
|
||||
start_engine_loop: bool = True,
|
||||
stat_loggers: Optional[list[StatLoggerFactory]] = None,
|
||||
client_addresses: Optional[dict[str, str]] = None,
|
||||
stat_loggers: list[StatLoggerFactory] | None = None,
|
||||
client_addresses: dict[str, str] | None = None,
|
||||
client_count: int = 1,
|
||||
client_index: int = 0,
|
||||
) -> None:
|
||||
@@ -771,7 +771,7 @@ class AsyncOmniStageLLM(AsyncLLM):
|
||||
)
|
||||
|
||||
# Loggers.
|
||||
self.logger_manager: Optional[StatLoggerManager] = None
|
||||
self.logger_manager: StatLoggerManager | None = None
|
||||
if self.log_stats:
|
||||
self.logger_manager = StatLoggerManager(
|
||||
vllm_config=vllm_config,
|
||||
@@ -782,7 +782,7 @@ class AsyncOmniStageLLM(AsyncLLM):
|
||||
)
|
||||
self.logger_manager.log_engine_initialized()
|
||||
|
||||
self.output_handler: Optional[asyncio.Task] = None
|
||||
self.output_handler: asyncio.Task | None = None
|
||||
try:
|
||||
# Start output handler eagerly if we are in the asyncio eventloop.
|
||||
asyncio.get_running_loop()
|
||||
@@ -819,10 +819,10 @@ class AsyncOmniStageLLM(AsyncLLM):
|
||||
engine_args: AsyncOmniEngineArgs,
|
||||
start_engine_loop: bool = True,
|
||||
usage_context: UsageContext = UsageContext.ENGINE_CONTEXT,
|
||||
stat_loggers: Optional[list[StatLoggerFactory]] = None,
|
||||
stat_loggers: list[StatLoggerFactory] | None = None,
|
||||
enable_log_requests: bool = False,
|
||||
disable_log_stats: bool = False,
|
||||
client_addresses: Optional[dict[str, str]] = None,
|
||||
client_addresses: dict[str, str] | None = None,
|
||||
client_count: int = 1,
|
||||
client_index: int = 0,
|
||||
disable_log_requests: bool = True, # Deprecated, will be removed
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from collections.abc import Awaitable, Iterable
|
||||
from typing import Any, Optional, Union, cast
|
||||
from typing import Any, cast
|
||||
|
||||
import numpy as np
|
||||
from openai.types.chat import ChatCompletionContentPartTextParam
|
||||
@@ -33,13 +33,13 @@ class OmniAsyncMultiModalItemTracker(AsyncMultiModalItemTracker):
|
||||
class OmniAsyncMultiModalContentParser(AsyncMultiModalContentParser):
|
||||
def __init__(self, tracker: AsyncMultiModalItemTracker) -> None:
|
||||
super().__init__(tracker=tracker)
|
||||
self._mm_processor_kwargs: Optional[dict[str, Any]] = None
|
||||
self._mm_processor_kwargs: dict[str, Any] | None = None
|
||||
|
||||
def set_mm_processor_kwargs(self, mm_processor_kwargs: Optional[dict[str, Any]]) -> None:
|
||||
def set_mm_processor_kwargs(self, mm_processor_kwargs: dict[str, Any] | None) -> None:
|
||||
"""Set mm_processor_kwargs for use in parsing."""
|
||||
self._mm_processor_kwargs = mm_processor_kwargs
|
||||
|
||||
def parse_video(self, video_url: Optional[str], uuid: Optional[str] = None) -> None:
|
||||
def parse_video(self, video_url: str | None, uuid: str | None = None) -> None:
|
||||
video = self._connector.fetch_video_async(video_url=video_url) if video_url else None
|
||||
|
||||
placeholder = self._tracker.add("video", video, uuid)
|
||||
@@ -51,7 +51,7 @@ class OmniAsyncMultiModalContentParser(AsyncMultiModalContentParser):
|
||||
audio_placeholder = self._tracker.add("audio", audio_coro, uuid)
|
||||
self._add_placeholder("audio", audio_placeholder)
|
||||
|
||||
async def _extract_audio_from_video_async(self, video_url: str) -> tuple[np.ndarray, Union[int, float]]:
|
||||
async def _extract_audio_from_video_async(self, video_url: str) -> tuple[np.ndarray, int | float]:
|
||||
"""
|
||||
Extract audio from video URL using librosa.
|
||||
Returns tuple of (audio_array, sample_rate) compatible with audio format.
|
||||
@@ -79,7 +79,7 @@ class OmniAsyncMultiModalContentParser(AsyncMultiModalContentParser):
|
||||
temp_file.write(data)
|
||||
return temp_file.name
|
||||
|
||||
def _load_audio_sync(file_path: str) -> tuple[np.ndarray, Union[int, float]]:
|
||||
def _load_audio_sync(file_path: str) -> tuple[np.ndarray, int | float]:
|
||||
"""Synchronous audio loading with librosa - runs in thread pool."""
|
||||
import librosa
|
||||
|
||||
@@ -131,11 +131,11 @@ def parse_chat_messages_futures(
|
||||
model_config: ModelConfig,
|
||||
tokenizer: AnyTokenizer,
|
||||
content_format: _ChatTemplateContentFormat,
|
||||
mm_processor_kwargs: Optional[dict[str, Any]] = None,
|
||||
mm_processor_kwargs: dict[str, Any] | None = None,
|
||||
) -> tuple[
|
||||
list[ConversationMessage],
|
||||
Awaitable[Optional[MultiModalDataDict]],
|
||||
Optional[MultiModalUUIDDict],
|
||||
Awaitable[MultiModalDataDict | None],
|
||||
MultiModalUUIDDict | None,
|
||||
]:
|
||||
conversation: list[ConversationMessage] = []
|
||||
mm_tracker = OmniAsyncMultiModalItemTracker(model_config, tokenizer)
|
||||
@@ -165,7 +165,7 @@ def _parse_chat_message_content(
|
||||
mm_tracker: BaseMultiModalItemTracker,
|
||||
content_format: _ChatTemplateContentFormat,
|
||||
interleave_strings: bool,
|
||||
mm_processor_kwargs: Optional[dict[str, Any]] = None,
|
||||
mm_processor_kwargs: dict[str, Any] | None = None,
|
||||
) -> list[ConversationMessage]:
|
||||
role = message["role"]
|
||||
content = message.get("content")
|
||||
@@ -210,7 +210,7 @@ def _parse_chat_message_content_parts(
|
||||
*,
|
||||
wrap_dicts: bool,
|
||||
interleave_strings: bool,
|
||||
mm_processor_kwargs: Optional[dict[str, Any]] = None,
|
||||
mm_processor_kwargs: dict[str, Any] | None = None,
|
||||
) -> list[ConversationMessage]:
|
||||
content = list[_ContentPart]()
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import time
|
||||
import uuid
|
||||
from collections.abc import Sequence
|
||||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||
from typing import Any, Optional, Union
|
||||
from typing import Any
|
||||
|
||||
import cloudpickle
|
||||
from pydantic import ValidationError
|
||||
@@ -89,9 +89,9 @@ class OmniLLM:
|
||||
def __init__(
|
||||
self,
|
||||
model: str,
|
||||
stage_configs_path: Optional[str] = None,
|
||||
stage_configs_path: str | None = None,
|
||||
log_stats: bool = False,
|
||||
log_file: Optional[str] = None,
|
||||
log_file: str | None = None,
|
||||
init_sleep_seconds: int = 20,
|
||||
shm_threshold_bytes: int = 65536,
|
||||
batch_timeout: int = 10,
|
||||
@@ -228,8 +228,8 @@ class OmniLLM:
|
||||
|
||||
def generate(
|
||||
self,
|
||||
prompts: Union[PromptType, Sequence[PromptType]],
|
||||
sampling_params_list: Optional[Union[SamplingParams, Sequence[SamplingParams]]] = None,
|
||||
prompts: PromptType | Sequence[PromptType],
|
||||
sampling_params_list: SamplingParams | Sequence[SamplingParams] | None = None,
|
||||
) -> list[OmniRequestOutput]:
|
||||
"""Generate outputs for the given prompts.
|
||||
|
||||
@@ -262,8 +262,8 @@ class OmniLLM:
|
||||
|
||||
def _run_generation(
|
||||
self,
|
||||
prompts: Union[PromptType, Sequence[PromptType]],
|
||||
sampling_params_list: Optional[Union[SamplingParams, Sequence[SamplingParams]]] = None,
|
||||
prompts: PromptType | Sequence[PromptType],
|
||||
sampling_params_list: SamplingParams | Sequence[SamplingParams] | None = None,
|
||||
) -> list[OmniRequestOutput]:
|
||||
logger.debug("[Orchestrator] generate() called")
|
||||
if sampling_params_list is None:
|
||||
@@ -559,9 +559,9 @@ class OmniStageLLM(LLM):
|
||||
def __init__(
|
||||
self,
|
||||
model: str,
|
||||
compilation_config: Optional[Union[int, dict[str, Any], CompilationConfig]] = None,
|
||||
hf_overrides: Optional[dict[str, Any]] = None,
|
||||
structured_outputs_config: Optional[Union[dict[str, Any], StructuredOutputsConfig]] = None,
|
||||
compilation_config: int | dict[str, Any] | CompilationConfig | None = None,
|
||||
hf_overrides: dict[str, Any] | None = None,
|
||||
structured_outputs_config: dict[str, Any] | StructuredOutputsConfig | None = None,
|
||||
**kwargs: Any,
|
||||
):
|
||||
"""LLM constructor."""
|
||||
@@ -633,7 +633,7 @@ class OmniStageLLM(LLM):
|
||||
self.engine_class = type(self.llm_engine)
|
||||
|
||||
self.request_counter = Counter()
|
||||
self.default_sampling_params: Union[dict[str, Any], None] = None
|
||||
self.default_sampling_params: dict[str, Any] | None = None
|
||||
|
||||
supported_tasks = self.llm_engine.get_supported_tasks() # type: ignore
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ import logging
|
||||
import multiprocessing as mp
|
||||
import os
|
||||
import sys
|
||||
from typing import Any, Optional, Union
|
||||
from typing import Any
|
||||
|
||||
from vllm.inputs import TextPrompt
|
||||
from vllm.inputs.preprocess import InputPreprocessor
|
||||
@@ -81,10 +81,10 @@ class OmniStage:
|
||||
default_sampling_params = getattr(stage_config, "default_sampling_params", {})
|
||||
self.default_sampling_params = SamplingParams(**_to_dict(default_sampling_params))
|
||||
# Runtime orchestration state (added)
|
||||
self._in_q: Optional[mp.Queue] = None
|
||||
self._out_q: Optional[mp.Queue] = None
|
||||
self._proc: Optional[mp.Process] = None
|
||||
self._log_file: Optional[str] = None
|
||||
self._in_q: mp.Queue | None = None
|
||||
self._out_q: mp.Queue | None = None
|
||||
self._proc: mp.Process | None = None
|
||||
self._log_file: str | None = None
|
||||
self._shm_threshold_bytes: int = 65536
|
||||
self._logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -160,11 +160,11 @@ class OmniStage:
|
||||
model: str,
|
||||
*,
|
||||
is_async: bool = False,
|
||||
log_file: Optional[str] = None,
|
||||
log_file: str | None = None,
|
||||
shm_threshold_bytes: int = 65536,
|
||||
ctx: Optional[mp.context.BaseContext] = None,
|
||||
ctx: mp.context.BaseContext | None = None,
|
||||
batch_timeout: int = 10,
|
||||
connectors_config: Optional[dict] = None,
|
||||
connectors_config: dict | None = None,
|
||||
worker_backend: str = "multi_process",
|
||||
**kwargs: Any,
|
||||
) -> None:
|
||||
@@ -303,7 +303,7 @@ class OmniStage:
|
||||
assert self._in_q is not None
|
||||
self._in_q.put(payload)
|
||||
|
||||
def try_collect(self) -> Optional[dict[str, Any]]:
|
||||
def try_collect(self) -> dict[str, Any] | None:
|
||||
"""Try to collect a result from the stage worker without blocking.
|
||||
|
||||
Returns:
|
||||
@@ -317,8 +317,8 @@ class OmniStage:
|
||||
return None
|
||||
|
||||
def process_engine_inputs(
|
||||
self, stage_list: list[Any], prompt: Union[OmniTokensPrompt, TextPrompt] = None
|
||||
) -> list[Union[OmniTokensPrompt, TextPrompt]]:
|
||||
self, stage_list: list[Any], prompt: OmniTokensPrompt | TextPrompt = None
|
||||
) -> list[OmniTokensPrompt | TextPrompt]:
|
||||
"""Process engine inputs for this stage from upstream stage outputs.
|
||||
|
||||
Derives inputs for this stage from outputs of upstream stages.
|
||||
@@ -372,7 +372,7 @@ def _stage_worker(
|
||||
stage_payload: dict[str, Any],
|
||||
in_q: mp.Queue,
|
||||
out_q: mp.Queue,
|
||||
log_file: Optional[str] = None,
|
||||
log_file: str | None = None,
|
||||
batch_timeout: int = 10,
|
||||
) -> None:
|
||||
"""Stage worker entry: device setup, LLM init, batching, SHM IPC."""
|
||||
|
||||
@@ -5,7 +5,7 @@ from argparse import Namespace
|
||||
from collections.abc import AsyncIterator
|
||||
from contextlib import asynccontextmanager
|
||||
from http import HTTPStatus
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
|
||||
import vllm.envs as envs
|
||||
from fastapi import Depends, HTTPException, Request
|
||||
@@ -111,8 +111,8 @@ async def omni_run_server_worker(listen_address, sock, args, client_config=None,
|
||||
async def build_async_omni(
|
||||
args: Namespace,
|
||||
*,
|
||||
disable_frontend_multiprocessing: Optional[bool] = None,
|
||||
client_config: Optional[dict[str, Any]] = None,
|
||||
disable_frontend_multiprocessing: bool | None = None,
|
||||
client_config: dict[str, Any] | None = None,
|
||||
) -> AsyncIterator[EngineClient]:
|
||||
"""Build an AsyncOmni instance from command-line arguments.
|
||||
|
||||
@@ -152,7 +152,7 @@ async def build_async_omni_from_stage_config(
|
||||
args: Namespace,
|
||||
*,
|
||||
disable_frontend_multiprocessing: bool = False,
|
||||
client_config: Optional[dict[str, Any]] = None,
|
||||
client_config: dict[str, Any] | None = None,
|
||||
) -> AsyncIterator[EngineClient]:
|
||||
"""Create AsyncOmni from stage configuration.
|
||||
|
||||
@@ -182,7 +182,7 @@ async def build_async_omni_from_stage_config(
|
||||
"To disable frontend multiprocessing, set VLLM_USE_V1=0."
|
||||
)
|
||||
|
||||
async_omni: Optional[EngineClient] = None
|
||||
async_omni: EngineClient | None = None
|
||||
|
||||
try:
|
||||
async_omni = AsyncOmni(model=args.model, cli_args=args)
|
||||
@@ -257,7 +257,7 @@ async def omni_init_app_state(
|
||||
)
|
||||
|
||||
if args.tool_server == "demo":
|
||||
tool_server: Optional[ToolServer] = DemoToolServer()
|
||||
tool_server: ToolServer | None = DemoToolServer()
|
||||
assert isinstance(tool_server, DemoToolServer)
|
||||
await tool_server.init_and_validate()
|
||||
elif args.tool_server:
|
||||
@@ -314,7 +314,7 @@ async def omni_init_app_state(
|
||||
state.server_load_metrics = 0
|
||||
|
||||
|
||||
def Omnichat(request: Request) -> Optional[OmniOpenAIServingChat]:
|
||||
def Omnichat(request: Request) -> OmniOpenAIServingChat | None:
|
||||
return request.app.state.openai_serving_chat
|
||||
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@ import base64
|
||||
import json
|
||||
import time
|
||||
import uuid
|
||||
from collections.abc import AsyncGenerator, AsyncIterator, Sequence
|
||||
from collections.abc import AsyncGenerator, AsyncIterator, Callable, Sequence
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from io import BytesIO
|
||||
from typing import Any, Callable, Optional, Union
|
||||
from typing import Any
|
||||
|
||||
import jinja2
|
||||
from fastapi import Request
|
||||
@@ -78,8 +78,8 @@ class OmniOpenAIServingChat(OpenAIServingChat):
|
||||
async def create_chat_completion(
|
||||
self,
|
||||
request: ChatCompletionRequest,
|
||||
raw_request: Optional[Request] = None,
|
||||
) -> Union[AsyncGenerator[str, None], ChatCompletionResponse, ErrorResponse]:
|
||||
raw_request: Request | None = None,
|
||||
) -> AsyncGenerator[str, None] | ChatCompletionResponse | ErrorResponse:
|
||||
"""
|
||||
Chat Completion API similar to OpenAI's API.
|
||||
|
||||
@@ -236,17 +236,17 @@ class OmniOpenAIServingChat(OpenAIServingChat):
|
||||
|
||||
async def _preprocess_chat(
|
||||
self,
|
||||
request: Union[ChatLikeRequest, ResponsesRequest],
|
||||
request: ChatLikeRequest | ResponsesRequest,
|
||||
tokenizer: AnyTokenizer,
|
||||
messages: list[ChatCompletionMessageParam],
|
||||
chat_template: Optional[str],
|
||||
chat_template: str | None,
|
||||
chat_template_content_format: ChatTemplateContentFormatOption,
|
||||
add_generation_prompt: bool = True,
|
||||
continue_final_message: bool = False,
|
||||
tool_dicts: Optional[list[dict[str, Any]]] = None,
|
||||
documents: Optional[list[dict[str, str]]] = None,
|
||||
chat_template_kwargs: Optional[dict[str, Any]] = None,
|
||||
tool_parser: Optional[Callable[[AnyTokenizer], ToolParser]] = None,
|
||||
tool_dicts: list[dict[str, Any]] | None = None,
|
||||
documents: list[dict[str, str]] | None = None,
|
||||
chat_template_kwargs: dict[str, Any] | None = None,
|
||||
tool_parser: Callable[[AnyTokenizer], ToolParser] | None = None,
|
||||
add_special_tokens: bool = False,
|
||||
) -> tuple[
|
||||
list[ConversationMessage],
|
||||
@@ -279,7 +279,7 @@ class OmniOpenAIServingChat(OpenAIServingChat):
|
||||
)
|
||||
_chat_template_kwargs.update(chat_template_kwargs or {})
|
||||
|
||||
request_prompt: Union[str, list[int]]
|
||||
request_prompt: str | list[int]
|
||||
|
||||
if tokenizer is None:
|
||||
request_prompt = "placeholder"
|
||||
@@ -365,9 +365,9 @@ class OmniOpenAIServingChat(OpenAIServingChat):
|
||||
def _log_inputs(
|
||||
self,
|
||||
request_id: str,
|
||||
inputs: Union[RequestPrompt, PromptType],
|
||||
params_list: Optional[list[SamplingParams]],
|
||||
lora_request: Optional[LoRARequest],
|
||||
inputs: RequestPrompt | PromptType,
|
||||
params_list: list[SamplingParams] | None,
|
||||
lora_request: LoRARequest | None,
|
||||
) -> None:
|
||||
if self.request_logger is None:
|
||||
return
|
||||
@@ -399,9 +399,9 @@ class OmniOpenAIServingChat(OpenAIServingChat):
|
||||
conversation: list[ConversationMessage],
|
||||
tokenizer: AnyTokenizer,
|
||||
request_metadata: RequestResponseMetadata,
|
||||
) -> Union[ErrorResponse, ChatCompletionResponse]:
|
||||
) -> ErrorResponse | ChatCompletionResponse:
|
||||
created_time = int(time.time())
|
||||
final_res: Optional[RequestOutput] = None
|
||||
final_res: RequestOutput | None = None
|
||||
|
||||
final_outputs: list[OmniRequestOutput] = []
|
||||
try:
|
||||
@@ -698,7 +698,7 @@ class OmniOpenAIServingChat(OpenAIServingChat):
|
||||
choices.append(choice_data)
|
||||
|
||||
if request.echo:
|
||||
last_msg_content: Union[str, list[dict[str, str]]] = ""
|
||||
last_msg_content: str | list[dict[str, str]] = ""
|
||||
if conversation and "content" in conversation[-1] and conversation[-1].get("role") == role:
|
||||
last_msg_content = conversation[-1]["content"] or ""
|
||||
if isinstance(last_msg_content, list):
|
||||
|
||||
@@ -2,7 +2,7 @@ import os
|
||||
from collections import Counter
|
||||
from dataclasses import asdict, is_dataclass
|
||||
from pathlib import Path
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
|
||||
from omegaconf import OmegaConf
|
||||
from vllm.transformers_utils.config import get_config
|
||||
@@ -97,7 +97,7 @@ def resolve_model_config_path(model: str) -> str:
|
||||
return str(stage_config_path)
|
||||
|
||||
|
||||
def load_stage_configs_from_model(model: str, base_engine_args: Optional[dict] = None) -> list:
|
||||
def load_stage_configs_from_model(model: str, base_engine_args: dict | None = None) -> list:
|
||||
"""Load stage configurations from model's default config file.
|
||||
|
||||
Loads stage configurations based on the model type and device type.
|
||||
@@ -120,7 +120,7 @@ def load_stage_configs_from_model(model: str, base_engine_args: Optional[dict] =
|
||||
return stage_configs
|
||||
|
||||
|
||||
def load_stage_configs_from_yaml(config_path: str, base_engine_args: Optional[dict] = None) -> list:
|
||||
def load_stage_configs_from_yaml(config_path: str, base_engine_args: dict | None = None) -> list:
|
||||
"""Load stage configurations from a YAML file.
|
||||
|
||||
Args:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
|
||||
try:
|
||||
from typing import NotRequired
|
||||
@@ -73,10 +73,10 @@ class OmniEmbedsPrompt(EmbedsPrompt):
|
||||
|
||||
def token_inputs_omni(
|
||||
prompt_token_ids: list[int],
|
||||
prompt: Optional[str] = None,
|
||||
cache_salt: Optional[str] = None,
|
||||
prompt_embeds: Optional[torch.Tensor] = None,
|
||||
additional_information: Optional[dict[str, Any]] = None,
|
||||
prompt: str | None = None,
|
||||
cache_salt: str | None = None,
|
||||
prompt_embeds: torch.Tensor | None = None,
|
||||
additional_information: dict[str, Any] | None = None,
|
||||
) -> OmniTokenInputs:
|
||||
"""Construct token inputs with optional embeddings and metadata.
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import Any, Optional, Union
|
||||
from typing import Any
|
||||
|
||||
from typing_extensions import assert_never
|
||||
from vllm.inputs.data import SingletonInputs, SingletonPrompt, TextPrompt, TokensPrompt
|
||||
@@ -23,15 +23,15 @@ class OmniInputPreprocessor(InputPreprocessor):
|
||||
def _process_tokens(
|
||||
self,
|
||||
parsed_content: TokensPrompt,
|
||||
tokenization_kwargs: Optional[dict[str, Any]] = None,
|
||||
tokenization_kwargs: dict[str, Any] | None = None,
|
||||
*,
|
||||
mm_uuids: Optional[MultiModalUUIDDict] = None,
|
||||
) -> Union[OmniTokenInputs, MultiModalInputs]:
|
||||
mm_uuids: MultiModalUUIDDict | None = None,
|
||||
) -> OmniTokenInputs | MultiModalInputs:
|
||||
prompt_token_ids = self._truncate_inputs(parsed_content["prompt_token_ids"], tokenization_kwargs)
|
||||
prompt_embeds = parsed_content.get("prompt_embeds")
|
||||
additional_information = parsed_content.get("additional_information")
|
||||
|
||||
inputs: Union[OmniTokenInputs, MultiModalInputs]
|
||||
inputs: OmniTokenInputs | MultiModalInputs
|
||||
if multi_modal_data := parsed_content.get("multi_modal_data"):
|
||||
inputs = self._process_multimodal(
|
||||
prompt_token_ids,
|
||||
@@ -55,9 +55,9 @@ class OmniInputPreprocessor(InputPreprocessor):
|
||||
def _prompt_to_llm_inputs(
|
||||
self,
|
||||
prompt: SingletonPrompt,
|
||||
tokenization_kwargs: Optional[dict[str, Any]] = None,
|
||||
tokenization_kwargs: dict[str, Any] | None = None,
|
||||
*,
|
||||
mm_uuids: Optional[MultiModalUUIDDict] = None,
|
||||
mm_uuids: MultiModalUUIDDict | None = None,
|
||||
) -> SingletonInputs:
|
||||
"""
|
||||
Extract the singleton inputs from a prompt.
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import itertools
|
||||
from typing import Optional, Union
|
||||
|
||||
import numpy as np
|
||||
import torch
|
||||
@@ -50,11 +49,11 @@ class MRotaryEmbedding(RotaryEmbedding):
|
||||
base: float,
|
||||
is_neox_style: bool,
|
||||
dtype: torch.dtype,
|
||||
mrope_section: Optional[list[int]] = None,
|
||||
mrope_section: list[int] | None = None,
|
||||
mrope_interleaved: bool = False,
|
||||
# YaRN parameters.
|
||||
*,
|
||||
scaling_factor: Optional[float] = None,
|
||||
scaling_factor: float | None = None,
|
||||
extrapolation_factor: float = 1,
|
||||
attn_factor: float = 1,
|
||||
beta_fast: int = 32,
|
||||
@@ -85,8 +84,8 @@ class MRotaryEmbedding(RotaryEmbedding):
|
||||
self,
|
||||
positions: torch.Tensor,
|
||||
query: torch.Tensor,
|
||||
key: Optional[torch.Tensor] = None,
|
||||
) -> tuple[torch.Tensor, Optional[torch.Tensor]]:
|
||||
key: torch.Tensor | None = None,
|
||||
) -> tuple[torch.Tensor, torch.Tensor | None]:
|
||||
"""PyTorch-native implementation equivalent to forward().
|
||||
|
||||
Args:
|
||||
@@ -138,12 +137,12 @@ class MRotaryEmbedding(RotaryEmbedding):
|
||||
cls,
|
||||
input_tokens: list[int],
|
||||
hf_config: PretrainedConfig,
|
||||
image_grid_thw: Optional[Union[list[list[int]], torch.Tensor]],
|
||||
video_grid_thw: Optional[Union[list[list[int]], torch.Tensor]],
|
||||
second_per_grid_ts: Optional[list[float]],
|
||||
image_grid_thw: list[list[int]] | torch.Tensor | None,
|
||||
video_grid_thw: list[list[int]] | torch.Tensor | None,
|
||||
second_per_grid_ts: list[float] | None,
|
||||
context_len: int = 0,
|
||||
seq_len: Optional[int] = None,
|
||||
audio_feature_lengths: Optional[torch.Tensor] = None,
|
||||
seq_len: int | None = None,
|
||||
audio_feature_lengths: torch.Tensor | None = None,
|
||||
use_audio_in_video: bool = False,
|
||||
) -> tuple[list[list[int]], int]:
|
||||
"""Get mrope input positions and delta value."""
|
||||
@@ -171,12 +170,12 @@ class MRotaryEmbedding(RotaryEmbedding):
|
||||
cls,
|
||||
input_tokens: list[int],
|
||||
hf_config: PretrainedConfig,
|
||||
image_grid_thw: Union[list[list[int]], torch.Tensor],
|
||||
video_grid_thw: Union[list[list[int]], torch.Tensor],
|
||||
image_grid_thw: list[list[int]] | torch.Tensor,
|
||||
video_grid_thw: list[list[int]] | torch.Tensor,
|
||||
second_per_grid_ts: list[float],
|
||||
context_len: int = 0,
|
||||
seq_len: Optional[int] = None,
|
||||
audio_feature_lengths: Optional[torch.Tensor] = None,
|
||||
seq_len: int | None = None,
|
||||
audio_feature_lengths: torch.Tensor | None = None,
|
||||
use_audio_in_video: bool = False,
|
||||
) -> tuple[torch.Tensor, int]:
|
||||
from vllm.transformers_utils.config import thinker_uses_mrope
|
||||
@@ -218,10 +217,10 @@ class MRotaryEmbedding(RotaryEmbedding):
|
||||
cls,
|
||||
input_tokens: list[int],
|
||||
hf_config: PretrainedConfig,
|
||||
image_grid_thw: Union[list[list[int]], torch.Tensor],
|
||||
video_grid_thw: Union[list[list[int]], torch.Tensor],
|
||||
image_grid_thw: list[list[int]] | torch.Tensor,
|
||||
video_grid_thw: list[list[int]] | torch.Tensor,
|
||||
context_len: int = 0,
|
||||
seq_len: Optional[int] = None,
|
||||
seq_len: int | None = None,
|
||||
) -> tuple[torch.Tensor, int]:
|
||||
"""Get mrope input positions and delta value for GLM4V."""
|
||||
|
||||
@@ -319,11 +318,11 @@ class MRotaryEmbedding(RotaryEmbedding):
|
||||
cls,
|
||||
input_tokens: list[int],
|
||||
hf_config: PretrainedConfig,
|
||||
image_grid_thw: Union[list[list[int]], torch.Tensor],
|
||||
video_grid_thw: Union[list[list[int]], torch.Tensor],
|
||||
image_grid_thw: list[list[int]] | torch.Tensor,
|
||||
video_grid_thw: list[list[int]] | torch.Tensor,
|
||||
second_per_grid_ts: list[float],
|
||||
context_len: int = 0,
|
||||
seq_len: Optional[int] = None,
|
||||
seq_len: int | None = None,
|
||||
) -> tuple[torch.Tensor, int]:
|
||||
"""Get mrope input positions and delta value."""
|
||||
|
||||
@@ -417,12 +416,12 @@ class MRotaryEmbedding(RotaryEmbedding):
|
||||
cls,
|
||||
input_tokens: list[int],
|
||||
hf_config: PretrainedConfig,
|
||||
image_grid_thw: Union[list[list[int]], torch.Tensor],
|
||||
video_grid_thw: Union[list[list[int]], torch.Tensor],
|
||||
second_per_grid_ts: Optional[list[float]] = None,
|
||||
image_grid_thw: list[list[int]] | torch.Tensor,
|
||||
video_grid_thw: list[list[int]] | torch.Tensor,
|
||||
second_per_grid_ts: list[float] | None = None,
|
||||
context_len: int = 0,
|
||||
seq_len: Optional[int] = None,
|
||||
audio_feature_lengths: Optional[torch.Tensor] = None,
|
||||
seq_len: int | None = None,
|
||||
audio_feature_lengths: torch.Tensor | None = None,
|
||||
use_audio_in_video: bool = False,
|
||||
) -> tuple[torch.Tensor, int]:
|
||||
"""Get mrope input positions and delta value (Qwen2.5-Omni version).
|
||||
@@ -642,7 +641,7 @@ class MRotaryEmbedding(RotaryEmbedding):
|
||||
cls,
|
||||
thinker_config: PretrainedConfig,
|
||||
audio_len: int,
|
||||
video_grid_thw: Union[list[int], torch.Tensor],
|
||||
video_grid_thw: list[int] | torch.Tensor,
|
||||
video_second_per_grid_t: float,
|
||||
) -> list[int]:
|
||||
"""Get video prompt updates when `use_audio_in_video` is True.
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import time
|
||||
from pathlib import Path
|
||||
from typing import Optional, Union
|
||||
|
||||
import huggingface_hub
|
||||
import vllm.envs as envs
|
||||
@@ -17,10 +16,10 @@ logger = init_logger(__name__)
|
||||
|
||||
def download_weights_from_hf_specific(
|
||||
model_name_or_path: str,
|
||||
cache_dir: Optional[str],
|
||||
cache_dir: str | None,
|
||||
allow_patterns: list[str],
|
||||
revision: Optional[str] = None,
|
||||
ignore_patterns: Optional[Union[str, list[str]]] = None,
|
||||
revision: str | None = None,
|
||||
ignore_patterns: str | list[str] | None = None,
|
||||
) -> str:
|
||||
"""Download model weights from Hugging Face Hub. Users can specify the
|
||||
allow_patterns to download only the necessary weights.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import NamedTuple, Optional
|
||||
from typing import NamedTuple
|
||||
|
||||
import torch
|
||||
from vllm.sequence import IntermediateTensors
|
||||
@@ -8,6 +8,6 @@ class OmniOutput(NamedTuple):
|
||||
"""Output from the merged Omni model containing both text and audio."""
|
||||
|
||||
text_hidden_states: torch.Tensor
|
||||
multimodal_outputs: Optional[dict] = None
|
||||
intermediate_tensors: Optional[IntermediateTensors] = None
|
||||
next_token_id: Optional[torch.Tensor] = None
|
||||
multimodal_outputs: dict | None = None
|
||||
intermediate_tensors: IntermediateTensors | None = None
|
||||
next_token_id: torch.Tensor | None = None
|
||||
@@ -2,7 +2,6 @@ import glob
|
||||
import os
|
||||
from collections.abc import Iterable
|
||||
from functools import cached_property
|
||||
from typing import Optional, Union
|
||||
|
||||
import numpy as np
|
||||
import torch
|
||||
@@ -136,9 +135,9 @@ class Qwen2_5OmniForConditionalGeneration(
|
||||
def move_submodules_to_devices(
|
||||
self,
|
||||
*,
|
||||
thinker_device: Optional[Union[str, torch.device]] = None,
|
||||
talker_device: Optional[Union[str, torch.device]] = None,
|
||||
token2wav_device: Optional[Union[str, torch.device]] = None,
|
||||
thinker_device: str | torch.device | None = None,
|
||||
talker_device: str | torch.device | None = None,
|
||||
token2wav_device: str | torch.device | None = None,
|
||||
) -> None:
|
||||
"""Optionally move thinker/talker/token2wav to different devices.
|
||||
|
||||
@@ -182,17 +181,17 @@ class Qwen2_5OmniForConditionalGeneration(
|
||||
self,
|
||||
input_ids: torch.Tensor,
|
||||
positions: torch.Tensor,
|
||||
intermediate_tensors: Optional[IntermediateTensors] = None,
|
||||
inputs_embeds: Optional[torch.Tensor] = None,
|
||||
intermediate_tensors: IntermediateTensors | None = None,
|
||||
inputs_embeds: torch.Tensor | None = None,
|
||||
generate_audio: bool = True,
|
||||
voice_type: str = "Chelsie",
|
||||
codec: Optional[torch.Tensor] = None,
|
||||
sampling_metadata: Optional[SamplingMetadata] = None,
|
||||
logits_index: Optional[int] = None,
|
||||
codec: torch.Tensor | None = None,
|
||||
sampling_metadata: SamplingMetadata | None = None,
|
||||
logits_index: int | None = None,
|
||||
sampler=None,
|
||||
additional_information: Optional[dict[str, object]] = None,
|
||||
additional_information: dict[str, object] | None = None,
|
||||
**kwargs: object,
|
||||
) -> Union[torch.Tensor, IntermediateTensors, OmniOutput]:
|
||||
) -> torch.Tensor | IntermediateTensors | OmniOutput:
|
||||
"""
|
||||
Workflow:
|
||||
1) Thinker: multimodal understanding → text hidden states.
|
||||
@@ -292,9 +291,9 @@ class Qwen2_5OmniForConditionalGeneration(
|
||||
inputs_embeds = self.talker.get_input_embeddings(input_ids)
|
||||
|
||||
# ------- Request-scoped additional information (no cross-request concat) -------
|
||||
request_ids: Optional[list[str]] = kwargs.get("request_ids") # ordered
|
||||
request_token_spans: Optional[list[tuple[int, int]]] = kwargs.get("request_token_spans")
|
||||
addi_by_req: Optional[dict] = kwargs.get("additional_information_by_req_id")
|
||||
request_ids: list[str] | None = kwargs.get("request_ids") # ordered
|
||||
request_token_spans: list[tuple[int, int]] | None = kwargs.get("request_token_spans")
|
||||
addi_by_req: dict | None = kwargs.get("additional_information_by_req_id")
|
||||
runtime_addi = kwargs.get("runtime_additional_information")
|
||||
|
||||
# Normalize runtime_addi into a mapping by request_id for convenience
|
||||
@@ -796,7 +795,7 @@ class Qwen2_5OmniForConditionalGeneration(
|
||||
) # for decode
|
||||
return output_token_ids, processed_output_token_embeds
|
||||
|
||||
def compute_logits(self, hidden_states: Union[torch.Tensor, OmniOutput]) -> Optional[torch.Tensor]:
|
||||
def compute_logits(self, hidden_states: torch.Tensor | OmniOutput) -> torch.Tensor | None:
|
||||
# Handle OmniOutput type
|
||||
if isinstance(hidden_states, OmniOutput):
|
||||
hidden_states = hidden_states.text_hidden_states
|
||||
@@ -808,7 +807,7 @@ class Qwen2_5OmniForConditionalGeneration(
|
||||
self,
|
||||
logits: torch.Tensor,
|
||||
sampling_metadata: SamplingMetadata,
|
||||
) -> Optional[SamplerOutput]:
|
||||
) -> SamplerOutput | None:
|
||||
# Use thinker model for sampling
|
||||
return self.model.sample(logits, sampling_metadata)
|
||||
|
||||
@@ -891,7 +890,7 @@ class Qwen2_5OmniForConditionalGeneration(
|
||||
key = os.path.basename(f).split("_")[0].lower()
|
||||
self._token2wav_ref_mels[key] = torch.as_tensor(np.load(f), device=device)
|
||||
|
||||
def _codec_to_audio(self, codec_tokens: torch.Tensor, voice_type: str = "default") -> Optional[torch.Tensor]:
|
||||
def _codec_to_audio(self, codec_tokens: torch.Tensor, voice_type: str = "default") -> torch.Tensor | None:
|
||||
if self.token2wav is None:
|
||||
self._init_token2wav_model()
|
||||
if self.token2wav is None:
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from collections.abc import Iterable
|
||||
from functools import cached_property
|
||||
from typing import Optional, Union
|
||||
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
@@ -107,7 +106,7 @@ class Qwen2_5OmniTalkerForConditionalGeneration(
|
||||
def get_input_embeddings(
|
||||
self,
|
||||
input_ids: torch.Tensor,
|
||||
multimodal_embeddings: Optional[MultiModalEmbeddings] = None,
|
||||
multimodal_embeddings: MultiModalEmbeddings | None = None,
|
||||
) -> torch.Tensor:
|
||||
inputs_embeds = self.language_model.get_input_embeddings(input_ids)
|
||||
if multimodal_embeddings is not None and len(multimodal_embeddings) != 0:
|
||||
@@ -129,10 +128,10 @@ class Qwen2_5OmniTalkerForConditionalGeneration(
|
||||
self,
|
||||
input_ids: torch.Tensor = None,
|
||||
positions: torch.Tensor = None,
|
||||
intermediate_tensors: Optional[IntermediateTensors] = None,
|
||||
inputs_embeds: Optional[torch.Tensor] = None,
|
||||
intermediate_tensors: IntermediateTensors | None = None,
|
||||
inputs_embeds: torch.Tensor | None = None,
|
||||
**kwargs: object,
|
||||
) -> Union[torch.Tensor, IntermediateTensors]:
|
||||
) -> torch.Tensor | IntermediateTensors:
|
||||
assert input_ids is not None or inputs_embeds is not None, "input_ids or inputs_embeds must be provided"
|
||||
# forward_context: ForwardContext = get_forward_context() # unused variable
|
||||
|
||||
@@ -158,7 +157,7 @@ class Qwen2_5OmniTalkerForConditionalGeneration(
|
||||
logits[..., bos_id] = -1e9
|
||||
return logits
|
||||
|
||||
def compute_logits(self, hidden_states: torch.Tensor) -> Optional[torch.Tensor]:
|
||||
def compute_logits(self, hidden_states: torch.Tensor) -> torch.Tensor | None:
|
||||
logits = self.language_model.compute_logits(hidden_states)
|
||||
logits = self.bad_word_processor(logits)
|
||||
return logits
|
||||
@@ -167,7 +166,7 @@ class Qwen2_5OmniTalkerForConditionalGeneration(
|
||||
self,
|
||||
logits: torch.Tensor,
|
||||
sampling_metadata: SamplingMetadata,
|
||||
) -> Optional[SamplerOutput]:
|
||||
) -> SamplerOutput | None:
|
||||
return self.language_model.sample(logits, sampling_metadata)
|
||||
|
||||
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from collections import defaultdict
|
||||
from collections.abc import Iterable, Mapping, Sequence
|
||||
from collections.abc import Callable, Iterable, Mapping, Sequence
|
||||
from functools import partial
|
||||
from typing import Annotated, Any, Callable, Literal, Optional, Union
|
||||
from typing import Annotated, Any, Literal
|
||||
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
@@ -86,7 +86,7 @@ class Qwen2_5OmniAudioFeatureInputs(TensorSchema):
|
||||
|
||||
type: Literal["audio_features"]
|
||||
input_features: Annotated[
|
||||
Union[torch.Tensor, list[torch.Tensor]],
|
||||
torch.Tensor | list[torch.Tensor],
|
||||
TensorShape("nmb", "tsl"),
|
||||
]
|
||||
|
||||
@@ -155,7 +155,7 @@ def create_qwen2_5_omni_thinker_field_factory(
|
||||
class Qwen2_5OmniThinkerMultiModalDataParser(Qwen2VLMultiModalDataParser):
|
||||
def _parse_audio_data(
|
||||
self,
|
||||
data: Union[dict[str, torch.Tensor], ModalityData[ImageItem]],
|
||||
data: dict[str, torch.Tensor] | ModalityData[ImageItem],
|
||||
) -> ModalityDataItems[Any, Any]:
|
||||
if isinstance(data, dict):
|
||||
return DictEmbeddingItems(
|
||||
@@ -185,7 +185,7 @@ class Qwen2_5OmniThinkerProcessingInfo(Qwen2AudioProcessingInfo, Qwen2_5_VLProce
|
||||
assert isinstance(feature_extractor, WhisperFeatureExtractor)
|
||||
return feature_extractor
|
||||
|
||||
def get_supported_mm_limits(self) -> Mapping[str, Optional[int]]:
|
||||
def get_supported_mm_limits(self) -> Mapping[str, int | None]:
|
||||
return {"audio": None, "image": None, "video": None}
|
||||
|
||||
|
||||
@@ -608,7 +608,7 @@ class Qwen2_5OmniThinkerMultiModalProcessor(BaseMultiModalProcessor[Qwen2_5OmniT
|
||||
|
||||
def _apply_hf_processor_main(
|
||||
self,
|
||||
prompt: Union[str, list[int]],
|
||||
prompt: str | list[int],
|
||||
mm_items: MultiModalDataItems,
|
||||
hf_processor_mm_kwargs: Mapping[str, object],
|
||||
tokenization_kwargs: Mapping[str, object],
|
||||
@@ -676,7 +676,7 @@ class Qwen2_5OmniConditionalGenerationMixin:
|
||||
else:
|
||||
return torch.concat(mm_input, dim=dim)
|
||||
|
||||
def _parse_and_validate_audio_input(self, **kwargs: object) -> Optional[Qwen2_5OmniAudioFeatureInputs]:
|
||||
def _parse_and_validate_audio_input(self, **kwargs: object) -> Qwen2_5OmniAudioFeatureInputs | None:
|
||||
input_audio_features = kwargs.pop("input_audio_features", None)
|
||||
audio_feature_lengths = kwargs.pop("audio_feature_lengths", None)
|
||||
feature_attention_mask = kwargs.pop("feature_attention_mask", None)
|
||||
@@ -699,7 +699,7 @@ class Qwen2_5OmniConditionalGenerationMixin:
|
||||
def _parse_and_validate_image_input(
|
||||
self,
|
||||
**kwargs: dict[str, Any],
|
||||
) -> Optional[Qwen2_5_VLImageInputs]:
|
||||
) -> Qwen2_5_VLImageInputs | None:
|
||||
pixel_values = kwargs.pop("pixel_values", None)
|
||||
image_embeds = kwargs.pop("image_embeds", None)
|
||||
image_grid_thw = kwargs.pop("image_grid_thw", None)
|
||||
@@ -731,7 +731,7 @@ class Qwen2_5OmniConditionalGenerationMixin:
|
||||
def _parse_and_validate_video_input(
|
||||
self,
|
||||
**kwargs: dict[str, Any],
|
||||
) -> Optional[Qwen2_5_VLVideoInputs]:
|
||||
) -> Qwen2_5_VLVideoInputs | None:
|
||||
pixel_values_videos = kwargs.pop("pixel_values_videos", None)
|
||||
video_embeds = kwargs.pop("video_embeds", None)
|
||||
video_grid_thw = kwargs.pop("video_grid_thw", None)
|
||||
@@ -841,7 +841,7 @@ class Qwen2_5OmniThinkerForConditionalGeneration(
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def get_placeholder_str(cls, modality: str, i: int) -> Optional[str]:
|
||||
def get_placeholder_str(cls, modality: str, i: int) -> str | None:
|
||||
if modality.startswith("image"):
|
||||
return "<|vision_start|><|IMAGE|><|vision_end|>"
|
||||
if modality.startswith("video"):
|
||||
@@ -940,7 +940,7 @@ class Qwen2_5OmniThinkerForConditionalGeneration(
|
||||
def get_input_embeddings(
|
||||
self,
|
||||
input_ids: torch.Tensor,
|
||||
multimodal_embeddings: Optional[MultiModalEmbeddings] = None,
|
||||
multimodal_embeddings: MultiModalEmbeddings | None = None,
|
||||
) -> torch.Tensor:
|
||||
inputs_embeds = self.language_model.get_input_embeddings(input_ids)
|
||||
if multimodal_embeddings is not None and len(multimodal_embeddings) != 0:
|
||||
@@ -958,7 +958,7 @@ class Qwen2_5OmniThinkerForConditionalGeneration(
|
||||
)
|
||||
return inputs_embeds
|
||||
|
||||
def get_multimodal_embeddings_v0(self, **kwargs: object) -> Optional[NestedTensors]:
|
||||
def get_multimodal_embeddings_v0(self, **kwargs: object) -> NestedTensors | None:
|
||||
audio_input = self._parse_and_validate_audio_input(**kwargs)
|
||||
image_input = self._parse_and_validate_image_input(**kwargs)
|
||||
video_input = self._parse_and_validate_video_input(**kwargs)
|
||||
@@ -982,7 +982,7 @@ class Qwen2_5OmniThinkerForConditionalGeneration(
|
||||
def get_input_embeddings_v0(
|
||||
self,
|
||||
input_ids: torch.Tensor,
|
||||
multimodal_embeddings: Optional[NestedTensors] = None,
|
||||
multimodal_embeddings: NestedTensors | None = None,
|
||||
) -> torch.Tensor:
|
||||
inputs_embeds = self.language_model.get_input_embeddings(input_ids)
|
||||
if multimodal_embeddings is None or len(multimodal_embeddings) == 0:
|
||||
@@ -1002,10 +1002,10 @@ class Qwen2_5OmniThinkerForConditionalGeneration(
|
||||
self,
|
||||
input_ids: torch.Tensor,
|
||||
positions: torch.Tensor,
|
||||
intermediate_tensors: Optional[IntermediateTensors] = None,
|
||||
inputs_embeds: Optional[torch.Tensor] = None,
|
||||
intermediate_tensors: IntermediateTensors | None = None,
|
||||
inputs_embeds: torch.Tensor | None = None,
|
||||
**kwargs: object,
|
||||
) -> Union[torch.Tensor, IntermediateTensors]:
|
||||
) -> torch.Tensor | IntermediateTensors:
|
||||
if intermediate_tensors is not None:
|
||||
inputs_embeds = None
|
||||
|
||||
@@ -1031,7 +1031,7 @@ class Qwen2_5OmniThinkerForConditionalGeneration(
|
||||
)
|
||||
return text_inputs_embeds, hidden_states.unsqueeze(0) # (1, S, D)
|
||||
|
||||
def compute_logits(self, hidden_states: torch.Tensor) -> Optional[torch.Tensor]:
|
||||
def compute_logits(self, hidden_states: torch.Tensor) -> torch.Tensor | None:
|
||||
return self.language_model.compute_logits(hidden_states)
|
||||
|
||||
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
import math
|
||||
from collections.abc import Iterable
|
||||
from typing import Optional, Union
|
||||
|
||||
import numpy as np
|
||||
import torch
|
||||
@@ -395,9 +394,9 @@ class DiTInputEmbedding(nn.Module):
|
||||
speaker_embedding: torch.Tensor,
|
||||
condition_vector: torch.Tensor,
|
||||
code_embed: torch.Tensor,
|
||||
drop_audio_cond: Optional[bool] = False,
|
||||
code_embed_uncond: Optional[bool] = None,
|
||||
apply_cfg: Optional[bool] = True,
|
||||
drop_audio_cond: bool | None = False,
|
||||
code_embed_uncond: bool | None = None,
|
||||
apply_cfg: bool | None = True,
|
||||
):
|
||||
if apply_cfg:
|
||||
hidden_states = torch.cat([hidden_states, hidden_states], dim=0)
|
||||
@@ -1324,7 +1323,7 @@ class Qwen2_5OmniToken2WavDiTModel(Qwen2_5OmniPreTrainedModel):
|
||||
y0: torch.Tensor,
|
||||
num_steps: int = 10,
|
||||
guidance_scale: float = 0.5,
|
||||
sway_coefficient: Optional[float] = -1.0,
|
||||
sway_coefficient: float | None = -1.0,
|
||||
) -> torch.Tensor:
|
||||
"""
|
||||
Block-wise ODE sampling starting from provided initial state y0.
|
||||
@@ -1521,7 +1520,7 @@ class Qwen2_5OmniToken2WavModel(Qwen2_5OmniPreTrainedModel):
|
||||
steps: int,
|
||||
prev_generated: torch.Tensor,
|
||||
finished: bool = False,
|
||||
) -> tuple[Optional[torch.Tensor], torch.Tensor]:
|
||||
) -> tuple[torch.Tensor | None, torch.Tensor]:
|
||||
"""Streaming per small chunk: returns (mel_or_None, audio_slice)."""
|
||||
start_index = max(i * self.chunk_size - self.past_cache_size, 0)
|
||||
end_index = min(
|
||||
@@ -1560,9 +1559,9 @@ class Qwen2_5OmniToken2WavModel(Qwen2_5OmniPreTrainedModel):
|
||||
y_all: torch.Tensor,
|
||||
i: int,
|
||||
steps: int,
|
||||
prev_generated: Union[torch.Tensor, list[torch.Tensor]],
|
||||
prev_generated: torch.Tensor | list[torch.Tensor],
|
||||
finished: bool = False,
|
||||
) -> tuple[Union[torch.Tensor, list[torch.Tensor]], torch.Tensor]:
|
||||
) -> tuple[torch.Tensor | list[torch.Tensor], torch.Tensor]:
|
||||
"""High-level chunk API aligning to qwen2_code2wav_dit signature."""
|
||||
if not isinstance(prev_generated, torch.Tensor):
|
||||
prev_generated = prev_generated[0] if len(prev_generated) > 0 else None
|
||||
@@ -1585,7 +1584,7 @@ class Qwen2_5OmniToken2WavModel(Qwen2_5OmniPreTrainedModel):
|
||||
start_index: int,
|
||||
end_index: int,
|
||||
finished: bool,
|
||||
prev_generated: Optional[torch.Tensor],
|
||||
prev_generated: torch.Tensor | None,
|
||||
generated: torch.Tensor,
|
||||
) -> tuple[torch.Tensor, torch.Tensor]:
|
||||
"""
|
||||
@@ -1671,7 +1670,7 @@ class Qwen2_5OmniToken2WavForConditionalGenerationVLLM(nn.Module, SupportsPP):
|
||||
num_steps: int = 10,
|
||||
guidance_scale: float = 0.5,
|
||||
sway_coefficient: float = -1.0,
|
||||
intermediate_tensors: Optional[IntermediateTensors] = None,
|
||||
intermediate_tensors: IntermediateTensors | None = None,
|
||||
**kwargs,
|
||||
) -> torch.Tensor:
|
||||
# Delegate to HF token2wav model
|
||||
@@ -1685,7 +1684,7 @@ class Qwen2_5OmniToken2WavForConditionalGenerationVLLM(nn.Module, SupportsPP):
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
def compute_logits(self, hidden_states: torch.Tensor) -> Optional[torch.Tensor]:
|
||||
def compute_logits(self, hidden_states: torch.Tensor) -> torch.Tensor | None:
|
||||
# Token2Wav outputs waveform; logits are not applicable
|
||||
return hidden_states
|
||||
|
||||
@@ -1693,7 +1692,7 @@ class Qwen2_5OmniToken2WavForConditionalGenerationVLLM(nn.Module, SupportsPP):
|
||||
self,
|
||||
logits: torch.Tensor,
|
||||
sampling_metadata: SamplingMetadata,
|
||||
) -> Optional[SamplerOutput]:
|
||||
) -> SamplerOutput | None:
|
||||
return None
|
||||
|
||||
def load_weights_without_buffers(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
|
||||
@@ -1782,7 +1781,7 @@ class Qwen2_5OmniToken2WavForConditionalGenerationVLLM(nn.Module, SupportsPP):
|
||||
)
|
||||
|
||||
@torch.inference_mode()
|
||||
def process_chunk_bigvgan_batch(self, mel_batch: torch.Tensor) -> Optional[torch.Tensor]:
|
||||
def process_chunk_bigvgan_batch(self, mel_batch: torch.Tensor) -> torch.Tensor | None:
|
||||
# BigVGAN is not part of this wrapper; return None for parity.
|
||||
return None
|
||||
|
||||
@@ -1797,7 +1796,7 @@ class Qwen2_5OmniToken2WavForConditionalGenerationVLLM(nn.Module, SupportsPP):
|
||||
steps: int,
|
||||
prev_generated: torch.Tensor,
|
||||
finished: bool = False,
|
||||
) -> tuple[Optional[torch.Tensor], torch.Tensor]:
|
||||
) -> tuple[torch.Tensor | None, torch.Tensor]:
|
||||
mel = self.token2wav(
|
||||
code=codec_all,
|
||||
conditioning=conditioning,
|
||||
@@ -1815,9 +1814,9 @@ class Qwen2_5OmniToken2WavForConditionalGenerationVLLM(nn.Module, SupportsPP):
|
||||
y_all: torch.Tensor,
|
||||
i: int,
|
||||
steps: int,
|
||||
prev_generated: Union[torch.Tensor, list[torch.Tensor]],
|
||||
prev_generated: torch.Tensor | list[torch.Tensor],
|
||||
finished: bool = False,
|
||||
) -> tuple[Union[torch.Tensor, list[torch.Tensor]], torch.Tensor]:
|
||||
) -> tuple[torch.Tensor | list[torch.Tensor], torch.Tensor]:
|
||||
_mel, out = self.process_little_chunk(
|
||||
conditioning=conditioning,
|
||||
reference_mel=reference_mel,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
from collections.abc import Iterable
|
||||
from typing import Optional, Union
|
||||
|
||||
import torch
|
||||
from torch import nn
|
||||
@@ -43,7 +42,7 @@ class Qwen2MLP(nn.Module):
|
||||
hidden_size: int,
|
||||
intermediate_size: int,
|
||||
hidden_act: str,
|
||||
quant_config: Optional[QuantizationConfig] = None,
|
||||
quant_config: QuantizationConfig | None = None,
|
||||
prefix: str = "",
|
||||
) -> None:
|
||||
super().__init__()
|
||||
@@ -80,10 +79,10 @@ class Qwen2Attention(nn.Module):
|
||||
num_kv_heads: int,
|
||||
max_position: int = 4096 * 32,
|
||||
rope_theta: float = 10000,
|
||||
head_dim: Optional[int] = None,
|
||||
cache_config: Optional[CacheConfig] = None,
|
||||
quant_config: Optional[QuantizationConfig] = None,
|
||||
rope_scaling: Optional[tuple] = None,
|
||||
head_dim: int | None = None,
|
||||
cache_config: CacheConfig | None = None,
|
||||
quant_config: QuantizationConfig | None = None,
|
||||
rope_scaling: tuple | None = None,
|
||||
prefix: str = "",
|
||||
attn_type: str = AttentionType.DECODER,
|
||||
) -> None:
|
||||
@@ -161,8 +160,8 @@ class Qwen2DecoderLayer(nn.Module):
|
||||
def __init__(
|
||||
self,
|
||||
config: Qwen2Config,
|
||||
cache_config: Optional[CacheConfig] = None,
|
||||
quant_config: Optional[QuantizationConfig] = None,
|
||||
cache_config: CacheConfig | None = None,
|
||||
quant_config: QuantizationConfig | None = None,
|
||||
prefix: str = "",
|
||||
) -> None:
|
||||
super().__init__()
|
||||
@@ -207,7 +206,7 @@ class Qwen2DecoderLayer(nn.Module):
|
||||
self,
|
||||
positions: torch.Tensor,
|
||||
hidden_states: torch.Tensor,
|
||||
residual: Optional[torch.Tensor],
|
||||
residual: torch.Tensor | None,
|
||||
) -> tuple[torch.Tensor, torch.Tensor]:
|
||||
# Self Attention
|
||||
if residual is None:
|
||||
@@ -302,9 +301,9 @@ class Qwen2Model(nn.Module):
|
||||
self,
|
||||
input_ids: torch.Tensor,
|
||||
positions: torch.Tensor,
|
||||
intermediate_tensors: Optional[IntermediateTensors] = None,
|
||||
inputs_embeds: Optional[torch.Tensor] = None,
|
||||
) -> Union[torch.Tensor, IntermediateTensors]:
|
||||
intermediate_tensors: IntermediateTensors | None = None,
|
||||
inputs_embeds: torch.Tensor | None = None,
|
||||
) -> torch.Tensor | IntermediateTensors:
|
||||
if get_pp_group().is_first_rank:
|
||||
if inputs_embeds is not None:
|
||||
hidden_states = inputs_embeds
|
||||
@@ -428,16 +427,16 @@ class Qwen2ForCausalLM(nn.Module, SupportsLoRA, SupportsPP):
|
||||
self,
|
||||
input_ids: torch.Tensor,
|
||||
positions: torch.Tensor,
|
||||
intermediate_tensors: Optional[IntermediateTensors] = None,
|
||||
inputs_embeds: Optional[torch.Tensor] = None,
|
||||
) -> Union[torch.Tensor, IntermediateTensors]:
|
||||
intermediate_tensors: IntermediateTensors | None = None,
|
||||
inputs_embeds: torch.Tensor | None = None,
|
||||
) -> torch.Tensor | IntermediateTensors:
|
||||
hidden_states = self.model(input_ids, positions, intermediate_tensors, inputs_embeds)
|
||||
return hidden_states
|
||||
|
||||
def compute_logits(
|
||||
self,
|
||||
hidden_states: torch.Tensor,
|
||||
) -> Optional[torch.Tensor]:
|
||||
) -> torch.Tensor | None:
|
||||
logits = self.logits_processor(self.lm_head, hidden_states)
|
||||
return logits
|
||||
|
||||
@@ -445,7 +444,7 @@ class Qwen2ForCausalLM(nn.Module, SupportsLoRA, SupportsPP):
|
||||
self,
|
||||
logits: torch.Tensor,
|
||||
sampling_metadata: SamplingMetadata,
|
||||
) -> Optional[SamplerOutput]:
|
||||
) -> SamplerOutput | None:
|
||||
next_tokens = self.sampler(logits, sampling_metadata)
|
||||
return next_tokens
|
||||
|
||||
@@ -503,7 +502,7 @@ class Qwen2EmbeddingModel(nn.Module, SupportsLoRA, SupportsPP):
|
||||
self,
|
||||
input_ids: torch.Tensor,
|
||||
positions: torch.Tensor,
|
||||
intermediate_tensors: Optional[IntermediateTensors] = None,
|
||||
intermediate_tensors: IntermediateTensors | None = None,
|
||||
) -> torch.Tensor:
|
||||
return self.model(input_ids, positions, intermediate_tensors)
|
||||
|
||||
@@ -511,7 +510,7 @@ class Qwen2EmbeddingModel(nn.Module, SupportsLoRA, SupportsPP):
|
||||
self,
|
||||
hidden_states: torch.Tensor,
|
||||
pooling_metadata: PoolingMetadata,
|
||||
) -> Optional[PoolerOutput]:
|
||||
) -> PoolerOutput | None:
|
||||
return self._pooler(hidden_states, pooling_metadata)
|
||||
|
||||
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]):
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
from collections import defaultdict
|
||||
from collections.abc import Iterable
|
||||
from functools import cached_property
|
||||
from typing import Optional, Union
|
||||
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
@@ -198,10 +197,10 @@ class Qwen3OmniMoeForConditionalGeneration(
|
||||
def move_submodules_to_devices(
|
||||
self,
|
||||
*,
|
||||
thinker_device: Optional[Union[str, torch.device]] = None,
|
||||
talker_device: Optional[Union[str, torch.device]] = None,
|
||||
code_predictor_device: Optional[Union[str, torch.device]] = None,
|
||||
code2wav_device: Optional[Union[str, torch.device]] = None,
|
||||
thinker_device: str | torch.device | None = None,
|
||||
talker_device: str | torch.device | None = None,
|
||||
code_predictor_device: str | torch.device | None = None,
|
||||
code2wav_device: str | torch.device | None = None,
|
||||
) -> None:
|
||||
"""
|
||||
Optionally move thinker/talker/code2wav to different devices.
|
||||
@@ -257,16 +256,16 @@ class Qwen3OmniMoeForConditionalGeneration(
|
||||
self,
|
||||
input_ids: torch.Tensor,
|
||||
positions: torch.Tensor,
|
||||
intermediate_tensors: Optional[IntermediateTensors] = None,
|
||||
inputs_embeds: Optional[torch.Tensor] = None,
|
||||
intermediate_tensors: IntermediateTensors | None = None,
|
||||
inputs_embeds: torch.Tensor | None = None,
|
||||
generate_audio: bool = True,
|
||||
voice_type: str = "ethan",
|
||||
codec: Optional[torch.Tensor] = None,
|
||||
sampling_metadata: Optional[SamplingMetadata] = None,
|
||||
logits_index: Optional[int] = None,
|
||||
additional_information: Optional[dict[str, object]] = None,
|
||||
codec: torch.Tensor | None = None,
|
||||
sampling_metadata: SamplingMetadata | None = None,
|
||||
logits_index: int | None = None,
|
||||
additional_information: dict[str, object] | None = None,
|
||||
**kwargs: object,
|
||||
) -> Union[torch.Tensor, IntermediateTensors, OmniOutput]:
|
||||
) -> torch.Tensor | IntermediateTensors | OmniOutput:
|
||||
"""
|
||||
Unified forward pass for all model stages.
|
||||
|
||||
@@ -383,9 +382,9 @@ class Qwen3OmniMoeForConditionalGeneration(
|
||||
inputs_embeds = self.talker.get_input_embeddings(input_ids)
|
||||
|
||||
# ------- Request-scoped additional information (no cross-request concat) -------
|
||||
request_ids: Optional[list[str]] = kwargs.get("request_ids") # ordered
|
||||
request_token_spans: Optional[list[tuple[int, int]]] = kwargs.get("request_token_spans")
|
||||
addi_by_req: Optional[dict] = kwargs.get("additional_information_by_req_id")
|
||||
request_ids: list[str] | None = kwargs.get("request_ids") # ordered
|
||||
request_token_spans: list[tuple[int, int]] | None = kwargs.get("request_token_spans")
|
||||
addi_by_req: dict | None = kwargs.get("additional_information_by_req_id")
|
||||
runtime_addi = kwargs.get("runtime_additional_information")
|
||||
|
||||
# Normalize runtime_addi into a mapping by request_id for convenience
|
||||
@@ -808,14 +807,14 @@ class Qwen3OmniMoeForConditionalGeneration(
|
||||
self,
|
||||
thinker_embed: torch.Tensor,
|
||||
thinker_hidden: torch.Tensor,
|
||||
multimodal_mask: Optional[torch.Tensor],
|
||||
multimodal_mask: torch.Tensor | None,
|
||||
input_ids: torch.Tensor,
|
||||
thinker_result_ids: torch.Tensor,
|
||||
speaker_id,
|
||||
tts_bos_thinker: Optional[torch.Tensor] = None,
|
||||
tts_eos_thinker: Optional[torch.Tensor] = None,
|
||||
tts_pad_thinker: Optional[torch.Tensor] = None,
|
||||
) -> tuple[torch.Tensor, torch.Tensor, Optional[torch.Tensor]]:
|
||||
tts_bos_thinker: torch.Tensor | None = None,
|
||||
tts_eos_thinker: torch.Tensor | None = None,
|
||||
tts_pad_thinker: torch.Tensor | None = None,
|
||||
) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor | None]:
|
||||
"""
|
||||
Project thinker outputs to talker inputs during prefill stage.
|
||||
|
||||
@@ -845,7 +844,7 @@ class Qwen3OmniMoeForConditionalGeneration(
|
||||
return x[-1]
|
||||
return x.view(1, 1, -1)
|
||||
|
||||
def _proj_from_thinker(x_opt: Optional[torch.Tensor]) -> torch.Tensor:
|
||||
def _proj_from_thinker(x_opt: torch.Tensor | None) -> torch.Tensor:
|
||||
if isinstance(x_opt, torch.Tensor) and x_opt.numel() > 0:
|
||||
xin = _ensure_1x1(x_opt).to(talker_dev)
|
||||
else:
|
||||
@@ -863,7 +862,7 @@ class Qwen3OmniMoeForConditionalGeneration(
|
||||
|
||||
talker_input_embeds = [] # [1 t d]
|
||||
talker_input_ids = []
|
||||
trailing_text_hidden_all: Optional[torch.Tensor] = None
|
||||
trailing_text_hidden_all: torch.Tensor | None = None
|
||||
# For every chatml parts
|
||||
for i in range(len(im_start_indexes) - 1):
|
||||
im_start_index = im_start_indexes[i].item()
|
||||
@@ -986,8 +985,8 @@ class Qwen3OmniMoeForConditionalGeneration(
|
||||
|
||||
def _talker_to_code_predictor(
|
||||
self,
|
||||
talker_hidden_states: Optional[torch.Tensor],
|
||||
layer0_token_ids: Optional[torch.Tensor],
|
||||
talker_hidden_states: torch.Tensor | None,
|
||||
layer0_token_ids: torch.Tensor | None,
|
||||
) -> tuple[torch.Tensor, torch.Tensor]:
|
||||
"""
|
||||
Project talker outputs to code predictor inputs.
|
||||
@@ -1025,9 +1024,9 @@ class Qwen3OmniMoeForConditionalGeneration(
|
||||
|
||||
def compute_logits(
|
||||
self,
|
||||
hidden_states: Union[torch.Tensor, OmniOutput],
|
||||
hidden_states: torch.Tensor | OmniOutput,
|
||||
sampling_metadata: SamplingMetadata = None,
|
||||
) -> Optional[torch.Tensor]:
|
||||
) -> torch.Tensor | None:
|
||||
"""Compute logits from hidden states."""
|
||||
# Handle OmniOutput type
|
||||
from vllm.v1.sample.logits_processor import LogitsProcessors
|
||||
@@ -1083,7 +1082,7 @@ class Qwen3OmniMoeForConditionalGeneration(
|
||||
self,
|
||||
logits: torch.Tensor,
|
||||
sampling_metadata: SamplingMetadata,
|
||||
) -> Optional[SamplerOutput]:
|
||||
) -> SamplerOutput | None:
|
||||
"""Sample from logits."""
|
||||
return self.model.sample(logits, sampling_metadata)
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ autoregressively, predicting layers 1 to N based on layer-0 codes from the talke
|
||||
"""
|
||||
|
||||
from collections import namedtuple
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
@@ -136,10 +136,10 @@ class Qwen3OmniCodePredictorAttention(nn.Module):
|
||||
causal_mask: torch.Tensor,
|
||||
cos: torch.Tensor,
|
||||
sin: torch.Tensor,
|
||||
past_key_values: Optional[Cache] = None,
|
||||
cache_position: Optional[torch.LongTensor] = None,
|
||||
past_key_values: Cache | None = None,
|
||||
cache_position: torch.LongTensor | None = None,
|
||||
use_cache: bool = False,
|
||||
position_ids: Optional[torch.LongTensor] = None,
|
||||
position_ids: torch.LongTensor | None = None,
|
||||
) -> torch.Tensor:
|
||||
bsz, seq_len, _ = hidden_states.shape
|
||||
|
||||
@@ -253,8 +253,8 @@ class Qwen3OmniCodePredictorMTPLayer(nn.Module):
|
||||
prefix: str,
|
||||
model_config: ModelConfig,
|
||||
layer_idx: int,
|
||||
cache_config: Optional[CacheConfig] = None,
|
||||
quant_config: Optional[QuantizationConfig] = None,
|
||||
cache_config: CacheConfig | None = None,
|
||||
quant_config: QuantizationConfig | None = None,
|
||||
) -> None:
|
||||
super().__init__()
|
||||
self.layer_idx = layer_idx
|
||||
@@ -284,10 +284,10 @@ class Qwen3OmniCodePredictorMTPLayer(nn.Module):
|
||||
causal_mask: torch.Tensor,
|
||||
cos: torch.Tensor,
|
||||
sin: torch.Tensor,
|
||||
past_key_values: Optional[Cache] = None,
|
||||
cache_position: Optional[torch.LongTensor] = None,
|
||||
past_key_values: Cache | None = None,
|
||||
cache_position: torch.LongTensor | None = None,
|
||||
use_cache: bool = False,
|
||||
position_ids: Optional[torch.LongTensor] = None,
|
||||
position_ids: torch.LongTensor | None = None,
|
||||
) -> torch.Tensor:
|
||||
# Self-attention with residual
|
||||
residual = hidden_states
|
||||
@@ -310,7 +310,7 @@ class Qwen3OmniCodePredictorMTPLayer(nn.Module):
|
||||
input_ids: torch.Tensor,
|
||||
positions: torch.Tensor,
|
||||
previous_hidden_states: torch.Tensor,
|
||||
inputs_embeds: Optional[torch.Tensor] = None,
|
||||
inputs_embeds: torch.Tensor | None = None,
|
||||
spec_step_index: int = 0,
|
||||
) -> torch.Tensor:
|
||||
assert inputs_embeds is not None, "inputs_embeds required for MTP"
|
||||
@@ -396,11 +396,11 @@ class Qwen3OmniCodePredictorBaseModel(nn.Module):
|
||||
def forward(
|
||||
self,
|
||||
inputs_embeds: torch.Tensor,
|
||||
attention_mask: Optional[torch.Tensor] = None,
|
||||
position_ids: Optional[torch.LongTensor] = None,
|
||||
past_key_values: Optional[Any] = None,
|
||||
use_cache: Optional[bool] = False,
|
||||
cache_position: Optional[torch.LongTensor] = None,
|
||||
attention_mask: torch.Tensor | None = None,
|
||||
position_ids: torch.LongTensor | None = None,
|
||||
past_key_values: Any | None = None,
|
||||
use_cache: bool | None = False,
|
||||
cache_position: torch.LongTensor | None = None,
|
||||
**kwargs: Any,
|
||||
) -> Any:
|
||||
"""
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
from typing import Union
|
||||
|
||||
import torch
|
||||
from vllm.inputs import TextPrompt
|
||||
|
||||
@@ -13,7 +11,7 @@ TALKER_CODEC_END_TOKEN_ID = 8294
|
||||
def thinker2talker(
|
||||
stage_list,
|
||||
engine_input_source,
|
||||
prompt: Union[OmniTokensPrompt, TextPrompt] = None,
|
||||
prompt: OmniTokensPrompt | TextPrompt = None,
|
||||
requires_multimodal_data: bool = False,
|
||||
):
|
||||
if not engine_input_source:
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# Copyright 2025 The Qwen team.
|
||||
"""Stage input processor for Qwen3 Omni MoE: Thinker → Talker transition."""
|
||||
|
||||
from typing import Any, Union
|
||||
from typing import Any
|
||||
|
||||
import torch
|
||||
from vllm.inputs import TextPrompt
|
||||
@@ -49,7 +49,7 @@ def _compute_talker_prompt_ids_length(info):
|
||||
def thinker2talker(
|
||||
stage_list: list[Any],
|
||||
engine_input_source: list[int],
|
||||
prompt: Union[OmniTokensPrompt, TextPrompt, None] = None,
|
||||
prompt: OmniTokensPrompt | TextPrompt | None = None,
|
||||
requires_multimodal_data: bool = False,
|
||||
) -> list[OmniTokensPrompt]:
|
||||
"""
|
||||
@@ -114,7 +114,7 @@ def thinker2talker(
|
||||
def talker2code2wav(
|
||||
stage_list: list[Any],
|
||||
engine_input_source: list[int],
|
||||
prompt: Union[OmniTokensPrompt, TextPrompt, None] = None,
|
||||
prompt: OmniTokensPrompt | TextPrompt | None = None,
|
||||
requires_multimodal_data: bool = False,
|
||||
) -> list[OmniTokensPrompt]:
|
||||
"""
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional
|
||||
|
||||
import torch
|
||||
from vllm.outputs import RequestOutput
|
||||
@@ -17,7 +16,7 @@ class OmniModelRunnerOutput(ModelRunnerOutput):
|
||||
output tensors (e.g., {"image": tensor, "audio": tensor})
|
||||
"""
|
||||
|
||||
multimodal_outputs: Optional[dict[str, torch.Tensor]] = None
|
||||
multimodal_outputs: dict[str, torch.Tensor] | None = None
|
||||
|
||||
|
||||
@dataclass
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from typing import TYPE_CHECKING, Callable, Optional
|
||||
from collections.abc import Callable
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from vllm.v1.request import Request
|
||||
from vllm.v1.structured_output.request import StructuredOutputRequest
|
||||
@@ -25,22 +26,22 @@ class OmniRequest(Request):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
prompt_embeds: Optional[PromptEmbedsPayload] = None,
|
||||
additional_information: Optional[AdditionalInformationPayload] = None,
|
||||
prompt_embeds: PromptEmbedsPayload | None = None,
|
||||
additional_information: AdditionalInformationPayload | None = None,
|
||||
*args,
|
||||
**kwargs,
|
||||
):
|
||||
super().__init__(*args, **kwargs)
|
||||
# Serialized prompt embeddings payload (optional)
|
||||
self.prompt_embeds: Optional[PromptEmbedsPayload] = prompt_embeds
|
||||
self.prompt_embeds: PromptEmbedsPayload | None = prompt_embeds
|
||||
# Serialized additional information payload (optional)
|
||||
self.additional_information: Optional[AdditionalInformationPayload] = additional_information
|
||||
self.additional_information: AdditionalInformationPayload | None = additional_information
|
||||
|
||||
@classmethod
|
||||
def from_engine_core_request(
|
||||
cls,
|
||||
request: OmniEngineCoreRequest,
|
||||
block_hasher: Optional[Callable[["Request"], list["BlockHash"]]],
|
||||
block_hasher: Callable[["Request"], list["BlockHash"]] | None,
|
||||
) -> "Request":
|
||||
"""Create an OmniRequest from an OmniEngineCoreRequest.
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import TYPE_CHECKING, Any, Optional, Union, cast
|
||||
from typing import TYPE_CHECKING, Any, cast
|
||||
|
||||
import numpy as np
|
||||
import torch
|
||||
@@ -307,7 +307,7 @@ class OmniGPUModelRunner(GPUModelRunner):
|
||||
self.input_batch.refresh_metadata()
|
||||
|
||||
@torch.inference_mode()
|
||||
def extract_multimodal_outputs(self, hidden_states: Union[torch.Tensor, list[torch.Tensor]]) -> dict:
|
||||
def extract_multimodal_outputs(self, hidden_states: torch.Tensor | list[torch.Tensor]) -> dict:
|
||||
if hasattr(self.model, "have_multimodal_outputs") and self.model.have_multimodal_outputs:
|
||||
text_hidden_states = hidden_states.text_hidden_states
|
||||
multimodal_outputs = hidden_states.multimodal_outputs
|
||||
@@ -326,7 +326,7 @@ class OmniGPUModelRunner(GPUModelRunner):
|
||||
def _dummy_run(
|
||||
self,
|
||||
num_tokens: int,
|
||||
cudagraph_runtime_mode: Optional[CUDAGraphMode] = None,
|
||||
cudagraph_runtime_mode: CUDAGraphMode | None = None,
|
||||
force_attention: bool = False,
|
||||
uniform_decode: bool = False,
|
||||
allow_microbatching: bool = True,
|
||||
@@ -444,7 +444,7 @@ class OmniGPUModelRunner(GPUModelRunner):
|
||||
num_tokens_across_dp = num_tokens_after_padding
|
||||
num_tokens_after_padding = int(num_tokens_after_padding[0].item())
|
||||
|
||||
attn_metadata: Optional[PerLayerAttnMetadata] = None
|
||||
attn_metadata: PerLayerAttnMetadata | None = None
|
||||
|
||||
# If force_attention is True, we always capture attention. Otherwise,
|
||||
# it only happens for cudagraph_runtime_mode=FULL.
|
||||
@@ -612,19 +612,19 @@ class OmniGPUModelRunner(GPUModelRunner):
|
||||
self,
|
||||
scheduler_output: "SchedulerOutput",
|
||||
num_scheduled_tokens_np: np.ndarray,
|
||||
intermediate_tensors: Optional[IntermediateTensors] = None,
|
||||
ubatch_slices: Optional[UBatchSlices] = None,
|
||||
num_tokens_after_padding: Optional[torch.Tensor] = None,
|
||||
intermediate_tensors: IntermediateTensors | None = None,
|
||||
ubatch_slices: UBatchSlices | None = None,
|
||||
num_tokens_after_padding: torch.Tensor | None = None,
|
||||
) -> tuple[
|
||||
int,
|
||||
int,
|
||||
Optional[torch.Tensor],
|
||||
Optional[torch.Tensor],
|
||||
Optional[torch.Tensor],
|
||||
torch.Tensor | None,
|
||||
torch.Tensor | None,
|
||||
torch.Tensor | None,
|
||||
torch.Tensor,
|
||||
Optional[IntermediateTensors],
|
||||
IntermediateTensors | None,
|
||||
dict[str, Any],
|
||||
Optional[dict[str, dict]],
|
||||
dict[str, dict] | None,
|
||||
]:
|
||||
num_scheduled_tokens = scheduler_output.total_num_scheduled_tokens
|
||||
if ubatch_slices:
|
||||
@@ -638,7 +638,7 @@ class OmniGPUModelRunner(GPUModelRunner):
|
||||
|
||||
# _prepare_inputs may reorder the batch, so we must gather multi
|
||||
# modal outputs after that to ensure the correct order
|
||||
per_req_additional_information: Optional[dict[str, dict]] = None
|
||||
per_req_additional_information: dict[str, dict] | None = None
|
||||
if self.supports_mm_inputs and get_pp_group().is_first_rank and not self.model_config.is_encoder_decoder:
|
||||
# Build multimodal inputs and overlay prompt embeds; collect per-request info
|
||||
per_req_additional_information = self._build_mm_inputs_and_overlays(
|
||||
@@ -784,7 +784,7 @@ class OmniGPUModelRunner(GPUModelRunner):
|
||||
|
||||
def _build_model_kwargs_extra(
|
||||
self,
|
||||
per_req_additional_information: Optional[dict[str, dict]],
|
||||
per_req_additional_information: dict[str, dict] | None,
|
||||
num_scheduled_tokens_np,
|
||||
) -> dict:
|
||||
"""Build extra keyword arguments passed to the model for this step, including:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
||||
|
||||
import math
|
||||
from typing import TYPE_CHECKING, Any, Optional, Union, cast
|
||||
from typing import TYPE_CHECKING, Any, cast
|
||||
|
||||
import numpy as np
|
||||
import torch
|
||||
@@ -293,8 +293,8 @@ class OmniNPUModelRunner(NPUModelRunner):
|
||||
|
||||
@torch.inference_mode()
|
||||
def extract_multimodal_outputs(
|
||||
self, hidden_states: Union[torch.Tensor, list[torch.Tensor]]
|
||||
) -> tuple[torch.Tensor, Union[torch.Tensor, list[torch.Tensor], dict]]:
|
||||
self, hidden_states: torch.Tensor | list[torch.Tensor]
|
||||
) -> tuple[torch.Tensor, torch.Tensor | list[torch.Tensor] | dict]:
|
||||
"""Extract multimodal outputs from hidden states."""
|
||||
if hasattr(self.model, "have_multimodal_outputs") and self.model.have_multimodal_outputs:
|
||||
text_hidden_states = hidden_states.text_hidden_states
|
||||
@@ -373,7 +373,7 @@ class OmniNPUModelRunner(NPUModelRunner):
|
||||
num_tokens: int,
|
||||
with_prefill: bool = False,
|
||||
is_torchair_compile: bool = False,
|
||||
aclgraph_runtime_mode: Optional[CUDAGraphMode] = None,
|
||||
aclgraph_runtime_mode: CUDAGraphMode | None = None,
|
||||
force_attention: bool = False,
|
||||
uniform_decode: bool = False,
|
||||
) -> torch.Tensor:
|
||||
|
||||
Reference in new issue
Block a user