common : auto-detect spec type from draft GGUF metadata - #26814
Conversation
When -md loads a local draft model without --spec-type, the sidecar inference in common_models_handler_apply only checks HF repo sidecars and misses local files. The draft model loads into VRAM but speculative decoding never activates (types stays NONE). Read general.architecture from the draft GGUF header and map: dflash + markov_w1.weight tensor -> draft-dspark dflash without markov head -> draft-dflash Assisted-by: opencode
|
Hi @aic0d3r, thanks for your contribution! Per our contribution guidelines, the automated PR checker found the following issue(s) that need your attention:
Please note that maintainers reserve the right to make final decisions on PRs. If you believe there is a mistake, please comment below. |
|
/bot review |
Automated code reviewCode Review: common : auto-detect spec type from draft GGUF metadata (#26814)The change is small and well-scoped: when a local draft model is loaded with No blocking issues found. Items below. Will slow the review(point 1) Split-GGUF misclassification (correctness edge case). (point 2) Auto-enabling speculative decoding is a behavior change. Previously, (point 3) Duplicated dspark detection / double GGUF read. Nits(point 4) Initializer comment spacing. (point 5) Magic strings. (point 6) No diagnostic log. When auto-detection sets the type, there is no This review was generated automatically by pi coding agent using |
|
@aic0d3r Can you check the bot's comments? #26814 (comment) |
- Fix comment spacing to match surrounding style (/* .x = */ not /*.x =*/) - Add LOG_INF when auto-detection fires so users can see why spec decoding enabled - Document single-file assumption for split-GGUF edge case Addresses bot review feedback on ggml-org#26814.
Thanks for the review @taronaeo. Addressed the bot's feedback in 07d7f1f: Point 1 (split-GGUF edge case): Added a comment documenting the single-file assumption. DSpark drafters are single-file in practice — the bf16 drafter is ~11GB and the Q2K is ~6.5GB, both well below any split threshold. A sharded drafter would be unusual, but if it happens the user can work around it with explicit Point 2 (behavior change): Intended. The previous behavior (load draft into VRAM but silently never use it) was the bug this PR fixes. Users can still opt out with Point 3 (duplicated detection): Fair point on long-term design. The clean approach would be to infer Nits 4-6: Fixed comment spacing, added LOG_INF lines for both detection branches. This directly fixes a real issue I hit: loading a local DSpark drafter with |
| // infer spec type from draft GGUF metadata when no sidecar or explicit type was given. | ||
| // NOTE: reads only the first split — DSpark drafters are single-file in practice | ||
| // (~11GB bf16, ~6.5GB Q2K), well below any split threshold. |
There was a problem hiding this comment.
remove out-of-context comments
There was a problem hiding this comment.
see agents.md for acceptable code comment style
| /* .no_alloc = */ true, | ||
| /* .ctx = */ nullptr, | ||
| }; | ||
| struct gguf_context * gguf_ctx = gguf_init_from_file(params.speculative.draft.mparams.path.c_str(), meta_params); |
There was a problem hiding this comment.
use RAII version of gguf_context in ggml-cpp.h
| if (spec_types_is_default(params) && !params.speculative.draft.mparams.path.empty()) { | ||
| struct gguf_init_params meta_params = { | ||
| /* .no_alloc = */ true, | ||
| /* .ctx = */ nullptr, | ||
| }; | ||
| struct gguf_context * gguf_ctx = gguf_init_from_file(params.speculative.draft.mparams.path.c_str(), meta_params); | ||
| if (gguf_ctx) { | ||
| int64_t arch_idx = gguf_find_key(gguf_ctx, "general.architecture"); | ||
| if (arch_idx >= 0) { |
There was a problem hiding this comment.
I believe the whole code should be part of speculative.cpp/.h
There was a problem hiding this comment.
Thanks for the detailed review, i agree with your points and have made the needed changes.
all three of ngxson's comments addressed in dd71b82, pushed to the PR branch:
- arg.cpp:589 "should be part of speculative.cpp/.h" → logic moved to new common_speculative_types_from_gguf() in common/speculative.cpp:2231; arg.cpp keeps a 7-line call site; #include "gguf.h" dropped from arg.cpp.
- arg.cpp:586 "use RAII" → now uses gguf_context_ptr from ggml-cpp.h; also added a gguf_get_kv_type string-type check so a malformed GGUF can't hit the gguf_get_val_str assert.
- arg.cpp:580 "out-of-context comments" / agents.md style → split-size NOTE deleted; one-line comment matching the adjacent sidecar block.
Verified: llama-common builds clean; runnable check against real models — DSpark drafter Q2K and bf16 → draft-dspark, vocab GGUF and missing file → empty (no crash).
- add common_speculative_types_from_gguf() in speculative.cpp/.h - use gguf_context_ptr (RAII) from ggml-cpp.h - reduce comments to a single line per AGENTS.md style Addresses review feedback on ggml-org#26814
Overview
When -md loads a local draft model without --spec-type, the sidecar inference only checks HF repo sidecars and misses local files. The draft model loads into VRAM but speculative decoding never activates (types stays NONE, tok/decode-pass = 1.000).
Reads general.architecture from the draft GGUF header and maps dflash + markov_w1.weight to draft-dspark, dflash without markov to draft-dflash.
Related: #26636 #26339
Requirements