| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 |
- # SPDX-License-Identifier: Apache-2.0
- # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
- from typing import Any
- import torch
- import torch.nn as nn
- from vllm.config import VllmConfig
- from vllm.triton_utils import tl, triton
- from vllm.v1.worker.gpu.input_batch import InputBatch
- from vllm.v1.worker.gpu.mm.encoder_cache import EncoderCache
- from vllm.v1.worker.gpu.model_states.default import DefaultModelState
- from vllm.v1.worker.gpu.states import RequestState
- @triton.jit
- def _gather_lookback_kernel(
- lookback_ptr,
- idx_mapping_ptr,
- num_computed_tokens_ptr,
- all_token_ids_ptr,
- all_token_ids_stride,
- num_reqs,
- DEPTH: tl.constexpr,
- BLOCK_DEPTH: tl.constexpr,
- ):
- # One program per lookback row; rows past the batch are filled with -1.
- batch_idx = tl.program_id(0)
- in_batch = batch_idx < num_reqs
- req_state_idx = tl.load(idx_mapping_ptr + batch_idx, mask=in_batch, other=0)
- num_computed = tl.load(num_computed_tokens_ptr + req_state_idx)
- offs = tl.arange(0, BLOCK_DEPTH)
- pos = num_computed - 1 - offs
- valid = in_batch & (offs < DEPTH) & (pos >= 0)
- ids = tl.load(
- all_token_ids_ptr + req_state_idx * all_token_ids_stride + pos,
- mask=valid,
- other=-1,
- )
- tl.store(lookback_ptr + batch_idx * DEPTH + offs, ids, mask=offs < DEPTH)
- class DeepseekV41ModelState(DefaultModelState):
- """DefaultModelState plus the engram lookback window.
- The engram n-gram hash needs the ids of the ``depth`` tokens preceding
- each request's chunk start (see ``common/engram.py``). The runner keeps
- the full token history on device, so the window is gathered there every
- step: exact for prompt and generated tokens alike, whatever instance
- produced their KV.
- """
- def __init__(
- self,
- vllm_config: VllmConfig,
- model: nn.Module,
- encoder_cache: EncoderCache | None,
- device: torch.device,
- ):
- super().__init__(vllm_config, model, encoder_cache, device)
- depth = model.token_lookback_depth
- self.lookback_token_ids: torch.Tensor | None = None
- if depth > 0:
- # Persistent so a captured graph can read it on replay.
- self.lookback_token_ids = torch.full(
- (self.max_num_reqs, depth), -1, dtype=torch.int32, device=device
- )
- def prepare_inputs(
- self, input_batch: InputBatch, req_states: RequestState
- ) -> dict[str, torch.Tensor | None]:
- model_inputs = super().prepare_inputs(input_batch, req_states)
- window = self.lookback_token_ids
- if window is None:
- return model_inputs
- all_token_ids = req_states.all_token_ids.gpu
- depth = window.shape[1]
- _gather_lookback_kernel[(window.shape[0],)](
- window,
- input_batch.idx_mapping,
- req_states.num_computed_tokens.gpu,
- all_token_ids,
- all_token_ids.stride(0),
- input_batch.idx_mapping.shape[0],
- DEPTH=depth,
- BLOCK_DEPTH=triton.next_power_of_2(depth),
- )
- model_inputs["lookback_token_ids"] = window
- return model_inputs
- def prepare_dummy_inputs(self, num_reqs: int, num_tokens: int) -> dict[str, Any]:
- model_inputs = super().prepare_dummy_inputs(num_reqs, num_tokens)
- if self.lookback_token_ids is not None:
- # The captured graph reads this buffer; replays refill it in place.
- self.lookback_token_ids.fill_(-1)
- model_inputs["lookback_token_ids"] = self.lookback_token_ids
- return model_inputs
|