From e4e805867e0f46eea551884f5f46bf0c9d7ae2e1 Mon Sep 17 00:00:00 2001 From: Nyarlathoteppppp Date: Thu, 29 Oct 2026 13:44:53 +1100 Subject: [PATCH] App load and tune keep a DeepSeek model's --vision on/off pair and drop only a bare --vision when picture reading is off; quant_quality does the same (#4507) --- apps/host/server/native-control.mjs | 2 +- apps/host/tests/draft-layer.test.mjs | 15 +++++++++++++++ tests/terminal/test_launch_vision_value.py | 19 +++++++++++++++++++ tools/quant_quality.py | 2 +- 4 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 tests/terminal/test_launch_vision_value.py diff --git a/apps/host/server/native-control.mjs b/apps/host/server/native-control.mjs index 895ec054f5c..81f1053fc5e 100644 --- a/apps/host/server/native-control.mjs +++ b/apps/host/server/native-control.mjs @@ -243,7 +243,7 @@ return {summary:result.summary??'Deleted',removed:result.plan?.gb??null};} if(cfg.vision){if(cfg.vision_tokens!=null)cfg.vision={...cfg.vision,max_tokens:cfg.vision_tokens};if(cfg.vision_min_tokens!=null)cfg.vision={...cfg.vision,min_tokens:cfg.vision_min_tokens};}cfg.mcp={...(cfg.mcp??{}),...(cfg.mcp_timeout_s!=null?{timeout_s:cfg.mcp_timeout_s}:{}),...(cfg.mcp_max_rounds!=null?{max_rounds:cfg.mcp_max_rounds}:{}),...(cfg.mcp_max_result_chars!=null?{max_result_chars:cfg.mcp_max_result_chars}:{})}; /* The model's own choices win over what setup wrote into the arguments: "Draft layer (MTP)" off leaves --mtp out of every start, and a picture reading that is off leaves --vision out (setup writes both again whenever it runs; the saved settings are applied here, on every load). */ if((cfg.mtp===false||cfg.drafting==='off')&&Array.isArray(cfg.args))cfg.args=withoutDraftLayer(cfg.args); - if(!cfg.vision&&Array.isArray(cfg.args))cfg.args=cfg.args.filter(a=>a!=='--vision'); + if(!cfg.vision&&Array.isArray(cfg.args))cfg.args=cfg.args.filter((a,i,list)=>a!=='--vision'||(i+1 { + for (const vision of [['--vision', 'off'], ['--vision', 'on'], ['--vision']]) { + for (const tail of [[], ['--dspark', 'none']]) { + const base = ['--pack', '/p', '--eos', '1']; + const f = fixture({ arch: 'deepseek41', exe: 'strata-dsv41', args: [...base, ...vision, ...tail] }); + try { + await f.native.refresh(true); + const job = await finish(f.native, f.native.operation('load', { model: 'q2_0' }).id); + assert.equal(job.state, 'done', job.error); + assert.deepEqual(f.saved[0].args, [...base, ...(vision.length===2?vision:[]), ...tail]); + } finally { await f.native.close(); f.cleanup(); } + } + } +}); + test('picture reading on keeps --vision; the Models screen sees the prepared pictures instead of "off"', async () => { const f = fixture({ vision: visionSection }); try { diff --git a/tests/terminal/test_launch_vision_value.py b/tests/terminal/test_launch_vision_value.py new file mode 100644 index 00000000000..6a3f25fbe46 --- /dev/null +++ b/tests/terminal/test_launch_vision_value.py @@ -0,0 +1,19 @@ +"""DeepSeek's valued picture option stays intact (#4507).""" +import unittest + +from tools.quant_quality import engine_args + + +class VisionValue(unittest.TestCase): + def test_quant_quality_keeps_valued_vision(self): + base = ["--pack", "/p", "--eos", "1"] + for vision in (["--vision", "off"], ["--vision", "on"], ["--vision"]): + for tail in ([], ["--dspark", "none"]): + args = base + vision + tail + with self.subTest(vision=vision, tail=tail): + cfg = {"exe": "strata-dsv41", "arch": "deepseek41", "args": args} + expected = engine_args({**cfg, "args": base + tail}, None, 512) + if len(vision) == 2: + expected[2 + len(base):2 + len(base)] = vision + self.assertEqual(engine_args(cfg, None, 512), expected) + self.assertEqual(cfg["args"], args) diff --git a/tools/quant_quality.py b/tools/quant_quality.py index 10065e3a0ae..89b4e50a088 100644 --- a/tools/quant_quality.py +++ b/tools/quant_quality.py @@ -85,7 +85,7 @@ def engine_args(cfg: dict, gpu_experts, seg_tokens: int) -> list[str]: base, out, i = list(cfg["args"]), [], 0 while i < len(base): x = base[i] - if x in DROP_FLAG: + if x in DROP_FLAG and not (x == "--vision" and i + 1 < len(base) and not base[i + 1].startswith("--")): i += 1 continue if x in DROP_VALUE: