Skip to content

nemotron : support non-standard GQA, BPE tokenizer and domyn-small pre-type - #23343

Merged
CISC merged 5 commits into
ggml-org:masterfrom
martin-cimmino:fix/vocab-minerva-metaspace
Oct 22, 2026
Merged

CISC merged 5 commits into
ggml-org:masterfrom
martin-cimmino:fix/vocab-minerva-metaspace

Conversation

@martin-cimmino

@martin-cimmino martin-cimmino commented May 19, 2026 •

Copy link
Copy Markdown
Contributor

Overview

This PR adds support for domyn/Domyn-Small-v1.0, fixing issues in both the vocab decoder and the Nemotron model loader/converter.

Vocab decoder: without a dedicated pre-tokenizer type, the current code routes the Domyn-Small tokenizer through the generic GPT-2 BPE decode path, which cannot handle Metaspace-encoded spaces (▁ U+2581) and produces corrupted output for every space-prefixed token. This PR adds LLAMA_VOCAB_PRE_TYPE_DOMYN_SMALL = 52 in llama-vocab.h and a new branch in llama-vocab.cpp that sets escape_whitespaces = true. Domyn-Small shares the same regex rules as minerva-7b (same tokenizer family), but we kept that path untouched and added a new key.

Nemotron model loader: create_tensor_qkv was called with n_embd for the Q-projection width and layer.wo was shaped as {n_embd, n_embd}. For a 48-head model like Domyn-Small this causes a tensor shape mismatch crash on load. Fixed to use n_embd_head_k * n_head explicitly for both.

Nemotron converter: the formula int(rot_pct * n_embd) // n_head produces 42 for a 48-head model instead of the correct 64. Fixed to read head_dim from the model config (falling back to n_embd // n_head if absent). Additionally, NemotronModel.set_vocab() unconditionally called _set_vocab_sentencepiece(), crashing when no tokenizer.model file is present. Added a fallback to _set_vocab_gpt2() for BPE-only tokenizers, and registered the Domyn-Small tokenizer hash in get_vocab_base_pre().

Additional information

Tested with domyn/Domyn-Small-v1.0 (BF16 GGUF, 45/45 CTest pass).

Note that this PR only affects models that already have tokenizer.ggml.pre = "domyn-small" in their GGUF.

Hugging Face model link at https://huggingface.co/domyn/Domyn-Small-v1.0

Requirements

  • I have read and agree with the contributing guidelines
  • AI usage disclosure: Yes, I used Claude Code to help locate relevant code paths and draft this PR description. All changes were reviewed and tested by me.

@martin-cimmino
martin-cimmino requested a review from CISC as a code owner May 19, 2026 14:52
@ggml-gh-bot

This comment was marked as resolved.

@martin-cimmino

Copy link
Copy Markdown
Contributor Author

I think there was a mistake in classifying this PR as AI generated

@CISC

CISC commented May 19, 2026

Copy link
Copy Markdown
Member

Note that this PR only affects models that already have tokenizer.ggml.pre = "domyn-small" in their GGUF.

And how would they get that? :)

This value needs to be introduced at conversion, does this model have a unique tokenizer chkhsh?

@martin-cimmino

Copy link
Copy Markdown
Contributor Author

Yes, the "domyn-small" string is written during conversion by the companion PR at #23391.

chkhsh = 6e4d72c6e5260b90606e26a0931fa15e4b42ec6e97719d12919f2b1f93478262
That hash is unique to the Domyn-Small-v1.0 tokenizer.

Happy to combine them into a single PR if that's preferred.

@CISC

CISC commented May 20, 2026

Copy link
Copy Markdown
Member

Happy to combine them into a single PR if that's preferred.

Yes, makes no sense to separate them, one does not work without the other.

@martin-cimmino

martin-cimmino commented May 20, 2026 •

Copy link
Copy Markdown
Contributor Author

@CISC Done, I've also updated the PR description.

@martin-cimmino
martin-cimmino force-pushed the fix/vocab-minerva-metaspace branch from c7a2ea1 to 6652333 Compare May 20, 2026 09:38
@martin-cimmino
martin-cimmino requested a review from a team as a code owner May 20, 2026 09:38
@martin-cimmino
martin-cimmino force-pushed the fix/vocab-minerva-metaspace branch from 6652333 to af15aee Compare May 20, 2026 09:39
@martin-cimmino martin-cimmino changed the title vocab : add domyn-small Metaspace BPE pre-tokenizer type nemotron : support non-standard GQA, BPE tokenizer and domyn-small pre-type May 20, 2026
@github-actions github-actions Bot added model Model specific python python script changes labels May 20, 2026
@martin-cimmino

Copy link
Copy Markdown
Contributor Author

@CISC friendly ping on this one when you have a moment 🙏 I've combined the two PRs as you suggested and the branch is ready for another look. No rush — just flagging it in case it got buried. Happy to make any further changes.

@CISC

CISC commented May 27, 2026

Copy link
Copy Markdown
Member

@CISC friendly ping on this one when you have a moment 🙏 I've combined the two PRs as you suggested and the branch is ready for another look. No rush — just flagging it in case it got buried. Happy to make any further changes.

It's in my queue, however this one requires checking that we do not break any nemotron models, so might be in the queue a while.

