Files
2026-05-16 14:47:37 -07:00

169 lines
5.7 KiB
Python

"""Compatibility shims so the vendored GLM-ASR code runs on
fastvideo's pinned ``transformers==4.57.3``.
The vendored code was extracted from ``transformers==5.8.0``. Five
symbols it imports do not exist in 4.57.3:
- ``PreTrainedConfig`` (renamed in 5.x; was ``PretrainedConfig``).
- ``utils.generic.maybe_autocast`` — autocast context helper.
- ``utils.generic.merge_with_config_defaults`` — config-default decorator.
- ``integrations.use_kernelized_func`` — kernel-dispatch decorator.
- ``utils.output_capturing.capture_outputs`` — hook-based outputs decorator.
The first three we vendor so semantics match 5.x. The last two are
optimization / introspection helpers — stubbing them as identity
decorators keeps the standard forward path intact, and our ASR caller
(``model.generate``) never opts into the captured outputs anyway.
"""
from __future__ import annotations
from contextlib import nullcontext
from dataclasses import MISSING, fields
from functools import wraps
from typing import Any
import torch
from transformers.configuration_utils import PretrainedConfig
# 5.x renamed the base config class. Alias keeps the vendored config
# files unchanged.
PreTrainedConfig = PretrainedConfig
def maybe_autocast(
device_type: str,
dtype: torch.dtype | None = None,
enabled: bool = True,
cache_enabled: bool | None = None,
) -> Any:
"""Vendored from ``transformers.utils.generic`` (5.x).
Only autocasts if autocast is already enabled for this device, or
if the caller passed ``enabled=True``. Avoids spurious autocast
context insertion under ``torch.compile``.
"""
if device_type == "meta":
return nullcontext()
if torch.is_autocast_enabled(device_type) or enabled:
return torch.autocast(device_type, dtype=dtype, enabled=enabled, cache_enabled=cache_enabled)
return nullcontext()
def merge_with_config_defaults(func: Any) -> Any:
"""Vendored from ``transformers.utils.generic`` (5.x).
Decorator: for a small allow-list of args (vision_feature_layer,
use_cache, etc.), fall back to ``self.config.<arg>`` when the
caller didn't pass them. GLM-ASR uses this for ``use_cache``.
"""
@wraps(func)
def wrapper(self: Any, *args: Any, **kwargs: Any) -> Any:
args_with_config_defaults = (
"use_cache",
"vision_feature_layer",
"vision_feature_select_strategy",
"vision_aspect_ratio",
)
for arg_name in args_with_config_defaults:
arg_index = None
if arg_name in func.__code__.co_varnames:
arg_index = func.__code__.co_varnames.index(arg_name) - 1
if arg_index is not None and len(args) > arg_index and args[arg_index] is not None:
continue
if kwargs.get(arg_name) is not None:
continue
cfg_value = getattr(getattr(self, "config", None), arg_name, None)
if cfg_value is not None:
kwargs[arg_name] = cfg_value
return func(self, *args, **kwargs)
return wrapper
def use_kernelized_func(*_a: Any, **_kw: Any) -> Any:
"""Stub: identity decorator factory.
5.x uses this to dispatch to optional optimized kernels (Triton
flash variants, etc.). Without it, the model still runs via the
standard PyTorch path — we just lose the kernel speed-up. Safe to
drop for correctness.
"""
def decorator(fn: Any) -> Any:
return fn
return decorator
def capture_outputs(func: Any = None, **_kw: Any) -> Any:
"""Stub: identity decorator.
5.x uses this to hook into intermediate-layer outputs when the
caller passes ``output_attentions=True`` / ``output_hidden_states=True``
on a forward call. Our ASR caller (``model.generate(...)``) never
sets either, and the stubbed-out decorator preserves the normal
forward signature.
"""
if func is None:
return lambda f: f
return func
def _patch_attention_interface() -> None:
"""Add 5.x's ``.get_interface(...)`` to 4.57's ``ALL_ATTENTION_FUNCTIONS``.
4.57's ``AttentionInterface`` is dict-like (``.get``, ``.keys``,
subscript) but lacks the 5.x-only ``.get_interface(impl, default)``
method that 5.x's modeling code expects. The shim falls back to the
default callable when ``impl`` is ``None``, ``"eager"``, or absent
from the registry — matching the 5.x semantics.
"""
from transformers.modeling_utils import ALL_ATTENTION_FUNCTIONS
cls = type(ALL_ATTENTION_FUNCTIONS)
if hasattr(cls, "get_interface"):
return
def get_interface(self: Any, attn_implementation: str | None, default: Any) -> Any:
if attn_implementation is None or attn_implementation == "eager":
return default
return self.get(attn_implementation, default)
cls.get_interface = get_interface
_patch_attention_interface()
def auto_docstring(*args: Any, **_kw: Any) -> Any:
"""Stub: identity decorator (no docstring synthesis).
transformers 4.57's ``auto_docstring`` chokes on PEP 604 unions
(e.g. ``int | None``) used in the vendored 5.x signatures —
``types.UnionType`` has no ``__name__``. The decorator is purely
cosmetic (auto-builds a help docstring from the signature), so
stubbing it preserves behaviour and avoids the parser crash.
"""
if len(args) == 1 and callable(args[0]) and not _kw:
return args[0]
def decorator(fn: Any) -> Any:
return fn
return decorator
# Dataclass helpers re-exported for the vendored config to depend on
# stable names regardless of where they live in transformers' API.
__all__ = [
"PreTrainedConfig",
"maybe_autocast",
"merge_with_config_defaults",
"use_kernelized_func",
"capture_outputs",
"MISSING",
"fields",
]