Skip to content

Commit a8c0505

Browse files
hmellorclaude
andcommitted
Move aux hidden state layer 0 support to vllm-project#66546
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Harry Mellor <19981378+hmellor@users.noreply.github.com>
1 parent 5fc1391 commit a8c0505

4 files changed

Lines changed: 2 additions & 62 deletions

File tree

‎tests/v1/kv_connector/extract_hidden_states_integration/test_extraction.py‎

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -358,41 +358,3 @@ def test_extract_hidden_states_tp2():
358358
len(layer_ids),
359359
hidden_size,
360360
)
361-
362-
363-
@pytest.mark.parametrize("model_impl", ["vllm", "transformers"])
364-
@create_new_process_for_each_test()
365-
def test_extract_layer_zero_is_input_embeddings(tmp_path, model_impl):
366-
"""Layer 0 is the input to the first decoder layer, i.e. the input embeddings."""
367-
from transformers import AutoModelForCausalLM
368-
369-
model = "meta-llama/Llama-3.2-1B-Instruct"
370-
llm = LLM(
371-
model=model,
372-
model_impl=model_impl,
373-
speculative_config={
374-
"method": "extract_hidden_states",
375-
"num_speculative_tokens": 1,
376-
"draft_model_config": {
377-
"hf_config": {"eagle_aux_hidden_state_layer_ids": [0, 1]}
378-
},
379-
},
380-
kv_transfer_config={
381-
"kv_connector": "ExampleHiddenStatesConnector",
382-
"kv_role": "kv_producer",
383-
"kv_connector_extra_config": {"shared_storage_path": str(tmp_path)},
384-
},
385-
max_model_len=256,
386-
enforce_eager=True,
387-
gpu_memory_utilization=0.4,
388-
)
389-
hidden_size = llm.llm_engine.model_config.get_hidden_size()
390-
sampling_params = SamplingParams(max_tokens=1, temperature=0.0)
391-
output = llm.generate(["Hello world"], sampling_params)[0]
392-
expected_shape = (len(output.prompt_token_ids), 2, hidden_size)
393-
token_ids, hidden_states = get_and_check_output(output, expected_shape)
394-
395-
hf_model = AutoModelForCausalLM.from_pretrained(model, dtype=hidden_states.dtype)
396-
with torch.no_grad():
397-
embeddings = hf_model.get_input_embeddings()(token_ids)
398-
torch.testing.assert_close(hidden_states[:, 0, :], embeddings)

‎vllm/model_executor/models/interfaces.py‎

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1658,11 +1658,7 @@ def _maybe_add_hidden_state(
16581658
residual: torch.Tensor | None,
16591659
) -> list[torch.Tensor]:
16601660
if layer_idx in self.aux_hidden_state_layers:
1661-
if residual is None:
1662-
# The first layer updates its residual (the embeddings) in place
1663-
value = hidden_states.clone()
1664-
else:
1665-
value = hidden_states + residual
1661+
value = hidden_states + residual if residual is not None else hidden_states
16661662
aux_hidden_states.append(value)
16671663
return aux_hidden_states
16681664

‎vllm/model_executor/models/transformers/base.py‎

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,6 @@ def __init__(self, *, vllm_config: "VllmConfig", prefix: str = ""):
160160
"""Mapping from layer index to layer name for Eagle3."""
161161
self._output_aux_hidden_states_kwargs: dict[str, bool] = {}
162162
"""Kwargs to pass to model forward for Eagle3 aux hidden states."""
163-
self._aux_embeddings = False
164-
"""Whether layer 0 (the input embeddings) is an Eagle3 aux hidden state."""
165163

166164
if self.quant_config:
167165
quant_method_name = self.quant_config.get_name()
@@ -804,13 +802,6 @@ def forward(
804802
if input_ids is not None and inputs_embeds is not None:
805803
input_ids = None
806804

807-
aux_embeddings = None
808-
if self._aux_embeddings:
809-
if inputs_embeds is None:
810-
inputs_embeds = self.embed_input_ids(input_ids)
811-
input_ids = None
812-
aux_embeddings = inputs_embeds[0, ...]
813-
814805
outputs = self.model(
815806
input_ids=input_ids,
816807
inputs_embeds=inputs_embeds,
@@ -823,16 +814,13 @@ def forward(
823814

824815
# Remove batch dimension after exiting Transformers model
825816
hidden_states = outputs[0][0, ...]
826-
aux_hidden_states = []
827817
if self._output_aux_hidden_states_kwargs:
828818
aux_hidden_states = [x[0][0, ...] for x in outputs[1:]]
829-
if aux_embeddings is not None:
830-
aux_hidden_states.insert(0, aux_embeddings)
831819

832820
if not self.pp_group.is_last_rank:
833821
return IntermediateTensors({"hidden_states": hidden_states})
834822

835-
if aux_hidden_states:
823+
if self._output_aux_hidden_states_kwargs and len(aux_hidden_states) > 0:
836824
return hidden_states, aux_hidden_states
837825
return hidden_states
838826

@@ -865,11 +853,7 @@ def set_aux_hidden_state_layers(self, layers: tuple[int, ...]) -> None:
865853
self.model._can_record_outputs = {}
866854

867855
target_class = self._target_class
868-
# The input to layer 0 is captured in `forward`
869-
self._aux_embeddings = 0 in layers
870856
for layer in layers:
871-
if layer == 0:
872-
continue
873857
# layer - 1 because we want the input to the layer
874858
layer_name = self._layer_names[layer - 1]
875859
layer_key = f"aux_hidden_state_{layer}"

‎vllm/v1/worker/gpu/spec_decode/extract_hidden_states_config.py‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@ def configure(cls, spec: "SpeculativeConfig") -> None:
3737
hf_config = {}
3838

3939
spec.draft_model_config = copy.copy(spec.target_model_config)
40-
# The target's `model_impl` doesn't apply to the vLLM-only draft model
41-
spec.draft_model_config.model_impl = "auto"
4240
spec.draft_model_config.hf_config = ExtractHiddenStatesConfig(
4341
spec.draft_model_config.hf_config, **hf_config
4442
)

0 commit comments

Comments
 (0)