Keep Unsloth's 1-bit DeepSeek sets off the Mac until the Metal engine has an IQ1_S kernel (lists, --model, --model-path, app check, setup)

This commit is contained in:
Niko1221 committed 2026-10-30 19:57:24 +01:00
1 parent ad4755c249
commit 32806f82aa
8 files changed
+226

No files matched your search

+4
View File
@@ -8401,9 +8401,13 @@ def install_dsv41(a, family, gpu, hip, amd, cuda_tk, multi, port, ram, adopted,
except Exception: # noqa: BLE001 - the disk is only a hint here
room = None
rec = dsv41_fit.recommend(ram, room) # the best version this computer's memory and disk suit; warn-never-refuse
if mac: # the Unsloth 1-bit sets have no Metal kernel yet: not in a Mac's menu
names = [m for m in names if m not in dsv41_fit.MAC_NOT_YET]
for i, m in enumerate(names, 1):
say(f" {i}) {fam['models'][m].get('label', m)}: {fam['models'][m]['about']}" + (" (recommended)" if m == rec else ""))
model = names[int(ask("Which version?", [str(i) for i in range(1, len(names) + 1)], str(names.index(rec) + 1), a.yes)) - 1]
if mac and model in dsv41_fit.MAC_NOT_YET: # IQ1_S experts: no Metal kernel yet (strata_control/dsv41_fit.MAC_NOT_YET); said before anything is fetched or packed
fail(dsv41_fit.MAC_NOT_YET_LINE, "choose --model IST-DAS-2.00bpw or --model IST-DAS-2.25bpw (their files work with --gguf-dir too); nothing has been downloaded")
ok(f"size: {model}")
md = fam["models"][model]
say(" Its GGUF files: " + ("IST-DAS / ISTA-DASLab (huggingface.co/ISTA-DASLab/DeepSeek-V4.1-Flash-1017-GSQ-RCO-GGUF), with the DSpark drafter and a small metadata file from Unsloth"
+8
View File
@@ -383,6 +383,8 @@ class Catalog:
near = S.closest(family, list(families))
raise ValueError(f"There is no model family called '{family}'." + (f" Did you mean '{near}'?" if near else "")
+ " Families: " + ", ".join(families) + ".")
if match in self.strata.dsv41_not_on_mac() and self._mac_hardware():
raise ValueError(self.strata.dsv41_not_on_mac_line() + " Use ist-das-2.00bpw or ist-das-2.25bpw.")
offered = [f for f in families if match in self.strata.sizes_of(models, f)]
if family is not None:
if family not in offered:
@@ -497,6 +499,12 @@ class Catalog:
vram = comp.main_vram_gb
return VR.default_mode(vram, "intel" if comp.engine_vendor == "intel" else "") if vram > 0 else "cpu" # no usable card: nothing to read on, the CPU reader
def _mac_hardware(self) -> bool:
try:
return bool(self.hardware().get("mac"))
except Exception: # noqa: BLE001 - no hardware report: not a Mac as far as this check knows
return False
def is_mac(self) -> bool:
"""An Apple Silicon Mac: the chip's memory is the system's (the Metal engine; strata_control/vision_reader.py)."""
return self.engine_backend() == "metal"
+4
View File
@@ -1309,6 +1309,10 @@ class Runner:
if found is None:
return False
model, d, folder = found
if sys.platform == "darwin" and model in self.catalog.strata.dsv41_not_on_mac(): # IQ1_S experts: no Metal kernel yet; said before an engine or a download is touched
raise LaunchError(self.catalog.strata.dsv41_not_on_mac_line(),
"Use the 2.00 or 2.25 files (--model ist-das-2.00bpw or --model ist-das-2.25bpw, or --model-path to those files). "
"Nothing was downloaded or changed.", 2)
if s.family and s.family != "deepseek41":
raise LaunchError(f"These are DeepSeek-V4.1-Flash's files, not {s.family} {s.model}'s.",
"Leave --model out, or use --model " + model + ".", 2)
+4
View File
@@ -9,6 +9,7 @@ from __future__ import annotations
import os
import shutil
import sys
import threading
from pathlib import Path
from typing import Any
@@ -559,6 +560,9 @@ class ModelScreen(Base):
if found is None:
return False
model, d, folder = found
if sys.platform == "darwin" and model in self.ctx.catalog.strata.dsv41_not_on_mac():
self.say(self.ctx.catalog.strata.dsv41_not_on_mac_line() + " Pick the 2.00 or 2.25 version from the list, or point to those files.", True)
return True
_layout, names, missing = mod.dsv41_parts(d, lambda n: (folder / n).exists()) # the pinned four-shard layout, or ISTA's six-shard one (0.2.8.1)
if missing:
self.say(f"These are DeepSeek-V4.1-Flash {d.get('label', model)} files, but {len(missing)} of {len(names)} parts are not in {folder} "
+5
View File
@@ -607,6 +607,11 @@ def mac_plan(ram_gb: float, quant: str = "IQ2_XS", disk_free_gb: float | None =
# the 1.75 bpw set shares the 2.00 set's IQ1_M kernel but was never run there, so it is not offered on a Mac.
MAC_SET_PACK = {"IST-DAS-2.00bpw": "IQ2_XXS", "IST-DAS-2.25bpw": "IQ2_XS"}
# Unsloth's UD-IQ1_S / UD-IQ1_M (0.2.9) carry IQ1_S experts, which the Metal DeepSeek engine has no kernel for yet (metal/src/engine/msl/ds4_iq.metal:
# IQ1_S and IQ4_NL are CUDA / HIP only). They are kept off the Mac everywhere: the model lists (MAC_SET_PACK above does that on its own), setup, the
# launch and the "I already have the model" check, with this one line. Remove a name here when its Metal kernel lands.
MAC_NOT_YET = ("UD-IQ1_S", "UD-IQ1_M")
MAC_NOT_YET_LINE = "Unsloth's 1-bit DeepSeek sets don't run on a Mac yet; the 2.00 and 2.25 sets do."
MAC_SMALL_RAM_GB = 64.0 # below this the measured M5 Max numbers do not apply (nothing smaller than 32 GB was ever started)
+20
View File
@@ -19,6 +19,7 @@ import json
import os
import re
import stat
import sys
from pathlib import Path
from strata_control import discovery
@@ -336,6 +337,7 @@ def _already_set_up(shards: list[Path], candidate: dict | None) -> dict | None:
ISSUE_WORDS = {
"not_on_this_mac": "Unsloth's 1-bit DeepSeek sets don't run on a Mac yet; the 2.00 and 2.25 sets do",
"multiple_model_groups": "the folder holds more than one model",
"incomplete_or_invalid_shard_set": "some parts of the model are missing",
"unrecognized_or_unsupported_model_variant": "this is not a model size Strata knows",
@@ -366,6 +368,20 @@ _REASON_WORDS = (
)
def _on_mac() -> bool:
return sys.platform == "darwin"
def _mac_not_yet() -> tuple:
from strata_control import dsv41_fit
return dsv41_fit.MAC_NOT_YET
def _mac_not_yet_line() -> str:
from strata_control import dsv41_fit
return dsv41_fit.MAC_NOT_YET_LINE
def plain_issue(code: str) -> str:
"""One problem from the GGUF preview, in words, with the file's name when it is about one file
(`file.gguf: GGUF shard is not a nonempty regular file`)."""
@@ -667,6 +683,10 @@ def _dsv41_plan(path: Path, details) -> dict | None:
candidate = {"family": dsv41_sets.FAMILY, "model": row["model"], "basis": "known_names_and_sizes", "expected_expert_types": [],
"expected_tensor_count": None,
"setup_args_hint": ["--family", dsv41_sets.FAMILY, "--model", row["model"], "--gguf-dir", str(place)]}
if _on_mac() and row["model"] in _mac_not_yet(): # recommend, never force: say what does work and stop before anything is copied or packed
issues.append("not_on_this_mac")
candidate = None
messages.append(_mac_not_yet_line())
messages.append(f"This is DeepSeek-V4.1-Flash, {row['label']}: all {len(row['present'])} model files are here"
+ (", and the n-gram table." if row["engram"] else "."))
if not row["engram"]:
+168
View File
@@ -0,0 +1,168 @@
"""Unsloth's UD-IQ1_S / UD-IQ1_M DeepSeek sets on a Mac (0.2.9): their IQ1_S experts have no Metal kernel yet, so the sets are not offered there
(model list, `--model`, `--model-path`, the app's "I already have the model" check, setup), and the line says what does work.
On every other computer nothing changes."""
from __future__ import annotations
import os
import sys
import unittest
from pathlib import Path
from unittest import mock
from strata_cli.launch import settings as S
from strata_cli.launch.catalog import Catalog
from strata_cli.launch.runner import LaunchError, Runner
from strata_control import dsv41_fit, dsv41_sets, models
from tests.terminal.launch_support import HW_12, Home, catalog
LINE = "Unsloth's 1-bit DeepSeek sets don't run on a Mac yet; the 2.00 and 2.25 sets do."
MAC = {**HW_12, "mac": True, "ram_gb": 128.0, "disk_free_gb": 900.0, "gpus": [], "engine_vendor": "apple"}
PC = {**HW_12, "ram_gb": 64.0, "disk_free_gb": 900.0, "engine_vendor": "nvidia"}
UD = ("UD-IQ1_S", "UD-IQ1_M")
def ud_files(model):
return {**dsv41_sets.tables()["sets"][model]["shards"], **dsv41_sets.tables()["sets"][model]["engram_alt"]}
class Line(unittest.TestCase):
def test_the_line_and_the_names(self):
self.assertEqual(dsv41_fit.MAC_NOT_YET, UD)
self.assertEqual(dsv41_fit.MAC_NOT_YET_LINE, LINE)
self.assertFalse(set(UD) & set(dsv41_fit.MAC_SET_PACK))
class Lists(unittest.TestCase):
def setUp(self):
self.home = Home().__enter__()
self.addCleanup(self.home.__exit__, None, None, None)
self.hw = dict(MAC)
p = mock.patch.object(Catalog, "hardware", lambda s, fresh=False: dict(self.hw))
p.start()
self.addCleanup(p.stop)
def models(self):
return [r.model for r in catalog(self.hw).rows() if r.family == "deepseek41"]
def test_a_mac_is_not_offered_the_unsloth_sets(self):
got = self.models()
for m in UD:
self.assertNotIn(m, got)
self.assertFalse(set(got) - set(dsv41_fit.MAC_SET_PACK), got)
def test_a_pc_is_offered_them(self):
self.hw = dict(PC)
got = self.models()
for m in UD:
self.assertIn(m, got)
def test_model_flag_on_a_mac_says_what_works(self):
with self.assertRaises(ValueError) as cm:
catalog(self.hw).resolve("ud-iq1_m", None)
self.assertIn(LINE, str(cm.exception))
self.assertIn("ist-das-2.25bpw", str(cm.exception))
self.assertEqual(catalog(self.hw).resolve("ist-das-2.25bpw"), ("deepseek41", "IST-DAS-2.25bpw"))
def test_model_flag_on_a_pc_is_unchanged(self):
self.hw = dict(PC)
self.assertEqual(catalog(self.hw).resolve("ud-iq1_s"), ("deepseek41", "UD-IQ1_S"))
class OwnFiles(unittest.TestCase):
def setUp(self):
self.home = Home().__enter__()
self.addCleanup(self.home.__exit__, None, None, None)
self.hw = dict(MAC)
p = mock.patch.object(Catalog, "hardware", lambda s, fresh=False: dict(self.hw))
p.start()
self.addCleanup(p.stop)
def folder(self, model):
folder = Path(os.environ["STRATA_INSTALL_DIR"]) / model
folder.mkdir(parents=True, exist_ok=True)
for name in dsv41_sets.tables()["sets"][model]["shards"]:
(folder / name).write_bytes(b"GGUF")
return folder
def test_model_path_of_a_ud_folder_on_a_mac_stops_with_the_line(self):
for model in UD:
folder = self.folder(model)
with mock.patch.object(sys, "platform", "darwin"):
with self.assertRaises(LaunchError) as cm:
Runner(S.LaunchSettings(model_path=str(folder)), catalog=catalog(self.hw)).check_own_files()
self.assertIn(LINE, cm.exception.text)
self.assertIn("2.25", cm.exception.hint if hasattr(cm.exception, "hint") else cm.exception.text)
def test_the_same_folder_on_another_computer_is_the_model(self):
folder = self.folder("UD-IQ1_S")
with mock.patch.object(sys, "platform", "linux"):
r = Runner(S.LaunchSettings(model_path=str(folder)), catalog=catalog(self.hw))
r.check_own_files()
self.assertEqual((r.s.family, r.s.model), ("deepseek41", "UD-IQ1_S"))
class AppCheck(unittest.TestCase):
def preview(self, model, platform):
with mock.patch.object(models, "_dsv41_files", return_value=ud_files(model)), mock.patch.object(sys, "platform", platform), \
__import__("tempfile").TemporaryDirectory() as tmp:
return models.plan_import(tmp)
def test_on_a_mac_the_preview_says_so_and_selects_nothing(self):
for model in UD:
plan = self.preview(model, "darwin")
self.assertIn(LINE, plan["messages"])
self.assertIn("not_on_this_mac", plan["issues"])
self.assertEqual(plan["file_set_status"], "invalid_or_incomplete")
self.assertIsNone(plan["candidate_selection"])
self.assertIn(LINE.rstrip("."), plan["plain_issues"])
def test_on_a_pc_the_preview_is_the_set(self):
for model in UD:
plan = self.preview(model, "linux")
self.assertEqual(plan["file_set_status"], "plausible", plan["issues"])
self.assertEqual(plan["candidate_selection"]["model"], model)
self.assertNotIn(LINE, plan["messages"])
def test_an_ist_das_set_on_a_mac_is_still_the_set(self):
t = dsv41_sets.tables()["sets"]["IST-DAS-2.25bpw"]["shards"]
eng = next(iter(dsv41_sets.tables()["engram"]))
with mock.patch.object(models, "_dsv41_files", return_value={**t, eng: dsv41_sets.tables()["engram"][eng]}), \
mock.patch.object(sys, "platform", "darwin"), __import__("tempfile").TemporaryDirectory() as tmp:
plan = models.plan_import(tmp)
self.assertEqual(plan["file_set_status"], "plausible", plan["issues"])
self.assertEqual(plan["candidate_selection"]["model"], "IST-DAS-2.25bpw")
class Setup(unittest.TestCase):
"""setup.py is the last stop: the line, before an engine, a download or a pack is touched."""
def run_setup(self, model, platform):
import contextlib
import importlib.util
import io
import types
root = Path(__file__).resolve().parents[2]
spec = importlib.util.spec_from_file_location("setup_mac_ud", root / "setup.py")
setup = importlib.util.module_from_spec(spec)
spec.loader.exec_module(setup)
a = types.SimpleNamespace(model=model, models_dir="/nonexistent/models", yes=True, gguf_dir=None)
out = io.StringIO()
with mock.patch.object(sys, "platform", platform), contextlib.redirect_stdout(out), contextlib.redirect_stderr(out):
try:
setup.install_dsv41(a, "deepseek41", {}, False, False, 13, True, 8080, 128.0, False)
except BaseException as exc: # noqa: BLE001 - fail() exits; anything after the check would raise something else
return type(exc).__name__, out.getvalue()
return None, out.getvalue()
def test_a_mac_is_stopped_before_anything_else(self):
for model in UD:
exc, text = self.run_setup(model, "darwin")
self.assertEqual(exc, "SystemExit", (model, text[-400:]))
self.assertIn(LINE, text)
self.assertIn("IST-DAS-2.25bpw", text)
self.assertIn("nothing has been downloaded", text)
if __name__ == "__main__":
unittest.main()
+13
View File
@@ -1338,6 +1338,17 @@ class Strata:
"sizes": sizes})
return out
@staticmethod
def dsv41_not_on_mac() -> tuple:
"""The DeepSeek sets the Metal engine cannot run yet (IQ1_S experts): strata_control/dsv41_fit.MAC_NOT_YET."""
from strata_control import dsv41_fit
return dsv41_fit.MAC_NOT_YET
@staticmethod
def dsv41_not_on_mac_line() -> str:
from strata_control import dsv41_fit
return dsv41_fit.MAC_NOT_YET_LINE
@staticmethod
def dsv41_disk_gb(d: dict) -> float:
"""The free disk a DeepSeek set needs: its whole download plus the pack and room to work (the card text says "about")."""
@@ -2274,6 +2285,8 @@ class Tools:
gpu = gpus = kv = low_ram = None
if md.get("multi_file"): # DeepSeek on a Mac (0.2.7.1): the sets that were run there, 8K like everywhere, text only
from strata_control import dsv41_fit
if model in dsv41_fit.MAC_NOT_YET:
raise ToolError(dsv41_fit.MAC_NOT_YET_LINE)
if model not in dsv41_fit.MAC_SET_PACK:
raise ToolError(f"{model} is not offered on a Mac: DeepSeek runs there as " + " or ".join(dsv41_fit.MAC_SET_PACK))
if vision in ("yes", "gpu", "cpu"):