Handle broken causal_conv1d at import time (#4047)
* Handle broken causal_conv1d import at runtime Add a startup import-time probe for causal_conv1d and disable the fast path when the shared library is ABI broken. This keeps Falcon H1/model loading resilient without requiring env flags. - Add disable_broken_causal_conv1d in import_fixes. - Invoke it early from unsloth/__init__ during package init. - Make Falcon H1 optional imports in loader and models/__init__ soft-fail instead of failing hard. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Enforce unavailable semantics for broken causal_conv1d * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Remove Falcon H1 import swallowing * Restore optional Falcon H1 import guard * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Remove causal_conv1d regression tests * Trim FA2 fallback messaging --------- Co-authored-by: Daniel Hanchen <danielhanchen@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
2a7d098203
commit
c14917b96e
3 changed files with 162 additions and 4 deletions
|
|
@ -28,16 +28,19 @@ already_imported = [mod for mod in critical_modules if mod in sys.modules]
|
|||
from .import_fixes import (
|
||||
fix_message_factory_issue,
|
||||
check_fbgemm_gpu_version,
|
||||
disable_broken_causal_conv1d,
|
||||
torchvision_compatibility_check,
|
||||
fix_diffusers_warnings,
|
||||
fix_huggingface_hub,
|
||||
)
|
||||
|
||||
disable_broken_causal_conv1d()
|
||||
fix_message_factory_issue()
|
||||
check_fbgemm_gpu_version()
|
||||
torchvision_compatibility_check()
|
||||
fix_diffusers_warnings()
|
||||
fix_huggingface_hub()
|
||||
del disable_broken_causal_conv1d
|
||||
del fix_message_factory_issue
|
||||
del check_fbgemm_gpu_version
|
||||
del torchvision_compatibility_check
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@
|
|||
# limitations under the License.
|
||||
|
||||
import os
|
||||
import importlib.abc
|
||||
import importlib.machinery
|
||||
import importlib.util
|
||||
from pathlib import Path
|
||||
from importlib.metadata import version as importlib_version
|
||||
|
|
@ -21,6 +23,7 @@ import re
|
|||
import logging
|
||||
import textwrap
|
||||
import warnings
|
||||
import sys
|
||||
|
||||
# We cannot do from unsloth_zoo.log import logger since FBGEMM might cause seg faults.
|
||||
UNSLOTH_ENABLE_LOGGING = os.environ.get("UNSLOTH_ENABLE_LOGGING", "0") in (
|
||||
|
|
@ -1163,3 +1166,157 @@ def disable_torchcodec_if_broken():
|
|||
tf_import_utils._torchcodec_available = False
|
||||
except (ImportError, AttributeError):
|
||||
pass
|
||||
|
||||
|
||||
CAUSAL_CONV1D_BROKEN = False
|
||||
_CAUSAL_CONV1D_PREFIX = "causal_conv1d"
|
||||
_CAUSAL_CONV1D_BLOCKER_SENTINEL = "_unsloth_causal_conv1d_blocker"
|
||||
|
||||
|
||||
def _is_causal_conv1d_name(module_name: str) -> bool:
|
||||
return module_name == _CAUSAL_CONV1D_PREFIX or module_name.startswith(
|
||||
_CAUSAL_CONV1D_PREFIX + "."
|
||||
)
|
||||
|
||||
|
||||
def _resolve_module_name(module_name, package):
|
||||
if not isinstance(module_name, str):
|
||||
return module_name
|
||||
if module_name.startswith("."):
|
||||
try:
|
||||
return importlib.util.resolve_name(module_name, package)
|
||||
except Exception:
|
||||
return module_name
|
||||
return module_name
|
||||
|
||||
|
||||
def _is_broken_causal_conv1d_error(error) -> bool:
|
||||
checked = set()
|
||||
current = error
|
||||
while current is not None and id(current) not in checked:
|
||||
checked.add(id(current))
|
||||
message = str(current).lower()
|
||||
if (
|
||||
("causal_conv1d_cuda" in message and "undefined symbol" in message)
|
||||
or ("_zn3c103hip28c10_hip_check_implementation" in message)
|
||||
or ("causal_conv1d" in message and "undefined symbol" in message)
|
||||
):
|
||||
return True
|
||||
current = getattr(current, "__cause__", None) or getattr(
|
||||
current, "__context__", None
|
||||
)
|
||||
return False
|
||||
|
||||
|
||||
class _CausalConv1dImportBlockerLoader(importlib.abc.Loader):
|
||||
__slots__ = ("module_name",)
|
||||
|
||||
def __init__(self, module_name):
|
||||
self.module_name = module_name
|
||||
|
||||
def create_module(self, spec):
|
||||
return None
|
||||
|
||||
def exec_module(self, module):
|
||||
raise ModuleNotFoundError(f"No module named '{self.module_name}'")
|
||||
|
||||
|
||||
class _CausalConv1dImportBlockerFinder(importlib.abc.MetaPathFinder):
|
||||
__slots__ = (_CAUSAL_CONV1D_BLOCKER_SENTINEL,)
|
||||
|
||||
def __init__(self):
|
||||
setattr(self, _CAUSAL_CONV1D_BLOCKER_SENTINEL, True)
|
||||
|
||||
def find_spec(self, fullname, path = None, target = None):
|
||||
if not CAUSAL_CONV1D_BROKEN or not _is_causal_conv1d_name(fullname):
|
||||
return None
|
||||
return importlib.machinery.ModuleSpec(
|
||||
name = fullname,
|
||||
loader = _CausalConv1dImportBlockerLoader(fullname),
|
||||
is_package = fullname == _CAUSAL_CONV1D_PREFIX,
|
||||
)
|
||||
|
||||
|
||||
def _patch_find_spec_for_causal_conv1d():
|
||||
current_find_spec = importlib.util.find_spec
|
||||
if getattr(current_find_spec, "_unsloth_causal_conv1d_find_spec_patch", False):
|
||||
return
|
||||
|
||||
def _blocked_find_spec(name, package = None):
|
||||
resolved_name = _resolve_module_name(name, package)
|
||||
if CAUSAL_CONV1D_BROKEN and isinstance(resolved_name, str):
|
||||
if _is_causal_conv1d_name(resolved_name):
|
||||
return None
|
||||
return current_find_spec(name, package)
|
||||
|
||||
_blocked_find_spec._unsloth_causal_conv1d_find_spec_patch = True
|
||||
_blocked_find_spec._unsloth_original_find_spec = current_find_spec
|
||||
importlib.util.find_spec = _blocked_find_spec
|
||||
|
||||
|
||||
def _install_causal_conv1d_blocker():
|
||||
_patch_find_spec_for_causal_conv1d()
|
||||
for finder in sys.meta_path:
|
||||
if getattr(finder, _CAUSAL_CONV1D_BLOCKER_SENTINEL, False):
|
||||
return
|
||||
sys.meta_path.insert(0, _CausalConv1dImportBlockerFinder())
|
||||
|
||||
|
||||
def _clear_causal_conv1d_modules():
|
||||
for module_name in list(sys.modules):
|
||||
if _is_causal_conv1d_name(module_name):
|
||||
sys.modules.pop(module_name, None)
|
||||
|
||||
|
||||
def _disable_transformers_causal_conv1d():
|
||||
try:
|
||||
import transformers.utils.import_utils as tf_import_utils
|
||||
except Exception:
|
||||
return
|
||||
|
||||
if hasattr(tf_import_utils, "is_causal_conv1d_available"):
|
||||
tf_import_utils.is_causal_conv1d_available = lambda: False
|
||||
|
||||
for attr_name in (
|
||||
"_causal_conv1d_available",
|
||||
"_is_causal_conv1d_available",
|
||||
):
|
||||
if hasattr(tf_import_utils, attr_name):
|
||||
setattr(tf_import_utils, attr_name, False)
|
||||
|
||||
|
||||
def disable_broken_causal_conv1d():
|
||||
"""Disable causal_conv1d dynamically when its shared library is ABI-broken.
|
||||
|
||||
This mirrors Unsloth's FlashAttention fallback behavior: if importing causal_conv1d
|
||||
fails with a known binary symbol error, we disable it at startup so model imports do
|
||||
not hard-fail.
|
||||
"""
|
||||
global CAUSAL_CONV1D_BROKEN
|
||||
if CAUSAL_CONV1D_BROKEN:
|
||||
_install_causal_conv1d_blocker()
|
||||
_disable_transformers_causal_conv1d()
|
||||
return
|
||||
|
||||
try:
|
||||
if importlib.util.find_spec("causal_conv1d") is None:
|
||||
return
|
||||
except Exception:
|
||||
return
|
||||
|
||||
try:
|
||||
import causal_conv1d # noqa: F401
|
||||
|
||||
return
|
||||
except Exception as error:
|
||||
if not _is_broken_causal_conv1d_error(error):
|
||||
return
|
||||
|
||||
CAUSAL_CONV1D_BROKEN = True
|
||||
_clear_causal_conv1d_modules()
|
||||
_install_causal_conv1d_blocker()
|
||||
_disable_transformers_causal_conv1d()
|
||||
print(
|
||||
"Unsloth: Detected broken causal_conv1d binary; "
|
||||
"disabling causal_conv1d fast path and continuing import."
|
||||
)
|
||||
|
|
|
|||
|
|
@ -845,8 +845,7 @@ if DEVICE_TYPE == "cuda":
|
|||
"Unsloth: Your Flash Attention 2 installation seems to be broken?\n"
|
||||
"A possible explanation is you have a new CUDA version which isn't\n"
|
||||
"yet compatible with FA2? Please file a ticket to Unsloth or FA2.\n"
|
||||
"We shall now use Xformers instead, which does not have any performance hits!\n"
|
||||
"We found this negligible impact by benchmarking on 1x A100."
|
||||
"We shall now use Xformers instead, which does not have any performance hits!"
|
||||
)
|
||||
|
||||
# Stop Flash Attention from importing!
|
||||
|
|
@ -897,8 +896,7 @@ elif DEVICE_TYPE == "hip":
|
|||
"Unsloth: Your Flash Attention 2 installation seems to be broken?\n"
|
||||
"A possible explanation is you have a new CUDA version which isn't\n"
|
||||
"yet compatible with FA2? Please file a ticket to Unsloth or FA2.\n"
|
||||
"We shall now use Xformers instead, which does not have any performance hits!\n"
|
||||
"We found this negligible impact by benchmarking on 1x A100."
|
||||
"We shall now use Xformers instead, which does not have any performance hits!"
|
||||
)
|
||||
|
||||
# Stop Flash Attention from importing!
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue