Skip to content

fix(multimodal): handle BaseModelOutputWithPooling return type in CLIPScore for transformers >= 5.0 - #3428

Open
rityagodala wants to merge 2 commits into
Lightning-AI:masterfrom
rityagodala:fix/clip-score-transformers-5
Open

fix(multimodal): handle BaseModelOutputWithPooling return type in CLIPScore for transformers >= 5.0#3428
rityagodala wants to merge 2 commits into
Lightning-AI:masterfrom
rityagodala:fix/clip-score-transformers-5

Conversation

@rityagodala

Copy link
Copy Markdown

Summary

CLIPScore crashes with AttributeError: 'BaseModelOutputWithPooling' object has no attribute 'norm' when used with transformers >= 5.0.

Root cause: In transformers >= 5.0, CLIPModel.get_image_features and get_text_features now return BaseModelOutputWithPooling rather than a raw tensor. The code in _get_features passed this object directly to the caller, where .norm(p=2, dim=-1, keepdim=True) was called on it — causing the crash.

Changes

  • src/torchmetrics/functional/multimodal/clip_score.py: In _get_features, after calling get_image_features / get_text_features, check isinstance(features, Tensor). If the return value is a BaseModelOutputWithPooling (transformers ≥ 5.0), extract .pooler_output — the projected embedding tensor — before returning. Both old and new transformers versions are handled transparently.

Repro (before fix)

import torch
from torchmetrics.multimodal.clip_score import CLIPScore

metric = CLIPScore(model_name_or_path="openai/clip-vit-base-patch16")
image = torch.randint(255, (3, 224, 224), generator=torch.Generator().manual_seed(42))
score = metric(image, "a photo of a cat")
# Before: AttributeError: 'BaseModelOutputWithPooling' object has no attribute 'norm'
# After:  tensor(24.)

Fixes #3407

…>= 5.0 in CLIPScore

In transformers >= 5.0, `CLIPModel.get_image_features` and `get_text_features`
return `BaseModelOutputWithPooling` instead of a raw tensor. This caused
`CLIPScore` to crash with:

    AttributeError: 'BaseModelOutputWithPooling' object has no attribute 'norm'

Fix: unwrap the output in `_get_features` when it is not already a `Tensor`,
extracting `.pooler_output` which contains the projected embedding.

Fixes Lightning-AI#3407

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Fixes CLIPScore compatibility with transformers >= 5.0, where CLIPModel.get_image_features() / get_text_features() can return a BaseModelOutputWithPooling object instead of a raw embedding tensor, leading to runtime failures during feature normalization.

Changes:

  • Unwrap get_image_features return values by extracting .pooler_output when the returned value is not a Tensor.
  • Unwrap get_text_features return values by extracting .pooler_output when the returned value is not a Tensor.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +134 to +136
# transformers >= 5.0 changed get_image_features / get_text_features to return
# BaseModelOutputWithPooling instead of a raw tensor; unwrap when needed.
return image_features if isinstance(image_features, Tensor) else image_features.pooler_output
Comment on lines +133 to +136
image_features = model.get_image_features(processed["pixel_values"].to(device))
# transformers >= 5.0 changed get_image_features / get_text_features to return
# BaseModelOutputWithPooling instead of a raw tensor; unwrap when needed.
return image_features if isinstance(image_features, Tensor) else image_features.pooler_output
Comment on lines +150 to +155
text_features = model.get_text_features(
processed["input_ids"].to(device), processed["attention_mask"].to(device)
)
# transformers >= 5.0 changed get_image_features / get_text_features to return
# BaseModelOutputWithPooling instead of a raw tensor; unwrap when needed.
return text_features if isinstance(text_features, Tensor) else text_features.pooler_output
@codecov-commenter

codecov-commenter commented Jul 15, 2026

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 0% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 31%. Comparing base (d184220) to head (c6ec65d).
⚠️ Report is 8 commits behind head on master.
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

❗ There is a different number of reports uploaded between BASE (d184220) and HEAD (c6ec65d). Click for more details.

HEAD has 784 uploads less than BASE
Flag BASE (d184220) HEAD (c6ec65d)
torch2.0.1+cpu 20 2
python3.10 129 13
Windows 30 3
cpu 218 22
torch2.9.1 9 1
macOS 39 4
python3.12 89 9
torch2.9.1+cpu 30 3
torch2.8.0+cpu 30 3
torch2.8.0 10 1
Linux 149 15
torch2.10.0 10 1
torch2.7.1+cpu 20 2
torch2.10.0+cpu 20 2
torch2.4.1+cpu 10 1
torch2.2.2+cpu 10 1
torch2.1.2+cpu 10 1
torch2.5.1+cpu 10 1
torch2.0.1 10 1
torch2.3.1+cpu 9 1
torch2.6.0+cpu 10 1
Additional details and impacted files
@@           Coverage Diff            @@
##           master   #3428     +/-   ##
========================================
- Coverage      37%     31%     -5%     
========================================
  Files         349     349             
  Lines       19901   19907      +6     
========================================
- Hits         7264    6250   -1014     
- Misses      12637   13657   +1020     
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CLIPScore fails with transformers >= 5.0 — get_image_features/get_text_features returns BaseModelOutputWithPooling instead of a tensor

3 participants