Skip to content

Commit 94f15b4

Browse files
authored
Merge pull request #138 from javierpazo/xabicasa/dflash-gguf-draft-loader-target-layers
fix(dflash): derive n_target_layers fallback in gguf_draft_loader
2 parents 332f7dc + da04f6f commit 94f15b4

1 file changed

Lines changed: 52 additions & 24 deletions

File tree

dflash/src/draft/draft_gguf_loader.cpp

Lines changed: 52 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,10 @@
66
// types — ggml's ggml_mul_mat handles Q8_0 × F32 dequantization transparently.
77
//
88
// GGUF arch: "qwen35-dflash-draft" (from convert_dflash_to_gguf.py /
9-
// quantize_draft_q8.py) or the newer "dflash-draft" export. Tensor naming
10-
// convention:
9+
// quantize_draft_q8.py). Tensor naming convention:
1110
//
12-
// dflash.fc.weight / dflash_fc.weight [5*hidden, hidden] Q8_0 / F16
13-
// dflash.hidden_norm.weight /
14-
// dflash_hidden_norm.weight [hidden] F32
11+
// dflash.fc.weight [5*hidden, hidden] Q8_0 / F16
12+
// dflash.hidden_norm.weight [hidden] F32
1513
// output_norm.weight [hidden] F32
1614
// blk.<i>.attn_norm.weight [hidden] F32
1715
// blk.<i>.ffn_norm.weight [hidden] F32
@@ -108,6 +106,14 @@ uint32_t get_u32_or(const gguf_context * g, const char * key, uint32_t fallback)
108106
return gguf_get_val_u32(g, id);
109107
}
110108

109+
int count_swa_layers(const DraftWeights & w) {
110+
int n_swa = 0;
111+
for (const DraftLayer & layer : w.layers) {
112+
if (layer.is_swa) n_swa++;
113+
}
114+
return n_swa;
115+
}
116+
111117
} // namespace
112118

113119
bool load_draft_gguf(const std::string & path,
@@ -126,6 +132,7 @@ bool load_draft_gguf(const std::string & path,
126132
}
127133

128134
// Validate arch
135+
std::string arch_s;
129136
{
130137
int64_t arch_id = gguf_find_key(gctx, "general.architecture");
131138
if (arch_id < 0) {
@@ -134,8 +141,8 @@ bool load_draft_gguf(const std::string & path,
134141
return false;
135142
}
136143
const char * arch = gguf_get_val_str(gctx, arch_id);
137-
if (std::string(arch) != "qwen35-dflash-draft" &&
138-
std::string(arch) != "dflash-draft") {
144+
arch_s = arch;
145+
if (arch_s != "qwen35-dflash-draft" && arch_s != "dflash-draft") {
139146
set_last_error(std::string("unexpected draft arch: ") + arch +
140147
" (expected qwen35-dflash-draft or dflash-draft)");
141148
gguf_free(gctx);
@@ -144,8 +151,7 @@ bool load_draft_gguf(const std::string & path,
144151
}
145152

146153
// Read dimensions from GGUF metadata
147-
int64_t arch_id = gguf_find_key(gctx, "general.architecture");
148-
const char * A = gguf_get_val_str(gctx, arch_id);
154+
const char * A = arch_s.c_str();
149155
char key[128];
150156

151157
auto read_u32 = [&](const char * suffix, uint32_t fallback) -> uint32_t {
@@ -162,16 +168,17 @@ bool load_draft_gguf(const std::string & path,
162168
const uint32_t block_sz = read_u32("dflash.block_size", 0);
163169
uint32_t n_tgt_lay = read_u32("dflash.n_target_layers", 0);
164170
if (n_tgt_lay == 0) {
165-
const uint32_t n_tgt_feat = read_u32("dflash.n_target_features", 0);
166-
if (n_tgt_feat != 0 && n_embd != 0 && (n_tgt_feat % n_embd) == 0) {
167-
n_tgt_lay = n_tgt_feat / n_embd;
171+
std::snprintf(key, sizeof(key), "%s.%s", A, "dflash.target_layer_ids");
172+
const int64_t target_ids_id = gguf_find_key(gctx, key);
173+
if (target_ids_id >= 0 &&
174+
gguf_get_kv_type(gctx, target_ids_id) == GGUF_TYPE_ARRAY) {
175+
n_tgt_lay = (uint32_t)gguf_get_arr_n(gctx, target_ids_id);
168176
}
169177
}
170-
if (n_tgt_lay == 0) {
171-
std::snprintf(key, sizeof(key), "%s.%s", A, "dflash.target_layer_ids");
172-
int64_t id = gguf_find_key(gctx, key);
173-
if (id >= 0) {
174-
n_tgt_lay = (uint32_t)gguf_get_arr_n(gctx, id);
178+
if (n_tgt_lay == 0 && n_embd != 0) {
179+
const uint32_t n_target_features = read_u32("dflash.n_target_features", 0);
180+
if (n_target_features != 0 && (n_target_features % n_embd) == 0) {
181+
n_tgt_lay = n_target_features / n_embd;
175182
}
176183
}
177184

@@ -240,17 +247,17 @@ bool load_draft_gguf(const std::string & path,
240247
auto g = [&](const char * name) -> ggml_tensor * {
241248
return ggml_get_tensor(meta_ctx, name);
242249
};
243-
244-
auto first = [](ggml_tensor * a, ggml_tensor * b) -> ggml_tensor * {
245-
return a ? a : b;
250+
auto g_any = [&](const char * a, const char * b) -> ggml_tensor * {
251+
if (ggml_tensor * t = g(a)) return t;
252+
return g(b);
246253
};
247254

248-
out.fc = first(g("dflash.fc.weight"), g("dflash_fc.weight"));
249-
out.hidden_norm = first(g("dflash.hidden_norm.weight"), g("dflash_hidden_norm.weight"));
255+
out.fc = g_any("dflash.fc.weight", "dflash_fc.weight");
256+
out.hidden_norm = g_any("dflash.hidden_norm.weight", "dflash_hidden_norm.weight");
250257
out.out_norm = g("output_norm.weight");
251258
if (!out.fc || !out.hidden_norm || !out.out_norm) {
252259
set_last_error("draft GGUF: missing top-level tensors "
253-
"(dflash fc / dflash hidden norm / output_norm)");
260+
"(dflash.fc|dflash_fc / dflash.hidden_norm|dflash_hidden_norm / output_norm)");
254261
gguf_free(gctx);
255262
return false;
256263
}
@@ -263,7 +270,8 @@ bool load_draft_gguf(const std::string & path,
263270
};
264271
DraftLayer & L = out.layers[il];
265272
L.attn_norm = fnd("attn_norm.weight");
266-
L.ffn_norm = first(fnd("ffn_norm.weight"), fnd("post_attention_norm.weight"));
273+
L.ffn_norm = fnd("ffn_norm.weight");
274+
if (!L.ffn_norm) L.ffn_norm = fnd("post_attention_norm.weight");
267275
L.wq = fnd("attn_q.weight");
268276
L.wk = fnd("attn_k.weight");
269277
L.wv = fnd("attn_v.weight");
@@ -283,6 +291,26 @@ bool load_draft_gguf(const std::string & path,
283291
}
284292
}
285293

294+
// GGUF Qwen3.6 drafters carry SWA metadata emitted by the converter:
295+
// dflash-draft.attention.sliding_window = 2048
296+
// dflash-draft.attention.sliding_window_pattern = [true,true,true,true,false]
297+
out.swa_window = (int)read_u32("attention.sliding_window", 0);
298+
std::snprintf(key, sizeof(key), "%s.%s", A, "attention.sliding_window_pattern");
299+
int64_t swp_id = gguf_find_key(gctx, key);
300+
if (swp_id >= 0 && gguf_get_kv_type(gctx, swp_id) == GGUF_TYPE_ARRAY &&
301+
gguf_get_arr_type(gctx, swp_id) == GGUF_TYPE_BOOL) {
302+
const size_t n = gguf_get_arr_n(gctx, swp_id);
303+
const bool * pattern = static_cast<const bool *>(gguf_get_arr_data(gctx, swp_id));
304+
for (size_t il = 0; il < n && il < out.layers.size(); il++) {
305+
out.layers[il].is_swa = pattern[il];
306+
}
307+
}
308+
const int n_swa = count_swa_layers(out);
309+
if (n_swa > 0) {
310+
std::fprintf(stderr, "[draft GGUF] SWA layers: %d/%d (window=%d)\n",
311+
n_swa, out.n_layer, out.swa_window);
312+
}
313+
286314
// ── 3. Allocate CUDA buffer for all tensors ──────────────────────────
287315
out.buf = ggml_backend_alloc_ctx_tensors(meta_ctx, backend);
288316
if (!out.buf) {

0 commit comments

Comments
 (0)