Skip to content

Commit f65e568

Browse files
authored
common : auto-detect spec type from draft GGUF metadata (#26814)
* common : auto-detect spec type from draft GGUF metadata 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 * common : address review feedback on spec-type auto-detect PR - 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 #26814. * common : move spec-type GGUF auto-detect into speculative module - 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 #26814 * common : add doc note and join SPC_INF line in spec-type auto-detect Assisted-by: opencode
1 parent 0d0bfcd commit f65e568

3 files changed

Lines changed: 44 additions & 0 deletions

File tree

‎common/arg.cpp‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,15 @@ void common_models_handler_apply(common_models_handler & handler, common_params
561561
}
562562
}
563563

564+
// infer the speculative type from the draft GGUF metadata when none is requested
565+
// note: reads only the first split - sharded drafts need an explicit --spec-type
566+
if (spec_types_is_default(params) && !params.speculative.draft.mparams.path.empty()) {
567+
const auto types_gguf = common_speculative_types_from_gguf(params.speculative.draft.mparams.path);
568+
if (!types_gguf.empty()) {
569+
params.speculative.types = types_gguf;
570+
}
571+
}
572+
564573
// when a sidecar type is requested, the draft repo resolves to its sidecar instead of a full model
565574
const bool spec_sidecar_found = !plan_spec.mtp.local_path.empty() ||
566575
!plan_spec.dflash.local_path.empty() ||

‎common/speculative.cpp‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "common.h"
44
#include "ggml.h"
5+
#include "ggml-cpp.h"
56
#include "llama.h"
67
#include "log.h"
78
#include "ngram-cache.h"
@@ -2227,6 +2228,37 @@ common_speculative_type common_speculative_type_from_name(const std::string & na
22272228
return it->second;
22282229
}
22292230

2231+
std::vector<common_speculative_type> common_speculative_types_from_gguf(const std::string & path) {
2232+
struct gguf_init_params gguf_params = {
2233+
/* .no_alloc = */ true,
2234+
/* .ctx = */ nullptr,
2235+
};
2236+
2237+
gguf_context_ptr gguf_ctx(gguf_init_from_file(path.c_str(), gguf_params));
2238+
if (!gguf_ctx) {
2239+
return {};
2240+
}
2241+
2242+
const int64_t arch_id = gguf_find_key(gguf_ctx.get(), "general.architecture");
2243+
if (arch_id < 0 || gguf_get_kv_type(gguf_ctx.get(), arch_id) != GGUF_TYPE_STRING) {
2244+
return {};
2245+
}
2246+
2247+
const std::string arch = gguf_get_val_str(gguf_ctx.get(), arch_id);
2248+
if (arch != "dflash") {
2249+
return {};
2250+
}
2251+
2252+
// the Markov head distinguishes draft-dspark from draft-dflash
2253+
const auto type = gguf_find_tensor(gguf_ctx.get(), "markov_w1.weight") >= 0
2254+
? COMMON_SPECULATIVE_TYPE_DRAFT_DSPARK
2255+
: COMMON_SPECULATIVE_TYPE_DRAFT_DFLASH;
2256+
2257+
SPC_INF("auto-detected speculative type '%s' from the draft model metadata\n", common_speculative_type_to_str(type).c_str());
2258+
2259+
return { type };
2260+
}
2261+
22302262
static uint32_t common_get_enabled_speculative_configs(const std::vector<common_speculative_type> & configs) {
22312263
uint32_t result = 0;
22322264
for (size_t i = 0; i < configs.size(); i++) {

‎common/speculative.h‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ const char * common_speculative_all_types_str();
1414
// parse user provided types
1515
std::vector<enum common_speculative_type> common_speculative_types_from_names(const std::vector<std::string> & names);
1616

17+
// infer the spec types from the GGUF metadata of a draft model; empty if unknown
18+
std::vector<enum common_speculative_type> common_speculative_types_from_gguf(const std::string & path);
19+
1720
// convert string to type
1821
enum common_speculative_type common_speculative_type_from_name(const std::string & name);
1922

0 commit comments

Comments
 (0)