Time Series Forecasting
MLX
Safetensors
apple-silicon
timestral
time-series
forecasting
quantile-regression
Instructions to use jbilcke/timestral-mlx with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- MLX
How to use jbilcke/timestral-mlx with MLX:
# Download the model from the Hub pip install huggingface_hub[hf_xet] hf download jbilcke/timestral-mlx --local-dir timestral-mlx
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- LM Studio
- Atomic Chat
File size: 3,461 Bytes
d35e174 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | """Convert pinned source weights to strict MLX FP32 bundles. No training or quantization."""
import argparse
import importlib.metadata
import json
import platform
import shutil
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT))
sys.path.insert(0, str(ROOT / "scripts"))
import numpy as np
import mlx.core as mx
from safetensors.numpy import load_file
from timestral_mlx.config import TimestralConfig
from timestral_mlx.model import TimestralModel
from download import VARIANTS, sha256
def convert(variant):
src, dst = ROOT / "models" / "source" / variant, ROOT / "models" / variant
source = json.loads((src / "source.json").read_text())
for name, entry in source["files"].items():
if sha256(src / name) != entry["sha256"]:
raise ValueError(f"source integrity check failed: {name}")
dst.mkdir(parents=True, exist_ok=True)
weights = load_file(src / "model.safetensors")
if any(v.dtype != np.float32 for v in weights.values()):
raise ValueError("expected original FP32 weights")
converted = {k.replace("._gate.", ".gate."): mx.array(v) for k, v in weights.items()}
config = TimestralConfig.load(src / "config.json")
model = TimestralModel(config)
model.load_weights(list(converted.items()), strict=True)
mx.eval(model.parameters())
mx.save_safetensors(str(dst / "model.safetensors"), converted,
metadata={"format": "mlx", "source": source["repo_id"], "revision": source["revision"]})
# Check every serialized tensor, including exact source values and key mapping.
restored = mx.load(str(dst / "model.safetensors"))
if set(restored) != set(converted):
raise ValueError("serialized key inventory mismatch")
for k, v in weights.items():
if not np.array_equal(v, np.array(restored[k.replace("._gate.", ".gate.")])):
raise ValueError(f"lossless conversion check failed: {k}")
shutil.copyfile(src / "config.json", dst / "config.json")
shutil.copyfile(src / "LICENSE", dst / "LICENSE")
manifest = {
"format": "timestral-mlx-fp32-v1", "variant": variant, "dtype": "float32",
"source": source, "source_code": {"url": "https://github.com/mistralai/timestral",
"revision": "a534bdbd244d64f3d9d743f46c7bf6fc330ed4ff"},
"conversion": {"tensor_count": len(weights), "parameter_count": sum(v.size for v in weights.values()),
"mapping": "Replace ._gate. with .gate.; tensor layouts and FP32 values unchanged",
"lossless_roundtrip_verified": True, "training": False, "quantization": False},
"environment": {"python": platform.python_version(), "mlx": importlib.metadata.version("mlx"),
"numpy": np.__version__, "platform": platform.platform()},
"files": {name: {"sha256": sha256(dst / name), "bytes": (dst / name).stat().st_size}
for name in ("config.json", "model.safetensors", "LICENSE")},
}
(dst / "manifest.json").write_text(json.dumps(manifest, indent=2) + "\n")
print(f"Converted {variant}: {len(weights)} tensors, {manifest['conversion']['parameter_count']:,} parameters; lossless FP32 verified", flush=True)
if __name__ == "__main__":
p = argparse.ArgumentParser(description=__doc__)
p.add_argument("variants", nargs="*", choices=VARIANTS, default=list(VARIANTS))
for size in p.parse_args().variants:
convert(size)
|