Joakimpalm-Zen commited on
Commit
28bb939
·
verified ·
1 Parent(s): 36ba122

merge study: --merge-lora artifacts — Q4 merge erases the adapter (measured), Q8_0/F16 preserve it; standalone merged-Q8_0 + provenance

Browse files
.gitattributes CHANGED
@@ -37,3 +37,4 @@ Qwen3-4B-ToolUse-LoRA.gguf filter=lfs diff=lfs merge=lfs -text
37
  study/adapter-trained-through-Q4_K_M.gguf filter=lfs diff=lfs merge=lfs -text
38
  study/adapter-trained-through-Q8_0.gguf filter=lfs diff=lfs merge=lfs -text
39
  study/adapter-trained-through-bf16.gguf filter=lfs diff=lfs merge=lfs -text
 
 
37
  study/adapter-trained-through-Q4_K_M.gguf filter=lfs diff=lfs merge=lfs -text
38
  study/adapter-trained-through-Q8_0.gguf filter=lfs diff=lfs merge=lfs -text
39
  study/adapter-trained-through-bf16.gguf filter=lfs diff=lfs merge=lfs -text
40
+ merged/merged-Q8_0.gguf filter=lfs diff=lfs merge=lfs -text
README.md CHANGED
@@ -100,19 +100,48 @@ difference costs nothing: every adapter scores 1.000, and the bf16- and
100
  Q8-trained adapters drop onto the Q4_K_M serving base at 1.000 too. All
101
  three study adapters and their provenance records are in `study/`.
102
 
103
- ## Measured envelope (adaptation D7)
104
 
105
- `Qwen3-4B-ToolUse-LoRA.gguf.envelope.json` — the adapter's measured
106
- compatibility record against its base, dated:
 
 
 
107
 
108
- | axis | measured |
109
- |---|---|
110
- | task capability | right-tool 0.724 → 1.000, exact-call 0.690 → 1.000 (held-out, n=29) |
111
- | neutral-corpus drift | nll/token 4.063 → 4.026 over 490 scored tokens (Δ −0.037 — the adapter leaves unrelated text alone) |
112
- | identity | adapter + base sha256 pinned in the sidecar |
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
 
114
- A dated observation, never a standing property: rerun the two `--score`
115
- commands against the shas above to re-measure it yourself.
116
 
117
  ## Honest limits
118
 
@@ -131,5 +160,9 @@ commands against the shas above to re-measure it yourself.
131
 
132
  - `Qwen3-4B-ToolUse-LoRA.gguf` — the adapter (+ `.train.json` provenance)
133
  - `data/` — the deterministic dataset (train + held-out eval)
134
- - `evals/` — every eval JSON quoted above, unedited
 
135
  - `study/` — the three precision-study adapters, provenance, divergence
 
 
 
 
100
  Q8-trained adapters drop onto the Q4_K_M serving base at 1.000 too. All
101
  three study adapters and their provenance records are in `study/`.
102
 
103
+ ## The merge study (`merged/`) — or: why this repo ships an adapter
104
 
105
+ Runner's `--merge-lora` folds the adapter into the base weights
106
+ (`W' = W + (alpha/r)·B·A`, deterministic: same inputs → byte-identical
107
+ merged file) so the result runs in **any** GGUF runtime. We merged this
108
+ adapter into three output precisions of the same Q4_K_M base and re-ran
109
+ the held-out eval on each standalone file:
110
 
