Skip to content

llama: support tied Hadamard output weights (contract version 2) - #257

Merged
khosravipasha merged 1 commit into
prismfrom
hadamard/tied-output-runtime
Sep 24, 2026
Merged

khosravipasha merged 1 commit into
prismfrom
hadamard/tied-output-runtime

Conversation

@bri-prism

Copy link
Copy Markdown
Collaborator

What

GGUF Hadamard contract version 2, with prism.hadamard.tied_output, so a Hadamard-folded model with tied embeddings can store its latent token embedding once and use it for both lookup and the output projection. Until now a tied pack had to carry a byte-identical copy of the embedding as output.weight.

  • Loader: version 2 requires tied_output=true and no output.weight; version 1 forbids the flag. The output projection gets its forward transform from the embedding's block size and signs, bound to whichever tensor the output actually uses, which can be a separate allocation on another device.
  • Graph verifier: rejects a latent lookup table consumed by a matmul without a registered forward transform.
  • Converter: accepts manifest schema 3 (tied_output=true, a tied HF config, no separate head) and writes contract version 2. Schema 3 makes older converters reject the manifest instead of silently ignoring the flag.
  • Docs: docs/development/hadamard-tied-output.md describes the contract.

Why

Our export tooling now omits the duplicate head for tied models and emits schema 3. Without this change those files can't be loaded; with it, the tied 2B band is 135 MB smaller, with identical output.

Compatibility

Version-1 files load exactly as before. A runtime without this change refuses a version-2 file at load with unsupported prism.hadamard.version: 2, so version-2 files should only be published once a release carries this.

How it was checked

A 2B PQ2_0 band rewritten to version 2, with the duplicate output.weight removed and data repacked, compared against the original file. 8 x 512-token perplexity chunks, KL divergence against saved logits:

Metal CPU (-dev none)
version-2 tied file vs original, this branch max KLD 5.0e-5, top-1 100% max KLD 4.2e-5, top-1 100%
parent commit vs this branch, original file max KLD 5.0e-5, top-1 100% max KLD 4.2e-5, top-1 100%

Both rows sit at the saved-logit floor (the second row is the no-change control), so the tied file matches the duplicate-head file and version-1 behaviour is unchanged. The release build b10685 refuses the version-2 file cleanly. Not checked: CUDA, Vulkan, SYCL and HIP; the 4B; vision.

A Hadamard-folded model with tied embeddings stores its latent token
embedding once and uses it for both row lookup and the output projection.
Until now the packer had to ship a byte-identical copy as output.weight so
the output matmul went through the normal folded-weight path.

This adds GGUF Hadamard contract version 2 with prism.hadamard.tied_output:

- Loader: version 2 requires tied_output=true and no output.weight, and
  version 1 forbids the flag. The output projection gets its forward
  transform from the embedding's block size and signs, bound to whichever
  tensor the output actually uses (a separate allocation when placed on
  another device).
- Graph verifier: rejects a latent lookup table consumed by a matmul
  without a registered forward transform.
- Converter: accepts manifest schema 3 with tied_output=true, a tied HF
  config and no separate head, and writes contract version 2. Schema 3
  makes older converters reject the manifest instead of ignoring the flag.

Version-1 files are unchanged, and a runtime without this change refuses
version 2 at load ("unsupported prism.hadamard.version: 2").

Checked on a 2B PQ2_0 band, rewritten to version 2 with the duplicate head
removed (135 MB smaller): 8x512 perplexity chunks give KLD and top-1
agreement against the original at the logit-file floor on both Metal and
CPU (max KLD 5.0e-5 / 4.2e-5, top-1 100%), matching the parent commit's
own result on the original file.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

conversion documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants