Instructions to use fukujusou/Anima-mlx with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- MLX
How to use fukujusou/Anima-mlx with MLX:
# Download the model from the Hub pip install huggingface_hub[hf_xet] huggingface-cli download --local-dir Anima-mlx fukujusou/Anima-mlx
- Diffusion Single File
How to use fukujusou/Anima-mlx with Diffusion Single File:
# No code snippets available yet for this library. # To use this model, check the repository files and the library's documentation. # Want to help? PRs adding snippets are welcome at: # https://github.com/huggingface/huggingface.js
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- LM Studio
| """Weight loading helpers for local Anima safetensors artifacts. | |
| The Anima checkpoints are BF16. ``safetensors`` can expose those tensors to | |
| PyTorch reliably, while its NumPy path cannot represent BF16 on the system | |
| Python used by this project. Keep the PyTorch dependency lazy so metadata-only | |
| and source-contract tests can run without importing heavy runtimes. | |
| """ | |
| from __future__ import annotations | |
| from pathlib import Path | |
| from typing import Callable, Mapping | |
| MLX_WEIGHT_ROOT_NAME = "mlx_weights" | |
| def load_torch_safetensors_subset( | |
| path: str | Path, | |
| *, | |
| prefix: str | None = None, | |
| strip_prefix: str | None = None, | |
| key_filter: Callable[[str], bool] | None = None, | |
| dtype: str = "float32", | |
| ) -> dict[str, object]: | |
| """Load a filtered safetensors subset as CPU PyTorch tensors. | |
| Args: | |
| path: Safetensors file path. | |
| prefix: Optional source-key prefix filter. | |
| strip_prefix: Optional prefix to remove from returned keys. | |
| key_filter: Optional arbitrary source-key predicate. | |
| dtype: Either ``"float32"`` or ``"native"``. | |
| """ | |
| try: | |
| import torch | |
| from safetensors import safe_open | |
| except ModuleNotFoundError as exc: # pragma: no cover - depends on env | |
| raise RuntimeError("PyTorch and safetensors are required to load BF16 weights") from exc | |
| if dtype not in {"float32", "native"}: | |
| raise ValueError(f"unsupported dtype: {dtype}") | |
| weights: dict[str, object] = {} | |
| with safe_open(str(path), framework="pt", device="cpu") as handle: | |
| for source_key in handle.keys(): | |
| if prefix is not None and not source_key.startswith(prefix): | |
| continue | |
| if key_filter is not None and not key_filter(source_key): | |
| continue | |
| target_key = source_key | |
| if strip_prefix is not None: | |
| if not target_key.startswith(strip_prefix): | |
| continue | |
| target_key = target_key.removeprefix(strip_prefix) | |
| tensor = handle.get_tensor(source_key) | |
| if dtype == "float32": | |
| tensor = tensor.float() | |
| weights[target_key] = tensor | |
| return weights | |
| def torch_to_mlx_weights( | |
| weights: Mapping[str, object], | |
| *, | |
| dtype: str = "float32", | |
| ) -> dict[str, object]: | |
| """Convert a mapping of CPU PyTorch tensors to MLX arrays. | |
| MLX is imported lazily because importing it inside the default sandbox can | |
| crash the local Metal runtime. Callers should do this only in MLX-enabled | |
| processes. | |
| """ | |
| import numpy as np | |
| import mlx.core as mx | |
| dtype_map = { | |
| "float32": mx.float32, | |
| "float16": mx.float16, | |
| "bfloat16": mx.bfloat16, | |
| } | |
| if dtype not in dtype_map: | |
| raise ValueError(f"unsupported MLX dtype: {dtype}") | |
| converted: dict[str, object] = {} | |
| for key, tensor in weights.items(): | |
| if hasattr(tensor, "detach"): | |
| array = tensor.detach().cpu().float().numpy() | |
| else: | |
| array = np.asarray(tensor, dtype=np.float32) | |
| converted[key] = mx.array(array, dtype=dtype_map[dtype]) | |
| return converted | |
| def load_native_mlx_safetensors( | |
| path: str | Path, | |
| *, | |
| prefix: str | None = None, | |
| strip_prefix: str | None = None, | |
| key_filter: Callable[[str], bool] | None = None, | |
| dtype: str = "native", | |
| ) -> dict[str, object]: | |
| """Load a safetensors file with MLX and optionally filter/cast its arrays.""" | |
| import mlx.core as mx | |
| dtype_map = { | |
| "native": None, | |
| "float32": mx.float32, | |
| "float16": mx.float16, | |
| "bfloat16": mx.bfloat16, | |
| } | |
| if dtype not in dtype_map: | |
| raise ValueError(f"unsupported MLX dtype: {dtype}") | |
| arrays = mx.load(str(path), format="safetensors") | |
| target_dtype = dtype_map[dtype] | |
| filtered: dict[str, object] = {} | |
| for source_key, value in arrays.items(): | |
| if prefix is not None and not source_key.startswith(prefix): | |
| continue | |
| if key_filter is not None and not key_filter(source_key): | |
| continue | |
| target_key = source_key | |
| if strip_prefix is not None: | |
| if not target_key.startswith(strip_prefix): | |
| continue | |
| target_key = target_key.removeprefix(strip_prefix) | |
| if target_dtype is not None and hasattr(value, "astype"): | |
| value = value.astype(target_dtype) | |
| filtered[target_key] = value | |
| return filtered | |
| def load_mlx_safetensors_subset( | |
| path: str | Path, | |
| *, | |
| prefix: str | None = None, | |
| strip_prefix: str | None = None, | |
| key_filter: Callable[[str], bool] | None = None, | |
| dtype: str = "float32", | |
| ) -> dict[str, object]: | |
| """Load a safetensors subset into MLX arrays via the BF16-safe torch path.""" | |
| if _is_converted_mlx_weight_path(path): | |
| return load_native_mlx_safetensors( | |
| path, | |
| prefix=prefix, | |
| strip_prefix=strip_prefix, | |
| key_filter=key_filter, | |
| dtype=dtype, | |
| ) | |
| torch_weights = load_torch_safetensors_subset( | |
| path, | |
| prefix=prefix, | |
| strip_prefix=strip_prefix, | |
| key_filter=key_filter, | |
| dtype="float32", | |
| ) | |
| return torch_to_mlx_weights(torch_weights, dtype=dtype) | |
| def _is_converted_mlx_weight_path(path: str | Path) -> bool: | |
| resolved = Path(path) | |
| return MLX_WEIGHT_ROOT_NAME in resolved.parts or ".mlx." in resolved.name | |