111
+ | merged into | right tool | exact call | verdict |
112
+ |---|---|---|---|
113
+ | Q4_K_M (base's own type) | 0.724 | 0.690 | **adapter erased — scores exactly the base** |
114
+ | Q8_0 | **1.000** | **1.000** | behavior fully preserved |
115
+ | F16 | **1.000** | **1.000** | behavior fully preserved |
116
+
117
+ The 4-bit merge is not slightly worse — it reproduces the base's numbers
118
+ to the prompt. Byte-level comparison shows why: after requantizing to
119
+ Q4_K_M, only **1.45% of weight bytes differ from the base** — the LoRA
120
+ delta is small relative to the 4-bit grid step, so quantization rounds it
121
+ back to the original codes almost everywhere. The visible symptom (via
122
+ stock llama.cpp b10581, raw completion): the Q8_0 and F16 merges answer
123
+ with JSON only, exactly as trained; the Q4_K_M merge answers, then drifts
124
+ into conversational prose — the base's behavior.
125
+
126
+ **Deployment guidance, measured:** to serve 4-bit with this adaptation,
127
+ serve `base + --lora` (exact, and how the 1.000 row above is produced).
128
+ To ship a standalone merged file, merge into Q8_0 or wider and *measure
129
+ it* — this repo's `merged/merged-Q8_0.gguf` is that artifact, verified
130
+ 1.000 on the eval and runnable in stock llama.cpp. Merging into a 4-bit
131
+ base is where fine-tunes silently disappear; if you do it anywhere, eval
132
+ the merged file, not the adapter.
133
+
134
+ The Q4_K_M and F16 merges are not uploaded (one is behaviorally the base,
135
+ the other is 8 GB); their provenance records with sha256s are in
136
+ `merged/`, and because the merge is deterministic, one command reproduces
137
+ either file byte-for-byte:
138
+
139
+ ```sh
140
+ runner -m Qwen_Qwen3-4B-Q4_K_M.gguf --lora Qwen3-4B-ToolUse-LoRA.gguf \
141
+ --merge-lora merged-Q4_K_M.gguf # sha256 17443f0d55f5bb33…
142
+ ```
143
 
144
+ (`--merge-lora` needs runner newer than v0.2.0 — main at `54fe720`+.)
 
145
 
146
  ## Honest limits
147
 
 
160
 
161
  - `Qwen3-4B-ToolUse-LoRA.gguf` — the adapter (+ `.train.json` provenance)
162
  - `data/` — the deterministic dataset (train + held-out eval)
163
+ - `evals/` — every eval JSON quoted above, unedited (incl. the three
164
+ merged-artifact evals)
165
  - `study/` — the three precision-study adapters, provenance, divergence
166
+ - `merged/` — the standalone merged Q8_0 GGUF (runs in any GGUF runtime,
167
+ verified 1.000 on the eval and smoke-tested in llama.cpp b10581) +
168
+ `.merge.json` provenance for all three merge targets
evals/merged-F16.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"model": "merged-F16.gguf", "adapter": false, "n": 29, "json_parses": 1.0, "right_tool": 1.0, "schema_args": 1.0, "exact_call": 1.0}
evals/merged-Q4_K_M.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"model": "merged-Q4_K_M.gguf", "adapter": false, "n": 29, "json_parses": 1.0, "right_tool": 0.7241, "schema_args": 0.7241, "exact_call": 0.6897}
evals/merged-Q8_0.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"model": "merged-Q8_0.gguf", "adapter": false, "n": 29, "json_parses": 1.0, "right_tool": 1.0, "schema_args": 1.0, "exact_call": 1.0}
merged/merged-F16.gguf.merge.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"schema_version":"xyntetik.runner.merge.v1","runner":"0.2.0","base":{"path":"/home/lab/workspace/models/Qwen3-4B-tooluse/Qwen_Qwen3-4B-Q4_K_M.gguf","sha256":"fbe1d5edd4ce802ae3ae7c7e4ab7d09789d697fdac1fc7929f8df4ca3c41bae3"},"adapter":{"path":"/tmp/hf-repo/Qwen3-4B-ToolUse-LoRA.gguf","sha256":"ea38f80c33d381c9aa62c874920d2fa058dd307e7186e9b7c347d782f35b88e4"},"lora_scale":1,"target":"f16","merged":{"path":"/home/lab/workspace/models/Qwen3-4B-tooluse/merged-F16.gguf","sha256":"95f9a45d1859a6dcfdd34908066a3503ed18fd3c9104cafaf2e073823458f250"}}
merged/merged-Q4_K_M.gguf.merge.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"schema_version":"xyntetik.runner.merge.v1","runner":"0.2.0","base":{"path":"/home/lab/workspace/models/Qwen3-4B-tooluse/Qwen_Qwen3-4B-Q4_K_M.gguf","sha256":"fbe1d5edd4ce802ae3ae7c7e4ab7d09789d697fdac1fc7929f8df4ca3c41bae3"},"adapter":{"path":"/tmp/hf-repo/Qwen3-4B-ToolUse-LoRA.gguf","sha256":"ea38f80c33d381c9aa62c874920d2fa058dd307e7186e9b7c347d782f35b88e4"},"lora_scale":1,"target":"keep","merged":{"path":"/home/lab/workspace/models/Qwen3-4B-tooluse/merged-Q4_K_M.gguf","sha256":"17443f0d55f5bb33d1de4ae3529446d42c2d9f06f258d160b4d2a9176b9cc9f1"}}
merged/merged-Q8_0.gguf ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b9d21e525d91b20a1fc3437cf34c7ecfa03afda722d960b95bcfd113f2b7ea02
3
+ size 4280405440
merged/merged-Q8_0.gguf.merge.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"schema_version":"xyntetik.runner.merge.v1","runner":"0.2.0","base":{"path":"/home/lab/workspace/models/Qwen3-4B-tooluse/Qwen_Qwen3-4B-Q4_K_M.gguf","sha256":"fbe1d5edd4ce802ae3ae7c7e4ab7d09789d697fdac1fc7929f8df4ca3c41bae3"},"adapter":{"path":"/tmp/hf-repo/Qwen3-4B-ToolUse-LoRA.gguf","sha256":"ea38f80c33d381c9aa62c874920d2fa058dd307e7186e9b7c347d782f35b88e4"},"lora_scale":1,"target":"q8_0","merged":{"path":"/home/lab/workspace/models/Qwen3-4B-tooluse/merged-Q8_0.gguf","sha256":"b9d21e525d91b20a1fc3437cf34c7ecfa03afda722d960b95bcfd113f2b7ea02"}}