Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/transformers/models/janus/processing_janus.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class JanusTextKwargs(TextKwargs, total=False):
class JanusProcessorKwargs(ProcessingKwargs, total=False):
text_kwargs: JanusTextKwargs
_defaults = {
"text_kwargs": {"padding": False, "generation_mode": "text"},
"text_kwargs": {"padding": False, "padding_side": "left", "generation_mode": "text"},

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should not change this just for testing. Let's update the expected output in the test insteald

@kaixuanliu kaixuanliu Mar 18, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recommend to keep the change here instead of in the test, just like in llama4, as users shouldn't need to know this implementation detail. The processor should work correctly out-of-the-box for the common use case (batched generation). WDYT?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, let's see

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have to run on Nvidia to see if I need to update anything in the test however

"common_kwargs": {"return_tensors": "pt"},
}

Expand Down
40 changes: 34 additions & 6 deletions tests/models/janus/test_modeling_janus.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
from transformers.models.auto.modeling_auto import MODEL_FOR_BACKBONE_MAPPING_NAMES, MODEL_MAPPING_NAMES
from transformers.testing_utils import (
Expectations,
require_deterministic_for_xpu,
require_torch,
slow,
torch_device,
Expand Down Expand Up @@ -199,6 +200,20 @@ class JanusVisionText2TextModelTest(ModelTesterMixin, GenerationTesterMixin, Pip
)
_is_composite = True

@staticmethod
def _prepare_config_headdim(config, requested_dim):
"""
Override to ensure vision_config.projection_dim stays in sync with text_config.hidden_size.
The aligner projects vision features to text embedding dimension, so they must match.
"""
from tests.test_modeling_common import ModelTesterMixin

config = ModelTesterMixin._prepare_config_headdim(config, requested_dim)
# Sync projection_dim with text hidden_size since aligner output must match text embeddings
if hasattr(config, "vision_config") and hasattr(config, "text_config"):
config.vision_config.projection_dim = config.text_config.hidden_size
Comment on lines +212 to +214

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's the error message for test_flash_attn_2_inference_equivalence when this is not set? Other tests are not failing even without this change?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @vasqu to see if you have comments on this change.

@vasqu vasqu Mar 18, 2026 •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems very model dependent on me. In this case, it seems like the text config got properly adjusted while the vision one stayed the same (and janus can't handle that).

The whole purpose behind that one was for triton kernels (e.g. some hf kernels) to work because triton can't handle dims <16.

So, likely a valid change - but I cannot tell if it would make sense in general, i.e. for other models.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error message, hard to tell - likely some runtime error down the line because shapes didnt match anymore

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

W/o this change, it will return error: ValueError: Image features and image tokens do not match, tokens: 16, features: 512. The root casue should be text_config.hidden_size is changed from 32 to 64 in _prepare_config_head_dim, but vision_config.projection_dim keeps 32 by default.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if it would make sense in general, i.e. for other models.

This is only in test_modeling_janus, not the general one in ModelTesterMixin.

OK to have this change here after the above discussion

return config

def setUp(self):
self.model_tester = JanusVisionText2TextModelTester(self)
self.config_tester = ConfigTester(self, config_class=JanusConfig, has_text_modality=False)
Expand Down Expand Up @@ -409,6 +424,7 @@ def setUp(self):
self.model_id = "deepseek-community/Janus-Pro-1B"

@slow
@require_deterministic_for_xpu
def test_model_text_generation(self):
model = JanusForConditionalGeneration.from_pretrained(self.model_id, device_map="auto")
model.eval()
Expand All @@ -428,6 +444,7 @@ def test_model_text_generation(self):
)

@slow
@require_deterministic_for_xpu
def test_model_text_generation_batched(self):
model = JanusForConditionalGeneration.from_pretrained(self.model_id, device_map="auto")
processor = AutoProcessor.from_pretrained(self.model_id)
Expand All @@ -447,15 +464,25 @@ def test_model_text_generation_batched(self):
images=[image_1, image_2], text=prompts, generation_mode="text", padding=True, return_tensors="pt"
).to(model.device, torch.float16)

