## [1.3.1] - 2026-08-20
Browse files# Changelog
All notable changes to this project are documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.3.1] - 2026-08-20
### Changed
- Standardized AutoRound int4 tier progression to position `Compact` (33%) as the top tier in automated batch runs (`02_BF16-GGUF-to-ASHQ1.py` and `ASHQ1.py --tier all`).
- Configured `INT4_MODULE_PROFILES` to target `compact` for MTP and dspark modules on AutoRound int4 lineage checkpoints.
- Introduced `ASHQ1_INCLUDE_QUALITY=1` environment variable override for selective evaluation of the 36% Quality tier on int4 lineage models.
### Removed
- Retired default generation of the `Quality` tier on AutoRound int4 lineage, reflecting empirical validation across 1B to 9B models where perplexity improvement over `Compact` (33%) remains negligible (+0.0358 PPL on 9B, below 0.04 across all tested scales).
- 02_BF16-GGUF-to-ASHQ1.py +12 -9
- ASHQ1.py +6 -4
- CHARTER.md +2 -2
- README.md +2 -2
- USAGE.md +2 -1
|
@@ -1,15 +1,15 @@
|
|
| 1 |
#!/usr/bin/env python3
|
| 2 |
r"""02_BF16-GGUF-to-ASHQ1.py — Automated ASHQ1 orchestrator.
|
| 3 |
|
| 4 |
-
Execution order: modules (mmproj, MTP…) → tiers Mini →
|
| 5 |
-
On AutoRound int4 lineage (provenance), Fidelity
|
| 6 |
-
information ceiling reached at
|
| 7 |
-
(
|
| 8 |
The COMPLETE model (including MTP head) is preferred over the no-mtp trunk:
|
| 9 |
ASHQ1 keeps the nextn layer at Q8_0 (Q6_K on int4 lineage) and excludes it from the size budget.
|
| 10 |
Final naming: model-AutoRound-ASHQ1-Compact-33pc.gguf (AutoRound lineage detected
|
| 11 |
via step 00 sidecar), model-ASHQ1-…-NNpc.gguf otherwise; mmproj-ASHQ1-Balanced-NNpc.gguf
|
| 12 |
-
(pct relative to source mmproj).
|
| 13 |
Lineage override: ASHQ1_LINEAGE=autoround|plain.
|
| 14 |
"""
|
| 15 |
import os,re,sys,subprocess
|
|
@@ -23,7 +23,7 @@ MAIN_TIERS=["mini","compact","quality","fidelity"]
|
|
| 23 |
# Longest running and least used: executed last
|
| 24 |
LAST_TIER="nano"
|
| 25 |
MODULE_PROFILES={"mtp":"fidelity","dspark":"fidelity"}
|
| 26 |
-
INT4_MODULE_PROFILES={"mtp":"
|
| 27 |
|
| 28 |
def find_file_case_insensitive(directory,filename):
|
| 29 |
for f in os.listdir(directory):
|
|
@@ -178,10 +178,13 @@ def main():
|
|
| 178 |
print(f" ℹ {len(imatrix)} imatrix file(s) merged (max method): {', '.join(os.path.basename(p) for p in imatrix)}")
|
| 179 |
|
| 180 |
int4_lineage=int4_lineage_of(main_model) if has_main_model else False
|
| 181 |
-
if int4_lineage
|
| 182 |
-
|
|
|
|
|
|
|
|
|
|
| 183 |
module_profiles=INT4_MODULE_PROFILES
|
| 184 |
-
print("\n ℹ AutoRound int4 lineage detected — Fidelity skipped (information ceiling reached), modules set to
|
| 185 |
else:
|
| 186 |
main_tiers=MAIN_TIERS
|
| 187 |
module_profiles=MODULE_PROFILES
|
|
|
|
| 1 |
#!/usr/bin/env python3
|
| 2 |
r"""02_BF16-GGUF-to-ASHQ1.py — Automated ASHQ1 orchestrator.
|
| 3 |
|
| 4 |
+
Execution order: modules (mmproj, MTP…) → tiers Mini → Compact → Nano.
|
| 5 |
+
On AutoRound int4 lineage (provenance), Fidelity and Quality are skipped by default —
|
| 6 |
+
information ceiling reached at Compact (negligible perplexity delta from 1B to 9B) —
|
| 7 |
+
and modules use Compact (overrides: ASHQ1_INCLUDE_QUALITY=1, ASHQ1_INCLUDE_FIDELITY=1).
|
| 8 |
The COMPLETE model (including MTP head) is preferred over the no-mtp trunk:
|
| 9 |
ASHQ1 keeps the nextn layer at Q8_0 (Q6_K on int4 lineage) and excludes it from the size budget.
|
| 10 |
Final naming: model-AutoRound-ASHQ1-Compact-33pc.gguf (AutoRound lineage detected
|
| 11 |
via step 00 sidecar), model-ASHQ1-…-NNpc.gguf otherwise; mmproj-ASHQ1-Balanced-NNpc.gguf
|
| 12 |
+
(pct relative to source mmproj).
|
| 13 |
Lineage override: ASHQ1_LINEAGE=autoround|plain.
|
| 14 |
"""
|
| 15 |
import os,re,sys,subprocess
|
|
|
|
| 23 |
# Longest running and least used: executed last
|
| 24 |
LAST_TIER="nano"
|
| 25 |
MODULE_PROFILES={"mtp":"fidelity","dspark":"fidelity"}
|
| 26 |
+
INT4_MODULE_PROFILES={"mtp":"compact","dspark":"compact"}
|
| 27 |
|
| 28 |
def find_file_case_insensitive(directory,filename):
|
| 29 |
for f in os.listdir(directory):
|
|
|
|
| 178 |
print(f" ℹ {len(imatrix)} imatrix file(s) merged (max method): {', '.join(os.path.basename(p) for p in imatrix)}")
|
| 179 |
|
| 180 |
int4_lineage=int4_lineage_of(main_model) if has_main_model else False
|
| 181 |
+
if int4_lineage:
|
| 182 |
+
excluded=set()
|
| 183 |
+
if os.environ.get("ASHQ1_INCLUDE_FIDELITY")!="1":excluded.add("fidelity")
|
| 184 |
+
if os.environ.get("ASHQ1_INCLUDE_QUALITY")!="1":excluded.add("quality")
|
| 185 |
+
main_tiers=[t for t in MAIN_TIERS if t not in excluded]
|
| 186 |
module_profiles=INT4_MODULE_PROFILES
|
| 187 |
+
print("\n ℹ AutoRound int4 lineage detected — Fidelity & Quality skipped (information ceiling reached at Compact), modules set to Compact. Overrides: ASHQ1_INCLUDE_QUALITY=1, ASHQ1_INCLUDE_FIDELITY=1.")
|
| 188 |
else:
|
| 189 |
main_tiers=MAIN_TIERS
|
| 190 |
module_profiles=MODULE_PROFILES
|
|
@@ -1428,7 +1428,6 @@ def resolve_tier_ratio(tier,lineage):
|
|
| 1428 |
return TIER_RATIOS[tier]
|
| 1429 |
|
| 1430 |
ALL_RATIOS=dict(TIER_RATIOS)
|
| 1431 |
-
INT4_TIER_RATIOS={"quality":0.36}
|
| 1432 |
TIER_DISPLAY={"nano":"Nano"}
|
| 1433 |
|
| 1434 |
def tier_label(tier:str)->str:
|
|
@@ -1575,9 +1574,12 @@ def tiers_main(args_list=None):
|
|
| 1575 |
print(f"ERROR: Imatrix not found: {im}")
|
| 1576 |
sys.exit(1)
|
| 1577 |
tiers=["mini","compact","quality","fidelity","nano"] if args.tier=="all" else[args.tier]
|
| 1578 |
-
if args.tier=="all" and int4_lineage_of(args.model)
|
| 1579 |
-
|
| 1580 |
-
|
|
|
|
|
|
|
|
|
|
| 1581 |
extra_args=[]
|
| 1582 |
if args.allow_q3_or_lower:extra_args.append("--allow-q3-or-lower")
|
| 1583 |
extra_args.extend(["--imatrix-method",args.imatrix_method,"--lineage",args.lineage])
|
|
|
|
| 1428 |
return TIER_RATIOS[tier]
|
| 1429 |
|
| 1430 |
ALL_RATIOS=dict(TIER_RATIOS)
|
|
|
|
| 1431 |
TIER_DISPLAY={"nano":"Nano"}
|
| 1432 |
|
| 1433 |
def tier_label(tier:str)->str:
|
|
|
|
| 1574 |
print(f"ERROR: Imatrix not found: {im}")
|
| 1575 |
sys.exit(1)
|
| 1576 |
tiers=["mini","compact","quality","fidelity","nano"] if args.tier=="all" else[args.tier]
|
| 1577 |
+
if args.tier=="all" and int4_lineage_of(args.model):
|
| 1578 |
+
if os.environ.get("ASHQ1_INCLUDE_FIDELITY")!="1" and "fidelity" in tiers:
|
| 1579 |
+
tiers.remove("fidelity")
|
| 1580 |
+
if os.environ.get("ASHQ1_INCLUDE_QUALITY")!="1" and "quality" in tiers:
|
| 1581 |
+
tiers.remove("quality")
|
| 1582 |
+
print(f" ℹ AutoRound int4 lineage detected — Fidelity & Quality skipped (information ceiling reached at Compact). Overrides: ASHQ1_INCLUDE_QUALITY=1, ASHQ1_INCLUDE_FIDELITY=1.")
|
| 1583 |
extra_args=[]
|
| 1584 |
if args.allow_q3_or_lower:extra_args.append("--allow-q3-or-lower")
|
| 1585 |
extra_args.extend(["--imatrix-method",args.imatrix_method,"--lineage",args.lineage])
|
|
@@ -52,8 +52,8 @@ When tied layers are detected (such as shared input/output embeddings or symmetr
|
|
| 52 |
When weights are derived from an AutoRound W4A16 source (recorded via `.provenance.json` sidecars):
|
| 53 |
* **Information Saturation**: Because the underlying weights have been pre-conditioned for 4-bit representations, assigning container formats above `Q5_K` yields negligible signal recovery ($\Delta \mathcal{Q} \to 0$).
|
| 54 |
* **Automated Capping**: The ASHQ1 optimizer caps attention and FFN blocks at `Q5_K`, attention gates at `Q6_K`, and MTP heads at `Q6_K`, while recurrent memory states hold `Q8_0`. The bit-budget freed by these ceilings flows to the imatrix-ranked tensors that convert it into measurable error reduction.
|
| 55 |
-
* **Tier Pruning**: On AutoRound int4 lineage, generation of the 48% `Fidelity`
|
| 56 |
-
* **Cap Saturation**: On AutoRound int4 lineage, `Compact` (33%) drives every attention and FFN projection to the `Q5_K` cap. Measured on a 9B `qwen35` source (17 091 MiB BF16): `Compact` ships 33.06%, `Quality` ships 35.49% against a 36% target. Beyond `Compact`, the
|
| 57 |
* **Discrete Ceiling**: Once every capped class saturates, the upgrade queue holds only large indivisible moves — `output` Q5_K→Q6_K at +129 MiB, `token_embd` Q6_K→Q8_0 at +235 MiB. Reachable footprints become discrete: on the reference 9B source, 35.49%, then 36.25%, then 37.62%. A target landing between two steps delivers the lower one, which the greedy scheduler reports as remaining slack.
|
| 58 |
|
| 59 |
---
|
|
|
|
| 52 |
When weights are derived from an AutoRound W4A16 source (recorded via `.provenance.json` sidecars):
|
| 53 |
* **Information Saturation**: Because the underlying weights have been pre-conditioned for 4-bit representations, assigning container formats above `Q5_K` yields negligible signal recovery ($\Delta \mathcal{Q} \to 0$).
|
| 54 |
* **Automated Capping**: The ASHQ1 optimizer caps attention and FFN blocks at `Q5_K`, attention gates at `Q6_K`, and MTP heads at `Q6_K`, while recurrent memory states hold `Q8_0`. The bit-budget freed by these ceilings flows to the imatrix-ranked tensors that convert it into measurable error reduction.
|
| 55 |
+
* **Tier Pruning**: On AutoRound int4 lineage, generation of both the 48% `Fidelity` and 36% `Quality` tiers is skipped by default, focusing compute resources on optimal `Compact` (33%), `Mini` (27%), and `Nano` (24% in the 2026-08-20 validation run) variants.
|
| 56 |
+
* **Cap Saturation**: On AutoRound int4 lineage, `Compact` (33%) drives every attention and FFN projection to the `Q5_K` cap. Measured on a 9B `qwen35` source (17 091 MiB BF16): `Compact` ships 33.06%, `Quality` ships 35.49% against a 36% target. Beyond `Compact`, the perplexity difference remains negligible across all model sizes (1B to 9B, with Δ PPL ≤ 0.0358 on 9B), as blocks 1 through 31 remain identical between tiers. `Compact` therefore represents the maximum standard tier for this lineage.
|
| 57 |
* **Discrete Ceiling**: Once every capped class saturates, the upgrade queue holds only large indivisible moves — `output` Q5_K→Q6_K at +129 MiB, `token_embd` Q6_K→Q8_0 at +235 MiB. Reachable footprints become discrete: on the reference 9B source, 35.49%, then 36.25%, then 37.62%. A target landing between two steps delivers the lower one, which the greedy scheduler reports as remaining slack.
|
| 58 |
|
| 59 |
---
|
|
@@ -70,9 +70,9 @@ All tiers maintain strict byte-budget percentages relative to the original unqua
|
|
| 70 |
|
| 71 |
*Note: Models originating from an AutoRound int4 lineage cap their weight allocations at `Q5_K`, as theoretical information saturation is fully realized. Attention gates settle at `Q6_K` and recurrent states at `Q8_0` on that lineage, and every tensor missing from the imatrix keeps `IQ4_XS` or above.*
|
| 72 |
|
| 73 |
-
> **Int4 lineage tier ladder**: `Compact` (33%) already drives every attention and FFN projection to the `Q5_K` cap.
|
| 74 |
>
|
| 75 |
-
> Measured on a 9B `qwen35` source (17 091 MiB BF16): Nano **24.02%**, Mini **27.01%**, Compact **33.06%**
|
| 76 |
|
| 77 |
### Perplexity Benchmarks (Ornith-1.5-9B)
|
| 78 |
|
|
|
|
| 70 |
|
| 71 |
*Note: Models originating from an AutoRound int4 lineage cap their weight allocations at `Q5_K`, as theoretical information saturation is fully realized. Attention gates settle at `Q6_K` and recurrent states at `Q8_0` on that lineage, and every tensor missing from the imatrix keeps `IQ4_XS` or above.*
|
| 72 |
|
| 73 |
+
> **Int4 lineage tier ladder**: `Compact` (33%) already drives every attention and FFN projection to the `Q5_K` cap. Because the perplexity gain beyond `Compact` is near-zero across all model sizes (1B to 9B, with Δ PPL ≤ 0.0358), `Compact` serves as the top tier on this lineage. Both `Quality` and `Fidelity` are skipped by default.
|
| 74 |
>
|
| 75 |
+
> Measured on a 9B `qwen35` source (17 091 MiB BF16): Nano **24.02%**, Mini **27.01%**, Compact **33.06%**.
|
| 76 |
|
| 77 |
### Perplexity Benchmarks (Ornith-1.5-9B)
|
| 78 |
|
|
@@ -77,7 +77,7 @@ python 01_create-calibration-dataset-and-imatrix.py --cpu-only
|
|
| 77 |
Run script `02` to orchestrate multi-tier quantization:
|
| 78 |
|
| 79 |
```bash
|
| 80 |
-
# Quantize all standard tiers (Nano, Mini, Compact
|
| 81 |
python 02_BF16-GGUF-to-ASHQ1.py
|
| 82 |
```
|
| 83 |
|
|
@@ -120,6 +120,7 @@ Configure runtime behavior via optional environment variables:
|
|
| 120 |
| Variable | Values | Purpose |
|
| 121 |
| :--- | :---: | :--- |
|
| 122 |
| `ASHQ1_LINEAGE` | `auto`, `autoround`, `plain` | Overrides the file naming lineage tag. |
|
|
|
|
| 123 |
| `ASHQ1_INCLUDE_FIDELITY` | `1`, `0` | Forces generation of the 48% Fidelity tier on int4 lineage models. |
|
| 124 |
| `GGML_CUDA_ENABLE_UNIFIED_MEMORY` | `1`, `0` | Enables CUDA unified memory for large activation processing in `llama-imatrix`. |
|
| 125 |
| `LLAMA_CPP_DIR` | `/path/to/llama.cpp` | Specifies custom path to `llama.cpp` binaries. |
|
|
|
|
| 77 |
Run script `02` to orchestrate multi-tier quantization:
|
| 78 |
|
| 79 |
```bash
|
| 80 |
+
# Quantize all standard tiers (Nano, Mini, Compact on AutoRound int4; + Quality on plain BF16) + mmproj
|
| 81 |
python 02_BF16-GGUF-to-ASHQ1.py
|
| 82 |
```
|
| 83 |
|
|
|
|
| 120 |
| Variable | Values | Purpose |
|
| 121 |
| :--- | :---: | :--- |
|
| 122 |
| `ASHQ1_LINEAGE` | `auto`, `autoround`, `plain` | Overrides the file naming lineage tag. |
|
| 123 |
+
| `ASHQ1_INCLUDE_QUALITY` | `1`, `0` | Forces generation of the 36% Quality tier on int4 lineage models. |
|
| 124 |
| `ASHQ1_INCLUDE_FIDELITY` | `1`, `0` | Forces generation of the 48% Fidelity tier on int4 lineage models. |
|
| 125 |
| `GGML_CUDA_ENABLE_UNIFIED_MEMORY` | `1`, `0` | Enables CUDA unified memory for large activation processing in `llama-imatrix`. |
|
| 126 |
| `LLAMA_CPP_DIR` | `/path/to/llama.cpp` | Specifies custom path to `llama.cpp` binaries. |
|