main
py 143 lines 4.94 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3 """Model-runner state for Qwen4Exp PLE inputs."""
4
5 from typing import Any
6
7 import torch
8 import torch.nn as nn
9
10 from vllm.config import VllmConfig
11 from vllm.v1.worker.gpu.input_batch import InputBatch
12 from vllm.v1.worker.gpu.mm.encoder_cache import EncoderCache
13 from vllm.v1.worker.gpu.model_states.mamba_hybrid import MambaHybridModelState
14 from vllm.v1.worker.gpu.states import RequestState
15
16
17 class Qwen4ExpModelState(MambaHybridModelState):
18 """Add rollback-safe PLE n-gram context to the model inputs."""
19
20 def __init__(
21 self,
22 vllm_config: VllmConfig,
23 model: nn.Module,
24 encoder_cache: EncoderCache | None,
25 device: torch.device,
26 ) -> None:
27 super().__init__(vllm_config, model, encoder_cache, device)
28 config = self.model_config.hf_text_config
29 self.uses_ngram_embedding = bool(config.ple_layer_ids)
30 if not self.uses_ngram_embedding:
31 self.ngram_context_len = 0
32 self.ngram_eos_token_id = 0
33 return
34
35 if vllm_config.parallel_config.pipeline_parallel_size > 1:
36 raise RuntimeError(
37 "N-gram PLE embedding currently requires "
38 "pipeline_parallel_size=1 because non-first pipeline ranks do "
39 "not receive the raw input_ids required by PLE. Please run "
40 "with PP=1."
41 )
42
43 self.ngram_context_len = int(config.ngram_size) - 1
44 if self.ngram_context_len <= 0:
45 raise ValueError("N-gram embedding requires context length >= 1.")
46 self.ngram_eos_token_id = int(config.eos_token_id)
47 self.ngram_context = torch.full(
48 (self.max_num_reqs, self.ngram_context_len),
49 self.ngram_eos_token_id,
50 dtype=torch.int32,
51 device=self.device,
52 )
53 self.ngram_context_offsets = torch.arange(
54 -self.ngram_context_len,
55 0,
56 dtype=torch.int64,
57 device=self.device,
58 )
59 self.ple_query_start_loc = torch.zeros(
60 self.max_num_reqs + 1,
61 dtype=torch.int32,
62 device=self.device,
63 )
64
65 def _prepare_ngram_context(
66 self,
67 input_batch: InputBatch,
68 req_states: RequestState,
69 ) -> torch.Tensor:
70 num_reqs = input_batch.num_reqs
71 num_reqs_padded = input_batch.num_reqs_after_padding
72 context = self.ngram_context[:num_reqs_padded]
73 context.fill_(self.ngram_eos_token_id)
74 if num_reqs == 0:
75 return context
76
77 request_indices = input_batch.idx_mapping[:num_reqs].long()
78 context_end = req_states.num_computed_tokens.gpu[request_indices].long()
79 token_indices = context_end.unsqueeze(1) + self.ngram_context_offsets
80 valid_tokens = token_indices >= 0
81 token_indices.clamp_min_(0)
82 context_tokens = req_states.all_token_ids.gpu[
83 request_indices.unsqueeze(1), token_indices
84 ]
85 context[:num_reqs].copy_(
86 torch.where(
87 valid_tokens,
88 context_tokens,
89 context_tokens.new_full((), self.ngram_eos_token_id),
90 )
91 )
92 return context
93
94 def prepare_inputs(
95 self,
96 input_batch: InputBatch,
97 req_states: RequestState,
98 ) -> dict[str, Any]:
99 model_inputs = super().prepare_inputs(input_batch, req_states)
100 if not self.uses_ngram_embedding:
101 return model_inputs
102
103 num_reqs_padded = input_batch.num_reqs_after_padding
104 query_start_loc = self.ple_query_start_loc[: num_reqs_padded + 1]
105 query_start_loc.copy_(input_batch.query_start_loc[: num_reqs_padded + 1])
106 model_inputs.update(
107 query_start_loc=query_start_loc,
108 ngram_context=self._prepare_ngram_context(input_batch, req_states),
109 )
110 return model_inputs
111
112 def prepare_dummy_inputs(
113 self,
114 num_reqs: int,
115 num_tokens: int,
116 ) -> dict[str, Any]:
117 model_inputs = super().prepare_dummy_inputs(num_reqs, num_tokens)
118 if not self.uses_ngram_embedding:
119 return model_inputs
120
121 query_start_loc = self.ple_query_start_loc[: num_reqs + 1]
122 query_start_loc[0] = 0
123 tokens_per_req, num_extra_tokens = divmod(num_tokens, num_reqs)
124 query_lens = torch.full(
125 (num_reqs,),
126 tokens_per_req,
127 dtype=query_start_loc.dtype,
128 device=query_start_loc.device,
129 )
130 if num_extra_tokens > 0:
131 query_lens[-num_extra_tokens:] += 1
132 torch.cumsum(query_lens, dim=0, out=query_start_loc[1:])
133
134 ngram_context = self.ngram_context[:num_reqs]
135 ngram_context.fill_(self.ngram_eos_token_id)
136 model_inputs.update(
137 query_start_loc=query_start_loc,
138 ngram_context=ngram_context,
139 )
140 return model_inputs
141
142
143 __all__ = ["Qwen4ExpModelState"]