[Rebase] Rebase to vllm v0.21.0 (#3530)
Signed-off-by: tzhouam <tzhouam@connect.ust.hk> Signed-off-by: Zhou Taichang <tzhouam@connect.ust.hk> Signed-off-by: NumberWan <wantszkin2003@gmail.com> Signed-off-by: Divyansh Singhvi <divyanshsinghvi@gmail.com> Signed-off-by: dsinghvi <divyanshsinghvi@gmail.com> Signed-off-by: Dnoob <dxpouo@gmail.com> Signed-off-by: Yueqian Lin <70319226+linyueqian@users.noreply.github.com> Signed-off-by: knlnguyen1802 <knlnguyen1802@gmail.com> Signed-off-by: rein yang <ruiruyang2@gmail.com> Signed-off-by: Nick Cao <ncao@redhat.com> Signed-off-by: zhumingjue <zhumingjue@huawei.com> Signed-off-by: Ricardo Noriega De Soto <rnoriega@redhat.com> Signed-off-by: lyj-jjj <liuyingjun5@huawei.com> Signed-off-by: gcanlin <canlinguosdu@gmail.com> Signed-off-by: wangyu <410167048@qq.com> Signed-off-by: weizhoublue <weizhoublue@github.com> Signed-off-by: weizhou.lan@daocloud.io <weizhou.lan@daocloud.io> Signed-off-by: dengyunyang <584797741@qq.com> Signed-off-by: 汪志鹏 <wangzhipeng628@gmail.com> Signed-off-by: David Chen <530634352@qq.com> Signed-off-by: Jie Liu <33612777+keeper-jie@users.noreply.github.com> Signed-off-by: Yueqian Lin <linyueqian@outlook.com> Signed-off-by: princepride <wangzhipeng628@gmail.com> Signed-off-by: natureofnature <wzliu@connect.hku.hk> Signed-off-by: bjf-frz <frz123db@gmail.com> Signed-off-by: amy-why-3459 <wuhaiyan17@huawei.com> Signed-off-by: KexiongYu <yukexiong1@huawei.com> Signed-off-by: Huang, Zeyu <11222265+fhfuih@users.noreply.github.com> Signed-off-by: Zeyu Huang | 黃澤宇 <11222265+fhfuih@users.noreply.github.com> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: NumberWan <wantszkin2003@gmail.com> Co-authored-by: dsinghvi <divyanshsinghvi@gmail.com> Co-authored-by: Dnoob <dxpouo@gmail.com> Co-authored-by: Yueqian Lin <70319226+linyueqian@users.noreply.github.com> Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com> Co-authored-by: knlnguyen1802 <knlnguyen1802@gmail.com> Co-authored-by: Samit <285365963@qq.com> Co-authored-by: rein yang <73573651+R2-Y@users.noreply.github.com> Co-authored-by: Nick Cao <ncao@redhat.com> Co-authored-by: zhumingjue138 <zhumingjue@huawei.com> Co-authored-by: Ricardo Noriega <rnoriega@redhat.com> Co-authored-by: lyj-jjj <liuyingjun5@huawei.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: gcanlin <canlinguosdu@gmail.com> Co-authored-by: wangyu <53896905+yenuo26@users.noreply.github.com> Co-authored-by: weizhoublue <45163302+weizhoublue@users.noreply.github.com> Co-authored-by: weizhoublue <weizhoublue@github.com> Co-authored-by: dengyunyang <584797741@qq.com> Co-authored-by: 汪志鹏 <wangzhipeng628@gmail.com> Co-authored-by: WeiQing Chen <40507679+david6666666@users.noreply.github.com> Co-authored-by: Jie Liu <33612777+keeper-jie@users.noreply.github.com> Co-authored-by: Yueqian Lin <linyueqian@outlook.com> Co-authored-by: NATURE <wzliu@connect.hku.hk> Co-authored-by: bjf-frz <frz123db@gmail.com> Co-authored-by: amy-why-3459 <wuhaiyan17@huawei.com> Co-authored-by: Y. Fisher <yukexiong1@huawei.com> Co-authored-by: Zeyu Huang | 黃澤宇 <11222265+fhfuih@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
+20









Zhou Taichang
Claude Opus 4.7
NumberWan
dsinghvi
Dnoob
Yueqian Lin
Hongsheng Liu
knlnguyen1802
Samit
rein yang
Nick Cao
zhumingjue138
Ricardo Noriega
lyj-jjj
Cursor
gcanlin
wangyu
weizhoublue
weizhoublue
dengyunyang
汪志鹏
WeiQing Chen
Jie Liu
Yueqian Lin
NATURE
bjf-frz
amy-why-3459
Y. Fisher
Zeyu Huang | 黃澤宇
Copilot Autofix powered by AI authored and
GitHub committed 2026-05-16 18:18:43 +08:00
1 parent
5e1986206f
commit
eb4e60ee64
46 files changed
+589
-258
No files matched your search
@@ -1,5 +1,6 @@
|
|||||||
env:
|
env:
|
||||||
VLLM_WORKER_MULTIPROC_METHOD: spawn
|
VLLM_WORKER_MULTIPROC_METHOD: spawn
|
||||||
|
VLLM_USE_FLASHINFER_MOE_FP16: 0
|
||||||
HF_HUB_DOWNLOAD_TIMEOUT: 300
|
HF_HUB_DOWNLOAD_TIMEOUT: 300
|
||||||
HF_HUB_ETAG_TIMEOUT: 60
|
HF_HUB_ETAG_TIMEOUT: 60
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
env:
|
env:
|
||||||
VLLM_WORKER_MULTIPROC_METHOD: spawn
|
VLLM_WORKER_MULTIPROC_METHOD: spawn
|
||||||
|
VLLM_USE_FLASHINFER_MOE_FP16: 0
|
||||||
HF_HUB_DOWNLOAD_TIMEOUT: 300
|
HF_HUB_DOWNLOAD_TIMEOUT: 300
|
||||||
HF_HUB_ETAG_TIMEOUT: 60
|
HF_HUB_ETAG_TIMEOUT: 60
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
env:
|
env:
|
||||||
VLLM_WORKER_MULTIPROC_METHOD: spawn
|
VLLM_WORKER_MULTIPROC_METHOD: spawn
|
||||||
|
VLLM_USE_FLASHINFER_MOE_FP16: 0
|
||||||
HF_HUB_DOWNLOAD_TIMEOUT: 300
|
HF_HUB_DOWNLOAD_TIMEOUT: 300
|
||||||
HF_HUB_ETAG_TIMEOUT: 60
|
HF_HUB_ETAG_TIMEOUT: 60
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
env:
|
env:
|
||||||
VLLM_WORKER_MULTIPROC_METHOD: spawn
|
VLLM_WORKER_MULTIPROC_METHOD: spawn
|
||||||
|
VLLM_USE_FLASHINFER_MOE_FP16: 0
|
||||||
HF_HUB_DOWNLOAD_TIMEOUT: 300
|
HF_HUB_DOWNLOAD_TIMEOUT: 300
|
||||||
HF_HUB_ETAG_TIMEOUT: 60
|
HF_HUB_ETAG_TIMEOUT: 60
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
ARG VLLM_BASE_IMAGE=vllm/vllm-openai
|
ARG VLLM_BASE_IMAGE=vllm/vllm-openai
|
||||||
ARG VLLM_BASE_TAG=v0.20.0
|
ARG VLLM_BASE_TAG=v0.21.0
|
||||||
FROM ${VLLM_BASE_IMAGE}:${VLLM_BASE_TAG}
|
FROM ${VLLM_BASE_IMAGE}:${VLLM_BASE_TAG}
|
||||||
ARG APP_DIR=/workspace/vllm-omni
|
ARG APP_DIR=/workspace/vllm-omni
|
||||||
WORKDIR ${APP_DIR}
|
WORKDIR ${APP_DIR}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ vLLM-Omni is a Python library that supports the following GPU variants. The libr
|
|||||||
|
|
||||||
### Pre-built wheels
|
### Pre-built wheels
|
||||||
|
|
||||||
Note: Pre-built wheels are currently available for vLLM-Omni 0.11.0rc1, 0.12.0rc1, 0.14.0rc1, 0.14.0, 0.16.0, 0.18.0, and 0.20.0. If you need a newer unreleased revision, please [build from source](https://docs.vllm.ai/projects/vllm-omni/en/latest/getting_started/installation/gpu/#build-wheel-from-source).
|
Note: Pre-built wheels are currently available for vLLM-Omni 0.11.0rc1, 0.12.0rc1, 0.14.0rc1, 0.14.0, 0.16.0, 0.18.0, 0.20.0, and 0.21.0. If you need a newer unreleased revision, please [build from source](https://docs.vllm.ai/projects/vllm-omni/en/latest/getting_started/installation/gpu/#build-wheel-from-source).
|
||||||
|
|
||||||
=== "NVIDIA CUDA"
|
=== "NVIDIA CUDA"
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ Therefore, it is recommended to install vLLM and vLLM-Omni with a **fresh new**
|
|||||||
|
|
||||||
vLLM-Omni is built based on vLLM. Please install it with command below.
|
vLLM-Omni is built based on vLLM. Please install it with command below.
|
||||||
```bash
|
```bash
|
||||||
uv pip install vllm==0.20.0 --torch-backend=auto
|
uv pip install vllm==0.21.0 --torch-backend=auto
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Installation of vLLM-Omni
|
#### Installation of vLLM-Omni
|
||||||
@@ -39,13 +39,13 @@ uv pip install 'vllm-omni[demo]'
|
|||||||
# --8<-- [start:build-wheel-from-source]
|
# --8<-- [start:build-wheel-from-source]
|
||||||
|
|
||||||
#### Installation of vLLM
|
#### Installation of vLLM
|
||||||
If you do not need to modify source code of vLLM, you can directly install the stable 0.20.0 release version of the library
|
If you do not need to modify source code of vLLM, you can directly install the stable 0.21.0 release version of the library
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
uv pip install vllm==0.20.0 --torch-backend=auto
|
uv pip install vllm==0.21.0 --torch-backend=auto
|
||||||
```
|
```
|
||||||
|
|
||||||
The 0.20.0 release of vLLM ships CUDA 13.0-compatible binaries by default. If you need a different CUDA variant or want to reuse an existing PyTorch installation, build vLLM from source instead.
|
The 0.21.0 release of vLLM ships CUDA 13.0-compatible binaries by default. If you need a different CUDA variant or want to reuse an existing PyTorch installation, build vLLM from source instead.
|
||||||
|
|
||||||
#### Installation of vLLM-Omni
|
#### Installation of vLLM-Omni
|
||||||
Since vllm-omni is rapidly evolving, it's recommended to install it from source
|
Since vllm-omni is rapidly evolving, it's recommended to install it from source
|
||||||
@@ -66,12 +66,12 @@ If you want to check, modify or debug with source code of vLLM, install the libr
|
|||||||
```bash
|
```bash
|
||||||
git clone https://github.com/vllm-project/vllm.git
|
git clone https://github.com/vllm-project/vllm.git
|
||||||
cd vllm
|
cd vllm
|
||||||
git checkout v0.20.0
|
git checkout v0.21.0
|
||||||
```
|
```
|
||||||
Set up environment variables to get pre-built wheels. If there are internet problems, just download the whl file manually. And set `VLLM_PRECOMPILED_WHEEL_LOCATION` as your local absolute path of whl file.
|
Set up environment variables to get pre-built wheels. If there are internet problems, just download the whl file manually. And set `VLLM_PRECOMPILED_WHEEL_LOCATION` as your local absolute path of whl file.
|
||||||
```bash
|
```bash
|
||||||
#For CUDA 13.0 (the default for v0.20.0; the wheel filename has no `+cu130` suffix)
|
#For CUDA 13.0 (the default for v0.21.0; the wheel filename has no `+cu130` suffix)
|
||||||
export VLLM_PRECOMPILED_WHEEL_LOCATION=https://github.com/vllm-project/vllm/releases/download/v0.20.0/vllm-0.20.0-cp38-abi3-manylinux_2_35_x86_64.whl
|
export VLLM_PRECOMPILED_WHEEL_LOCATION=https://github.com/vllm-project/vllm/releases/download/v0.21.0/vllm-0.21.0-cp38-abi3-manylinux_2_35_x86_64.whl
|
||||||
```
|
```
|
||||||
Install vllm with command below (If you have no existing PyTorch).
|
Install vllm with command below (If you have no existing PyTorch).
|
||||||
```bash
|
```bash
|
||||||
@@ -102,7 +102,7 @@ docker run --runtime nvidia --gpus 2 \
|
|||||||
--env "HF_TOKEN=$HF_TOKEN" \
|
--env "HF_TOKEN=$HF_TOKEN" \
|
||||||
-p 8091:8091 \
|
-p 8091:8091 \
|
||||||
--ipc=host \
|
--ipc=host \
|
||||||
vllm/vllm-omni:v0.20.0 \
|
vllm/vllm-omni:v0.21.0 \
|
||||||
--model Qwen/Qwen3-Omni-30B-A3B-Instruct --port 8091
|
--model Qwen/Qwen3-Omni-30B-A3B-Instruct --port 8091
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ vLLM-Omni current recommends the steps in under setup through Docker Images.
|
|||||||
|
|
||||||
vLLM-Omni is built based on vLLM. Please install it with command below.
|
vLLM-Omni is built based on vLLM. Please install it with command below.
|
||||||
```bash
|
```bash
|
||||||
uv pip install vllm==0.20.0+rocm721 --extra-index-url https://wheels.vllm.ai/rocm/0.20.0/rocm721
|
uv pip install vllm==0.21.0+rocm721 --extra-index-url https://wheels.vllm.ai/rocm/0.21.0/rocm721
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Installation of vLLM-Omni
|
#### Installation of vLLM-Omni
|
||||||
@@ -34,13 +34,13 @@ uv pip install onnxruntime-rocm
|
|||||||
# --8<-- [start:build-wheel-from-source]
|
# --8<-- [start:build-wheel-from-source]
|
||||||
|
|
||||||
#### Installation of vLLM
|
#### Installation of vLLM
|
||||||
If you do not need to modify source code of vLLM, you can directly install the stable 0.20.0 release version of the library
|
If you do not need to modify source code of vLLM, you can directly install the stable 0.21.0 release version of the library
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
uv pip install vllm==0.20.0+rocm721 --extra-index-url https://wheels.vllm.ai/rocm/0.20.0/rocm721
|
uv pip install vllm==0.21.0+rocm721 --extra-index-url https://wheels.vllm.ai/rocm/0.21.0/rocm721
|
||||||
```
|
```
|
||||||
|
|
||||||
The pre-built 0.20.0 vLLM wheel targets ROCm 7.2.1. If you need a different ROCm stack or want to reuse an existing PyTorch installation, build vLLM from source instead.
|
The pre-built 0.21.0 vLLM wheel targets ROCm 7.2.1. If you need a different ROCm stack or want to reuse an existing PyTorch installation, build vLLM from source instead.
|
||||||
|
|
||||||
#### Installation of vLLM-Omni
|
#### Installation of vLLM-Omni
|
||||||
Since vllm-omni is rapidly evolving, it's recommended to install it from source
|
Since vllm-omni is rapidly evolving, it's recommended to install it from source
|
||||||
@@ -58,7 +58,7 @@ If you want to check, modify or debug with source code of vLLM, install the libr
|
|||||||
```bash
|
```bash
|
||||||
git clone https://github.com/vllm-project/vllm.git
|
git clone https://github.com/vllm-project/vllm.git
|
||||||
cd vllm
|
cd vllm
|
||||||
git checkout v0.20.0
|
git checkout v0.21.0
|
||||||
python3 -m pip install -r requirements/rocm.txt
|
python3 -m pip install -r requirements/rocm.txt
|
||||||
python3 setup.py develop
|
python3 setup.py develop
|
||||||
```
|
```
|
||||||
@@ -130,7 +130,7 @@ docker run --rm \
|
|||||||
-v ~/.cache/huggingface:/root/.cache/huggingface \
|
-v ~/.cache/huggingface:/root/.cache/huggingface \
|
||||||
--env "HF_TOKEN=$HF_TOKEN" \
|
--env "HF_TOKEN=$HF_TOKEN" \
|
||||||
-p 8091:8091 \
|
-p 8091:8091 \
|
||||||
vllm/vllm-omni-rocm:v0.20.0 \
|
vllm/vllm-omni-rocm:v0.21.0 \
|
||||||
--model Qwen/Qwen3-Omni-30B-A3B-Instruct --omni --port 8091
|
--model Qwen/Qwen3-Omni-30B-A3B-Instruct --omni --port 8091
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -149,7 +149,7 @@ docker run --rm -it \
|
|||||||
-v ~/.cache/huggingface:/root/.cache/huggingface \
|
-v ~/.cache/huggingface:/root/.cache/huggingface \
|
||||||
--env "HF_TOKEN=$HF_TOKEN" \
|
--env "HF_TOKEN=$HF_TOKEN" \
|
||||||
--entrypoint bash \
|
--entrypoint bash \
|
||||||
vllm/vllm-omni-rocm:v0.20.0
|
vllm/vllm-omni-rocm:v0.21.0
|
||||||
```
|
```
|
||||||
|
|
||||||
# --8<-- [end:pre-built-images]
|
# --8<-- [end:pre-built-images]
|
||||||
@@ -19,10 +19,10 @@ uv venv --python 3.12 --seed
|
|||||||
source .venv/bin/activate
|
source .venv/bin/activate
|
||||||
|
|
||||||
# On CUDA
|
# On CUDA
|
||||||
uv pip install vllm==0.20.0 --torch-backend=auto
|
uv pip install vllm==0.21.0 --torch-backend=auto
|
||||||
|
|
||||||
# On ROCm
|
# On ROCm
|
||||||
uv pip install vllm==0.20.0+rocm721 --extra-index-url https://wheels.vllm.ai/rocm/0.20.0/rocm721
|
uv pip install vllm==0.21.0+rocm721 --extra-index-url https://wheels.vllm.ai/rocm/0.21.0/rocm721
|
||||||
|
|
||||||
git clone https://github.com/vllm-project/vllm-omni.git
|
git clone https://github.com/vllm-project/vllm-omni.git
|
||||||
cd vllm-omni
|
cd vllm-omni
|
||||||
@@ -35,7 +35,7 @@ For additional installation methods — please see the [installation guide](inst
|
|||||||
!!! note
|
!!! note
|
||||||
It is important to install the same major & minor version of vLLM and vLLM Omni, otherwise things may not work as expected. If the versions are misaligned, you will see a warning when you import vLLM Omni.
|
It is important to install the same major & minor version of vLLM and vLLM Omni, otherwise things may not work as expected. If the versions are misaligned, you will see a warning when you import vLLM Omni.
|
||||||
|
|
||||||
If you are seeing strange behavior with the `vllm` command not handling the `--omni` flag correctly, you most likely have a version mismatch with vLLM < `0.20.0` and vLLM Omni `0.20.0`, as vLLM Omni no longer hijacks the vLLM entrypoint. Updating vLLM should resolve this issue.
|
If you are seeing strange behavior with the `vllm` command not handling the `--omni` flag correctly, you most likely have a version mismatch with vLLM < `0.21.0` and vLLM Omni `0.21.0`, as vLLM Omni no longer hijacks the vLLM entrypoint. Updating vLLM should resolve this issue.
|
||||||
|
|
||||||
## Offline Inference
|
## Offline Inference
|
||||||
|
|
||||||
|
|||||||
@@ -394,6 +394,9 @@ class TestAttentionInitUsesCurrentDiffusionConfig:
|
|||||||
per_role={"cross": AttentionSpec(backend="TORCH_SDPA", extra={"block_size": 128})},
|
per_role={"cross": AttentionSpec(backend="TORCH_SDPA", extra={"block_size": 128})},
|
||||||
),
|
),
|
||||||
parallel_config=SimpleNamespace(ring_degree=2),
|
parallel_config=SimpleNamespace(ring_degree=2),
|
||||||
|
diffusion_kv_cache_dtype=None,
|
||||||
|
diffusion_kv_cache_skip_step_indices=None,
|
||||||
|
diffusion_kv_cache_skip_layer_indices=None,
|
||||||
)
|
)
|
||||||
|
|
||||||
with set_current_diffusion_config(od_config):
|
with set_current_diffusion_config(od_config):
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import pytest
|
|||||||
import torch
|
import torch
|
||||||
from vllm.distributed.parallel_state import cleanup_dist_env_and_memory
|
from vllm.distributed.parallel_state import cleanup_dist_env_and_memory
|
||||||
|
|
||||||
|
from tests.helpers import skip_if_gated_repo_inaccessible
|
||||||
from tests.helpers.env import DeviceMemoryMonitor
|
from tests.helpers.env import DeviceMemoryMonitor
|
||||||
from tests.helpers.mark import hardware_test
|
from tests.helpers.mark import hardware_test
|
||||||
from tests.helpers.runtime import OmniRunner
|
from tests.helpers.runtime import OmniRunner
|
||||||
@@ -21,6 +22,11 @@ IMAGE_VIDEO_MODELS = {
|
|||||||
|
|
||||||
MODELS = {**AUDIO_MODEL, **IMAGE_VIDEO_MODELS}
|
MODELS = {**AUDIO_MODEL, **IMAGE_VIDEO_MODELS}
|
||||||
|
|
||||||
|
_GATED_MODELS = {"stabilityai/stable-audio-open-1.0"}
|
||||||
|
|
||||||
|
# Aliased for backward compatibility (imported by test_diffusion_layerwise_offload.py).
|
||||||
|
_skip_if_gated_repo_inaccessible = skip_if_gated_repo_inaccessible
|
||||||
|
|
||||||
AUDIO_MODEL_PARAMS = {
|
AUDIO_MODEL_PARAMS = {
|
||||||
"runner_params": {},
|
"runner_params": {},
|
||||||
"sampler_params": {},
|
"sampler_params": {},
|
||||||
@@ -94,10 +100,23 @@ def check_audio_determinism(audio1, audio2, atol=1e-2):
|
|||||||
@hardware_test(res={"cuda": "L4", "rocm": "MI325"})
|
@hardware_test(res={"cuda": "L4", "rocm": "MI325"})
|
||||||
@pytest.mark.parametrize("model_name", list(MODELS.keys()))
|
@pytest.mark.parametrize("model_name", list(MODELS.keys()))
|
||||||
def test_cpu_offload_diffusion_model(model_name: str):
|
def test_cpu_offload_diffusion_model(model_name: str):
|
||||||
|
if model_name in _GATED_MODELS:
|
||||||
|
_skip_if_gated_repo_inaccessible(model_name)
|
||||||
try:
|
try:
|
||||||
offload_peak_memory, output_offload = inference(model_name, offload=True)
|
offload_peak_memory, output_offload = inference(model_name, offload=True)
|
||||||
cleanup_dist_env_and_memory()
|
cleanup_dist_env_and_memory()
|
||||||
no_offload_peak_memory, output_no_offload = inference(model_name, offload=False)
|
no_offload_peak_memory, output_no_offload = inference(model_name, offload=False)
|
||||||
|
except ValueError as exc:
|
||||||
|
# omni_snapshot_download wraps GatedRepoError in a ValueError.
|
||||||
|
# If the pre-flight guard above did not catch it (e.g. partial
|
||||||
|
# HF_TOKEN where config.json is accessible but weight shards are
|
||||||
|
# blocked), skip instead of failing.
|
||||||
|
if "Access to model" in str(exc) and "is restricted" in str(exc):
|
||||||
|
pytest.skip(
|
||||||
|
f"Skipping: gated HF repo {model_name!r} inaccessible "
|
||||||
|
f"({exc}). See docs/contributing/ci/hf_credentials.md."
|
||||||
|
)
|
||||||
|
pytest.fail(f"Inference failed: {exc}")
|
||||||
except Exception:
|
except Exception:
|
||||||
pytest.fail("Inference failed")
|
pytest.fail("Inference failed")
|
||||||
print(f"Offload peak memory: {offload_peak_memory} MB")
|
print(f"Offload peak memory: {offload_peak_memory} MB")
|
||||||
|
|||||||
@@ -3,6 +3,10 @@ import pytest
|
|||||||
import torch
|
import torch
|
||||||
from vllm.distributed.parallel_state import cleanup_dist_env_and_memory
|
from vllm.distributed.parallel_state import cleanup_dist_env_and_memory
|
||||||
|
|
||||||
|
from tests.diffusion.offloader.test_diffusion_cpu_offload import (
|
||||||
|
_GATED_MODELS,
|
||||||
|
_skip_if_gated_repo_inaccessible,
|
||||||
|
)
|
||||||
from tests.helpers.env import DeviceMemoryMonitor
|
from tests.helpers.env import DeviceMemoryMonitor
|
||||||
from tests.helpers.runtime import OmniRunner
|
from tests.helpers.runtime import OmniRunner
|
||||||
from vllm_omni.inputs.data import OmniDiffusionSamplingParams
|
from vllm_omni.inputs.data import OmniDiffusionSamplingParams
|
||||||
@@ -96,6 +100,8 @@ def test_layerwise_offload_diffusion_model(model_name: str):
|
|||||||
offloader keeps only a single transformer block on GPU at a time, with
|
offloader keeps only a single transformer block on GPU at a time, with
|
||||||
prefetching for compute-memory overlap.
|
prefetching for compute-memory overlap.
|
||||||
"""
|
"""
|
||||||
|
if model_name in _GATED_MODELS:
|
||||||
|
_skip_if_gated_repo_inaccessible(model_name)
|
||||||
try:
|
try:
|
||||||
# Run without layerwise offloading (baseline)
|
# Run without layerwise offloading (baseline)
|
||||||
no_offload_peak_memory, output_no_offload = run_inference(model_name, layerwise_offload=False)
|
no_offload_peak_memory, output_no_offload = run_inference(model_name, layerwise_offload=False)
|
||||||
@@ -104,6 +110,17 @@ def test_layerwise_offload_diffusion_model(model_name: str):
|
|||||||
# Run with layerwise offloading (1 layer on device)
|
# Run with layerwise offloading (1 layer on device)
|
||||||
layerwise_offload_peak_memory, output_offload = run_inference(model_name, layerwise_offload=True)
|
layerwise_offload_peak_memory, output_offload = run_inference(model_name, layerwise_offload=True)
|
||||||
cleanup_dist_env_and_memory()
|
cleanup_dist_env_and_memory()
|
||||||
|
except ValueError as exc:
|
||||||
|
# omni_snapshot_download wraps GatedRepoError in a ValueError.
|
||||||
|
# If the pre-flight guard above did not catch it (e.g. partial
|
||||||
|
# HF_TOKEN where config.json is accessible but weight shards are
|
||||||
|
# blocked), skip instead of failing.
|
||||||
|
if "Access to model" in str(exc) and "is restricted" in str(exc):
|
||||||
|
pytest.skip(
|
||||||
|
f"Skipping: gated HF repo {model_name!r} inaccessible "
|
||||||
|
f"({exc}). See docs/contributing/ci/hf_credentials.md."
|
||||||
|
)
|
||||||
|
pytest.fail(f"Inference failed: {exc}")
|
||||||
except Exception:
|
except Exception:
|
||||||
pytest.fail("Inference failed")
|
pytest.fail("Inference failed")
|
||||||
|
|
||||||
|
|||||||
@@ -540,6 +540,7 @@ def test_generation_scheduler_calls_cleanup_on_finished(monkeypatch, mocker: Moc
|
|||||||
kv_connector_output=None,
|
kv_connector_output=None,
|
||||||
cudagraph_stats=None,
|
cudagraph_stats=None,
|
||||||
req_id_to_index={"req-s1": 0},
|
req_id_to_index={"req-s1": 0},
|
||||||
|
routed_experts_dict=None,
|
||||||
)
|
)
|
||||||
|
|
||||||
OmniGenerationScheduler.update_from_output(scheduler, scheduler_output, model_runner_output)
|
OmniGenerationScheduler.update_from_output(scheduler, scheduler_output, model_runner_output)
|
||||||
@@ -625,6 +626,7 @@ def test_ar_scheduler_defers_cleanup_and_queues_save_on_finished(mocker: MockerF
|
|||||||
cudagraph_stats=None,
|
cudagraph_stats=None,
|
||||||
req_id_to_index={"req-ar": 0},
|
req_id_to_index={"req-ar": 0},
|
||||||
kv_extracted_req_ids=None,
|
kv_extracted_req_ids=None,
|
||||||
|
routed_experts_dict=None,
|
||||||
)
|
)
|
||||||
|
|
||||||
OmniARScheduler.update_from_output(scheduler, scheduler_output, model_runner_output)
|
OmniARScheduler.update_from_output(scheduler, scheduler_output, model_runner_output)
|
||||||
|
|||||||
@@ -25,7 +25,11 @@ from vllm_omni.distributed.omni_connectors.connectors.mooncake_transfer_engine_c
|
|||||||
)
|
)
|
||||||
|
|
||||||
# All tests in this file require Mooncake TransferEngine and an RDMA environment.
|
# All tests in this file require Mooncake TransferEngine and an RDMA environment.
|
||||||
pytestmark = [pytest.mark.parallel, pytest.mark.core_model]
|
pytestmark = [
|
||||||
|
pytest.mark.parallel,
|
||||||
|
pytest.mark.core_model,
|
||||||
|
pytest.mark.skipif(TransferEngine is None, reason="Mooncake TransferEngine not installed"),
|
||||||
|
]
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Shared helpers
|
# Shared helpers
|
||||||
|
|||||||
@@ -106,18 +106,21 @@ def _build_request(
|
|||||||
|
|
||||||
def _collect_audio(omni: Omni, request: dict) -> tuple[torch.Tensor, int]:
|
def _collect_audio(omni: Omni, request: dict) -> tuple[torch.Tensor, int]:
|
||||||
"""Run a single request and return (waveform, sample_rate)."""
|
"""Run a single request and return (waveform, sample_rate)."""
|
||||||
# Omni.generate returns list[OmniRequestOutput] by default (py_generator=False).
|
for stage_outputs in omni.generate(request, DEFAULT_SAMPLING):
|
||||||
for omni_out in omni.generate(request, DEFAULT_SAMPLING):
|
req_output = stage_outputs.request_output
|
||||||
mm = omni_out.multimodal_output
|
if req_output is not None:
|
||||||
assert mm is not None, "Expected multimodal_output to be non-None"
|
mm = req_output.outputs[0].multimodal_output
|
||||||
audio = mm.get("audio")
|
assert mm is not None, "Expected multimodal_output to be non-None"
|
||||||
sr = mm.get("sr")
|
audio = mm.get("audio")
|
||||||
assert audio is not None, "Expected 'audio' key in multimodal_output"
|
sr = mm.get("sr")
|
||||||
assert isinstance(audio, torch.Tensor), f"audio should be Tensor, got {type(audio)}"
|
assert audio is not None, "Expected 'audio' key in multimodal_output"
|
||||||
return audio.cpu(), int(sr.item()) if sr is not None else SAMPLE_RATE
|
assert isinstance(audio, torch.Tensor), f"audio should be Tensor, got {type(audio)}"
|
||||||
|
return audio.cpu(), int(sr.item()) if sr is not None else SAMPLE_RATE
|
||||||
raise AssertionError("No stage outputs received")
|
raise AssertionError("No stage outputs received")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.advanced_model
|
||||||
|
@pytest.mark.omni
|
||||||
@hardware_test(res={"cuda": "L4"})
|
@hardware_test(res={"cuda": "L4"})
|
||||||
def test_moss_tts_nano_english(omni_runner: OmniRunner, ref_audio_path) -> None:
|
def test_moss_tts_nano_english(omni_runner: OmniRunner, ref_audio_path) -> None:
|
||||||
"""English TTS produces non-empty 48 kHz stereo audio."""
|
"""English TTS produces non-empty 48 kHz stereo audio."""
|
||||||
@@ -129,6 +132,8 @@ def test_moss_tts_nano_english(omni_runner: OmniRunner, ref_audio_path) -> None:
|
|||||||
assert not torch.all(audio == 0), "Audio should not be all-zeros (silence)"
|
assert not torch.all(audio == 0), "Audio should not be all-zeros (silence)"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.advanced_model
|
||||||
|
@pytest.mark.omni
|
||||||
@hardware_test(res={"cuda": "L4"})
|
@hardware_test(res={"cuda": "L4"})
|
||||||
def test_moss_tts_nano_chinese(omni_runner: OmniRunner, ref_audio_path) -> None:
|
def test_moss_tts_nano_chinese(omni_runner: OmniRunner, ref_audio_path) -> None:
|
||||||
"""Chinese TTS produces non-empty audio."""
|
"""Chinese TTS produces non-empty audio."""
|
||||||
@@ -140,6 +145,8 @@ def test_moss_tts_nano_chinese(omni_runner: OmniRunner, ref_audio_path) -> None:
|
|||||||
assert not torch.all(audio == 0)
|
assert not torch.all(audio == 0)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.advanced_model
|
||||||
|
@pytest.mark.omni
|
||||||
@hardware_test(res={"cuda": "L4"})
|
@hardware_test(res={"cuda": "L4"})
|
||||||
def test_moss_tts_nano_deterministic(omni_runner: OmniRunner, ref_audio_path) -> None:
|
def test_moss_tts_nano_deterministic(omni_runner: OmniRunner, ref_audio_path) -> None:
|
||||||
"""Same seed produces identical waveforms."""
|
"""Same seed produces identical waveforms."""
|
||||||
@@ -151,6 +158,8 @@ def test_moss_tts_nano_deterministic(omni_runner: OmniRunner, ref_audio_path) ->
|
|||||||
assert torch.allclose(audio1, audio2, atol=1e-4), "Waveforms should match with same seed"
|
assert torch.allclose(audio1, audio2, atol=1e-4), "Waveforms should match with same seed"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.advanced_model
|
||||||
|
@pytest.mark.omni
|
||||||
@hardware_test(res={"cuda": "L4"})
|
@hardware_test(res={"cuda": "L4"})
|
||||||
def test_moss_tts_nano_batch(omni_runner: OmniRunner, ref_audio_path) -> None:
|
def test_moss_tts_nano_batch(omni_runner: OmniRunner, ref_audio_path) -> None:
|
||||||
"""Batch of two requests returns audio for each."""
|
"""Batch of two requests returns audio for each."""
|
||||||
@@ -159,11 +168,13 @@ def test_moss_tts_nano_batch(omni_runner: OmniRunner, ref_audio_path) -> None:
|
|||||||
_build_request("Second request.", ref_audio_path),
|
_build_request("Second request.", ref_audio_path),
|
||||||
]
|
]
|
||||||
results = []
|
results = []
|
||||||
# Single-stage pipeline: one SamplingParams object is broadcast to all prompts.
|
# Single-stage model (num_stages=1): one sampling param for all requests.
|
||||||
for omni_out in omni_runner.omni.generate(requests, DEFAULT_SAMPLING):
|
for stage_outputs in omni_runner.omni.generate(requests, [DEFAULT_SAMPLING]):
|
||||||
mm = omni_out.multimodal_output
|
req_output = stage_outputs.request_output
|
||||||
assert mm is not None
|
if req_output is not None:
|
||||||
results.append(mm["audio"].cpu())
|
mm = req_output.outputs[0].multimodal_output
|
||||||
|
assert mm is not None
|
||||||
|
results.append(mm["audio"].cpu())
|
||||||
|
|
||||||
assert len(results) == 2, f"Expected 2 outputs, got {len(results)}"
|
assert len(results) == 2, f"Expected 2 outputs, got {len(results)}"
|
||||||
for i, audio in enumerate(results):
|
for i, audio in enumerate(results):
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import numpy as np
|
|||||||
import pytest
|
import pytest
|
||||||
import torch
|
import torch
|
||||||
|
|
||||||
|
from tests.helpers import skip_if_gated_repo_inaccessible
|
||||||
from tests.helpers.assertions import assert_audio_valid
|
from tests.helpers.assertions import assert_audio_valid
|
||||||
from tests.helpers.mark import hardware_test
|
from tests.helpers.mark import hardware_test
|
||||||
from vllm_omni import Omni
|
from vllm_omni import Omni
|
||||||
@@ -24,6 +25,8 @@ from vllm_omni.platforms import current_omni_platform
|
|||||||
|
|
||||||
pytestmark = [pytest.mark.full_model, pytest.mark.diffusion]
|
pytestmark = [pytest.mark.full_model, pytest.mark.diffusion]
|
||||||
|
|
||||||
|
_MODEL_REPO = "stabilityai/stable-audio-open-1.0"
|
||||||
|
|
||||||
_SAMPLE_RATE = 44100
|
_SAMPLE_RATE = 44100
|
||||||
_CLIP_DURATION_S = 2.0
|
_CLIP_DURATION_S = 2.0
|
||||||
|
|
||||||
@@ -77,6 +80,7 @@ def test_stable_audio_quantization_and_teacache() -> None:
|
|||||||
|
|
||||||
CI should provide ``HF_TOKEN`` if the checkpoint is gated.
|
CI should provide ``HF_TOKEN`` if the checkpoint is gated.
|
||||||
"""
|
"""
|
||||||
|
skip_if_gated_repo_inaccessible(_MODEL_REPO)
|
||||||
# ``model_class_name`` must be passed explicitly: the default-stage-cfg
|
# ``model_class_name`` must be passed explicitly: the default-stage-cfg
|
||||||
# factory in ``async_omni_engine.py`` reads it out of ``kwargs`` when
|
# factory in ``async_omni_engine.py`` reads it out of ``kwargs`` when
|
||||||
# deciding ``final_output_type`` (#2077), and at construction time the
|
# deciding ``final_output_type`` (#2077), and at construction time the
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ class FakeStageClient:
|
|||||||
self._diffusion_outputs = queue.Queue()
|
self._diffusion_outputs = queue.Queue()
|
||||||
|
|
||||||
# Orchestrator-facing interface.
|
# Orchestrator-facing interface.
|
||||||
async def add_request_async(self, *args, **_kwargs) -> None:
|
async def add_request_async(self, *args, **kwargs) -> None:
|
||||||
self.add_request_calls.append(args)
|
self.add_request_calls.append(args)
|
||||||
|
|
||||||
async def get_output_async(self):
|
async def get_output_async(self):
|
||||||
@@ -448,7 +448,7 @@ def test_stage_engine_core_client_shutdown_cleans_children_if_base_shutdown_fail
|
|||||||
assert recursive
|
assert recursive
|
||||||
return [fake_child]
|
return [fake_child]
|
||||||
|
|
||||||
def fail_base_shutdown(self):
|
def fail_base_shutdown(self, **kwargs):
|
||||||
raise RuntimeError("base shutdown failed")
|
raise RuntimeError("base shutdown failed")
|
||||||
|
|
||||||
monkeypatch.setattr(psutil, "Process", FakePsutilProcess)
|
monkeypatch.setattr(psutil, "Process", FakePsutilProcess)
|
||||||
@@ -480,7 +480,7 @@ def test_stage_engine_core_client_shutdown_kills_stubborn_children(monkeypatch):
|
|||||||
|
|
||||||
monkeypatch.setattr(psutil, "Process", FakePsutilProcess)
|
monkeypatch.setattr(psutil, "Process", FakePsutilProcess)
|
||||||
monkeypatch.setattr(psutil, "wait_procs", lambda procs, timeout: ([], list(procs)))
|
monkeypatch.setattr(psutil, "wait_procs", lambda procs, timeout: ([], list(procs)))
|
||||||
monkeypatch.setattr(AsyncMPClient, "shutdown", lambda self: None)
|
monkeypatch.setattr(AsyncMPClient, "shutdown", lambda self, **kwargs: None)
|
||||||
|
|
||||||
client = object.__new__(StageEngineCoreClient)
|
client = object.__new__(StageEngineCoreClient)
|
||||||
client._proc = fake_proc
|
client._proc = fake_proc
|
||||||
@@ -994,7 +994,7 @@ async def test_handle_streaming_update_passes_prompt_text_to_stage_pool() -> Non
|
|||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_stage_pool_submit_initial_rolls_back_output_processor_when_client_submit_fails() -> None:
|
async def test_stage_pool_submit_initial_rolls_back_output_processor_when_client_submit_fails() -> None:
|
||||||
class FailingStageClient(FakeStageClient):
|
class FailingStageClient(FakeStageClient):
|
||||||
async def add_request_async(self, *args, **_kwargs) -> None:
|
async def add_request_async(self, *args, **kwargs) -> None:
|
||||||
raise RuntimeError("submit failed")
|
raise RuntimeError("submit failed")
|
||||||
|
|
||||||
class TrackingOutputProcessor(FakeOutputProcessor):
|
class TrackingOutputProcessor(FakeOutputProcessor):
|
||||||
|
|||||||
@@ -389,7 +389,7 @@ class TestErrorHandling:
|
|||||||
|
|
||||||
async def empty_gen(*args, **kwargs):
|
async def empty_gen(*args, **kwargs):
|
||||||
return
|
return
|
||||||
yield # noqa: unreachable – makes this an async generator
|
yield # unreachable – makes this an async generator
|
||||||
|
|
||||||
engine.generate = MagicMock(side_effect=empty_gen)
|
engine.generate = MagicMock(side_effect=empty_gen)
|
||||||
server = _make_server(engine_client=engine)
|
server = _make_server(engine_client=engine)
|
||||||
@@ -448,7 +448,7 @@ class TestErrorHandling:
|
|||||||
|
|
||||||
async def gen_value_error(*args, **kwargs):
|
async def gen_value_error(*args, **kwargs):
|
||||||
raise ValueError("bad value")
|
raise ValueError("bad value")
|
||||||
yield # noqa: unreachable
|
yield # unreachable
|
||||||
|
|
||||||
engine.generate = MagicMock(side_effect=gen_value_error)
|
engine.generate = MagicMock(side_effect=gen_value_error)
|
||||||
server = _make_server(engine_client=engine)
|
server = _make_server(engine_client=engine)
|
||||||
@@ -463,7 +463,7 @@ class TestErrorHandling:
|
|||||||
|
|
||||||
async def gen_runtime_error(*args, **kwargs):
|
async def gen_runtime_error(*args, **kwargs):
|
||||||
raise RuntimeError("something went wrong")
|
raise RuntimeError("something went wrong")
|
||||||
yield # noqa: unreachable
|
yield # unreachable
|
||||||
|
|
||||||
engine.generate = MagicMock(side_effect=gen_runtime_error)
|
engine.generate = MagicMock(side_effect=gen_runtime_error)
|
||||||
server = _make_server(engine_client=engine)
|
server = _make_server(engine_client=engine)
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ def serving_chat():
|
|||||||
|
|
||||||
instance = object.__new__(OmniOpenAIServingChat)
|
instance = object.__new__(OmniOpenAIServingChat)
|
||||||
instance._supported_speakers = None
|
instance._supported_speakers = None
|
||||||
|
instance.has_kv_connector = False
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,3 +6,32 @@ refactor only inside the old monolithic ``conftest``; a greedy ``__init__``
|
|||||||
changes import order and can affect in-process Omni (``OmniRunner`` / offline
|
changes import order and can affect in-process Omni (``OmniRunner`` / offline
|
||||||
e2e) vs subprocess-based ``OmniServer`` tests.
|
e2e) vs subprocess-based ``OmniServer`` tests.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
def skip_if_gated_repo_inaccessible(repo_id: str) -> None:
|
||||||
|
"""Skip the test if a gated HuggingFace repo is not accessible.
|
||||||
|
|
||||||
|
Tries to download the model's config.json via ``hf_hub_download``,
|
||||||
|
which performs an actual file-access check (unlike ``HfApi().model_info()``
|
||||||
|
that only checks metadata). If the token has metadata access but not
|
||||||
|
file-download access, ``hf_hub_download`` will raise ``GatedRepoError``
|
||||||
|
and we skip cleanly.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
from huggingface_hub import hf_hub_download
|
||||||
|
from huggingface_hub.errors import GatedRepoError, RepositoryNotFoundError
|
||||||
|
except Exception:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
hf_hub_download(repo_id=repo_id, filename="config.json")
|
||||||
|
except GatedRepoError as exc:
|
||||||
|
pytest.skip(
|
||||||
|
f"Skipping: gated HF repo {repo_id!r} inaccessible to the current "
|
||||||
|
f"HF_TOKEN ({exc}). See docs/contributing/ci/hf_credentials.md."
|
||||||
|
)
|
||||||
|
except RepositoryNotFoundError as exc:
|
||||||
|
pytest.skip(f"Skipping: HF repo {repo_id!r} not found ({exc}).")
|
||||||
|
except Exception:
|
||||||
|
return
|
||||||
@@ -48,6 +48,7 @@ def _build_mock_modules(mocker: MockerFixture) -> dict[str, object]:
|
|||||||
"""Build the dict of modules to inject into sys.modules."""
|
"""Build the dict of modules to inject into sys.modules."""
|
||||||
platforms_mock = mocker.MagicMock()
|
platforms_mock = mocker.MagicMock()
|
||||||
platforms_mock.current_omni_platform.supports_torch_inductor.return_value = False
|
platforms_mock.current_omni_platform.supports_torch_inductor.return_value = False
|
||||||
|
platforms_mock.current_omni_platform.is_npu.return_value = False
|
||||||
|
|
||||||
logger_mock = mocker.MagicMock()
|
logger_mock = mocker.MagicMock()
|
||||||
logger_mock.init_logger = lambda name: mocker.MagicMock()
|
logger_mock.init_logger = lambda name: mocker.MagicMock()
|
||||||
@@ -211,6 +212,10 @@ class TestCodePredictorDtypeAlignment:
|
|||||||
predictor._model_dtype = torch.float16
|
predictor._model_dtype = torch.float16
|
||||||
predictor._compiled_model_fwd = predictor.model.forward
|
predictor._compiled_model_fwd = predictor.model.forward
|
||||||
|
|
||||||
|
# Ensure NPU path is not taken on non-NPU hardware
|
||||||
|
common_mod = sys.modules["vllm_omni.model_executor.models.common.qwen3_code_predictor"]
|
||||||
|
mocker.patch.object(common_mod.current_omni_platform, "is_npu", return_value=False)
|
||||||
|
|
||||||
# _warmup_buckets should fix the dtype mismatch
|
# _warmup_buckets should fix the dtype mismatch
|
||||||
predictor._warmup_buckets()
|
predictor._warmup_buckets()
|
||||||
|
|
||||||
@@ -230,6 +235,9 @@ class TestCodePredictorDtypeAlignment:
|
|||||||
predictor = predictor.to(torch.float16)
|
predictor = predictor.to(torch.float16)
|
||||||
|
|
||||||
assert predictor._model_dtype is None
|
assert predictor._model_dtype is None
|
||||||
|
# Ensure NPU path is not taken on non-NPU hardware
|
||||||
|
common_mod = sys.modules["vllm_omni.model_executor.models.common.qwen3_code_predictor"]
|
||||||
|
mocker.patch.object(common_mod.current_omni_platform, "is_npu", return_value=False)
|
||||||
predictor._setup_compile()
|
predictor._setup_compile()
|
||||||
assert predictor._model_dtype == torch.float16
|
assert predictor._model_dtype == torch.float16
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ def _make_runner(multimodal_outputs):
|
|||||||
runner.device = torch.device("cpu")
|
runner.device = torch.device("cpu")
|
||||||
runner.supports_mm_inputs = False
|
runner.supports_mm_inputs = False
|
||||||
runner.speculative_config = None
|
runner.speculative_config = None
|
||||||
|
runner.routed_experts_initialized = False
|
||||||
return runner
|
return runner
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -203,6 +203,14 @@ class OmniARScheduler(OmniSchedulerMixin, VLLMScheduler):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def schedule(self) -> SchedulerOutput: # type: ignore[override]
|
def schedule(self) -> SchedulerOutput: # type: ignore[override]
|
||||||
|
# Remove FINISHED_ABORTED requests before the upstream scheduler sees
|
||||||
|
# them. Upstream vllm raises RuntimeError on this status; omni allows
|
||||||
|
# async abort (e.g. client disconnect during TTS streaming) to leave
|
||||||
|
# requests in the waiting/running queues temporarily.
|
||||||
|
for queue in (self.waiting, self.running):
|
||||||
|
for req in list(queue):
|
||||||
|
if getattr(req, "status", None) == RequestStatus.FINISHED_ABORTED:
|
||||||
|
queue.remove(req)
|
||||||
connector_output = self._latest_omni_connector_output
|
connector_output = self._latest_omni_connector_output
|
||||||
self._latest_omni_connector_output = None
|
self._latest_omni_connector_output = None
|
||||||
if self.input_coordinator:
|
if self.input_coordinator:
|
||||||
@@ -250,6 +258,7 @@ class OmniARScheduler(OmniSchedulerMixin, VLLMScheduler):
|
|||||||
lora_request=nr.lora_request,
|
lora_request=nr.lora_request,
|
||||||
# Enrich with omni payloads from the live request object
|
# Enrich with omni payloads from the live request object
|
||||||
prompt_embeds=(getattr(request, "prompt_embeds", None) if request else None),
|
prompt_embeds=(getattr(request, "prompt_embeds", None) if request else None),
|
||||||
|
prompt_is_token_ids=nr.prompt_is_token_ids,
|
||||||
additional_information=(getattr(request, "additional_information", None) if request else None),
|
additional_information=(getattr(request, "additional_information", None) if request else None),
|
||||||
)
|
)
|
||||||
new_list.append(omni_nr)
|
new_list.append(omni_nr)
|
||||||
@@ -419,7 +428,11 @@ class OmniARScheduler(OmniSchedulerMixin, VLLMScheduler):
|
|||||||
stopped = True
|
stopped = True
|
||||||
|
|
||||||
if stopped:
|
if stopped:
|
||||||
routed_experts = self._get_routed_experts(request)
|
if (
|
||||||
|
model_runner_output.routed_experts_dict is not None
|
||||||
|
and req_id in model_runner_output.routed_experts_dict
|
||||||
|
):
|
||||||
|
routed_experts = model_runner_output.routed_experts_dict[req_id]
|
||||||
|
|
||||||
# Capture finish_reason BEFORE _handle_stopped_request, which may
|
# Capture finish_reason BEFORE _handle_stopped_request, which may
|
||||||
# reset the status to WAITING for streaming requests that continue.
|
# reset the status to WAITING for streaming requests that continue.
|
||||||
|
|||||||
@@ -337,6 +337,7 @@ class OmniGenerationScheduler(OmniSchedulerMixin, VLLMScheduler):
|
|||||||
lora_request=nr.lora_request,
|
lora_request=nr.lora_request,
|
||||||
# Enrich with omni payloads from the live request object
|
# Enrich with omni payloads from the live request object
|
||||||
prompt_embeds=(getattr(request, "prompt_embeds", None) if request else None),
|
prompt_embeds=(getattr(request, "prompt_embeds", None) if request else None),
|
||||||
|
prompt_is_token_ids=nr.prompt_is_token_ids,
|
||||||
additional_information=(getattr(request, "additional_information", None) if request else None),
|
additional_information=(getattr(request, "additional_information", None) if request else None),
|
||||||
)
|
)
|
||||||
new_list.append(omni_nr)
|
new_list.append(omni_nr)
|
||||||
@@ -520,7 +521,11 @@ class OmniGenerationScheduler(OmniSchedulerMixin, VLLMScheduler):
|
|||||||
stopped = True
|
stopped = True
|
||||||
|
|
||||||
if stopped:
|
if stopped:
|
||||||
routed_experts = self._get_routed_experts(request)
|
if (
|
||||||
|
model_runner_output.routed_experts_dict is not None
|
||||||
|
and req_id in model_runner_output.routed_experts_dict
|
||||||
|
):
|
||||||
|
routed_experts = model_runner_output.routed_experts_dict[req_id]
|
||||||
finish_reason = request.get_finished_reason()
|
finish_reason = request.get_finished_reason()
|
||||||
finished = self._handle_stopped_request(request)
|
finished = self._handle_stopped_request(request)
|
||||||
if finished:
|
if finished:
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ class OmniNewRequestData(NewRequestData):
|
|||||||
num_computed_tokens=request.num_computed_tokens,
|
num_computed_tokens=request.num_computed_tokens,
|
||||||
lora_request=request.lora_request,
|
lora_request=request.lora_request,
|
||||||
prompt_embeds=getattr(request, "prompt_embeds", None),
|
prompt_embeds=getattr(request, "prompt_embeds", None),
|
||||||
|
prompt_is_token_ids=getattr(request, "prompt_is_token_ids", None),
|
||||||
prefill_token_ids=prefill_token_ids,
|
prefill_token_ids=prefill_token_ids,
|
||||||
additional_information=getattr(request, "additional_information", None),
|
additional_information=getattr(request, "additional_information", None),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ connectors:
|
|||||||
stages:
|
stages:
|
||||||
- stage_id: 0
|
- stage_id: 0
|
||||||
max_num_seqs: 1
|
max_num_seqs: 1
|
||||||
gpu_memory_utilization: 0.3
|
gpu_memory_utilization: 0.5
|
||||||
enforce_eager: true
|
enforce_eager: true
|
||||||
trust_remote_code: true
|
trust_remote_code: true
|
||||||
enable_prefix_caching: false
|
enable_prefix_caching: false
|
||||||
@@ -42,7 +42,7 @@ stages:
|
|||||||
|
|
||||||
- stage_id: 1
|
- stage_id: 1
|
||||||
max_num_seqs: 1
|
max_num_seqs: 1
|
||||||
gpu_memory_utilization: 0.2
|
gpu_memory_utilization: 0.3
|
||||||
enforce_eager: true
|
enforce_eager: true
|
||||||
trust_remote_code: true
|
trust_remote_code: true
|
||||||
enable_prefix_caching: false
|
enable_prefix_caching: false
|
||||||
|
|||||||
@@ -391,6 +391,8 @@ class StageDiffusionClient(StageClientBase):
|
|||||||
return self._output_queue.get_nowait()
|
return self._output_queue.get_nowait()
|
||||||
except asyncio.QueueEmpty:
|
except asyncio.QueueEmpty:
|
||||||
if self._engine_dead:
|
if self._engine_dead:
|
||||||
|
if self._shutting_down:
|
||||||
|
return None
|
||||||
raise EngineDeadError()
|
raise EngineDeadError()
|
||||||
if not self._shutting_down and self._owns_process and self._proc is not None and not self._proc.is_alive():
|
if not self._shutting_down and self._owns_process and self._proc is not None and not self._proc.is_alive():
|
||||||
self._engine_dead = True
|
self._engine_dead = True
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ def _make_diffusion_vllm_model_config(od_config: OmniDiffusionConfig) -> _Diffus
|
|||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def _force_cutlass_fp8_linear_kernel(quant_config: object | None) -> Iterator[None]:
|
def _force_cutlass_fp8_linear_kernel(quant_config: object | None) -> Iterator[None]:
|
||||||
from vllm.model_executor.layers.quantization import modelopt as vllm_modelopt
|
import vllm.model_executor.layers.quantization.modelopt as vllm_modelopt
|
||||||
|
|
||||||
linear_method_cls = getattr(quant_config, "LinearMethodCls", None)
|
linear_method_cls = getattr(quant_config, "LinearMethodCls", None)
|
||||||
if linear_method_cls in {
|
if linear_method_cls in {
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ class OmniEngineCoreRequest(EngineCoreRequest):
|
|||||||
return cls(
|
return cls(
|
||||||
request_id=request.request_id,
|
request_id=request.request_id,
|
||||||
prompt_token_ids=request.prompt_token_ids,
|
prompt_token_ids=request.prompt_token_ids,
|
||||||
|
prompt_is_token_ids=request.prompt_is_token_ids,
|
||||||
mm_features=request.mm_features,
|
mm_features=request.mm_features,
|
||||||
sampling_params=request.sampling_params,
|
sampling_params=request.sampling_params,
|
||||||
pooling_params=request.pooling_params,
|
pooling_params=request.pooling_params,
|
||||||
@@ -109,6 +110,8 @@ class OmniEngineCoreRequest(EngineCoreRequest):
|
|||||||
resumable=request.resumable,
|
resumable=request.resumable,
|
||||||
external_req_id=request.external_req_id,
|
external_req_id=request.external_req_id,
|
||||||
reasoning_ended=request.reasoning_ended,
|
reasoning_ended=request.reasoning_ended,
|
||||||
|
reasoning_parser_kwargs=request.reasoning_parser_kwargs,
|
||||||
|
abort_immediately=request.abort_immediately,
|
||||||
additional_information=additional_information,
|
additional_information=additional_information,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
+105
-137
@@ -32,7 +32,6 @@ from vllm_omni.engine.messages import (
|
|||||||
EngineQueueMessage,
|
EngineQueueMessage,
|
||||||
ErrorMessage,
|
ErrorMessage,
|
||||||
OutputMessage,
|
OutputMessage,
|
||||||
ShutdownRequestMessage,
|
|
||||||
StageMetricsMessage,
|
StageMetricsMessage,
|
||||||
StageSubmissionMessage,
|
StageSubmissionMessage,
|
||||||
)
|
)
|
||||||
@@ -128,8 +127,8 @@ class Orchestrator:
|
|||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
request_async_queue: janus.AsyncQueue[EngineQueueMessage],
|
request_async_queue: janus.AsyncQueue[EngineQueueMessage],
|
||||||
output_async_queue: janus.AsyncQueue[EngineQueueMessage],
|
output_async_queue: janus.AsyncQueue[dict[str, Any]],
|
||||||
rpc_async_queue: janus.AsyncQueue[EngineQueueMessage],
|
rpc_async_queue: janus.AsyncQueue[dict[str, Any]],
|
||||||
stage_pools: list[StagePool],
|
stage_pools: list[StagePool],
|
||||||
*,
|
*,
|
||||||
async_chunk: bool = False,
|
async_chunk: bool = False,
|
||||||
@@ -174,6 +173,13 @@ class Orchestrator:
|
|||||||
await asyncio.gather(request_task, output_task)
|
await asyncio.gather(request_task, output_task)
|
||||||
except asyncio.CancelledError:
|
except asyncio.CancelledError:
|
||||||
raise
|
raise
|
||||||
|
except EngineDeadError as e:
|
||||||
|
# EngineDeadError from _orchestration_loop means the diffusion
|
||||||
|
# engine died. All pending requests were already notified and
|
||||||
|
# _shutdown_event was already set by the loop's handler.
|
||||||
|
# During teardown this is expected; the finally block handles
|
||||||
|
# proper cleanup. Do not re-raise.
|
||||||
|
logger.info("[Orchestrator] Engine dead during shutdown: %s", e)
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.exception("[Orchestrator] Fatal error in orchestrator tasks")
|
logger.exception("[Orchestrator] Fatal error in orchestrator tasks")
|
||||||
raise
|
raise
|
||||||
@@ -208,27 +214,32 @@ class Orchestrator:
|
|||||||
"""Read messages from the main thread via request_async_queue."""
|
"""Read messages from the main thread via request_async_queue."""
|
||||||
while True:
|
while True:
|
||||||
msg = await self.request_async_queue.get()
|
msg = await self.request_async_queue.get()
|
||||||
|
msg_type = msg.type
|
||||||
|
|
||||||
if isinstance(msg, StageSubmissionMessage):
|
if msg_type == "add_request":
|
||||||
if msg.type == "add_request":
|
await self._handle_add_request(msg)
|
||||||
await self._handle_add_request(msg)
|
elif msg_type == "streaming_update":
|
||||||
elif msg.type == "streaming_update":
|
await self._handle_streaming_update(msg)
|
||||||
await self._handle_streaming_update(msg)
|
elif msg_type == "add_companion_request":
|
||||||
else:
|
|
||||||
logger.warning("[Orchestrator] Unknown stage submission type: %s", msg.type)
|
|
||||||
elif isinstance(msg, AddCompanionRequestMessage):
|
|
||||||
await self._handle_add_companion(msg)
|
await self._handle_add_companion(msg)
|
||||||
elif isinstance(msg, AbortRequestMessage):
|
elif msg_type == "abort":
|
||||||
await self._handle_abort(msg)
|
await self._handle_abort(msg)
|
||||||
elif isinstance(msg, CollectiveRPCRequestMessage):
|
elif msg_type == "collective_rpc":
|
||||||
await self._handle_collective_rpc(msg)
|
await self._handle_collective_rpc(msg)
|
||||||
elif isinstance(msg, ShutdownRequestMessage):
|
elif msg_type == "shutdown":
|
||||||
logger.info("[Orchestrator] Received shutdown signal")
|
logger.info("[Orchestrator] Received shutdown signal")
|
||||||
self._shutdown_event.set()
|
self._shutdown_event.set()
|
||||||
|
# Pre-mark stage clients as shutting down to prevent
|
||||||
|
# proc_monitor daemon threads from flagging normal
|
||||||
|
# process exit as EngineDeadError during teardown.
|
||||||
|
for pool in self.stage_pools:
|
||||||
|
for client in pool.clients:
|
||||||
|
if hasattr(client, "_shutting_down"):
|
||||||
|
client._shutting_down = True
|
||||||
self._shutdown_stages()
|
self._shutdown_stages()
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
logger.warning("[Orchestrator] Unknown message type: %s", type(msg).__name__)
|
logger.warning("[Orchestrator] Unknown message type: %s", msg_type)
|
||||||
|
|
||||||
async def _handle_add_request(self, msg: StageSubmissionMessage) -> None:
|
async def _handle_add_request(self, msg: StageSubmissionMessage) -> None:
|
||||||
"""Handle an add_request message from the main thread."""
|
"""Handle an add_request message from the main thread."""
|
||||||
@@ -387,8 +398,8 @@ class Orchestrator:
|
|||||||
rpc_id = msg.rpc_id
|
rpc_id = msg.rpc_id
|
||||||
method = msg.method
|
method = msg.method
|
||||||
timeout = msg.timeout
|
timeout = msg.timeout
|
||||||
args = msg.args
|
args = tuple(msg.args)
|
||||||
kwargs = dict(msg.kwargs)
|
kwargs = dict(msg.kwargs or {})
|
||||||
requested_stage_ids = msg.stage_ids
|
requested_stage_ids = msg.stage_ids
|
||||||
|
|
||||||
target_pools: list[StagePool] = []
|
target_pools: list[StagePool] = []
|
||||||
@@ -793,120 +804,78 @@ class Orchestrator:
|
|||||||
"""Forward output from the current logical stage to the next one."""
|
"""Forward output from the current logical stage to the next one."""
|
||||||
next_logical = src_stage_id + 1
|
next_logical = src_stage_id + 1
|
||||||
next_pool = self.stage_pools[next_logical]
|
next_pool = self.stage_pools[next_logical]
|
||||||
|
next_client = next_pool.stage_client
|
||||||
if next_pool.stage_type == "diffusion":
|
|
||||||
await self._forward_to_diffusion_stage(
|
|
||||||
req_id,
|
|
||||||
src_stage_id,
|
|
||||||
output,
|
|
||||||
req_state,
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
await self._forward_to_llm_stage(
|
|
||||||
req_id,
|
|
||||||
src_stage_id,
|
|
||||||
output,
|
|
||||||
req_state,
|
|
||||||
is_streaming_session=is_streaming_session,
|
|
||||||
is_final_update=is_final_update,
|
|
||||||
)
|
|
||||||
|
|
||||||
async def _forward_to_diffusion_stage(
|
|
||||||
self,
|
|
||||||
req_id: str,
|
|
||||||
src_stage_id: int,
|
|
||||||
output: Any,
|
|
||||||
req_state: OrchestratorRequestState,
|
|
||||||
) -> None:
|
|
||||||
"""Forward output from an LLM stage to the next diffusion stage."""
|
|
||||||
next_logical = src_stage_id + 1
|
|
||||||
next_pool = self.stage_pools[next_logical]
|
|
||||||
params = req_state.sampling_params_list[next_logical]
|
|
||||||
source_outputs = [output]
|
|
||||||
already_submitted = self._next_stage_already_submitted(src_stage_id, req_state)
|
|
||||||
|
|
||||||
diffusion_client = next_pool.stage_client
|
|
||||||
if diffusion_client.custom_process_input_func is not None:
|
|
||||||
_t_ar2d = _time.perf_counter()
|
|
||||||
diffusion_prompt = diffusion_client.custom_process_input_func(
|
|
||||||
source_outputs,
|
|
||||||
req_state.prompt,
|
|
||||||
getattr(diffusion_client, "requires_multimodal_data", False),
|
|
||||||
)
|
|
||||||
_dt_ar2d = (_time.perf_counter() - _t_ar2d) * 1000
|
|
||||||
req_state.pipeline_timings["ar2diffusion_ms"] = _dt_ar2d
|
|
||||||
logger.info(
|
|
||||||
"[Orchestrator] ar2diffusion req=%s wall_time=%.3fms stage=%d->%d",
|
|
||||||
req_id,
|
|
||||||
_dt_ar2d,
|
|
||||||
src_stage_id,
|
|
||||||
next_logical,
|
|
||||||
)
|
|
||||||
if isinstance(diffusion_prompt, list):
|
|
||||||
if not diffusion_prompt:
|
|
||||||
error_output = OmniRequestOutput.from_error(
|
|
||||||
req_id,
|
|
||||||
f"Stage-{src_stage_id} produced no valid inputs for diffusion stage-{next_logical}",
|
|
||||||
)
|
|
||||||
logger.warning(
|
|
||||||
"[Orchestrator] req=%s stage=%d produced empty diffusion inputs for stage=%d; "
|
|
||||||
"routing terminal error output",
|
|
||||||
req_id,
|
|
||||||
src_stage_id,
|
|
||||||
next_logical,
|
|
||||||
)
|
|
||||||
await self.output_async_queue.put(
|
|
||||||
OutputMessage(
|
|
||||||
request_id=req_id,
|
|
||||||
stage_id=next_logical,
|
|
||||||
engine_outputs=error_output,
|
|
||||||
metrics=None,
|
|
||||||
finished=True,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
await self._cleanup_request_ids(
|
|
||||||
[req_id, *self._cfg_tracker.cleanup_parent(req_id)],
|
|
||||||
)
|
|
||||||
return
|
|
||||||
if already_submitted and len(diffusion_prompt) == 1:
|
|
||||||
diffusion_prompt = diffusion_prompt[0]
|
|
||||||
else:
|
|
||||||
diffusion_prompt = req_state.prompt
|
|
||||||
|
|
||||||
if already_submitted:
|
|
||||||
await next_pool.submit_update(req_id, req_state, diffusion_prompt)
|
|
||||||
else:
|
|
||||||
await next_pool.submit_initial(
|
|
||||||
req_id,
|
|
||||||
req_state,
|
|
||||||
diffusion_prompt,
|
|
||||||
submit_kwargs={
|
|
||||||
"kv_sender_info": self._build_kv_sender_info(
|
|
||||||
list(getattr(diffusion_client, "engine_input_source", None) or [src_stage_id]),
|
|
||||||
request_id=req_id,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
params_override=self._maybe_clone_diffusion_params_for_cfg(req_id, params),
|
|
||||||
)
|
|
||||||
req_state.stage_submit_ts[next_logical] = _time.time()
|
|
||||||
|
|
||||||
async def _forward_to_llm_stage(
|
|
||||||
self,
|
|
||||||
req_id: str,
|
|
||||||
src_stage_id: int,
|
|
||||||
output: Any,
|
|
||||||
req_state: OrchestratorRequestState,
|
|
||||||
*,
|
|
||||||
is_streaming_session: bool = False,
|
|
||||||
is_final_update: bool = False,
|
|
||||||
) -> None:
|
|
||||||
"""Forward output from the current stage to the next LLM stage."""
|
|
||||||
next_logical = src_stage_id + 1
|
|
||||||
next_pool = self.stage_pools[next_logical]
|
|
||||||
params = req_state.sampling_params_list[next_logical]
|
params = req_state.sampling_params_list[next_logical]
|
||||||
source_outputs = [output]
|
source_outputs = [output]
|
||||||
next_stage_resumable = is_streaming_session and not is_final_update
|
next_stage_resumable = is_streaming_session and not is_final_update
|
||||||
already_submitted = self._next_stage_already_submitted(src_stage_id, req_state)
|
already_submitted = self._next_stage_already_submitted(src_stage_id, req_state)
|
||||||
|
requires_multimodal_data = getattr(next_client, "requires_multimodal_data", False)
|
||||||
|
|
||||||
|
if next_pool.stage_type == "diffusion":
|
||||||
|
if next_client.custom_process_input_func is not None:
|
||||||
|
_t_ar2d = _time.perf_counter()
|
||||||
|
diffusion_prompt = next_client.custom_process_input_func(
|
||||||
|
source_outputs,
|
||||||
|
req_state.prompt,
|
||||||
|
requires_multimodal_data,
|
||||||
|
)
|
||||||
|
_dt_ar2d = (_time.perf_counter() - _t_ar2d) * 1000
|
||||||
|
req_state.pipeline_timings["ar2diffusion_ms"] = _dt_ar2d
|
||||||
|
logger.info(
|
||||||
|
"[Orchestrator] ar2diffusion req=%s wall_time=%.3fms stage=%d->%d",
|
||||||
|
req_id,
|
||||||
|
_dt_ar2d,
|
||||||
|
src_stage_id,
|
||||||
|
next_logical,
|
||||||
|
)
|
||||||
|
if isinstance(diffusion_prompt, list):
|
||||||
|
if not diffusion_prompt:
|
||||||
|
error_output = OmniRequestOutput.from_error(
|
||||||
|
req_id,
|
||||||
|
f"Stage-{src_stage_id} produced no valid inputs for diffusion stage-{next_logical}",
|
||||||
|
)
|
||||||
|
logger.warning(
|
||||||
|
"[Orchestrator] req=%s stage=%d produced empty diffusion inputs for stage=%d; "
|
||||||
|
"routing terminal error output",
|
||||||
|
req_id,
|
||||||
|
src_stage_id,
|
||||||
|
next_logical,
|
||||||
|
)
|
||||||
|
await self.output_async_queue.put(
|
||||||
|
OutputMessage(
|
||||||
|
request_id=req_id,
|
||||||
|
stage_id=next_logical,
|
||||||
|
engine_outputs=error_output,
|
||||||
|
metrics=None,
|
||||||
|
finished=True,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
await self._cleanup_request_ids(
|
||||||
|
[req_id, *self._cfg_tracker.cleanup_parent(req_id)],
|
||||||
|
)
|
||||||
|
return
|
||||||
|
if already_submitted and len(diffusion_prompt) == 1:
|
||||||
|
diffusion_prompt = diffusion_prompt[0]
|
||||||
|
else:
|
||||||
|
diffusion_prompt = req_state.prompt
|
||||||
|
|
||||||
|
if already_submitted:
|
||||||
|
await next_pool.submit_update(req_id, req_state, diffusion_prompt)
|
||||||
|
else:
|
||||||
|
await next_pool.submit_initial(
|
||||||
|
req_id,
|
||||||
|
req_state,
|
||||||
|
diffusion_prompt,
|
||||||
|
submit_kwargs={
|
||||||
|
"kv_sender_info": self._build_kv_sender_info(
|
||||||
|
list(getattr(next_client, "engine_input_source", None) or [src_stage_id]),
|
||||||
|
request_id=req_id,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
params_override=self._maybe_clone_diffusion_params_for_cfg(req_id, params),
|
||||||
|
)
|
||||||
|
req_state.stage_submit_ts[next_logical] = _time.time()
|
||||||
|
return
|
||||||
|
|
||||||
# PD disaggregation: prefill → decode routing uses original prompt + KV transfer params
|
# PD disaggregation: prefill → decode routing uses original prompt + KV transfer params
|
||||||
if self._pd_pair is not None and (src_stage_id, next_logical) == self._pd_pair:
|
if self._pd_pair is not None and (src_stage_id, next_logical) == self._pd_pair:
|
||||||
@@ -953,7 +922,6 @@ class Orchestrator:
|
|||||||
{},
|
{},
|
||||||
)[req_id] = req_state.pd_prefill_multimodal_output
|
)[req_id] = req_state.pd_prefill_multimodal_output
|
||||||
|
|
||||||
next_client = next_pool.llm_stage_client
|
|
||||||
try:
|
try:
|
||||||
next_inputs = next_client.process_engine_inputs(
|
next_inputs = next_client.process_engine_inputs(
|
||||||
source_outputs,
|
source_outputs,
|
||||||
@@ -972,7 +940,7 @@ class Orchestrator:
|
|||||||
for next_input in next_inputs:
|
for next_input in next_inputs:
|
||||||
# Only AR thinker stages consume encoder mm_features; downstream
|
# Only AR thinker stages consume encoder mm_features; downstream
|
||||||
# (talker/code2wav/…) must not see them (avoids encoder-cache misses).
|
# (talker/code2wav/…) must not see them (avoids encoder-cache misses).
|
||||||
model_stage = next_client.model_stage
|
model_stage = getattr(next_client, "model_stage", None)
|
||||||
mm_features = req_state.mm_features if model_stage == "thinker" else None
|
mm_features = req_state.mm_features if model_stage == "thinker" else None
|
||||||
request = build_engine_core_request_from_tokens(
|
request = build_engine_core_request_from_tokens(
|
||||||
request_id=req_id,
|
request_id=req_id,
|
||||||
@@ -1022,7 +990,7 @@ class Orchestrator:
|
|||||||
req_state.prompt,
|
req_state.prompt,
|
||||||
submit_kwargs={
|
submit_kwargs={
|
||||||
"kv_sender_info": self._build_kv_sender_info(
|
"kv_sender_info": self._build_kv_sender_info(
|
||||||
list(next_pool.stage_client.engine_input_source or [next_stage_id - 1]),
|
list(getattr(next_pool.stage_client, "engine_input_source", None) or [next_stage_id - 1]),
|
||||||
request_id=request_id,
|
request_id=request_id,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@@ -1069,14 +1037,14 @@ class Orchestrator:
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
sender_pool = self.stage_pools[sender_stage_id]
|
sender_pool = self.stage_pools[sender_stage_id]
|
||||||
if sender_pool.stage_type == "diffusion":
|
sender_stage = sender_pool.get_bound_client(request_id) if request_id is not None else None
|
||||||
|
if sender_stage is None:
|
||||||
|
sender_stage = sender_pool.stage_client
|
||||||
|
get_sender_info = getattr(sender_stage, "get_kv_sender_info", None)
|
||||||
|
if not callable(get_sender_info):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
sender_stage = sender_pool.get_bound_llm_client(request_id) if request_id is not None else None
|
sender_info = get_sender_info()
|
||||||
if sender_stage is None:
|
|
||||||
sender_stage = sender_pool.llm_stage_client
|
|
||||||
|
|
||||||
sender_info = sender_stage.get_kv_sender_info()
|
|
||||||
if not sender_info:
|
if not sender_info:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
"[Orchestrator] Stage-%s has no KV sender info available",
|
"[Orchestrator] Stage-%s has no KV sender info available",
|
||||||
@@ -1110,7 +1078,7 @@ class Orchestrator:
|
|||||||
msg = self.request_async_queue.get_nowait()
|
msg = self.request_async_queue.get_nowait()
|
||||||
except Exception:
|
except Exception:
|
||||||
break
|
break
|
||||||
if isinstance(msg, StageSubmissionMessage) and msg.type == "add_request":
|
if msg.type == "add_request":
|
||||||
req_id = msg.request_id
|
req_id = msg.request_id
|
||||||
await self.output_async_queue.put(
|
await self.output_async_queue.put(
|
||||||
ErrorMessage(
|
ErrorMessage(
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ from typing import Any
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import torch
|
import torch
|
||||||
from vllm.logger import init_logger
|
from vllm.logger import init_logger
|
||||||
|
from vllm.model_executor.layers.fused_moe.routed_experts_capturer import (
|
||||||
|
split_routed_experts,
|
||||||
|
)
|
||||||
from vllm.outputs import PoolingRequestOutput
|
from vllm.outputs import PoolingRequestOutput
|
||||||
from vllm.sampling_params import RequestOutputKind
|
from vllm.sampling_params import RequestOutputKind
|
||||||
from vllm.tokenizers import TokenizerLike
|
from vllm.tokenizers import TokenizerLike
|
||||||
@@ -230,7 +233,17 @@ class OmniRequestState(RequestState):
|
|||||||
self.sent_tokens_offset = self.detokenizer.num_output_tokens()
|
self.sent_tokens_offset = self.detokenizer.num_output_tokens()
|
||||||
|
|
||||||
external_req_id = self.external_req_id
|
external_req_id = self.external_req_id
|
||||||
output = self._new_completion_output(new_token_ids, finish_reason, stop_reason, routed_experts)
|
|
||||||
|
# Split routing data into prompt and generation portions, matching
|
||||||
|
# upstream make_request_output behaviour.
|
||||||
|
prompt_routed_experts = None
|
||||||
|
gen_routed_experts = None
|
||||||
|
if routed_experts is not None:
|
||||||
|
prompt_len = len(self.prompt_token_ids) if self.prompt_token_ids else 0
|
||||||
|
num_gen = self.detokenizer.num_output_tokens() if self.detokenizer is not None else None
|
||||||
|
prompt_routed_experts, gen_routed_experts = split_routed_experts(routed_experts, prompt_len, num_gen)
|
||||||
|
|
||||||
|
output = self._new_completion_output(new_token_ids, finish_reason, stop_reason, gen_routed_experts)
|
||||||
|
|
||||||
if self.parent_req is None:
|
if self.parent_req is None:
|
||||||
outputs = [output]
|
outputs = [output]
|
||||||
@@ -240,7 +253,13 @@ class OmniRequestState(RequestState):
|
|||||||
return None
|
return None
|
||||||
external_req_id = self.parent_req.external_req_id
|
external_req_id = self.parent_req.external_req_id
|
||||||
|
|
||||||
return self._new_request_output(external_req_id, outputs, finished, kv_transfer_params)
|
return self._new_request_output(
|
||||||
|
external_req_id,
|
||||||
|
outputs,
|
||||||
|
finished,
|
||||||
|
kv_transfer_params,
|
||||||
|
prompt_routed_experts,
|
||||||
|
)
|
||||||
|
|
||||||
def _new_completion_output(
|
def _new_completion_output(
|
||||||
self,
|
self,
|
||||||
|
|||||||
@@ -80,7 +80,8 @@ class StageEngineCoreClientBase(StageClientBase):
|
|||||||
def make_async_mp_client(
|
def make_async_mp_client(
|
||||||
vllm_config: Any,
|
vllm_config: Any,
|
||||||
executor_class: type,
|
executor_class: type,
|
||||||
metadata: StageMetadata,
|
log_stats: bool = False,
|
||||||
|
metadata: StageMetadata | None = None,
|
||||||
client_addresses: dict[str, str] | None = None,
|
client_addresses: dict[str, str] | None = None,
|
||||||
proc: Any = None,
|
proc: Any = None,
|
||||||
engine_manager: Any = None,
|
engine_manager: Any = None,
|
||||||
@@ -93,6 +94,7 @@ class StageEngineCoreClientBase(StageClientBase):
|
|||||||
client_args = dict(
|
client_args = dict(
|
||||||
vllm_config=vllm_config,
|
vllm_config=vllm_config,
|
||||||
executor_class=executor_class,
|
executor_class=executor_class,
|
||||||
|
log_stats=log_stats,
|
||||||
metadata=metadata,
|
metadata=metadata,
|
||||||
client_addresses=client_addresses,
|
client_addresses=client_addresses,
|
||||||
proc=proc,
|
proc=proc,
|
||||||
@@ -441,7 +443,7 @@ class StageEngineCoreClientBase(StageClientBase):
|
|||||||
kwargs=kwargs,
|
kwargs=kwargs,
|
||||||
)
|
)
|
||||||
|
|
||||||
def shutdown(self) -> None:
|
def shutdown(self, timeout: float | None = None) -> None:
|
||||||
"""Shutdown managed resources and any externally spawned subprocess."""
|
"""Shutdown managed resources and any externally spawned subprocess."""
|
||||||
child_procs: list[psutil.Process] = []
|
child_procs: list[psutil.Process] = []
|
||||||
if self._proc is not None and self._proc.pid is not None:
|
if self._proc is not None and self._proc.pid is not None:
|
||||||
@@ -451,7 +453,7 @@ class StageEngineCoreClientBase(StageClientBase):
|
|||||||
child_procs = []
|
child_procs = []
|
||||||
|
|
||||||
try:
|
try:
|
||||||
super().shutdown()
|
super().shutdown(timeout=timeout)
|
||||||
finally:
|
finally:
|
||||||
if self._proc is not None and self._proc.is_alive():
|
if self._proc is not None and self._proc.is_alive():
|
||||||
self._proc.terminate()
|
self._proc.terminate()
|
||||||
|
|||||||
@@ -232,6 +232,7 @@ class AsyncOmni(EngineClient, OmniBase):
|
|||||||
priority: int = 0,
|
priority: int = 0,
|
||||||
data_parallel_rank: int | None = None,
|
data_parallel_rank: int | None = None,
|
||||||
reasoning_ended: bool | None = None,
|
reasoning_ended: bool | None = None,
|
||||||
|
reasoning_parser_kwargs: dict[str, Any] | None = None,
|
||||||
) -> AsyncGenerator[OmniRequestOutput, None]:
|
) -> AsyncGenerator[OmniRequestOutput, None]:
|
||||||
"""Generate outputs for the given prompt(s) asynchronously.
|
"""Generate outputs for the given prompt(s) asynchronously.
|
||||||
|
|
||||||
@@ -938,6 +939,37 @@ class AsyncOmni(EngineClient, OmniBase):
|
|||||||
"""Check if tracing is enabled."""
|
"""Check if tracing is enabled."""
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
async def notify_kv_transfer_request_rejected(
|
||||||
|
self,
|
||||||
|
request_id: str,
|
||||||
|
kv_transfer_params: dict[str, Any],
|
||||||
|
*,
|
||||||
|
data_parallel_rank: int | None = None,
|
||||||
|
) -> None:
|
||||||
|
"""Notify engine that a KV-transfer request was rejected before admission.
|
||||||
|
|
||||||
|
Omni does not currently use KV-transfer pre-admission resources,
|
||||||
|
so this is a no-op.
|
||||||
|
"""
|
||||||
|
logger.debug(
|
||||||
|
"KV-transfer request rejected (no-op in omni): request_id=%s",
|
||||||
|
request_id,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def start_weight_update(self, is_checkpoint_format: bool = True) -> None:
|
||||||
|
"""Start a new weight update.
|
||||||
|
|
||||||
|
Omni does not currently support weight transfer, so this is a no-op.
|
||||||
|
"""
|
||||||
|
logger.debug("Weight update start requested (no-op in omni)")
|
||||||
|
|
||||||
|
async def finish_weight_update(self) -> None:
|
||||||
|
"""Finish the current weight update.
|
||||||
|
|
||||||
|
Omni does not currently support weight transfer, so this is a no-op.
|
||||||
|
"""
|
||||||
|
logger.debug("Weight update finish requested (no-op in omni)")
|
||||||
|
|
||||||
async def do_log_stats(self) -> None:
|
async def do_log_stats(self) -> None:
|
||||||
"""Log statistics.
|
"""Log statistics.
|
||||||
|
|
||||||
|
|||||||
@@ -148,6 +148,8 @@ class OmniOpenAIServingChat(OpenAIServingChat, AudioMixin):
|
|||||||
instance._diffusion_mode = True
|
instance._diffusion_mode = True
|
||||||
instance._diffusion_engine = diffusion_engine
|
instance._diffusion_engine = diffusion_engine
|
||||||
instance._diffusion_model_name = model_name
|
instance._diffusion_model_name = model_name
|
||||||
|
instance.engine_client = None
|
||||||
|
instance.has_kv_connector = False
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
def _get_diffusion_extra_body_params(self) -> frozenset[str]:
|
def _get_diffusion_extra_body_params(self) -> frozenset[str]:
|
||||||
@@ -216,6 +218,15 @@ class OmniOpenAIServingChat(OpenAIServingChat, AudioMixin):
|
|||||||
For diffusion models, this generates images and returns them
|
For diffusion models, this generates images and returns them
|
||||||
in a chat completion response format.
|
in a chat completion response format.
|
||||||
"""
|
"""
|
||||||
|
return await self._with_kv_transfer_rejection_cleanup(
|
||||||
|
self._create_chat_completion(request, raw_request), request, raw_request
|
||||||
|
)
|
||||||
|
|
||||||
|
async def _create_chat_completion(
|
||||||
|
self,
|
||||||
|
request: ChatCompletionRequest,
|
||||||
|
raw_request: Request | None = None,
|
||||||
|
) -> AsyncGenerator[str, None] | ChatCompletionResponse | ErrorResponse:
|
||||||
# Handle diffusion mode
|
# Handle diffusion mode
|
||||||
if self._diffusion_mode:
|
if self._diffusion_mode:
|
||||||
return await self._create_diffusion_chat_completion(request, raw_request)
|
return await self._create_diffusion_chat_completion(request, raw_request)
|
||||||
@@ -996,6 +1007,9 @@ class OmniOpenAIServingChat(OpenAIServingChat, AudioMixin):
|
|||||||
# when handling audio/image responses
|
# when handling audio/image responses
|
||||||
role = self.get_chat_request_role(request)
|
role = self.get_chat_request_role(request)
|
||||||
|
|
||||||
|
# Compute prompt_text once at first iteration (upstream #42052)
|
||||||
|
prompt_text = getattr(res, "prompt", None) if getattr(request, "return_prompt_text", None) else None
|
||||||
|
|
||||||
# We need to do it here, because if there are exceptions in
|
# We need to do it here, because if there are exceptions in
|
||||||
# the result_generator, it needs to be sent as the FIRST
|
# the result_generator, it needs to be sent as the FIRST
|
||||||
# response (by the try...catch).
|
# response (by the try...catch).
|
||||||
@@ -1022,6 +1036,7 @@ class OmniOpenAIServingChat(OpenAIServingChat, AudioMixin):
|
|||||||
choices=[choice_data],
|
choices=[choice_data],
|
||||||
model=model_name,
|
model=model_name,
|
||||||
prompt_token_ids=(res.prompt_token_ids if request.return_token_ids else None),
|
prompt_token_ids=(res.prompt_token_ids if request.return_token_ids else None),
|
||||||
|
prompt_text=prompt_text,
|
||||||
modality=final_output_type,
|
modality=final_output_type,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1740,6 +1755,13 @@ class OmniOpenAIServingChat(OpenAIServingChat, AudioMixin):
|
|||||||
response_metrics.update(extra)
|
response_metrics.update(extra)
|
||||||
choices.extend(choices_data)
|
choices.extend(choices_data)
|
||||||
|
|
||||||
|
# Compute prompt_text for non-streaming response (upstream #42052)
|
||||||
|
prompt_text = (
|
||||||
|
getattr(final_res, "prompt", None)
|
||||||
|
if final_res is not None and getattr(request, "return_prompt_text", None)
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
|
||||||
response = OmniChatCompletionResponse(
|
response = OmniChatCompletionResponse(
|
||||||
id=request_id,
|
id=request_id,
|
||||||
created=created_time,
|
created=created_time,
|
||||||
@@ -1748,6 +1770,7 @@ class OmniOpenAIServingChat(OpenAIServingChat, AudioMixin):
|
|||||||
usage=usage,
|
usage=usage,
|
||||||
prompt_logprobs=prompt_logprobs,
|
prompt_logprobs=prompt_logprobs,
|
||||||
prompt_token_ids=prompt_token_ids,
|
prompt_token_ids=prompt_token_ids,
|
||||||
|
prompt_text=prompt_text,
|
||||||
kv_transfer_params=kv_transfer_params,
|
kv_transfer_params=kv_transfer_params,
|
||||||
metrics=response_metrics,
|
metrics=response_metrics,
|
||||||
)
|
)
|
||||||
@@ -2034,13 +2057,17 @@ class OmniOpenAIServingChat(OpenAIServingChat, AudioMixin):
|
|||||||
mm_output = final_res.outputs[0].multimodal_output
|
mm_output = final_res.outputs[0].multimodal_output
|
||||||
audio_data = mm_output.get("audio")
|
audio_data = mm_output.get("audio")
|
||||||
if isinstance(audio_data, list):
|
if isinstance(audio_data, list):
|
||||||
if stream:
|
if not audio_data:
|
||||||
|
audio_tensor = None
|
||||||
|
elif stream:
|
||||||
audio_tensor = audio_data[-1]
|
audio_tensor = audio_data[-1]
|
||||||
else:
|
else:
|
||||||
audio_tensor = torch.cat(audio_data, dim=-1)
|
audio_tensor = torch.cat(audio_data, dim=-1)
|
||||||
else:
|
else:
|
||||||
audio_tensor = audio_data
|
audio_tensor = audio_data
|
||||||
audio_tensor = audio_tensor.float().detach().cpu().numpy()
|
if audio_tensor is None:
|
||||||
|
return self._create_error_response("Audio generation completed but no audio was produced.")
|
||||||
|
audio_tensor = audio_tensor.detach().cpu().float().numpy()
|
||||||
|
|
||||||
# Ensure audio is 1D (flatten if needed)
|
# Ensure audio is 1D (flatten if needed)
|
||||||
if audio_tensor.ndim > 1:
|
if audio_tensor.ndim > 1:
|
||||||
|
|||||||
@@ -2103,6 +2103,13 @@ class OmniOpenAIServingSpeech(OpenAIServing, AudioMixin):
|
|||||||
voice_lower = request.voice.lower()
|
voice_lower = request.voice.lower()
|
||||||
tts_params["voice_name"] = [voice_lower]
|
tts_params["voice_name"] = [voice_lower]
|
||||||
tts_params["voice_created_at"] = [self._voice_created_at(voice_lower)]
|
tts_params["voice_created_at"] = [self._voice_created_at(voice_lower)]
|
||||||
|
# Propagate seed from sampling params for deterministic generation.
|
||||||
|
# MOSS-TTS-Nano uses its own internal sampling inside
|
||||||
|
# inference_stream(), which reads seed from additional_information
|
||||||
|
# (not SamplingParams). Without this the model uses ambient RNG
|
||||||
|
# state and produces non-deterministic output.
|
||||||
|
if sampling_params_list and getattr(sampling_params_list[0], "seed", None) is not None:
|
||||||
|
tts_params["seed"] = [sampling_params_list[0].seed]
|
||||||
prompt = tokens_input(prompt_token_ids=[1])
|
prompt = tokens_input(prompt_token_ids=[1])
|
||||||
prompt["additional_information"] = tts_params
|
prompt["additional_information"] = tts_params
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -351,8 +351,10 @@ class CodePredictorBaseModel(nn.Module):
|
|||||||
# native bf16 support (Turing, Volta). The RMSNorm and RoPE
|
# native bf16 support (Turing, Volta). The RMSNorm and RoPE
|
||||||
# layers already upcast internally; this extends the same
|
# layers already upcast internally; this extends the same
|
||||||
# treatment to attention and MLP.
|
# treatment to attention and MLP.
|
||||||
|
# autocast to float32 is unsupported on CPU; skip fp32 upcast there
|
||||||
|
# (CPU uses full-precision intermediates internally).
|
||||||
input_dtype = inputs_embeds.dtype
|
input_dtype = inputs_embeds.dtype
|
||||||
use_fp32 = input_dtype == torch.float16
|
use_fp32 = input_dtype == torch.float16 and inputs_embeds.device.type != "cpu"
|
||||||
if use_fp32:
|
if use_fp32:
|
||||||
inputs_embeds = inputs_embeds.float()
|
inputs_embeds = inputs_embeds.float()
|
||||||
hidden_states = inputs_embeds
|
hidden_states = inputs_embeds
|
||||||
|
|||||||
@@ -61,8 +61,9 @@ class SnakeBeta(nn.Module):
|
|||||||
x = tl.load(x_ptr + bid * stride_b + cid * stride_c + t_off, mask=mask, other=0.0)
|
x = tl.load(x_ptr + bid * stride_b + cid * stride_c + t_off, mask=mask, other=0.0)
|
||||||
ea = tl.load(exp_alpha_ptr + cid)
|
ea = tl.load(exp_alpha_ptr + cid)
|
||||||
ib = tl.load(inv_beta_ptr + cid)
|
ib = tl.load(inv_beta_ptr + cid)
|
||||||
sin_val = tl.sin(x * ea)
|
x_float = x.to(tl.float32)
|
||||||
result = x + ib * sin_val * sin_val
|
sin_val = tl.sin(x_float * ea)
|
||||||
|
result = x + (ib * sin_val * sin_val).to(x.dtype)
|
||||||
|
|
||||||
tl.store(out_ptr + bid * stride_b + cid * stride_c + t_off, result, mask=mask)
|
tl.store(out_ptr + bid * stride_b + cid * stride_c + t_off, result, mask=mask)
|
||||||
|
|
||||||
|
|||||||
@@ -27,17 +27,8 @@ from vllm.distributed import (
|
|||||||
)
|
)
|
||||||
from vllm.inputs import MultiModalDataDict
|
from vllm.inputs import MultiModalDataDict
|
||||||
from vllm.logger import init_logger
|
from vllm.logger import init_logger
|
||||||
|
from vllm.model_executor.layers.fused_moe import FusedMoE as SharedFusedMoE
|
||||||
from vllm.model_executor.layers.fused_moe import fused_moe_make_expert_params_mapping
|
from vllm.model_executor.layers.fused_moe import fused_moe_make_expert_params_mapping
|
||||||
|
|
||||||
try:
|
|
||||||
from vllm.model_executor.layers.fused_moe.shared_fused_moe import SharedFusedMoE
|
|
||||||
except ImportError:
|
|
||||||
# PyPI vllm 0.20.x neither exports `SharedFusedMoE` from the package top-level
|
|
||||||
# nor ships a `shared_fused_moe.py` submodule. The functionality lives on
|
|
||||||
# `FusedMoE` directly (which gained a `shared_experts` parameter), so alias
|
|
||||||
# the symbol — call sites only use the classmethod `make_expert_params_mapping`
|
|
||||||
# and `__init__(shared_experts=..., ...)` which are present on `FusedMoE`.
|
|
||||||
from vllm.model_executor.layers.fused_moe import FusedMoE as SharedFusedMoE
|
|
||||||
from vllm.model_executor.layers.linear import (
|
from vllm.model_executor.layers.linear import (
|
||||||
ColumnParallelLinear,
|
ColumnParallelLinear,
|
||||||
ReplicatedLinear,
|
ReplicatedLinear,
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ class MossTTSNanoForGeneration(nn.Module):
|
|||||||
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
|
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
|
||||||
with self._lock:
|
with self._lock:
|
||||||
if self._lm is not None:
|
if self._lm is not None:
|
||||||
return set()
|
return None
|
||||||
_patch_torchaudio_load()
|
_patch_torchaudio_load()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -233,7 +233,7 @@ class MossTTSNanoForGeneration(nn.Module):
|
|||||||
# iterator so the underlying stream is closed cleanly.
|
# iterator so the underlying stream is closed cleanly.
|
||||||
for _ in weights:
|
for _ in weights:
|
||||||
pass
|
pass
|
||||||
return set()
|
return None
|
||||||
|
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
# Dummy run support
|
# Dummy run support
|
||||||
|
|||||||
+4
@@ -534,6 +534,10 @@ class Qwen3TTSTokenizerV2DecoderTransformerModel(Qwen3TTSTokenizerV2DecoderPreTr
|
|||||||
cache_position=None,
|
cache_position=None,
|
||||||
**kwargs,
|
**kwargs,
|
||||||
) -> BaseModelOutputWithPast:
|
) -> BaseModelOutputWithPast:
|
||||||
|
r"""
|
||||||
|
cache_position (`torch.LongTensor` of shape `(sequence_length)`, *optional*):
|
||||||
|
Indices depicting the position of the input sequence tokens in the sequence. Used to update the cache.
|
||||||
|
"""
|
||||||
if input_ids is not None:
|
if input_ids is not None:
|
||||||
raise ValueError("input_ids is not expected")
|
raise ValueError("input_ids is not expected")
|
||||||
if (input_ids is None) ^ (inputs_embeds is not None):
|
if (input_ids is None) ^ (inputs_embeds is not None):
|
||||||
|
|||||||
@@ -16,7 +16,11 @@ from vllm.distributed.kv_transfer import get_kv_transfer_group, has_kv_transfer_
|
|||||||
from vllm.distributed.parallel_state import get_pp_group, get_tp_group
|
from vllm.distributed.parallel_state import get_pp_group, get_tp_group
|
||||||
from vllm.forward_context import BatchDescriptor
|
from vllm.forward_context import BatchDescriptor
|
||||||
from vllm.logger import logger
|
from vllm.logger import logger
|
||||||
from vllm.model_executor.layers.fused_moe.routed_experts_capturer import RoutedExpertsCapturer
|
from vllm.model_executor.layers.fused_moe.routed_experts_capturer import (
|
||||||
|
extract_routed_experts_for_current_batch,
|
||||||
|
get_global_experts_capturer,
|
||||||
|
issue_routing_d2h_copy,
|
||||||
|
)
|
||||||
from vllm.sequence import IntermediateTensors
|
from vllm.sequence import IntermediateTensors
|
||||||
from vllm.v1.core.sched.output import GrammarOutput, SchedulerOutput
|
from vllm.v1.core.sched.output import GrammarOutput, SchedulerOutput
|
||||||
from vllm.v1.outputs import (
|
from vllm.v1.outputs import (
|
||||||
@@ -28,8 +32,8 @@ from vllm.v1.outputs import (
|
|||||||
from vllm.v1.spec_decode.metadata import SpecDecodeMetadata
|
from vllm.v1.spec_decode.metadata import SpecDecodeMetadata
|
||||||
from vllm.v1.structured_output.utils import apply_grammar_bitmask
|
from vllm.v1.structured_output.utils import apply_grammar_bitmask
|
||||||
from vllm.v1.utils import record_function_or_nullcontext
|
from vllm.v1.utils import record_function_or_nullcontext
|
||||||
from vllm.v1.worker import mamba_utils
|
|
||||||
from vllm.v1.worker.gpu_model_runner import AsyncGPUModelRunnerOutput, PerLayerAttnMetadata
|
from vllm.v1.worker.gpu_model_runner import AsyncGPUModelRunnerOutput, PerLayerAttnMetadata
|
||||||
|
from vllm.v1.worker.mamba_utils import preprocess_mamba
|
||||||
from vllm.v1.worker.ubatch_utils import maybe_create_ubatch_slices
|
from vllm.v1.worker.ubatch_utils import maybe_create_ubatch_slices
|
||||||
from vllm_ascend.ascend_forward_context import set_ascend_forward_context
|
from vllm_ascend.ascend_forward_context import set_ascend_forward_context
|
||||||
from vllm_ascend.attention.utils import AscendCommonAttentionMetadata
|
from vllm_ascend.attention.utils import AscendCommonAttentionMetadata
|
||||||
@@ -246,11 +250,9 @@ class NPUARModelRunner(OmniNPUModelRunner):
|
|||||||
intermediate_tensors: IntermediateTensors | None = None,
|
intermediate_tensors: IntermediateTensors | None = None,
|
||||||
) -> OmniModelRunnerOutput | IntermediateTensors | None:
|
) -> OmniModelRunnerOutput | IntermediateTensors | None:
|
||||||
if self.vllm_config.model_config.enable_return_routed_experts:
|
if self.vllm_config.model_config.enable_return_routed_experts:
|
||||||
capturer = RoutedExpertsCapturer.get_instance()
|
capturer = get_global_experts_capturer()
|
||||||
if capturer is not None:
|
if capturer is not None and hasattr(capturer, "finalize_pending_copy"):
|
||||||
capturer.clear_buffer()
|
capturer.finalize_pending_copy()
|
||||||
else:
|
|
||||||
logger.warning("RoutedExpertsCapturer is not initialized.")
|
|
||||||
if self.ascend_config.profiling_chunk_config.enabled:
|
if self.ascend_config.profiling_chunk_config.enabled:
|
||||||
self._sync_device()
|
self._sync_device()
|
||||||
self._execution_start_time = time.perf_counter()
|
self._execution_start_time = time.perf_counter()
|
||||||
@@ -299,7 +301,9 @@ class NPUARModelRunner(OmniNPUModelRunner):
|
|||||||
# TODO(Ronald1995): deepcopy is expensive when there is a large
|
# TODO(Ronald1995): deepcopy is expensive when there is a large
|
||||||
# number of requests, optimize it later.
|
# number of requests, optimize it later.
|
||||||
if ((
|
if ((
|
||||||
self.use_async_scheduling and self.num_spec_tokens and self._draft_token_ids is None # type: ignore[has-type]
|
self.use_async_scheduling
|
||||||
|
and self.num_spec_tokens
|
||||||
|
and self._draft_token_ids is None # type: ignore[has-type]
|
||||||
) or (
|
) or (
|
||||||
# NOTE: This branch specifically triggers a deepcopy during the prefill phase
|
# NOTE: This branch specifically triggers a deepcopy during the prefill phase
|
||||||
# only for PCP (Parallel Context Processing) + Multi-Modal (MM) scenarios.
|
# only for PCP (Parallel Context Processing) + Multi-Modal (MM) scenarios.
|
||||||
@@ -455,7 +459,7 @@ class NPUARModelRunner(OmniNPUModelRunner):
|
|||||||
if deferred_state_corrections_fn:
|
if deferred_state_corrections_fn:
|
||||||
deferred_state_corrections_fn()
|
deferred_state_corrections_fn()
|
||||||
deferred_state_corrections_fn = None
|
deferred_state_corrections_fn = None
|
||||||
mamba_utils.preprocess_mamba(
|
preprocess_mamba(
|
||||||
scheduler_output,
|
scheduler_output,
|
||||||
self.kv_cache_config,
|
self.kv_cache_config,
|
||||||
self.cache_config,
|
self.cache_config,
|
||||||
@@ -715,6 +719,15 @@ class NPUARModelRunner(OmniNPUModelRunner):
|
|||||||
# previous model forward without breaking async scheduling.
|
# previous model forward without breaking async scheduling.
|
||||||
if deferred_state_corrections_fn:
|
if deferred_state_corrections_fn:
|
||||||
deferred_state_corrections_fn()
|
deferred_state_corrections_fn()
|
||||||
|
|
||||||
|
if self.vllm_config.model_config.enable_return_routed_experts and hasattr(self, "_positions_cpu"):
|
||||||
|
issue_routing_d2h_copy(
|
||||||
|
input_batch_req_ids=self.input_batch.req_ids,
|
||||||
|
num_scheduled_tokens=scheduler_output.num_scheduled_tokens,
|
||||||
|
positions=self.positions,
|
||||||
|
positions_cpu=self._positions_cpu,
|
||||||
|
)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@torch.inference_mode()
|
@torch.inference_mode()
|
||||||
@@ -858,12 +871,17 @@ class NPUARModelRunner(OmniNPUModelRunner):
|
|||||||
if self.speculative_config is not None:
|
if self.speculative_config is not None:
|
||||||
self.finalize_kv_connector()
|
self.finalize_kv_connector()
|
||||||
|
|
||||||
|
routed_experts_dict = None
|
||||||
if self.model_config.enable_return_routed_experts:
|
if self.model_config.enable_return_routed_experts:
|
||||||
capturer = RoutedExpertsCapturer.get_instance()
|
capturer = get_global_experts_capturer()
|
||||||
if capturer is not None:
|
if capturer is not None and hasattr(self.input_batch, "num_tokens_no_spec"):
|
||||||
capturer.save_captured_experts(indices=self.cpu_slot_mapping)
|
routed_experts_dict = extract_routed_experts_for_current_batch(
|
||||||
else:
|
req_ids=req_ids_output_copy,
|
||||||
logger.warning("RoutedExpertsCapturer is not initialized.")
|
requests=self.requests,
|
||||||
|
req_id_to_index=self.input_batch.req_id_to_index,
|
||||||
|
num_tokens_no_spec=self.input_batch.num_tokens_no_spec,
|
||||||
|
max_model_len=self.max_model_len,
|
||||||
|
)
|
||||||
|
|
||||||
# -------------------------------------- Omni-new -------------------------------------------------
|
# -------------------------------------- Omni-new -------------------------------------------------
|
||||||
engine_output_type, downstream_req_ids = self._resolve_pooler_payload_req_ids(req_ids_output_copy)
|
engine_output_type, downstream_req_ids = self._resolve_pooler_payload_req_ids(req_ids_output_copy)
|
||||||
@@ -984,6 +1002,7 @@ class NPUARModelRunner(OmniNPUModelRunner):
|
|||||||
kv_connector_output=kv_connector_output,
|
kv_connector_output=kv_connector_output,
|
||||||
ec_connector_output=ec_connector_output if self.supports_mm_inputs else None,
|
ec_connector_output=ec_connector_output if self.supports_mm_inputs else None,
|
||||||
cudagraph_stats=cudagraph_stats,
|
cudagraph_stats=cudagraph_stats,
|
||||||
|
routed_experts_dict=routed_experts_dict,
|
||||||
)
|
)
|
||||||
model_runner_output.kv_extracted_req_ids = kv_extracted_req_ids
|
model_runner_output.kv_extracted_req_ids = kv_extracted_req_ids
|
||||||
# -------------------------------------- Omni-new -------------------------------------------------
|
# -------------------------------------- Omni-new -------------------------------------------------
|
||||||
|
|||||||
@@ -15,14 +15,18 @@ from vllm.distributed.ec_transfer import get_ec_transfer, has_ec_transfer
|
|||||||
from vllm.distributed.kv_transfer import get_kv_transfer_group, has_kv_transfer_group
|
from vllm.distributed.kv_transfer import get_kv_transfer_group, has_kv_transfer_group
|
||||||
from vllm.distributed.parallel_state import get_pp_group
|
from vllm.distributed.parallel_state import get_pp_group
|
||||||
from vllm.logger import logger
|
from vllm.logger import logger
|
||||||
from vllm.model_executor.layers.fused_moe.routed_experts_capturer import RoutedExpertsCapturer
|
from vllm.model_executor.layers.fused_moe.routed_experts_capturer import (
|
||||||
|
extract_routed_experts_for_current_batch,
|
||||||
|
get_global_experts_capturer,
|
||||||
|
issue_routing_d2h_copy,
|
||||||
|
)
|
||||||
from vllm.sequence import IntermediateTensors
|
from vllm.sequence import IntermediateTensors
|
||||||
from vllm.utils.math_utils import cdiv
|
from vllm.utils.math_utils import cdiv
|
||||||
from vllm.v1.core.sched.output import GrammarOutput, SchedulerOutput
|
from vllm.v1.core.sched.output import GrammarOutput, SchedulerOutput
|
||||||
from vllm.v1.outputs import EMPTY_MODEL_RUNNER_OUTPUT, AsyncModelRunnerOutput, make_empty_encoder_model_runner_output
|
from vllm.v1.outputs import EMPTY_MODEL_RUNNER_OUTPUT, AsyncModelRunnerOutput, make_empty_encoder_model_runner_output
|
||||||
from vllm.v1.utils import record_function_or_nullcontext
|
from vllm.v1.utils import record_function_or_nullcontext
|
||||||
from vllm.v1.worker import mamba_utils
|
|
||||||
from vllm.v1.worker.gpu_model_runner import AsyncGPUModelRunnerOutput, PerLayerAttnMetadata
|
from vllm.v1.worker.gpu_model_runner import AsyncGPUModelRunnerOutput, PerLayerAttnMetadata
|
||||||
|
from vllm.v1.worker.mamba_utils import preprocess_mamba
|
||||||
from vllm.v1.worker.ubatch_utils import maybe_create_ubatch_slices
|
from vllm.v1.worker.ubatch_utils import maybe_create_ubatch_slices
|
||||||
from vllm.v1.worker.utils import sanity_check_mm_encoder_outputs
|
from vllm.v1.worker.utils import sanity_check_mm_encoder_outputs
|
||||||
from vllm_ascend.ascend_forward_context import set_ascend_forward_context
|
from vllm_ascend.ascend_forward_context import set_ascend_forward_context
|
||||||
@@ -74,11 +78,9 @@ class NPUGenerationModelRunner(OmniNPUModelRunner):
|
|||||||
intermediate_tensors: IntermediateTensors | None = None,
|
intermediate_tensors: IntermediateTensors | None = None,
|
||||||
) -> OmniModelRunnerOutput | IntermediateTensors | None:
|
) -> OmniModelRunnerOutput | IntermediateTensors | None:
|
||||||
if self.vllm_config.model_config.enable_return_routed_experts:
|
if self.vllm_config.model_config.enable_return_routed_experts:
|
||||||
capturer = RoutedExpertsCapturer.get_instance()
|
capturer = get_global_experts_capturer()
|
||||||
if capturer is not None:
|
if capturer is not None and hasattr(capturer, "finalize_pending_copy"):
|
||||||
capturer.clear_buffer()
|
capturer.finalize_pending_copy()
|
||||||
else:
|
|
||||||
logger.warning("RoutedExpertsCapturer is not initialized.")
|
|
||||||
if self.ascend_config.profiling_chunk_config.enabled:
|
if self.ascend_config.profiling_chunk_config.enabled:
|
||||||
self._sync_device()
|
self._sync_device()
|
||||||
self._execution_start_time = time.perf_counter()
|
self._execution_start_time = time.perf_counter()
|
||||||
@@ -227,7 +229,7 @@ class NPUGenerationModelRunner(OmniNPUModelRunner):
|
|||||||
if deferred_state_corrections_fn:
|
if deferred_state_corrections_fn:
|
||||||
deferred_state_corrections_fn()
|
deferred_state_corrections_fn()
|
||||||
deferred_state_corrections_fn = None
|
deferred_state_corrections_fn = None
|
||||||
mamba_utils.preprocess_mamba(
|
preprocess_mamba(
|
||||||
scheduler_output,
|
scheduler_output,
|
||||||
self.kv_cache_config,
|
self.kv_cache_config,
|
||||||
self.cache_config,
|
self.cache_config,
|
||||||
@@ -383,6 +385,15 @@ class NPUGenerationModelRunner(OmniNPUModelRunner):
|
|||||||
# previous model forward without breaking async scheduling.
|
# previous model forward without breaking async scheduling.
|
||||||
if deferred_state_corrections_fn:
|
if deferred_state_corrections_fn:
|
||||||
deferred_state_corrections_fn()
|
deferred_state_corrections_fn()
|
||||||
|
|
||||||
|
if self.vllm_config.model_config.enable_return_routed_experts and hasattr(self, "_positions_cpu"):
|
||||||
|
issue_routing_d2h_copy(
|
||||||
|
input_batch_req_ids=self.input_batch.req_ids,
|
||||||
|
num_scheduled_tokens=scheduler_output.num_scheduled_tokens,
|
||||||
|
positions=self.positions,
|
||||||
|
positions_cpu=self._positions_cpu,
|
||||||
|
)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@torch.inference_mode()
|
@torch.inference_mode()
|
||||||
@@ -468,6 +479,17 @@ class NPUGenerationModelRunner(OmniNPUModelRunner):
|
|||||||
# [Omni] Copy req_id mappings to avoid async scheduling mutation.
|
# [Omni] Copy req_id mappings to avoid async scheduling mutation.
|
||||||
req_ids_output_copy = self.input_batch.req_ids.copy()
|
req_ids_output_copy = self.input_batch.req_ids.copy()
|
||||||
req_id_to_index_output_copy = self.input_batch.req_id_to_index.copy()
|
req_id_to_index_output_copy = self.input_batch.req_id_to_index.copy()
|
||||||
|
routed_experts_dict = None
|
||||||
|
if self.vllm_config.model_config.enable_return_routed_experts and hasattr(
|
||||||
|
self.input_batch, "num_tokens_no_spec"
|
||||||
|
):
|
||||||
|
routed_experts_dict = extract_routed_experts_for_current_batch(
|
||||||
|
req_ids=req_ids_output_copy,
|
||||||
|
requests=self.requests,
|
||||||
|
req_id_to_index=self.input_batch.req_id_to_index,
|
||||||
|
num_tokens_no_spec=self.input_batch.num_tokens_no_spec,
|
||||||
|
max_model_len=self.max_model_len,
|
||||||
|
)
|
||||||
output = OmniModelRunnerOutput(
|
output = OmniModelRunnerOutput(
|
||||||
req_ids=req_ids_output_copy,
|
req_ids=req_ids_output_copy,
|
||||||
req_id_to_index=req_id_to_index_output_copy,
|
req_id_to_index=req_id_to_index_output_copy,
|
||||||
@@ -478,6 +500,7 @@ class NPUGenerationModelRunner(OmniNPUModelRunner):
|
|||||||
kv_connector_output=kv_connector_output,
|
kv_connector_output=kv_connector_output,
|
||||||
ec_connector_output=ec_connector_output if self.supports_mm_inputs else None,
|
ec_connector_output=ec_connector_output if self.supports_mm_inputs else None,
|
||||||
cudagraph_stats=cudagraph_stats,
|
cudagraph_stats=cudagraph_stats,
|
||||||
|
routed_experts_dict=routed_experts_dict,
|
||||||
)
|
)
|
||||||
# -------------------------------------- Omni-new -------------------------------------------------
|
# -------------------------------------- Omni-new -------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ class OmniRequest(Request):
|
|||||||
client_index=request.client_index,
|
client_index=request.client_index,
|
||||||
prompt_token_ids=request.prompt_token_ids,
|
prompt_token_ids=request.prompt_token_ids,
|
||||||
prompt_embeds=request.prompt_embeds,
|
prompt_embeds=request.prompt_embeds,
|
||||||
|
prompt_is_token_ids=request.prompt_is_token_ids,
|
||||||
mm_features=request.mm_features,
|
mm_features=request.mm_features,
|
||||||
sampling_params=request.sampling_params,
|
sampling_params=request.sampling_params,
|
||||||
pooling_params=request.pooling_params,
|
pooling_params=request.pooling_params,
|
||||||
@@ -94,6 +95,8 @@ class OmniRequest(Request):
|
|||||||
additional_information=request.additional_information,
|
additional_information=request.additional_information,
|
||||||
resumable=request.resumable,
|
resumable=request.resumable,
|
||||||
reasoning_ended=request.reasoning_ended,
|
reasoning_ended=request.reasoning_ended,
|
||||||
|
reasoning_parser_kwargs=request.reasoning_parser_kwargs,
|
||||||
|
abort_immediately=request.abort_immediately,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ from vllm.distributed.parallel_state import get_pp_group, get_tp_group
|
|||||||
from vllm.forward_context import set_forward_context
|
from vllm.forward_context import set_forward_context
|
||||||
from vllm.logger import init_logger
|
from vllm.logger import init_logger
|
||||||
from vllm.model_executor.layers.fused_moe.routed_experts_capturer import (
|
from vllm.model_executor.layers.fused_moe.routed_experts_capturer import (
|
||||||
RoutedExpertsCapturer,
|
extract_routed_experts_for_current_batch,
|
||||||
|
get_global_experts_capturer,
|
||||||
|
issue_routing_d2h_copy,
|
||||||
)
|
)
|
||||||
from vllm.v1.core.sched.output import GrammarOutput, SchedulerOutput
|
from vllm.v1.core.sched.output import GrammarOutput, SchedulerOutput
|
||||||
from vllm.v1.outputs import AsyncModelRunnerOutput, make_empty_encoder_model_runner_output
|
from vllm.v1.outputs import AsyncModelRunnerOutput, make_empty_encoder_model_runner_output
|
||||||
@@ -28,6 +30,7 @@ from vllm.v1.spec_decode.dflash import DFlashProposer
|
|||||||
from vllm.v1.spec_decode.draft_model import DraftModelProposer
|
from vllm.v1.spec_decode.draft_model import DraftModelProposer
|
||||||
from vllm.v1.spec_decode.eagle import EagleProposer
|
from vllm.v1.spec_decode.eagle import EagleProposer
|
||||||
from vllm.v1.spec_decode.extract_hidden_states import ExtractHiddenStatesProposer
|
from vllm.v1.spec_decode.extract_hidden_states import ExtractHiddenStatesProposer
|
||||||
|
from vllm.v1.spec_decode.gemma4 import Gemma4Proposer
|
||||||
from vllm.v1.structured_output.utils import apply_grammar_bitmask
|
from vllm.v1.structured_output.utils import apply_grammar_bitmask
|
||||||
from vllm.v1.utils import record_function_or_nullcontext
|
from vllm.v1.utils import record_function_or_nullcontext
|
||||||
from vllm.v1.worker.gpu_model_runner import (
|
from vllm.v1.worker.gpu_model_runner import (
|
||||||
@@ -358,11 +361,21 @@ class GPUARModelRunner(OmniGPUModelRunner, OmniConnectorModelRunnerMixin):
|
|||||||
self.flush_full_payload_outputs(flush_ids)
|
self.flush_full_payload_outputs(flush_ids)
|
||||||
|
|
||||||
if self.routed_experts_initialized:
|
if self.routed_experts_initialized:
|
||||||
capturer = RoutedExpertsCapturer.get_instance()
|
capturer = get_global_experts_capturer()
|
||||||
if capturer is not None:
|
if capturer is not None and hasattr(capturer, "finalize_pending_copy"):
|
||||||
capturer.clear_buffer() # noqa
|
capturer.finalize_pending_copy()
|
||||||
else:
|
|
||||||
logger.error("RoutedExpertsCapturer not initialized.")
|
# If ngram_gpu is used, we need to copy the scheduler_output to avoid
|
||||||
|
# the modification has influence on the scheduler_output in engine core process.
|
||||||
|
# The replace is much faster than deepcopy.
|
||||||
|
if self.speculative_config is not None and self.speculative_config.use_ngram_gpu():
|
||||||
|
num_scheduled_tokens_copy = scheduler_output.num_scheduled_tokens.copy()
|
||||||
|
spec_decode_tokens_copy = scheduler_output.scheduled_spec_decode_tokens.copy()
|
||||||
|
scheduler_output = replace(
|
||||||
|
scheduler_output,
|
||||||
|
num_scheduled_tokens=num_scheduled_tokens_copy,
|
||||||
|
scheduled_spec_decode_tokens=spec_decode_tokens_copy,
|
||||||
|
)
|
||||||
|
|
||||||
if has_kv_transfer_group():
|
if has_kv_transfer_group():
|
||||||
kv_connector_metadata = scheduler_output.kv_connector_metadata
|
kv_connector_metadata = scheduler_output.kv_connector_metadata
|
||||||
@@ -678,6 +691,14 @@ class GPUARModelRunner(OmniGPUModelRunner, OmniConnectorModelRunnerMixin):
|
|||||||
if deferred_state_corrections_fn:
|
if deferred_state_corrections_fn:
|
||||||
deferred_state_corrections_fn()
|
deferred_state_corrections_fn()
|
||||||
|
|
||||||
|
if self.routed_experts_initialized and hasattr(self, "_positions_cpu"):
|
||||||
|
issue_routing_d2h_copy(
|
||||||
|
input_batch_req_ids=self.input_batch.req_ids,
|
||||||
|
num_scheduled_tokens=scheduler_output.num_scheduled_tokens,
|
||||||
|
positions=self.positions,
|
||||||
|
positions_cpu=self._positions_cpu,
|
||||||
|
)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def _sample(
|
def _sample(
|
||||||
@@ -829,7 +850,7 @@ class GPUARModelRunner(OmniGPUModelRunner, OmniConnectorModelRunnerMixin):
|
|||||||
if use_gpu_toks:
|
if use_gpu_toks:
|
||||||
assert isinstance(
|
assert isinstance(
|
||||||
self.drafter,
|
self.drafter,
|
||||||
EagleProposer | DFlashProposer | DraftModelProposer | ExtractHiddenStatesProposer,
|
EagleProposer | DFlashProposer | DraftModelProposer | ExtractHiddenStatesProposer | Gemma4Proposer,
|
||||||
)
|
)
|
||||||
sampled_token_ids = sampler_output.sampled_token_ids
|
sampled_token_ids = sampler_output.sampled_token_ids
|
||||||
if input_fits_in_drafter:
|
if input_fits_in_drafter:
|
||||||
@@ -1013,12 +1034,15 @@ class GPUARModelRunner(OmniGPUModelRunner, OmniConnectorModelRunnerMixin):
|
|||||||
self.accumulate_full_payload_output(rid, pooler_output[i], req_state)
|
self.accumulate_full_payload_output(rid, pooler_output[i], req_state)
|
||||||
|
|
||||||
with record_function_or_nullcontext("gpu_model_runner: ModelRunnerOutput"):
|
with record_function_or_nullcontext("gpu_model_runner: ModelRunnerOutput"):
|
||||||
|
routed_experts_dict = None
|
||||||
if self.routed_experts_initialized:
|
if self.routed_experts_initialized:
|
||||||
capturer = RoutedExpertsCapturer.get_instance()
|
routed_experts_dict = extract_routed_experts_for_current_batch(
|
||||||
if capturer is not None:
|
req_ids=req_ids_output_copy,
|
||||||
capturer.save_captured_experts(indices=self.slot_mapping) # noqa
|
requests=self.requests,
|
||||||
else:
|
req_id_to_index=self.input_batch.req_id_to_index,
|
||||||
logger.error("RoutedExpertsCapturer not initialized.")
|
num_tokens_no_spec=self.input_batch.num_tokens_no_spec,
|
||||||
|
max_model_len=self.max_model_len,
|
||||||
|
)
|
||||||
output = OmniModelRunnerOutput(
|
output = OmniModelRunnerOutput(
|
||||||
req_ids=req_ids_output_copy,
|
req_ids=req_ids_output_copy,
|
||||||
req_id_to_index=req_id_to_index_output_copy,
|
req_id_to_index=req_id_to_index_output_copy,
|
||||||
@@ -1030,6 +1054,7 @@ class GPUARModelRunner(OmniGPUModelRunner, OmniConnectorModelRunnerMixin):
|
|||||||
ec_connector_output=ec_connector_output if self.supports_mm_inputs else None,
|
ec_connector_output=ec_connector_output if self.supports_mm_inputs else None,
|
||||||
num_nans_in_logits=num_nans_in_logits,
|
num_nans_in_logits=num_nans_in_logits,
|
||||||
cudagraph_stats=cudagraph_stats,
|
cudagraph_stats=cudagraph_stats,
|
||||||
|
routed_experts_dict=routed_experts_dict,
|
||||||
)
|
)
|
||||||
output.kv_extracted_req_ids = kv_extracted_req_ids
|
output.kv_extracted_req_ids = kv_extracted_req_ids
|
||||||
output.omni_connector_output = self.get_omni_connector_output()
|
output.omni_connector_output = self.get_omni_connector_output()
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ from __future__ import annotations
|
|||||||
import gc
|
import gc
|
||||||
import logging
|
import logging
|
||||||
from copy import copy
|
from copy import copy
|
||||||
|
from dataclasses import replace
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import torch
|
import torch
|
||||||
@@ -18,7 +19,9 @@ from vllm.distributed.kv_transfer import get_kv_transfer_group, has_kv_transfer_
|
|||||||
from vllm.distributed.parallel_state import get_pp_group
|
from vllm.distributed.parallel_state import get_pp_group
|
||||||
from vllm.forward_context import set_forward_context
|
from vllm.forward_context import set_forward_context
|
||||||
from vllm.model_executor.layers.fused_moe.routed_experts_capturer import (
|
from vllm.model_executor.layers.fused_moe.routed_experts_capturer import (
|
||||||
RoutedExpertsCapturer,
|
extract_routed_experts_for_current_batch,
|
||||||
|
get_global_experts_capturer,
|
||||||
|
issue_routing_d2h_copy,
|
||||||
)
|
)
|
||||||
from vllm.utils.math_utils import cdiv
|
from vllm.utils.math_utils import cdiv
|
||||||
from vllm.v1.core.sched.output import GrammarOutput, SchedulerOutput
|
from vllm.v1.core.sched.output import GrammarOutput, SchedulerOutput
|
||||||
@@ -27,6 +30,7 @@ from vllm.v1.spec_decode.dflash import DFlashProposer
|
|||||||
from vllm.v1.spec_decode.draft_model import DraftModelProposer
|
from vllm.v1.spec_decode.draft_model import DraftModelProposer
|
||||||
from vllm.v1.spec_decode.eagle import EagleProposer
|
from vllm.v1.spec_decode.eagle import EagleProposer
|
||||||
from vllm.v1.spec_decode.extract_hidden_states import ExtractHiddenStatesProposer
|
from vllm.v1.spec_decode.extract_hidden_states import ExtractHiddenStatesProposer
|
||||||
|
from vllm.v1.spec_decode.gemma4 import Gemma4Proposer
|
||||||
from vllm.v1.utils import record_function_or_nullcontext
|
from vllm.v1.utils import record_function_or_nullcontext
|
||||||
from vllm.v1.worker.gpu_model_runner import (
|
from vllm.v1.worker.gpu_model_runner import (
|
||||||
EMPTY_MODEL_RUNNER_OUTPUT,
|
EMPTY_MODEL_RUNNER_OUTPUT,
|
||||||
@@ -111,11 +115,21 @@ class GPUGenerationModelRunner(OmniGPUModelRunner, OmniConnectorModelRunnerMixin
|
|||||||
self.flush_full_payload_outputs(flush_ids)
|
self.flush_full_payload_outputs(flush_ids)
|
||||||
|
|
||||||
if self.routed_experts_initialized:
|
if self.routed_experts_initialized:
|
||||||
capturer = RoutedExpertsCapturer.get_instance()
|
capturer = get_global_experts_capturer()
|
||||||
if capturer is not None:
|
if capturer is not None and hasattr(capturer, "finalize_pending_copy"):
|
||||||
capturer.clear_buffer() # noqa
|
capturer.finalize_pending_copy()
|
||||||
else:
|
|
||||||
logger.error("RoutedExpertsCapturer not initialized.")
|
# If ngram_gpu is used, we need to copy the scheduler_output to avoid
|
||||||
|
# the modification has influence on the scheduler_output in engine core process.
|
||||||
|
# The replace is much faster than deepcopy.
|
||||||
|
if self.speculative_config is not None and self.speculative_config.use_ngram_gpu():
|
||||||
|
num_scheduled_tokens_copy = scheduler_output.num_scheduled_tokens.copy()
|
||||||
|
spec_decode_tokens_copy = scheduler_output.scheduled_spec_decode_tokens.copy()
|
||||||
|
scheduler_output = replace(
|
||||||
|
scheduler_output,
|
||||||
|
num_scheduled_tokens=num_scheduled_tokens_copy,
|
||||||
|
scheduled_spec_decode_tokens=spec_decode_tokens_copy,
|
||||||
|
)
|
||||||
|
|
||||||
if has_kv_transfer_group():
|
if has_kv_transfer_group():
|
||||||
kv_connector_metadata = scheduler_output.kv_connector_metadata
|
kv_connector_metadata = scheduler_output.kv_connector_metadata
|
||||||
@@ -339,6 +353,14 @@ class GPUGenerationModelRunner(OmniGPUModelRunner, OmniConnectorModelRunnerMixin
|
|||||||
if deferred_state_corrections_fn:
|
if deferred_state_corrections_fn:
|
||||||
deferred_state_corrections_fn()
|
deferred_state_corrections_fn()
|
||||||
|
|
||||||
|
if self.routed_experts_initialized and hasattr(self, "_positions_cpu"):
|
||||||
|
issue_routing_d2h_copy(
|
||||||
|
input_batch_req_ids=self.input_batch.req_ids,
|
||||||
|
num_scheduled_tokens=scheduler_output.num_scheduled_tokens,
|
||||||
|
positions=self.positions,
|
||||||
|
positions_cpu=self._positions_cpu,
|
||||||
|
)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@torch.inference_mode()
|
@torch.inference_mode()
|
||||||
@@ -425,6 +447,15 @@ class GPUGenerationModelRunner(OmniGPUModelRunner, OmniConnectorModelRunnerMixin
|
|||||||
# [Omni] Copy req_id mappings to avoid async scheduling mutation.
|
# [Omni] Copy req_id mappings to avoid async scheduling mutation.
|
||||||
req_ids_output_copy = self.input_batch.req_ids.copy()
|
req_ids_output_copy = self.input_batch.req_ids.copy()
|
||||||
req_id_to_index_output_copy = self.input_batch.req_id_to_index.copy()
|
req_id_to_index_output_copy = self.input_batch.req_id_to_index.copy()
|
||||||
|
routed_experts_dict = None
|
||||||
|
if self.routed_experts_initialized:
|
||||||
|
routed_experts_dict = extract_routed_experts_for_current_batch(
|
||||||
|
req_ids=req_ids_output_copy,
|
||||||
|
requests=self.requests,
|
||||||
|
req_id_to_index=self.input_batch.req_id_to_index,
|
||||||
|
num_tokens_no_spec=self.input_batch.num_tokens_no_spec,
|
||||||
|
max_model_len=self.max_model_len,
|
||||||
|
)
|
||||||
if self._should_accumulate_full_payload_output():
|
if self._should_accumulate_full_payload_output():
|
||||||
for i, rid in enumerate(req_ids_output_copy):
|
for i, rid in enumerate(req_ids_output_copy):
|
||||||
req_state = self.requests.get(rid)
|
req_state = self.requests.get(rid)
|
||||||
@@ -442,6 +473,7 @@ class GPUGenerationModelRunner(OmniGPUModelRunner, OmniConnectorModelRunnerMixin
|
|||||||
num_nans_in_logits={},
|
num_nans_in_logits={},
|
||||||
cudagraph_stats=cudagraph_stats,
|
cudagraph_stats=cudagraph_stats,
|
||||||
ec_connector_output=ec_connector_output if self.supports_mm_inputs else None,
|
ec_connector_output=ec_connector_output if self.supports_mm_inputs else None,
|
||||||
|
routed_experts_dict=routed_experts_dict,
|
||||||
)
|
)
|
||||||
output.omni_connector_output = self.get_omni_connector_output()
|
output.omni_connector_output = self.get_omni_connector_output()
|
||||||
|
|
||||||
@@ -751,7 +783,7 @@ class GPUGenerationModelRunner(OmniGPUModelRunner, OmniConnectorModelRunnerMixin
|
|||||||
device=self.device,
|
device=self.device,
|
||||||
)
|
)
|
||||||
|
|
||||||
intermediate_tensors = self.sync_and_slice_intermediate_tensors(num_tokens_padded, None, False)
|
intermediate_tensors = self.sync_and_gather_intermediate_tensors(num_tokens_padded, None, False)
|
||||||
|
|
||||||
if ubatch_slices_padded is not None:
|
if ubatch_slices_padded is not None:
|
||||||
# Adjust values to reflect a single ubatch.
|
# Adjust values to reflect a single ubatch.
|
||||||
@@ -794,7 +826,7 @@ class GPUGenerationModelRunner(OmniGPUModelRunner, OmniConnectorModelRunnerMixin
|
|||||||
):
|
):
|
||||||
assert isinstance(
|
assert isinstance(
|
||||||
self.drafter,
|
self.drafter,
|
||||||
EagleProposer | DFlashProposer | DraftModelProposer | ExtractHiddenStatesProposer,
|
EagleProposer | DFlashProposer | DraftModelProposer | ExtractHiddenStatesProposer | Gemma4Proposer,
|
||||||
)
|
)
|
||||||
assert self.speculative_config is not None
|
assert self.speculative_config is not None
|
||||||
# Eagle currently only supports PIECEWISE cudagraphs.
|
# Eagle currently only supports PIECEWISE cudagraphs.
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import contextlib
|
import contextlib
|
||||||
|
from collections.abc import Callable
|
||||||
from typing import TYPE_CHECKING, Any, cast
|
from typing import TYPE_CHECKING, Any, cast
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
@@ -18,6 +19,11 @@ from vllm.v1.spec_decode.dflash import DFlashProposer
|
|||||||
from vllm.v1.spec_decode.draft_model import DraftModelProposer
|
from vllm.v1.spec_decode.draft_model import DraftModelProposer
|
||||||
from vllm.v1.spec_decode.eagle import EagleProposer
|
from vllm.v1.spec_decode.eagle import EagleProposer
|
||||||
from vllm.v1.spec_decode.extract_hidden_states import ExtractHiddenStatesProposer
|
from vllm.v1.spec_decode.extract_hidden_states import ExtractHiddenStatesProposer
|
||||||
|
from vllm.v1.spec_decode.gemma4 import Gemma4Proposer
|
||||||
|
from vllm.v1.spec_decode.ngram_proposer_gpu import (
|
||||||
|
update_ngram_gpu_tensors_incremental,
|
||||||
|
update_scheduler_for_invalid_drafts,
|
||||||
|
)
|
||||||
from vllm.v1.worker.gpu_input_batch import CachedRequestState
|
from vllm.v1.worker.gpu_input_batch import CachedRequestState
|
||||||
from vllm.v1.worker.gpu_model_runner import GPUModelRunner, IntermediateTensors, PerLayerAttnMetadata
|
from vllm.v1.worker.gpu_model_runner import GPUModelRunner, IntermediateTensors, PerLayerAttnMetadata
|
||||||
from vllm.v1.worker.ubatch_utils import maybe_create_ubatch_slices
|
from vllm.v1.worker.ubatch_utils import maybe_create_ubatch_slices
|
||||||
@@ -250,7 +256,7 @@ class OmniGPUModelRunner(GPUModelRunner):
|
|||||||
|
|
||||||
mrope_pos_ptr += completion_part_len
|
mrope_pos_ptr += completion_part_len
|
||||||
|
|
||||||
def _update_states(self, scheduler_output: "SchedulerOutput"):
|
def _update_states(self, scheduler_output: "SchedulerOutput") -> Callable | None:
|
||||||
"""Update the cached states and the persistent batch with the scheduler
|
"""Update the cached states and the persistent batch with the scheduler
|
||||||
output.
|
output.
|
||||||
|
|
||||||
@@ -284,8 +290,7 @@ class OmniGPUModelRunner(GPUModelRunner):
|
|||||||
if cleanup_finished_request is not None:
|
if cleanup_finished_request is not None:
|
||||||
cleanup_finished_request(req_id)
|
cleanup_finished_request(req_id)
|
||||||
|
|
||||||
if hasattr(self, "late_interaction_runner"):
|
self.late_interaction_runner.on_requests_finished(scheduler_output.finished_req_ids)
|
||||||
self.late_interaction_runner.on_requests_finished(scheduler_output.finished_req_ids)
|
|
||||||
# Remove the finished requests from the persistent batch.
|
# Remove the finished requests from the persistent batch.
|
||||||
# NOTE(woosuk): There could be an edge case where finished_req_ids and
|
# NOTE(woosuk): There could be an edge case where finished_req_ids and
|
||||||
# scheduled_req_ids overlap. This happens when a request is aborted and
|
# scheduled_req_ids overlap. This happens when a request is aborted and
|
||||||
@@ -326,8 +331,9 @@ class OmniGPUModelRunner(GPUModelRunner):
|
|||||||
for req_id in unscheduled_req_ids:
|
for req_id in unscheduled_req_ids:
|
||||||
self.input_batch.remove_request(req_id)
|
self.input_batch.remove_request(req_id)
|
||||||
|
|
||||||
if self.use_async_spec_decode:
|
is_ngram_gpu = self.speculative_config is not None and self.speculative_config.use_ngram_gpu()
|
||||||
self.prev_num_draft_tokens.np.fill(0)
|
if is_ngram_gpu:
|
||||||
|
ngram_gpu_new_reqs: list[CachedRequestState] = []
|
||||||
|
|
||||||
reqs_to_add: list[CachedRequestState] = []
|
reqs_to_add: list[CachedRequestState] = []
|
||||||
deferred_spec_decode_corrections = []
|
deferred_spec_decode_corrections = []
|
||||||
@@ -379,8 +385,7 @@ class OmniGPUModelRunner(GPUModelRunner):
|
|||||||
lora_request=new_req_data.lora_request,
|
lora_request=new_req_data.lora_request,
|
||||||
)
|
)
|
||||||
self.requests[req_id] = req_state
|
self.requests[req_id] = req_state
|
||||||
if hasattr(self, "late_interaction_runner"):
|
self.late_interaction_runner.register_request(req_id, pooling_params)
|
||||||
self.late_interaction_runner.register_request(req_id, pooling_params)
|
|
||||||
|
|
||||||
# If prompt embeddings are provided, decode and attach to inter_data
|
# If prompt embeddings are provided, decode and attach to inter_data
|
||||||
try:
|
try:
|
||||||
@@ -429,12 +434,30 @@ class OmniGPUModelRunner(GPUModelRunner):
|
|||||||
self._init_xdrope_positions(req_state)
|
self._init_xdrope_positions(req_state)
|
||||||
|
|
||||||
reqs_to_add.append(self.requests[req_id])
|
reqs_to_add.append(self.requests[req_id])
|
||||||
|
# Track new requests for ngram_gpu full tensor copy
|
||||||
|
if is_ngram_gpu:
|
||||||
|
ngram_gpu_new_reqs.append(req_state)
|
||||||
|
|
||||||
# Update the states of the running/resumed requests.
|
# Update the states of the running/resumed requests.
|
||||||
is_last_rank = get_pp_group().is_last_rank
|
is_last_rank = get_pp_group().is_last_rank
|
||||||
req_data = scheduler_output.scheduled_cached_reqs
|
req_data = scheduler_output.scheduled_cached_reqs
|
||||||
scheduled_spec_tokens = scheduler_output.scheduled_spec_decode_tokens
|
scheduled_spec_tokens = scheduler_output.scheduled_spec_decode_tokens
|
||||||
|
|
||||||
|
# Save scheduler-allocated spec lengths before trimming so
|
||||||
|
# prev_num_draft_len keeps the optimistic count for rejection correction.
|
||||||
|
original_num_spec_per_req: dict[str, int] = {}
|
||||||
|
if self.speculative_config is not None and self.speculative_config.use_ngram_gpu():
|
||||||
|
for req_id, toks in scheduled_spec_tokens.items():
|
||||||
|
original_num_spec_per_req[req_id] = len(toks)
|
||||||
|
update_scheduler_for_invalid_drafts(
|
||||||
|
self._num_valid_draft_tokens_event,
|
||||||
|
self._num_valid_draft_tokens_cpu,
|
||||||
|
scheduler_output,
|
||||||
|
self.input_batch.req_id_to_index,
|
||||||
|
)
|
||||||
|
if self.use_async_spec_decode:
|
||||||
|
self.prev_num_draft_tokens.np.fill(0)
|
||||||
|
|
||||||
for i, req_id in enumerate(req_data.req_ids):
|
for i, req_id in enumerate(req_data.req_ids):
|
||||||
req_state = self.requests[req_id]
|
req_state = self.requests[req_id]
|
||||||
num_computed_tokens = req_data.num_computed_tokens[i]
|
num_computed_tokens = req_data.num_computed_tokens[i]
|
||||||
@@ -473,6 +496,9 @@ class OmniGPUModelRunner(GPUModelRunner):
|
|||||||
if prev_req_index is not None:
|
if prev_req_index is not None:
|
||||||
self.prev_num_draft_tokens.np[prev_req_index] = optimistic_num_accepted
|
self.prev_num_draft_tokens.np[prev_req_index] = optimistic_num_accepted
|
||||||
|
|
||||||
|
if is_ngram_gpu and optimistic_num_accepted > 0:
|
||||||
|
self.input_batch.num_tokens_no_spec[req_index] += optimistic_num_accepted
|
||||||
|
|
||||||
# Update the cached states.
|
# Update the cached states.
|
||||||
req_state.num_computed_tokens = num_computed_tokens
|
req_state.num_computed_tokens = num_computed_tokens
|
||||||
|
|
||||||
@@ -521,6 +547,9 @@ class OmniGPUModelRunner(GPUModelRunner):
|
|||||||
req_state.output_token_ids = resumed_token_ids[-num_output_tokens:]
|
req_state.output_token_ids = resumed_token_ids[-num_output_tokens:]
|
||||||
|
|
||||||
reqs_to_add.append(req_state)
|
reqs_to_add.append(req_state)
|
||||||
|
# Track resumed requests for ngram_gpu full tensor copy
|
||||||
|
if is_ngram_gpu:
|
||||||
|
ngram_gpu_new_reqs.append(req_state)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Update the persistent batch.
|
# Update the persistent batch.
|
||||||
@@ -539,6 +568,11 @@ class OmniGPUModelRunner(GPUModelRunner):
|
|||||||
|
|
||||||
# Add spec_token_ids to token_ids_cpu.
|
# Add spec_token_ids to token_ids_cpu.
|
||||||
self.input_batch.update_req_spec_token_ids(req_state, scheduled_spec_tokens)
|
self.input_batch.update_req_spec_token_ids(req_state, scheduled_spec_tokens)
|
||||||
|
# Restore scheduler-side draft count after ngram trimming.
|
||||||
|
if original_num_spec_per_req:
|
||||||
|
orig = original_num_spec_per_req.get(req_id, 0)
|
||||||
|
if orig != req_state.prev_num_draft_len:
|
||||||
|
req_state.prev_num_draft_len = orig
|
||||||
|
|
||||||
# Add the new or resumed requests to the persistent batch.
|
# Add the new or resumed requests to the persistent batch.
|
||||||
# The smaller empty indices are filled first.
|
# The smaller empty indices are filled first.
|
||||||
@@ -553,6 +587,18 @@ class OmniGPUModelRunner(GPUModelRunner):
|
|||||||
# Refresh batch metadata with any pending updates.
|
# Refresh batch metadata with any pending updates.
|
||||||
self.input_batch.refresh_metadata()
|
self.input_batch.refresh_metadata()
|
||||||
|
|
||||||
|
# Incrementally update ngram_gpu tensors after batch is stable
|
||||||
|
if is_ngram_gpu:
|
||||||
|
update_ngram_gpu_tensors_incremental(
|
||||||
|
self.input_batch,
|
||||||
|
self.token_ids_gpu_tensor,
|
||||||
|
self.num_tokens_no_spec_gpu,
|
||||||
|
ngram_gpu_new_reqs,
|
||||||
|
self.device,
|
||||||
|
_pinned_idx_buf=self._ngram_pinned_idx_buf,
|
||||||
|
_pinned_val_buf=self._ngram_pinned_val_buf,
|
||||||
|
)
|
||||||
|
|
||||||
if deferred_spec_decode_corrections:
|
if deferred_spec_decode_corrections:
|
||||||
|
|
||||||
def correct_spec_decode_token_counts():
|
def correct_spec_decode_token_counts():
|
||||||
@@ -577,6 +623,9 @@ class OmniGPUModelRunner(GPUModelRunner):
|
|||||||
if cur_req_index is None:
|
if cur_req_index is None:
|
||||||
continue
|
continue
|
||||||
self.input_batch.num_computed_tokens_cpu[cur_req_index] -= correction
|
self.input_batch.num_computed_tokens_cpu[cur_req_index] -= correction
|
||||||
|
if is_ngram_gpu and correction > 0:
|
||||||
|
self.input_batch.num_tokens_no_spec[cur_req_index] -= correction
|
||||||
|
self.num_tokens_no_spec_gpu[cur_req_index] -= correction
|
||||||
|
|
||||||
return correct_spec_decode_token_counts
|
return correct_spec_decode_token_counts
|
||||||
else:
|
else:
|
||||||
@@ -846,7 +895,7 @@ class OmniGPUModelRunner(GPUModelRunner):
|
|||||||
device=self.device,
|
device=self.device,
|
||||||
)
|
)
|
||||||
|
|
||||||
intermediate_tensors = self.sync_and_slice_intermediate_tensors(num_tokens_padded, None, False)
|
intermediate_tensors = self.sync_and_gather_intermediate_tensors(num_tokens_padded, None, False)
|
||||||
|
|
||||||
if ubatch_slices_padded is not None:
|
if ubatch_slices_padded is not None:
|
||||||
# Adjust values to reflect a single ubatch.
|
# Adjust values to reflect a single ubatch.
|
||||||
@@ -900,7 +949,7 @@ class OmniGPUModelRunner(GPUModelRunner):
|
|||||||
):
|
):
|
||||||
assert isinstance(
|
assert isinstance(
|
||||||
self.drafter,
|
self.drafter,
|
||||||
EagleProposer | DFlashProposer | DraftModelProposer | ExtractHiddenStatesProposer,
|
EagleProposer | DFlashProposer | DraftModelProposer | ExtractHiddenStatesProposer | Gemma4Proposer,
|
||||||
)
|
)
|
||||||
assert self.speculative_config is not None
|
assert self.speculative_config is not None
|
||||||
# Eagle currently only supports PIECEWISE cudagraphs.
|
# Eagle currently only supports PIECEWISE cudagraphs.
|
||||||
@@ -1300,7 +1349,7 @@ class OmniGPUModelRunner(GPUModelRunner):
|
|||||||
intermediate_tensors = None
|
intermediate_tensors = None
|
||||||
else:
|
else:
|
||||||
assert intermediate_tensors is not None
|
assert intermediate_tensors is not None
|
||||||
intermediate_tensors = self.sync_and_slice_intermediate_tensors(
|
intermediate_tensors = self.sync_and_gather_intermediate_tensors(
|
||||||
num_input_tokens, intermediate_tensors, True
|
num_input_tokens, intermediate_tensors, True
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user