Fix transformers version

This commit is contained in:
Xin Wang
2026-08-27 15:24:59 +08:00
parent 694473b475
commit c4feeb47f4
5 changed files with 185 additions and 19 deletions
+34 -9
View File
@@ -26,6 +26,20 @@ from local_turn_features import (
)
TESTED_TRANSFORMERS_VERSIONS = ("4.52.3", "4.57.6")
def validate_local_transformers_version(version: str) -> str:
"""Keep the local encoder's tested API separate from the replay KV API."""
if version not in TESTED_TRANSFORMERS_VERSIONS:
supported = ", ".join(TESTED_TRANSFORMERS_VERSIONS)
raise RuntimeError(
f"Local encoder API is tested with transformers versions {supported}; found {version}. "
"Use a tested version or validate the encoder APIs before adding support."
)
return version
def model_config_digest(config: dict[str, Any]) -> str:
"""Ignore location fields so an explicitly identified checkpoint can move."""
def stable(value):
@@ -45,12 +59,13 @@ class FrozenQwenLocalEncoder:
import transformers
from transformers import Qwen2_5OmniProcessor, Qwen2_5OmniThinkerForConditionalGeneration
if transformers.__version__ != "4.52.3":
raise RuntimeError("Local encoder API is tested against transformers==4.52.3; use requirements.txt")
self.transformers_version = validate_local_transformers_version(transformers.__version__)
print(f"Local encoders: transformers={self.transformers_version}", flush=True)
self.device = torch.device(args.device)
if self.device.type == "cuda" and not torch.cuda.is_available():
raise RuntimeError(f"CUDA requested but unavailable: {args.device}")
kwargs = {"torch_dtype": getattr(torch, args.dtype), "device_map": {"": "cpu"},
dtype_key = "dtype" if self.transformers_version == "4.57.6" else "torch_dtype"
kwargs = {dtype_key: getattr(torch, args.dtype), "device_map": {"": "cpu"},
"output_loading_info": True}
if args.flash_attention_2:
kwargs["attn_implementation"] = "flash_attention_2"
@@ -70,7 +85,9 @@ class FrozenQwenLocalEncoder:
model.visual.to(self.device)
model.audio_tower.to(self.device)
self.model = model
self.processor = Qwen2_5OmniProcessor.from_pretrained(args.model_id)
# Keep PIL/slow image preprocessing consistent with the original B1
# definition, independently of newer Transformers' fast defaults.
self.processor = Qwen2_5OmniProcessor.from_pretrained(args.model_id, use_fast=False)
self.max_pixels = args.max_pixels
self.image_batch_size = args.image_batch_size
@@ -87,8 +104,9 @@ class FrozenQwenLocalEncoder:
tokens = self.model.get_image_features(pixels, grid)
merge = int(self.model.config.vision_config.spatial_merge_size)
counts = (grid.prod(-1) // (merge * merge)).tolist()
if tokens.ndim != 2 or tokens.shape != (sum(counts), self.visual_dim):
raise RuntimeError(f"Unexpected image encoder shape: {tuple(tokens.shape)}")
if not isinstance(tokens, torch.Tensor) or tokens.shape != (sum(counts), self.visual_dim):
raise RuntimeError(f"Unexpected image encoder output: {type(tokens).__name__}, "
f"shape={getattr(tokens, 'shape', None)}")
# Split BEFORE spatial mean: each person has one vote regardless of
# box size / number of visual tokens.
pieces.extend(part.float().mean(0).cpu() for part in tokens.split(counts))
@@ -108,8 +126,10 @@ class FrozenQwenLocalEncoder:
mask = batch["attention_mask"].to(self.device)
tokens = self.model.get_audio_features(features, feature_attention_mask=mask)
_, lengths = self.model.audio_tower._get_feat_extract_output_lengths(mask.sum(-1))
if tokens.ndim != 2 or tokens.shape != (int(lengths.sum()), self.audio_dim) or not len(tokens):
raise RuntimeError(f"Unexpected valid audio encoder shape: {tuple(tokens.shape)}")
if (not isinstance(tokens, torch.Tensor)
or tokens.shape != (int(lengths.sum()), self.audio_dim) or not len(tokens)):
raise RuntimeError(f"Unexpected valid audio encoder output: {type(tokens).__name__}, "
f"shape={getattr(tokens, 'shape', None)}")
# get_audio_features removes padding and verifies the output length.
return tokens.float().mean(0).cpu()
@@ -371,6 +391,11 @@ def parse_args(argv=None):
def main() -> None:
args = parse_args()
if not args.preview_only:
import transformers
# Fail before indexing/decoding source media, not after expensive I/O.
validate_local_transformers_version(transformers.__version__)
names = [normalize_sample_name(value, args.dataset) for value in args.samples]
if len(set(names)) != len(names):
raise ValueError("Duplicate samples")
@@ -417,7 +442,7 @@ def main() -> None:
"config": {
"encoder_id": args.encoder_id or args.model_id,
"model_config_sha256": encoder.model_config_sha256,
"transformers": "4.52.3", "dtype": args.dtype,
"transformers": encoder.transformers_version, "dtype": args.dtype,
"attention": "flash_attention_2" if args.flash_attention_2 else "default",
"visual_dim": encoder.visual_dim, "audio_dim": encoder.audio_dim,
"visual_fps": args.video_fps, "visual_window_seconds": args.visual_window_seconds,