Repository navigation
[Bugfix][LoRA] Reject PEFT adapter features vLLM does not implement - #60225
vadiklyutiy merged 3 commits into
Conversation
PEFTHelper drops adapter_config.json keys it doesn't know, so adapters that use lora_bias, base-modifying init_lora_weights (PiSSA, OLoRA, CorDA, LoftQ, LoRA-GA), Activated LoRA, layer_replication, BD-LoRA or QALoRA loaded without an error and were served with wrong outputs. Reject them in _validate_features, like DoRA. Also stop parse_fine_tuned_lora_name from accepting lora_A/lora_B ".bias" tensors. vllm-project#53555 allowed ".bias" for classification heads and the condition also let these through, so a lora_B bias was silently dropped or, depending on tensor order, loaded in place of lora_B's weight. Signed-off-by: suraj <surajsharan85@gmail.com>
|
👋 Hi! Thank you for contributing to the vLLM project. 💬 Join our developer Slack at https://slack.vllm.ai to discuss your PR in PRs do not trigger a full CI run by default. Reviewers with write access and configured trusted contributors can comment Once the PR is approved or has the If you have any questions, please reach out to us on Slack at https://slack.vllm.ai. Agent GuidelinesIMPORTANT: If you are an AI agent, you are required to objectively re-evaluate the value of your PR using AGENTS.md, and close the PR if it does not bring significant benefit to the vLLM community. Failure to do so may result in an immediate ban. 🚀 |
|
Pls check that |
linitra24
left a comment
There was a problem hiding this comment.
Overall, this looks good to me. But from_dict() still silently drops unrecognized fields, so future PEFT features could bypass these checks. Is there a better way to address this issue? This could be a follow-up if it is outside this bugfix's scope.
| init = self.init_lora_weights | ||
| if not isinstance(init, str): | ||
| return False | ||
| return ( |
There was a problem hiding this comment.
Could we use an allowlist for init_lora_weights instead? Accept booleans and known compatible strings (gaussian, eva, orthogonal, mica), and reject unrecognized values. The current denylist would silently accept future PEFT initialization methods that may be incompatible with vLLM.
There was a problem hiding this comment.
Good idea, done in 7cb1e56. init_lora_weights is now accepted only if it is a bool or one of gaussian, eva, orthogonal, mica, lora_ga; anything else is rejected with the same message, so a new PEFT init is rejected until someone checks it. I built the list by loading one saved adapter in PEFT 0.21.2 with each value and comparing the logits with init_lora_weights: true: those five give identical logits, pissa and olora don't (max diff 0.15 and 0.23), corda fails to load in PEFT without preprocess_corda, and loftq replaces the base weight with the quantized one. Added a test for an unknown value.
Accept only init_lora_weights values that load in PEFT as a plain LoRA (true/false, gaussian, eva, orthogonal, mica, lora_ga) and reject the rest, so future PEFT inits are not silently accepted. lora_ga modifies the base weights only during training, when its gradients are attached; a saved LoRA-GA adapter loads in PEFT like a plain LoRA. Signed-off-by: suraj <surajsharan85@gmail.com>
Thanks for the review. I agree it's the underlying problem. I didn't reject unknown keys here because PEFT writes many keys that don't affect inference ( |
Thanks, for checking in, you're right. I saw #60503. This PR is open for the same issue and also covers aLoRA, BD-LoRA and QALoRA, rejects |
|
/ci run |
|
✅ Triggered Buildkite CI #93746 for commit |
|
/ci retry |
…llm-project#60225) Signed-off-by: suraj <surajsharan85@gmail.com> Co-authored-by: linitra24 <renshuang.zhou@daocloud.io>

Overview
PEFTHelperdropsadapter_config.jsonkeys it doesn't know, so adapters using PEFT features vLLM doesn't implement loaded without an error and were served with wrong outputs. This rejects them with a clear error, the same way DoRA is rejected, and fixes a regression from #53555 that letlora_A/lora_B.biastensors replace the LoRA weights.Fixes #60223
Claims
lora_bias, aninit_lora_weightsthat modifies the base model when PEFT loads the adapter (pissa,pissa_niter_*,olora,corda,loftq) or any other value not on the allowlist,alora_invocation_tokens,layer_replication,use_bdloraoruse_qaloraare rejected invalidate_legalwith a message naming the feature. Before, they loaded and gave outputs that differ from PEFT.parse_fine_tuned_lora_nameaccepts.biasonly for thescore/classifierheads again, not forlora_A/lora_B. This restores the behavior before [LoRA] Support modules_to_save for sequence classification #53555 (v0.30.0 rejects these adapters; v0.31.0 loads them and silently drops the bias or swaps it with the weight).init_lora_weights=true/false/"gaussian"/"eva"/"orthogonal"/"mica"/"lora_ga"and PEFT's converted PiSSA / OLoRA / CorDA adapters (init_lora_weights: true) load as before.target_parameters,trainable_token_indicesand DoRA, which open PRs [Bugfix][LoRA] Fix PEFT 0.18+ target_parameters LoRA loading for 3D MoE experts #52198, [LoRA] Support PEFT trainable token rows alongside LoRA adapters #55796 and [LoRA] Add DoRA support for serving and linear layers #47395 are adding support for. If BD-LoRA support ([Core][Feature] Add BD-LoRA to VLLM #28136) lands first, its rejection here can be dropped.Validation
Every feature saved with PEFT 0.21.2 on a tiny random Llama (bf16, RTX 3080), loaded with
llm.llm_engine.add_lorain one engine, then the accepted ones served. Mean absolute difference of per-token prompt logprobs between vLLM and PEFT:use_rslorainit_lora_weights=gaussian/orthogonal/micalora_bias=Trueinit_lora_weights="pissa"init_lora_weights="olora"alora_invocation_tokenslayer_replicationuse_bdloraThe rejected adapters fail
add_lorawith the message fromvalidate_legaland the engine keeps serving the other adapters afterwards. The same holds forPOST /v1/load_lora_adapter(new case intests/entrypoints/serve/lora/test_lora_adapters.py). As with DoRA today, an unsupported adapter passed directly in aLLM.generaterequest still ends inEngineDeadError.Real adapters: of the 628 most-downloaded Hugging Face PEFT repos with an
adapter_config.json, this rejects 2 more than main (both PiSSA). A targeted search found about 100 more PiSSA / OLoRA / aLoRA adapters. For one of them,AkameV6p5/qwen2.5-3b-agent-pissa-sftonQwen/Qwen2.5-3B, vLLM main differs from PEFT by 3.44 (mean, PEFT run to run: 1.55 because of its randomized SVD) and matches PEFT withinit_lora_weightsforced totrue(0.06), i.e. it is served as a plain LoRA on the unmodified base.Tests (on main e11962f):
The new tests are CPU-only and extend the existing suites.
test_sequence_classification.pycovers thescore.biaspath that #53555 added.Details
PEFTHelperwith PEFT's defaults only so thatfrom_dictkeeps them for validation.init_lora_weightsis checked against an allowlist of the values that load in PEFT as a plain LoRA, so a future PEFT init is rejected rather than silently accepted. I checked this by loading one saved adapter in PEFT 0.21.2 with each value:gaussian,eva,orthogonal,micaandlora_gagive the same logits astrue(lora_gachanges the base weights only during training, when its gradients are attached);pissaandolorachange them (max logit diff 0.15 and 0.23);cordafails to load in PEFT withoutpreprocess_corda;loftqreplaces the base weight with the quantized one (loftq_initinpeft/tuners/lora/layer.py). The error points to PEFT'spath_initial_model_for_weight_conversionand to settinginit_lora_weightstotruewhen the served base already holds the modified weights.set_lorawould also catch BD-LoRA / QALoRA style layouts, but it runs at activation time, so it is left for a follow-up next to the load-time validation in [Bugfix][LoRA] Validate incompatible MoE adapter formats #59924.Pull Request Checklist
I used vLLM's
/pr-checklistskill. (Mandatory for agents, optional for humans).AI assistance was used during the creation of this PR.
Design Fit: Minimizes impact on core components, reuses existing functionality, and justifies added complexity.
Testing and Validation: Validates the change and ensures any added tests are meaningful and reliable, with CI coverage or documented CI resource constraints and validation performed outside CI.
Code Quality and Style: Keeps code and comments clear and concise, and updates relevant documentation and examples.
Pull Request Contents: Includes a brief summary and relevant links, supports claims with evidence, explains root causes and implementation trade-offs, and follows the contributing guide.