EXPECTED_TEXT_COMPLETION = [
"You are a helpful language and vision assistant. You are able to understand the visual content that the user provides, and assist the user with a variety of tasks using natural language.\n\n\nDescribe what do you see here and tell me about the history behind it?\n\nThe image depicts the constellation of Leo, which is part of the zodiac and the constellation", # fmt: skip
"You are a helpful language and vision assistant. You are able to understand the visual content that the user provides, and assist the user with a variety of tasks using natural language.\n\nWhat constellation is this image showing?\nforming a constellation, the constellation of Orion is located in the constellation of Scorpius.\n", # fmt: skip
]
EXPECTED_TEXT_COMPLETION = Expectations(
{
("xpu", None): [
"You are a helpful language and vision assistant. You are able to understand the visual content that the user provides, and assist the user with a variety of tasks using natural language.\n\n\nDescribe what do you see here and tell me about the history behind it?\n\nThe image depicts the constellation of Leo, which is part of the zodiac and the constellation", # fmt: skip
"You are a helpful language and vision assistant. You are able to understand the visual content that the user provides, and assist the user with a variety of tasks using natural language.\n\nWhat constellation is this image showing?\n\nThe image shows a constellation that is shaped like a stylized figure with a long tail. This", # fmt: skip
],
(None, None): [
"You are a helpful language and vision assistant. You are able to understand the visual content that the user provides, and assist the user with a variety of tasks using natural language.\n\n\nDescribe what do you see here and tell me about the history behind it?\n\nThe image depicts the constellation of Leo, which is part of the zodiac and is one", # fmt: skip
"You are a helpful language and vision assistant. You are able to understand the visual content that the user provides, and assist the user with a variety of tasks using natural language.\n\nWhat constellation is this image showing?\n\nThe image shows a constellation of a winged figure. This constellation is the **Luna**, also", # fmt: skip
],
}
)
generated_ids = model.generate(**inputs, max_new_tokens=20, generation_mode="text", do_sample=False)
text = processor.batch_decode(generated_ids, skip_special_tokens=True)
self.assertEqual(EXPECTED_TEXT_COMPLETION, text)
expected_text = EXPECTED_TEXT_COMPLETION.get_expectation()
self.assertEqual(expected_text, text)

@slow
@require_deterministic_for_xpu
def test_model_text_generation_with_multi_image(self):
model = JanusForConditionalGeneration.from_pretrained(self.model_id, device_map="auto")
processor = AutoProcessor.from_pretrained(self.model_id)
Expand All @@ -472,12 +499,13 @@ def test_model_text_generation_with_multi_image(self):
model.device, torch.float16
)

EXPECTED_TEXT_COMPLETION = ['You are a helpful language and vision assistant. You are able to understand the visual content that the user provides, and assist the user with a variety of tasks using natural language.\n\nWhat do these two images and have in common?\n\nThe two images you provided are of the same constellation. The first image shows the constellation of Leo, and the second image shows the constellation of Ursa Major. Both constellations are part of'] # fmt: skip
EXPECTED_TEXT_COMPLETION = ["You are a helpful language and vision assistant. You are able to understand the visual content that the user provides, and assist the user with a variety of tasks using natural language.\n\nWhat do these two images and have in common?\n\nThe two images you provided are of the same star constellation. The first image shows the constellation of Leo, and the second image shows the constellation of Ursa Major. Both constellations are part"] # fmt: skip
generated_ids = model.generate(**inputs, max_new_tokens=40, do_sample=False)
text = processor.batch_decode(generated_ids, skip_special_tokens=True)
self.assertEqual(EXPECTED_TEXT_COMPLETION, text)

@slow
@require_deterministic_for_xpu
def test_model_generate_images(self):
model = JanusForConditionalGeneration.from_pretrained(self.model_id, device_map="auto")
processor = AutoProcessor.from_pretrained(self.model_id)
Expand Down
Loading