Repository navigation
[Bugfix][Multimodal] Fix DeepSeek-OCR zero-sum patch guard in _encode… #64091
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
DarkLight1337
merged 5 commits into
vllm-project:main
from
nrenvo:fix/deepseek-ocr-zero-sum-patches
Oct 28, 2026
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
91c7398
[Bugfix][Multimodal] Fix DeepSeek-OCR zero-sum patch guard in _encode…
nrenvo e74ecc9
[Test][Multimodal] Move DeepSeek-OCR guard tests to generation directory
nrenvo eaad20d
Merge branch 'main' into fix/deepseek-ocr-zero-sum-patches
vllm-agent 12b8e37
[Test][Multimodal] Move DeepSeek-OCR guard tests to generation directory
nrenvo 7a6f22c
Merge branch 'main' into fix/deepseek-ocr-zero-sum-patches
vllm-agent File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| # SPDX-FileCopyrightText: Copyright contributors to the vLLM project | ||
| """Guard tests for DeepSeek-OCR _encode_local_features. | ||
|
|
||
| _encode_local_features must skip processing only for an empty-element | ||
| patches tensor, not for a zero-sum one. | ||
|
|
||
| Regression for #64075: the old guard ``torch.sum(patches).item() == 0`` | ||
| returned None for a 1536x768 half-white/half-black image whose two | ||
| normalised crop patches cancel to sum==0, causing a shape mismatch in | ||
| _merge_multimodal_embeddings and a fatal EngineCore crash. | ||
|
|
||
| The correct guard is ``patches.numel() == 0``. | ||
| """ | ||
|
|
||
| import pytest | ||
| import torch | ||
|
|
||
| from vllm.model_executor.models.deepseek_ocr import DeepseekOCRForCausalLM | ||
| from vllm.model_executor.models.deepseek_ocr2 import DeepseekOCR2ForCausalLM | ||
|
|
||
|
|
||
| class TestDeepseekOCREncodeLocalFeaturesGuard: | ||
| def test_ocr2_empty_patches_returns_none(self): | ||
| """Zero-element tensor → skip local encoding (non-tiled image).""" | ||
| empty = torch.empty(0, 3, 224, 224) | ||
| assert DeepseekOCR2ForCausalLM._encode_local_features(None, empty) is None | ||
|
|
||
| def test_ocr2_zero_sum_patches_enters_model_body(self): | ||
| """Non-empty patches that happen to sum to zero must NOT return None. | ||
|
|
||
| The method will raise AttributeError when it tries to call | ||
| self.sam_model on a None self – that is the expected outcome here | ||
| because it proves the guard was passed, not that encoding succeeded. | ||
| The real crash was a shape-mismatch ValueError that killed EngineCore. | ||
| """ | ||
| # Two patches that cancel: white (1.0) + black (-1.0) after Normalize. | ||
| wb = torch.cat([torch.ones(1, 3, 4, 4), -torch.ones(1, 3, 4, 4)]) | ||
| assert wb.numel() > 0 | ||
| assert wb.sum().item() == 0.0 | ||
| with pytest.raises(AttributeError): | ||
| DeepseekOCR2ForCausalLM._encode_local_features(None, wb) | ||
|
|
||
| def test_ocr1_empty_patches_returns_none(self): | ||
| """OCR-1: zero-element tensor → skip local encoding.""" | ||
| empty = torch.empty(0, 3, 224, 224) | ||
| crop_shape = torch.tensor([0, 0]) | ||
| assert ( | ||
| DeepseekOCRForCausalLM._encode_local_features(None, empty, crop_shape) | ||
| is None | ||
| ) | ||
|
|
||
| def test_ocr1_zero_sum_patches_enters_model_body(self): | ||
| """OCR-1: non-empty zero-sum patches must pass the guard.""" | ||
| wb = torch.cat([torch.ones(1, 3, 4, 4), -torch.ones(1, 3, 4, 4)]) | ||
| crop_shape = torch.tensor([1, 2]) | ||
| with pytest.raises(AttributeError): | ||
| DeepseekOCRForCausalLM._encode_local_features(None, wb, crop_shape) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.