mirror of
https://github.com/Heretek-AI/Strata.git
synced 2026-11-07 10:05:58 -10:00
Offer UD-IQ1_M on a Mac too: not run there, said plainly in its plan (the Mac gate stays as an empty mechanism)
This commit is contained in:
1 parent
38f56619cc
commit
33bbbca442
3 files changed
+80
-10
No files matched your search
@@ -515,6 +515,7 @@ MAC_PACKS: dict[str, dict[str, Any]] = {
|
||||
"IQ2_XXS": {"name": "2.00 bpw (IQ2_XXS), the default for most users", "routed_gb": 132.07, "backbone_gb": 138.24, "bpw": 2.00},
|
||||
"IQ2_XS": {"name": "2.25 bpw (IQ2_XS), the quality one", "routed_gb": 149.06, "backbone_gb": 155.23, "bpw": 2.25},
|
||||
"UD-IQ1_S": {"name": "Unsloth UD-IQ1_S (1-bit experts)", "routed_gb": 115.23, "backbone_gb": 122.38, "bpw": 1.75},
|
||||
"UD-IQ1_M": {"name": "Unsloth UD-IQ1_M (1-bit experts)", "routed_gb": 132.21, "backbone_gb": 139.81, "bpw": 2.00},
|
||||
}
|
||||
MAC_ENGRAM_GB = 110.60 # the same Engram table for all three, read row by row off the SSD
|
||||
MAC_ENGINE_FOOTPRINT_GB = 12.0 # the process' anonymous memory after the load (Metal buffers, host buffers, the KV cache)
|
||||
@@ -533,6 +534,7 @@ MAC_MEASURED_PACK = {
|
||||
"IQ2_XS": MAC_MEASURED,
|
||||
"UD-IQ1_S": ("M5 Max, 128 GB, Unsloth UD-IQ1_S: 15-18 tokens/s for a short answer (16-18 after a 3,000-token prompt), a 3,000-token prompt at "
|
||||
"about 230-310 tokens/s, 14,000 at about 520; the engine kept about 68 GB of the experts resident and the process used about 79 GB"),
|
||||
"UD-IQ1_M": "Not run on a Mac yet; UD-IQ1_S was. It keeps fewer experts in memory, so expect it to be slower.",
|
||||
}
|
||||
|
||||
|
||||
@@ -612,11 +614,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", "UD-IQ1_S": "UD-IQ1_S"}
|
||||
# Unsloth's UD-IQ1_S runs on the Metal engine since the IQ1_S kernels (f-039-mac-dsu). UD-IQ1_M has the same kernels but was never run on a Mac, so it is 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 set has run on a Mac.
|
||||
MAC_NOT_YET = ("UD-IQ1_M",)
|
||||
MAC_SET_PACK = {"IST-DAS-2.00bpw": "IQ2_XXS", "IST-DAS-2.25bpw": "IQ2_XS", "UD-IQ1_S": "UD-IQ1_S", "UD-IQ1_M": "UD-IQ1_M"}
|
||||
# Unsloth's UD-IQ1_S was run on an M5 Max (f-039-mac-dsu). UD-IQ1_M has the same kernels and was not run there; the owner chose to offer it anyway ("they
|
||||
# will tell if it works"), with a plain "not run yet" line in its plan. The gate stays as a mechanism, empty: put a name here to keep a set off a Mac
|
||||
# (the model lists, setup, the launch and the "I already have the model" check all read it through not_here()).
|
||||
MAC_NOT_YET = ()
|
||||
MAC_NOT_YET_LINE = "Unsloth's UD-IQ1_M set doesn't run on a Mac yet; the UD-IQ1_S, 2.00 and 2.25 sets do."
|
||||
# The same two sets were kept off a DGX Spark (linux-aarch64, GB10) until a Spark run passed: both passed there on 2026-10-30 (real `strata launch --model-path`,
|
||||
# 10 of 10 answers, tool call correct), so the tuple is empty. Put a name back here to hide a set from the Spark again.
|
||||
@@ -672,8 +674,9 @@ def _plan_mac(key: str, model: str, card: dict, ram_gb: float | None, disk_free_
|
||||
lines.append(f"DeepSeek-V4.1-Flash, {v['title']}: a {download:.0f} GB download ({v['set_bytes'] / GB:.0f} GB of model, "
|
||||
f"{ISTA_ENGRAM_BYTES / GB:.0f} GB n-gram table, {ISTA_DSPARK_BYTES / GB:.0f} GB drafter). Quality: {v['quality']}.")
|
||||
lines.extend(l for l in mp["lines"][1:] if not l.startswith("Measured on "))
|
||||
lines.append("Measured on " + MAC_MEASURED_PACK[MAC_SET_PACK[key]] + ".")
|
||||
out["measured"] = MAC_MEASURED_PACK[MAC_SET_PACK[key]]
|
||||
measured = MAC_MEASURED_PACK[MAC_SET_PACK[key]]
|
||||
lines.append(measured if measured.startswith("Not run") else "Measured on " + measured + ".")
|
||||
out["measured"] = measured
|
||||
warns.extend(mp["warnings"])
|
||||
if ram and ram < MAC_SMALL_RAM_GB and mp["verdict"] != "small":
|
||||
warns.append(f"This Mac has {ram:.0f} GB of memory and the set was measured on one with 128 GB: with less, more experts come from "
|
||||
|
||||
@@ -20,16 +20,29 @@ from tests.terminal.launch_support import HW_12, Home, catalog
|
||||
LINE = "Unsloth's UD-IQ1_M set doesn't run on a Mac yet; the UD-IQ1_S, 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_M",) # the sets kept off a Mac
|
||||
UD = ("UD-IQ1_M",) # the set the gate holds back in these tests (MAC_NOT_YET is empty in the product: the owner offers UD-IQ1_M on a Mac, not run there)
|
||||
RUNS = "UD-IQ1_S" # the one that was run there
|
||||
BOTH = ("UD-IQ1_S", "UD-IQ1_M") # both ran on a DGX Spark (10-30): AARCH64_NOT_YET is empty; SparkGate patches it back to test the mechanism
|
||||
|
||||
|
||||
def hidden(fn):
|
||||
"""Run a test with the Mac gate as it was while UD-IQ1_M was kept off a Mac (MAC_NOT_YET = UD, and no Mac fit words for it)."""
|
||||
import functools
|
||||
|
||||
@functools.wraps(fn)
|
||||
def run(*a, **k):
|
||||
pack = {m: v for m, v in dsv41_fit.MAC_SET_PACK.items() if m not in UD}
|
||||
with mock.patch.object(dsv41_fit, "MAC_NOT_YET", UD), mock.patch.object(dsv41_fit, "MAC_SET_PACK", pack):
|
||||
return fn(*a, **k)
|
||||
return run
|
||||
|
||||
|
||||
def ud_files(model):
|
||||
return {**dsv41_sets.tables()["sets"][model]["shards"], **dsv41_sets.tables()["sets"][model]["engram_alt"]}
|
||||
|
||||
|
||||
class Line(unittest.TestCase):
|
||||
@hidden
|
||||
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)
|
||||
@@ -48,6 +61,7 @@ class Lists(unittest.TestCase):
|
||||
def models(self):
|
||||
return [r.model for r in catalog(self.hw).rows() if r.family == "deepseek41"]
|
||||
|
||||
@hidden
|
||||
def test_a_mac_is_not_offered_the_unsloth_sets(self):
|
||||
got = self.models()
|
||||
for m in UD:
|
||||
@@ -67,6 +81,7 @@ class Lists(unittest.TestCase):
|
||||
for m in UD + (RUNS,):
|
||||
self.assertIn(m, got)
|
||||
|
||||
@hidden
|
||||
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)
|
||||
@@ -96,6 +111,7 @@ class OwnFiles(unittest.TestCase):
|
||||
(folder / name).write_bytes(b"GGUF")
|
||||
return folder
|
||||
|
||||
@hidden
|
||||
def test_model_path_of_a_ud_folder_on_a_mac_stops_with_the_line(self):
|
||||
for model in UD:
|
||||
folder = self.folder(model)
|
||||
@@ -120,12 +136,62 @@ class OwnFiles(unittest.TestCase):
|
||||
self.assertEqual((r.s.family, r.s.model), ("deepseek41", "UD-IQ1_S"))
|
||||
|
||||
|
||||
class OfferedOnAMac(unittest.TestCase):
|
||||
"""The product state: the Mac gate is empty, both Unsloth sets are offered; UD-IQ1_M says plainly that it was not run on a Mac."""
|
||||
PLAIN = "Not run on a Mac yet; UD-IQ1_S was. It keeps fewer experts in memory, so expect it to be slower."
|
||||
|
||||
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 test_the_gate_is_empty_and_both_sets_have_a_pack(self):
|
||||
self.assertEqual(dsv41_fit.MAC_NOT_YET, ())
|
||||
for m in ("UD-IQ1_S", "UD-IQ1_M"):
|
||||
self.assertIn(m, dsv41_fit.MAC_SET_PACK)
|
||||
self.assertIsNone(dsv41_fit.not_here(m))
|
||||
|
||||
def test_the_list_and_the_flag(self):
|
||||
got = [r.model for r in catalog(self.hw).rows() if r.family == "deepseek41"]
|
||||
for m in ("UD-IQ1_S", "UD-IQ1_M"):
|
||||
self.assertIn(m, got)
|
||||
self.assertEqual(catalog(self.hw).resolve("ud-iq1_m"), ("deepseek41", "UD-IQ1_M"))
|
||||
|
||||
def test_the_plan_of_ud_iq1_m_says_it_was_not_run_and_invents_no_numbers(self):
|
||||
plan = dsv41_fit.plan([{"vendor": "apple", "unified_gb": 128.0, "name": "Apple M5 Max"}], 128.0, 900.0, model="UD-IQ1_M")
|
||||
self.assertTrue(plan.get("mac"))
|
||||
self.assertIn(self.PLAIN, plan["words"])
|
||||
self.assertEqual(plan["measured"], self.PLAIN)
|
||||
self.assertNotIn("tokens/s", plan["words"])
|
||||
self.assertAlmostEqual(plan["download_gb"], 258.0, delta=1.0) # with the drafter and the Engram
|
||||
s = dsv41_fit.plan([{"vendor": "apple", "unified_gb": 128.0, "name": "Apple M5 Max"}], 128.0, 900.0, model="UD-IQ1_S")
|
||||
self.assertIn("tokens/s", s["words"])
|
||||
|
||||
def test_own_files_and_the_preview_on_a_mac(self):
|
||||
folder = Path(os.environ["STRATA_INSTALL_DIR"]) / "UD-IQ1_M"
|
||||
folder.mkdir(parents=True, exist_ok=True)
|
||||
for name in dsv41_sets.tables()["sets"]["UD-IQ1_M"]["shards"]:
|
||||
(folder / name).write_bytes(b"GGUF")
|
||||
with mock.patch.object(sys, "platform", "darwin"):
|
||||
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_M"))
|
||||
with mock.patch.object(models, "_dsv41_files", return_value=ud_files("UD-IQ1_M")), 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"], "UD-IQ1_M")
|
||||
|
||||
|
||||
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)
|
||||
|
||||
@hidden
|
||||
def test_on_a_mac_the_preview_says_so_and_selects_nothing(self):
|
||||
for model in UD:
|
||||
plan = self.preview(model, "darwin")
|
||||
@@ -182,6 +248,7 @@ class Setup(unittest.TestCase):
|
||||
return type(exc).__name__, out.getvalue()
|
||||
return None, out.getvalue()
|
||||
|
||||
@hidden
|
||||
def test_a_mac_is_stopped_before_anything_else(self):
|
||||
for model in UD:
|
||||
exc, text = self.run_setup(model, "darwin")
|
||||
@@ -228,7 +295,7 @@ class SparkGate(unittest.TestCase):
|
||||
self.assertIsNone(dsv41_fit.not_here("UD-IQ1_S"))
|
||||
with mock.patch.object(sys, "platform", "darwin"):
|
||||
self.assertIsNone(dsv41_fit.not_here("UD-IQ1_S"))
|
||||
self.assertEqual(dsv41_fit.not_here("UD-IQ1_M"), LINE)
|
||||
self.assertIsNone(dsv41_fit.not_here("UD-IQ1_M")) # offered on a Mac (not run there)
|
||||
|
||||
def test_not_in_the_list_on_a_spark_but_on_a_pc(self):
|
||||
with spark():
|
||||
|
||||
@@ -144,7 +144,7 @@ class CatalogRules(unittest.TestCase):
|
||||
with Home():
|
||||
cat = catalog(hw)
|
||||
rows = {r.model: r for r in cat.rows()}
|
||||
self.assertEqual(set(rows), {"Q2_0", "IQ3_XXS", "IQ3_S", "Gyro-S", "Gyro-M", "IST-DAS-2.00bpw", "IST-DAS-2.25bpw", "UD-IQ1_S"}) # DeepSeek (0.2.7.1): the two IST-DAS sets run on a Mac, UD-IQ1_S since f-039
|
||||
self.assertEqual(set(rows), {"Q2_0", "IQ3_XXS", "IQ3_S", "Gyro-S", "Gyro-M", "IST-DAS-2.00bpw", "IST-DAS-2.25bpw", "UD-IQ1_S", "UD-IQ1_M"}) # DeepSeek (0.2.7.1): the two IST-DAS sets run on a Mac, UD-IQ1_S since f-039
|
||||
self.assertEqual([r.model for r in rows.values() if r.recommended], ["Q2_0"])
|
||||
for name in ("IST-DAS-2.00bpw", "IST-DAS-2.25bpw"): # a 32 GB Mac: said plainly (mostly read from the SSD), never refused
|
||||
self.assertEqual(rows[name].family, "deepseek41")
|
||||
|
||||
Reference in new issue
Block a user