Skip to content

Commit 09ce1a4

Browse files
committed
Merge b10796 into the projector registry test
2 parents 7ad7512 + 9a4843c commit 09ce1a4

134 files changed

Lines changed: 26652 additions & 700 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/server-sanitize.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ jobs:
103103
source .venv/bin/activate
104104
cd tools/server/tests
105105
export ${{ matrix.extra_args }}
106-
./tests.sh
106+
PYTEST_WORKERS=1 ./tests.sh
107107
108108
- name: Slow tests
109109
id: server_integration_tests_slow
@@ -112,4 +112,4 @@ jobs:
112112
source .venv/bin/activate
113113
cd tools/server/tests
114114
export ${{ matrix.extra_args }}
115-
SLOW_TESTS=1 ./tests.sh
115+
PYTEST_WORKERS=1 SLOW_TESTS=1 ./tests.sh

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ The `llama.cpp` project is build on top of the [ggml](https://github.com/ggml-or
7474
| [CANN](docs/build.md#cann) | Ascend NPU |
7575
| [CUDA](docs/build.md#cuda) | Nvidia GPU |
7676
| [HIP](docs/build.md#hip) | AMD GPU |
77-
| [Hexagon [In Progress]](docs/backend/snapdragon/README.md) | Snapdragon |
77+
| [Hexagon](docs/backend/snapdragon/README.md) | Snapdragon |
7878
| [IBM zDNN](docs/backend/zDNN.md) | IBM Z & LinuxONE |
7979
| [MUSA](docs/build.md#musa) | Moore Threads GPU |
8080
| [Metal](docs/build.md#metal-build) | Apple Silicon |

common/json-schema-to-grammar.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,10 @@ class common_schema_converter {
748748
optional_props.push_back("*");
749749
}
750750

751+
if (required_props.empty() && optional_props.empty()) {
752+
return "\"{\" space \"}\"";
753+
}
754+
751755
std::string rule = "\"{\" space ";
752756
for (size_t i = 0; i < required_props.size(); i++) {
753757
if (i > 0) {

conversion/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@
188188
"NanbeigeForCausalLM": "nanbeige",
189189
"NemotronForCausalLM": "nemotron",
190190
"NemotronHForCausalLM": "nemotron",
191+
"NemotronHPuzzleForCausalLM": "nemotron",
191192
"NeoBERT": "bert",
192193
"NeoBERTForSequenceClassification": "bert",
193194
"NeoBERTLMHead": "bert",

conversion/deepseek.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,6 +1007,13 @@ def _map_dsv4_tensor_name(self, name: str, bid: int | None) -> tuple[gguf.MODEL_
10071007
return self._DSPARK_ROOT_MAP[name]
10081008
return super()._map_dsv4_tensor_name(name, bid)
10091009

1010+
def modify_tensors(self, data_torch: Tensor, name: str, bid: int | None) -> Iterable[tuple[str, Tensor]]:
1011+
# the DFlash draft uses the plain exp-probs bias (ffn.gate.bias -> FFN_EXP_PROBS_B);
1012+
# the mtmd-only hash routing tensors (bias_vl, tid2eid) are not part of the DFLASH arch
1013+
if name.endswith(".ffn.gate.bias_vl"):
1014+
return
1015+
yield from super().modify_tensors(data_torch, name, bid)
1016+
10101017
def set_vocab(self):
10111018
if self.target_model_dir is None:
10121019
raise ValueError("DeepSeek-V4 DSpark requires --target-model-dir with the target tokenizer")

conversion/nemotron.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import torch
66

77
if TYPE_CHECKING:
8+
from pathlib import Path
89
from torch import Tensor
910

1011
from .base import MmprojModel, ModelBase, TextModel, gguf, logger
@@ -201,6 +202,7 @@ class NemotronHModel(GraniteHybridModel):
201202
model_arch = gguf.MODEL_ARCH.NEMOTRON_H
202203
is_moe: bool = False
203204
supports_mtp_export = True
205+
_experts: list[dict[str, Tensor]] | None = None
204206

205207
_SSM_LAYER_TYPES = {"mamba", "linear_attention"}
206208
_ATTN_LAYER_TYPES = {"attention", "full_attention"}
@@ -513,3 +515,88 @@ def prepare_tensors(self):
513515
experts = [k for d in self._experts for k in d.keys()]
514516
if len(experts) > 0:
515517
raise ValueError(f"Unprocessed experts: {experts}")
518+
519+
520+
@ModelBase.register("NemotronHPuzzleForCausalLM")
521+
@ModelBase.example("nvidia/NVIDIA-Nemotron-Labs-3-Puzzle-75B-A9B-BF16")
522+
class NemotronHPuzzleModel(NemotronHModel):
523+
"""NVIDIA Puzzle: NemotronH with a per-block MoE config (block_configs).
524+
525+
The checkpoint also ships an MTP draft head (mtp.safetensors). It is skipped
526+
here: there is no Puzzle MTP inference path in tree, and the head is laid out
527+
by mtp_block_configs rather than the mtp.layers.* form NemotronHModel maps."""
528+
529+
model_arch = gguf.MODEL_ARCH.NEMOTRON_H_MOE
530+
is_moe: bool = True
531+
supports_mtp_export = False
532+
533+
def __init__(self, dir_model: "Path", *args, **kwargs):
534+
hparams = dict(kwargs.pop("hparams", None) or ModelBase.load_hparams(dir_model, self.is_mistral_format))
535+
536+
self.block_configs: list[dict] = hparams["block_configs"]
537+
self.n_layer_trunk = len(self.block_configs)
538+
539+
# block_configs carries the per-block MoE shape, and is the authority on the
540+
# block pattern too: the layers_block_type the HF config wrapper computes is
541+
# not sized to it.
542+
hparams["num_hidden_layers"] = self.n_layer_trunk
543+
hparams["layers_block_type"] = [bc["block_type"] for bc in self.block_configs]
544+
545+
self.model_arch = gguf.MODEL_ARCH.NEMOTRON_H_MOE
546+
547+
# Bypass NemotronHModel.__init__: it assumes a flat num_experts_per_tok /
548+
# moe_intermediate_size and a layers_block_type sized to block_count, neither
549+
# of which hold for Puzzle's per-block config.
550+
GraniteHybridModel.__init__(self, dir_model, *args, hparams=hparams, **kwargs)
551+
552+
self.head_dim = self.find_hparam(["head_dim", "attention_head_dim"])
553+
self.d_inner = self.find_hparam(["num_heads"]) * self.d_model
554+
555+
# NemotronHModel.__init__ folds an MTP block into block_count when the
556+
# config carries num_nextn_predict_layers; Puzzle's config does, but its
557+
# head has a different layout and no inference path, so stay opted out.
558+
self._mtp_bid = None
559+
560+
def set_gguf_parameters(self):
561+
GraniteHybridModel.set_gguf_parameters(self)
562+
563+
head_dim = self.head_dim
564+
if head_dim is None:
565+
raise ValueError("Could not find the attention head dim in config")
566+
self.gguf_writer.add_key_length(head_dim)
567+
self.gguf_writer.add_value_length(head_dim)
568+
569+
ffn_lengths = [bc.get("moe_intermediate_size") or 0 for bc in self.block_configs]
570+
experts_used = [bc.get("num_experts_per_tok") or 0 for bc in self.block_configs]
571+
572+
self.gguf_writer.add_feed_forward_length(ffn_lengths)
573+
self.gguf_writer.add_expert_feed_forward_length(ffn_lengths)
574+
self.gguf_writer.add_expert_used_count(experts_used)
575+
576+
self.gguf_writer.add_expert_shared_feed_forward_length(self.hparams["moe_shared_expert_intermediate_size"])
577+
self.gguf_writer.add_expert_count(self.hparams["n_routed_experts"])
578+
self.gguf_writer.add_expert_shared_count(self.hparams["n_shared_experts"])
579+
self.gguf_writer.add_expert_weights_norm(self.hparams["norm_topk_prob"])
580+
self.gguf_writer.add_expert_weights_scale(self.hparams["routed_scaling_factor"])
581+
self.gguf_writer.add_expert_group_count(self.hparams["n_group"])
582+
self.gguf_writer.add_moe_latent_size(self.hparams["moe_latent_size"])
583+
584+
def modify_tensors(self, data_torch: Tensor, name: str, bid: int | None) -> Iterable[tuple[str, Tensor]]:
585+
# The official BF16 checkpoint (NVIDIA-Nemotron-Labs-3-Puzzle-75B-A9B-BF16)
586+
# names the trunk "model.*" (model.layers.*, model.embeddings, model.norm_f)
587+
# where the original release used the NemotronH-style "backbone.*", and spells
588+
# the router bias "e_score_correction_bias" instead of "e_score_correction.bias";
589+
# normalize so both convert identically.
590+
if name.startswith("model."):
591+
name = "backbone." + name[len("model."):]
592+
if name.endswith("mixer.gate.e_score_correction_bias"):
593+
name = name[: -len("e_score_correction_bias")] + "e_score_correction.bias"
594+
595+
yield from super().modify_tensors(data_torch, name, bid)
596+
597+
@classmethod
598+
def filter_tensors(cls, item: tuple[str, Callable[[], Tensor]]) -> tuple[str, Callable[[], Tensor]] | None:
599+
# Drop the MTP head unconditionally; see the class docstring.
600+
if item[0].startswith("mtp."):
601+
return None
602+
return super().filter_tensors(item)

docs/backend/SYCL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -806,7 +806,7 @@ User can use the device management in [docs/multi-gpu.md](https://github.com/ggm
806806
| GGML_SYCL_ENABLE_MKL_FA | 1 (default) or 0 | Enable oneMKL GEMM flash attention for XMX-accelerated prompt processing with quantized KV cache. Automatically activates during prefill (prompt processing) when all conditions are met: (1) flash-attn enabled (`-fa` or `--flash-attn on`), (2) KV cache quantized (`--cache-type-k q8_0 --cache-type-v q8_0` or other `*_0/*_1` types), (3) batch size ≥ 1024 (`--batch-size 1024`), (4) prompt length ≥ 1024 tokens. Set to 0 to force the TILE kernel for A/B testing. Example minimum command: `llama-cli -m model.gguf -fa -ngl 99 --cache-type-k q8_0 --cache-type-v q8_0 --batch-size 1024 -p "your prompt"` |
807807
| GGML_SYCL_MKL_FA_DEBUG | 0 (default) or 1 | Enable per-call diagnostic logging for MKL flash attention: GEMM/softmax timings, interleaved-head detection, and buffer memory usage. |
808808
| GGML_SYCL_MKL_FA_DIAG | 0 (default) or 1 | Enable output fingerprinting for MKL flash attention. Dumps the first 64 float output values for the first 6 FA calls with n_kv ≥ 1024, labeled with kernel type (MKL/TILE/VEC) for cross-kernel comparison. |
809-
| GGML_SYCL_ENABLE_FUSION | 0 or 1 (default) | Enable fused-kernel dispatch in graph compute. |
809+
| GGML_SYCL_ENABLE_FUSION | 0 or 1 (default) | Enable fused-kernel dispatch in graph compute. Unsupported types and layouts fall back to the standalone op kernels. See `ggml_sycl_can_fuse()`. |
810810
| GGML_SYCL_ENABLE_ESIMD | 0 or 1 (default)| Enable ESIMD kernels when available. |
811811
| ZES_ENABLE_SYSMAN | 0 (default) or 1 | Support to get free memory of GPU by sycl::aspect::ext_intel_free_memory.<br>Recommended to use when --split-mode = layer |
812812
| UR_L0_ENABLE_RELAXED_ALLOCATION_LIMITS | 0 (default) or 1 | Allow SYCL/Unified Runtime Level Zero device allocations larger than 4 GiB. llama.cpp's direct Level Zero allocation path requests the relaxed maximum-size limit itself when GGML_SYCL_ENABLE_LEVEL_ZERO=1. |

docs/build.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ The following sections describe how to build with different backends and options
2727
* [OpenCL](#opencl)
2828
* [Android](#android-1)
2929
* [OpenVINO](#openvino)
30+
* [Hexagon](#hexagon)
3031
* [Notes about GPU-accelerated backends](#notes-about-gpu-accelerated-backends)
3132

3233
## CPU Build
@@ -830,6 +831,9 @@ To read documentation for how to build on IBM Z & LinuxONE, [click here](./build
830831
831832
For build instructions and usage examples, refer to [OPENVINO.md](backend/OPENVINO.md).
832833
834+
### Hexagon
835+
836+
Check [README.md](./backend/snapdragon/README.md) for target specific build and run info.
833837
834838
---
835839
## Notes about GPU-accelerated backends

0 commit comments

Comments
 (0)