Extracting a LoRA Adapter's Weights From an Already-Merged Model
9 min read · updated August 11, 2026
A merged model is W + BA stored as a single matrix. You cannot recover BA from that any more than you can recover the addends of a sum from the total. Extraction is possible only because you can usually obtain one of the addends separately.
Addition is not reversible
Merging computes, for each adapted projection, W’ = W + (alpha/r) · BA and writes W’. Every trace of the decomposition is gone: the merged checkpoint has the same tensor names, the same shapes and the same file size as the base, and its config.json does not mention an adapter. Nothing distinguishes a merged model from a full fine-tune, which is exactly why merging is a reasonable way to distribute one.
This is not an implementation gap that better tooling could close. A single matrix of the right shape is consistent with infinitely many pairs summing to it. Any claim to extract an adapter from a merged model alone is either wrong or is quietly assuming a base — and the assumption is usually “whatever this model’s card says it was fine-tuned from”, which is a guess with a citation.
What extraction actually does
Given both matrices, the update is immediate: D = W’ - W. That difference is sometimes called a task vector, and it is exact. The problem is that D is full-size — a 4096×4096 delta per projection, which is no smaller than the model you started from. Storing it gains nothing.
So extraction adds a second step: approximate D by a product of two thin matrices. The standard method is a singular value decomposition, D = U Σ V*, truncated to the largest r singular values. Fold the square roots of those values into the factors and you have B = U_r Σ_r^(1/2) and A = Σ_r^(1/2) V_r*— a rank-r pair in exactly the shape a LoRA adapter wants. The Eckart–Young theorem says this truncation is the best rank-r approximation of D available in the least-squares sense, so nothing better exists at that rank.
Why the result is an approximation
Two different reasons, and they apply in different situations.
- If the model really was a merged LoRA of rank
r, thenDhas rank at mostrand an SVD truncated atrrecovers it up to floating-point error. But it does not recover yourAandB: any invertibleRgives(BR)(R⁻¹A) = BA, so the factors are determined only up to that ambiguity. The product is right, the matrices are not the ones training produced, and a comparison of adapter files will show them as different. - If the model was a full fine-tune,
Dhas no reason to be low rank at all, and truncating to rank 32 discards every singular direction past the 32nd. What you get is the dominant part of the update. Whether that is most of the behaviour or half of it depends entirely on the fine-tune, and the only way to find out is to apply the extracted adapter to the base and compare against the merged model on real prompts.
There is also a floating-point floor. Subtracting two large, nearly equal bf16 matrices loses precision in exactly the small differences you are trying to keep, so extraction is done in fp32 where possible. And if the merged model was quantized before you got it, Dcontains the quantization error of the merged weights as well as the fine-tune — noise that the SVD will happily allocate singular values to.
The wrong base gives a plausible wrong answer
This is the failure worth planning against, because it does not raise anything. Diff a chat fine-tune against the wrong checkpoint — the base variant instead of the instruct variant, or a later revision of the same tag — and D quietly contains two updates: the one you wanted plus the entire difference between the two bases. The arithmetic succeeds, the SVD succeeds, and you get an adapter that encodes “become the instruct model, and also adopt this tone”.
Applied back to the base you diffed against, it will even look plausible, because the extra content is precisely what makes it plausible there. Applied to any other base it is wrong in a way that is hard to attribute. The defence is to record the base by commit hash rather than by tag, and to sanity-check the magnitude of D: a rank-16 tone adapter should produce a delta orders of magnitude smaller than the difference between two separately trained checkpoints.
Doing it, and when not to
The maintained tool is mergekit-extract-lora, from Arcee AI’s mergekit, which takes the fine-tuned model and the base explicitly:
mergekit-extract-lora \ --model ./merged-support-model \ --base-model ./Meta-Llama-3-8B-Instruct \ --out-path ./extracted-support-lora \ --max-rank 32 \ --cuda
The flags say the important things out loud. --base-model is required, which is the whole argument of this page expressed as an interface. --max-rank caps the truncation, and --sv-epsilon lets small singular values be dropped below a tolerance instead of at a fixed count. Verify the output the same way you would verify any adapter: apply it to the base and diff against the merged model on fixed prompts at temperature zero, exactly as on the adapter verification page.
- Worth it when you want to ship a behaviour as tens of megabytes rather than tens of gigabytes, when you want to combine two fine-tunes over one resident base, or when you want to apply a behaviour at reduced strength — a merged model has no dial and an adapter does.
- Not worth it when you have the original adapter. The extraction is strictly lossier than the file you already own, and applying an adapter at inference time costs so little that keeping the original is nearly always the better plan.
- Check the licence before extracting from somebody else’s merged model. An extracted adapter is a derivative of those weights, and the terms that came with the merged checkpoint travel with it.