Bump llama.cpp to 61881b1f7 (b10280), release v0.8.42 - #82
Merged
Conversation
Submodule ddd4ec142 -> 61881b1f7 (63 commits, tag b10217 -> b10280). Unlike the
last two ranges this one breaks the upstream C API.
Required API fix:
- `llama_sampler_init_penalties` gained a leading `int32_t n_vocab` (#26520, which
moved n_vocab out of llama_sampler_data so the CUDA backend sampler from #25262
can size its buffers). The one call site now passes
`llama_vocab_n_tokens(model->vocab())`. `llama_sampler_init_dry` also dropped
`n_ctx_train`, which the binding does not expose. `-1` no longer means "context
size" for penalty_last_n (#26524); the NIF hardcodes 64, so behaviour is
unchanged.
Fixed: MTP speculative decoding was entirely broken since v0.8.41.
b10217 added `bool load_mtp` to llama_model_params, defaulting to false. v0.8.41
read that field as inert because the NIF builds its params from
`llama_model_default_params()` — true at compile time, wrong at runtime: the MTP
layers stopped being loaded. `common_speculative_init` still succeeds, so the
failure surfaced as `verify decode failed: code=-1` far from the cause.
`Model.load/2` gains `:load_mtp` (default false, matching upstream), it is
recorded on `%Model{}`, and `MTP.init/2` refuses a model loaded without it since
the layers cannot be attached afterwards. Unnoticed because the :mtp suite had
never run against a real model; now verified end-to-end at ~67% draft acceptance.
Tests: three smoke tests asserted prefix reuse that hybrid GDN models cannot do.
Recurrent state cannot be rolled back to an arbitrary position, so a partial
seq_rm is refused and the Server correctly declines reuse — meaning the
hybrid-model regression test contradicted the fallback it documents. They passed
only because CI's generation model is dense. Each now branches on
`TestModels.seq_rm_kind/1` and asserts the documented behaviour for the model in
hand, with no catch-all clause so an unexpected verdict raises. Not a regression
from this bump: the recurrent and hybrid memory implementations are byte-identical
across the range.
The MTP suite also moved to its own module so the model loads once — a per-test
load accumulated Metal buffers until ggml-alloc aborted the VM.
Known issue: cancelling an MTP stream and immediately reusing the session aborts
the VM (cancellation is unacknowledged, and a session's contexts are shared).
Pre-existing, reachable only now that MTP works; documented, and the reproduction
is gated behind its own :mtp_cancel tag. Fixing it changes the cancellation
protocol non-MTP streaming shares, so it is not bundled here.
Validation: 374 passed (default), 502 passed with smoke+embeddings+slow against
both a :part model (Llama-3.2-3B) and a :full one (Qwen3.5-0.8B), 384 passed with
--include mtp against Qwen3.5-9B. Generation, chat templating, streaming,
JSON-schema sampling, grammar-with-penalties and the penalties path itself checked
across nine architectures. mix format and dialyzer clean.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Submodule
ddd4ec142→61881b1f7(63 commits, b10217 → b10280). Unlike the last two ranges, this one breaks the upstream C API. Validating it against real models also surfaceda separate bug that had left MTP speculative decoding inoperable since v0.8.41.
Required API fix
llama_sampler_init_penaltiesgained a leadingint32_t n_vocab(#26520, which movedn_vocabout ofllama_sampler_dataand intothe penalty sampler so the CUDA backend sampler from #25262 can size its buffers). The NIF's one call site now passes
llama_vocab_n_tokens(model->vocab()).The argument count changed, so a missed call site is a compile error — but the two leading
int32_ts are interchangeable to the compiler, so the penalties path is now coveredbehaviourally: a repetition-inducing prompt under greedy decoding must be diverted by
penalty_repeat, andpenalty_repeat: 1.0must be a byte-identical no-op. Previously onlysampler construction was tested.
Also in range, needing no change here:
llama_sampler_init_drydroppedn_ctx_train(the binding doesn't expose DRY), and-1no longer means "context size" forpenalty_last_n(#26524) — the NIF hardcodes
64, so behaviour is unchanged.Fixed: MTP was completely broken since v0.8.41
b10217 added
bool load_mtptollama_model_params, defaulting tofalse, so non-speculative callers don't pay for the MTP head's tensors. v0.8.41's changelog read the field asinert "because the NIF builds its params from
llama_model_default_params()… no change needed" — true at compile time, wrong at runtime: the MTP layers simply stopped being read offdisk.
Nothing on the way in objects. Both contexts build,
common_speculative_initreturnsok, and the first draft then fails withverify decode failed: code=-1, far from the cause.Model.load/2gains:load_mtp(defaultfalse, matching upstream)%Model{}MTP.init/2refuses a model loaded without it, naming the remedy — the layers cannot be attached after the fact, soinit/2is the only place the error is actionableThis went unnoticed because the
:mtpsuite had never been run against a real model — it needs an MTP-enabled GGUF and none was available when the tests were written. Now verifiedend-to-end against
Qwen3.5-9B(qwen35withnextn_predict_layers) at ~67% draft acceptance withn_draft: 3. The new guard immediately caught a second call site inllama_cpp_ex_test.exsthat was missing the flag.Tests: three smoke tests asserted something hybrid models cannot do
The cache-scope isolation test, the
PromptCache.restore/4partial-trim test, and — ironically — the hybridcache_promptregression test all requiredprefix_cache_tokens > 0.Recurrent state isn't preserved per token, so
llama_memory_seq_rmrefuses a partial range and the Server correctly declines reuse (server.ex:812). The test named for hybrid GDNmodels was therefore contradicting the very fallback its own comment documents. All three passed only because CI's generation model is dense.
Each now branches on
TestModels.seq_rm_kind/1(a memoisedcommon_context_can_seq_rmprobe) and asserts the documented contract for the model in hand: reuse on:part; the full-resetfallback and
{:error, :seq_rm_refused}on:full. No branch is a skip, and neithercasehas a catch-all, so an unexpected verdict raises rather than passing quietly.Not a regression from this bump —
llama-memory-recurrent.cppand both hybrid memory implementations are byte-identical between b10217 and b10280; only the densellama-kv-cache.cppwas refactored.
Cancelling an MTP stream and immediately reusing the session aborts the VM.
request_cancelsets a flag and the loop then stops without emitting a terminal event(
llama_nif.cpp:2009), soGenerator.stop/1has no completion signal to await and returns while the dirty scheduler may still be insidellama_decode. Harmless forstream/3(eachcall owns a context that dies with it); not for an
%MTP{}session, whose two long-lived contexts every call shares.Reachable only now that MTP works at all. The fix means acknowledging cancellation in the NIF and in the cancellation protocol non-MTP streaming shares — deliberately not bundled into
a submodule bump.
MTP's docs and the README carry the warning, and the reproduction lives inLlamaCppEx.MTPCancelTest, in its own module tagged only:mtp_cancel(not:mtp, since--includebeats--excludeand a second gate tag would abort--include mtpruns).Validation
Built from source against the bumped submodule (Metal,
LLAMA_BACKEND=auto):--include smoke --include embeddings --include slow,Llama-3.2-3B(:part)--include smoke --include embeddings --include slow,Qwen3.5-0.8B(:full)--include mtp,Qwen3.5-9BGeneration, chat templating, streaming, JSON-schema-constrained sampling, grammar-with-penalties and the penalties path were additionally exercised across nine architectures —
llama,qwen3,qwen35,qwen35moe,gemma4,gpt-oss,bert(Ministral) — plusQwen3-Embedding-0.6Bfor the embedding paths (L2 norm exactly 1.0; paraphrase similarity 0.73 vs 0.20 forunrelated text).
mix format --check-formattedandmix dialyzer(0 errors) both clean.Makefile'sLLAMA_COMMITfollows the submodule — verified identical, so Hex source builds don't drift from gitcheckouts.
checksum.exsdeliberately untouched; CI regenerates it after the release tag.