Conversation
`LLM_CONFIG_DEFAULTS` injected `gpu_layers: 99` into every LLM load. Fabric reads any set value as user intent and refuses to override it, so its automatic GPU/CPU placement aborted with "n_gpu_layers already set by user to 99" before it could pick anything. The best the SDK config could express was plain layer offload, and a model larger than VRAM was offloaded whole and spilled back to host memory by the driver — 2.5 tok/s on the reporter's box against 22 tok/s for the placement the fit would have chosen. The default is dropped. Nothing is substituted for it: with `gpu_layers` unset the addon receives fabric's own -1 sentinel, and llama already resolves a negative `n_gpu_layers` to `n_layer_all + 1` — every layer. So in every case where the fit does not run, or runs and fails, placement is byte-for-byte what `99` produced, and the only behaviour that changes is the one that was broken. For models with more than 99 layers it is strictly better, since 99 silently truncated. Setting `gpu_layers` explicitly still pins the layer count and still disables the fit, which is the documented escape hatch and an acceptance criterion on the ticket. The schema description and the generated SDK contract are updated to match. The contract was edited by hand rather than regenerated: a full `contract:export` in this checkout also rewrote four unrelated JSON-schema fragments, drift from a locally-resolved zod version rather than from this change. Note for reviewers: `EMBED_CONFIG_DEFAULTS.gpuLayers` keeps its 99. It has the same shape of problem but was outside this ticket's scope, and embedding models are small enough that the fit rarely has anything to reduce. Worth a follow-up. Verified: 131/132 @qvac/inference brittle tests pass, including the whole config-resolution-e2e suite and the llm plugin transform tests. The exception is native-probe-process.test.js, which fails identically before this change — it spawns child processes through a pnpm-installed `bare` shim that cannot resolve its darwin-arm64 runtime in this checkout. Typecheck, prettier and lunte are clean against an identical baseline. Refs QVAC-25039 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Contributor
License compliance — cleanNo new dependency license findings in this PR. Warn-only (shadow) mode — this check does not block merges yet. Updated automatically by the canonical license compliance workflow. NOTICE presence (advisory)Missing NOTICE (advisory, does not block):
|
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.
🎯 Problem
LLM_CONFIG_DEFAULTSinjectedgpu_layers: 99into every LLM load. Fabric reads any set value as user intent and refuses to override it, so its automatic GPU/CPU placement aborted before it could pick anything:The best the SDK config could express was plain layer offload, and a model larger than VRAM was offloaded whole and spilled back to host memory by the driver — 2.5 tok/s on the reporter's box against 22 tok/s for the placement the fit would have chosen. This is already noted in
model-fit/calibration/METHODOLOGY.md: "The SDK pinsn_gpu_layers: 99, so llama.cpp's own fit cannot reduce the..."This is one of three independent causes on QVAC-25039. The other two are fixed in their own PRs (the sharded load path in
inference-addon-cpp, llm-llamacpp's override buffer); none of the three depends on another.📝 How
The default is dropped, and nothing is substituted for it.
With
gpu_layersunset the addon receives fabric's own-1sentinel, and llama already resolves a negativen_gpu_layersto every layer:So in every case where the fit does not run, or runs and fails, placement is byte-for-byte what
99produced — the only behaviour that changes is the one that was broken. For models with more than 99 layers it is strictly better, since99silently truncated.Setting
gpu_layersexplicitly still pins the layer count and still disables the fit, which is the documented escape hatch and an acceptance criterion on the ticket. Device selection is unaffected: the addon resolves CPU-vs-GPU from thedevicekey via--device, never fromgpu_layers.The schema description and the generated SDK contract are updated to match. The contract was edited by hand rather than regenerated: a full
contract:exportin this checkout also rewrote four unrelated JSON-schema fragments (type: [...]→anyOf, and a tuple'sitems/minItems/maxItems), drift from a locally-resolved zod version rather than from this change. Worth a separate look if CI'scontract:checkdisagrees.🧪 Tested
131/132
@qvac/inferencebrittle tests pass, including the wholeconfig-resolution-e2esuite (16/16, 45 asserts) andllm-plugin-transform(9/9). No test asserted on the removed default; the ones that exercisegpu_layerspass it explicitly.The exception is
native-probe-process.test.js, which fails identically before this change — it spawns child processes through a pnpm-installedbareshim that cannot resolve itsdarwin-arm64runtime in this checkout.native-probe-run-isolated-fit.test.jscannot load at all here for the same reason (MODULE_NOT_FOUND: bare-events).Typecheck,
prettierandlunteare clean — verified against a pristine-file baseline, since this checkout has three pre-existing unrelated type errors insafe-fetch.tsandexamples/.None in behaviour, by the argument above:
-1and99produce identical placement whenever the fit is not in play, and an explicitgpu_layersis still honoured.One nuance worth flagging for reviewers:
gpu_layersno longer appears in the config object the SDK hands the addon, so anything reading it back off a resolved config will now seeundefinedrather than99. Nothing in this repo does.Not in scope:
EMBED_CONFIG_DEFAULTS.gpuLayerskeeps its99. It has the same shape of problem but was outside this ticket's scope, and embedding models are small enough that the fit rarely has anything to reduce. Worth a follow-up.🤖 Generated with Claude Code