@Jeronymous

Copy link
Copy Markdown

@martin-cimmino @CISC could this get rebased and merged? I just hit the exact bug it fixes and opened #30518: another public Nemotron model won't load (with a head_dim that doesn't match hidden_size/num_heads), involving the same attn_q shape mismatch as this PR solves. It would be a shame to let it stall since the fix is already here.

this one requires checking that we do not break any nemotron models

For what it's worth I went through the diff and the regression surface looks tiny: for standard Nemotron (head_dim = hidden/n_heads), n_embd_head_k * n_head == n_embd, so the Q/wo shapes are unchanged and K/V already used n_embd_gqa; the rope change falls back to n_embd // n_head, which gives the same rope_dimension_count as before; and set_vocab only adds an else-branch for models without a tokenizer.model, so sentencepiece ones are untouched. The only things that actually change are for the decoupled-head_dim case that can't load today.

@CISC

CISC commented Oct 15, 2026

Copy link
Copy Markdown
Member

Sorry for the delay.

@martin-cimmino Can you rebase and update convert_hf_to_gguf_update.py with an entry for the model?

@martin-cimmino
martin-cimmino force-pushed the fix/vocab-minerva-metaspace branch from 6a297f2 to d8634d1 Compare October 15, 2026 08:49
@martin-cimmino
martin-cimmino force-pushed the fix/vocab-minerva-metaspace branch from d8634d1 to 03a1ebb Compare October 15, 2026 09:42
@martin-cimmino

Copy link
Copy Markdown
Contributor Author

Hello @CISC, I rebased and updated the convert_hf_to_gguf_update.py as suggested.

However, while debugging and testing the generation I noticed something I overlooked in the past changes. The old version tokenized wrong, It used GPT-2 byte-level BPE but Domyn-Small is SentencePiece-style BPE. Basically, spaces came out as junk tokens, newlines were dropped, and <0x0A> appeared literally in the output. So I decided to reuse the existing Sarvam/Gemma4 SPM-style BPE path with two small additions: ▁ is added only at the start of the input, matching HF's Metaspace prepend_scheme: "first" and llama_detokenize strips that leading space again.

Also, I compared master vs this PR for Nemotron-Mini-4B checking that the converted GGUFs are byte-identical, as well as perplexity and generated output.

This should fix #30518, however @Jeronymous it would be good if you test your model on this branch.

Comment thread conversion/nemotron.py Resolved
Comment thread src/llama-vocab.cpp Resolved
Comment thread gguf-py/gguf/constants.py Resolved
Comment thread src/llama-vocab.cpp Resolved
@Jeronymous

Copy link
Copy Markdown

This should fix #30518, however @Jeronymous it would be good if you test your model on this branch.

Thanks @martin-cimmino.

I tested my model on this branch. With the loader fix it now loads and generates correctly.
Also no regression on standard Nemotron (I tested Luciole-1B-Instruct-1.1 and Luciole-23B-Instruct-1.1).

Concerning the conversion, I do it on a special fork (because of our special tokenizer) and I could test that your fix on the rope dimension works well for me as well.

@CISC CISC left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add TODOs for prepend_scheme for other tokenizers.

Comment thread src/llama-vocab.cpp Resolved
@martin-cimmino
martin-cimmino force-pushed the fix/vocab-minerva-metaspace branch from 4c75394 to 751ee47 Compare October 15, 2026 17:43
@CISC
CISC requested review from danbev and removed request for a team October 15, 2026 17:51
@martin-cimmino
martin-cimmino force-pushed the fix/vocab-minerva-metaspace branch from 751ee47 to 0e963d0 Compare October 21, 2026 08:57
@CISC

CISC commented Oct 21, 2026

Copy link
Copy Markdown
Member

@danbev gentle ping

Comment thread src/llama-vocab.cpp Resolved
@CISC CISC added the merge ready A maintainer can use this label to indicate that they consider the changes final and ready to merge. label Oct 21, 2026
@ggerganov

Copy link
Copy Markdown
Member

Needs rebase

@CISC CISC removed the merge ready A maintainer can use this label to indicate that they consider the changes final and ready to merge. label Oct 22, 2026
@martin-cimmino
martin-cimmino force-pushed the fix/vocab-minerva-metaspace branch from 98d6c00 to 6ed5f6a Compare October 22, 2026 09:36
@martin-cimmino

Copy link
Copy Markdown
Contributor Author

Needs rebase

Rebased. I moved Domyn-Small's pre-type number to 63 because Flint took 62.

@CISC
CISC merged commit 0693dbf into ggml-org:master Oct 22, 2026
23 checks passed
auRose94 pushed a commit to auRose94/llama.cpp that referenced this pull request Oct 28, 2026
…e-type (ggml-org#23343)

* nemotron : support non-standard GQA, BPE tokenizer and domyn-small pre-type

* gguf-py : write Metaspace prepend_scheme as GGUF metadata

* vocab : parse metaspace prepend_scheme into enum, rename key

* vocab : use metaspace prepend_scheme in detokenize, add TODOs for other tokenizers

* vocab : use constant for metaspace escaped space

---------

Co-authored-by: Martin Cimmino <martin.cimmino@domyn.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

conversion model Model specific python python script changes

Projects

None yet

6 participants