fix(multimodal): handle BaseModelOutputWithPooling return type in CLIPScore for transformers >= 5.0 - #3428
Conversation
…>= 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
for more information, see https://pre-commit.ci
There was a problem hiding this comment.
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_featuresreturn values by extracting.pooler_outputwhen the returned value is not aTensor. - Unwrap
get_text_featuresreturn values by extracting.pooler_outputwhen the returned value is not aTensor.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # 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 |
| 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 |
| 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 Report❌ Patch coverage is
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:
|
Summary
CLIPScorecrashes withAttributeError: 'BaseModelOutputWithPooling' object has no attribute 'norm'when used withtransformers >= 5.0.Root cause: In transformers >= 5.0,
CLIPModel.get_image_featuresandget_text_featuresnow returnBaseModelOutputWithPoolingrather than a raw tensor. The code in_get_featurespassed 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 callingget_image_features/get_text_features, checkisinstance(features, Tensor). If the return value is aBaseModelOutputWithPooling(transformers ≥ 5.0), extract.pooler_output— the projected embedding tensor — before returning. Both old and new transformers versions are handled transparently.Repro (before fix)
Fixes #3407