You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Parent epic:#929 Phase: 2 (follow-up to #1141 / PR #1454) Depends on: nothing Blocks: nothing
Problem
LocalFileBinding.release() does not fully deregister the adapter, so its qualified_name stays claimed for the backend's lifetime and no later binding can
register under it.
release() calls AdapterMixin.unload_peft_adapter, which removes the entry from LocalHFBackend._loaded_adapters — but nothing removes it from _added_adapters,
the registered set that add_adapter populates and that add_adapter itself
checks for duplicates. There is no inverse verb for add_adapter on the mixin, so
the binding has nothing to call.
Observed, with a fake backend reproducing LocalHFBackend.add_adapter's guards:
after prepare : backend set = True | _added_adapters = ['answerability_lora']
after release : backend = None | _staged_backend = None | _added_adapters STILL = ['answerability_lora']
re-prepare without bind_backend -> RuntimeError: requires bind_backend() to be called first
re-prepare after bind_backend -> RuntimeError: Backend refused to register 'answerability_lora'
Two consequences:
The name is burned. A differentLocalFileBinding for the same capability
can never be registered on that backend after the first one is released, even
though the first is fully torn down from the model's point of view.
The actual question: should re-registration be supported at all?
This issue is a question first, not an agreed fix. The merged WeightsBinding
contract (mellea/backends/adapters/_core.py, from #1134) says:
release() — terminal; releases all resources. The binding is not reusable
after release().
If "terminal" is meant strictly, then a released binding never being revivable is correct, and the only defects are the wording and the confusing error. But #1141's own text says the opposite — "prepare once per session (or explicit release()+prepare() cycle)" — which the merged ABC forbids. That contradiction
has been flagged on #1141 and needs settling here.
#1465 routes intrinsic generation through adapter_scope. If that work ends up
preparing a binding per call rather than once per session, it hits this
immediately — the second call cannot register. Worth resolving before #1465 picks a
lifetime for its bindings, even if the resolution is "terminal is correct, prepare
once".
Decide whether a released qualified_name should become re-claimable by a fresh
binding, and if so add the inverse of add_adapter to the mixin contract.
Whatever is decided, cover it with a test: either that re-registration after
release works, or that it fails with a clear, accurate error.
Not in scope
Changing unload_peft_adapter's own semantics — it correctly manages the loaded
set. The gap is the absent registered-set counterpart.
Parent epic: #929
Phase: 2 (follow-up to #1141 / PR #1454)
Depends on: nothing
Blocks: nothing
Problem
LocalFileBinding.release()does not fully deregister the adapter, so itsqualified_namestays claimed for the backend's lifetime and no later binding canregister under it.
release()callsAdapterMixin.unload_peft_adapter, which removes the entry fromLocalHFBackend._loaded_adapters— but nothing removes it from_added_adapters,the registered set that
add_adapterpopulates and thatadd_adapteritselfchecks for duplicates. There is no inverse verb for
add_adapteron the mixin, sothe binding has nothing to call.
Observed, with a fake backend reproducing
LocalHFBackend.add_adapter's guards:Two consequences:
LocalFileBindingfor the same capabilitycan never be registered on that backend after the first one is released, even
though the first is fully torn down from the model's point of view.
release()overstates itself. Its docstring said "releases all resources"and feat(backends): LocalFileBinding implements verbs (PEFT/aLoRA path) + from_catalog() (Epic #929 Phase 2) #1141's acceptance criterion says "
release()cleanly unregisters". Neitherwas accurate. PR feat(backends): LocalFileBinding implements verbs (PEFT/aLoRA path) + from_catalog() (Epic #929 Phase 2) #1454 corrects the docstring to say exactly what is and is not
released, and points here.
The actual question: should re-registration be supported at all?
This issue is a question first, not an agreed fix. The merged
WeightsBindingcontract (
mellea/backends/adapters/_core.py, from #1134) says:If "terminal" is meant strictly, then a released binding never being revivable is
correct, and the only defects are the wording and the confusing error. But
#1141's own text says the opposite — "
prepareonce per session (or explicitrelease()+prepare()cycle)" — which the merged ABC forbids. That contradictionhas been flagged on #1141 and needs settling here.
So, in order:
release()? The ABC saysno; feat(backends): LocalFileBinding implements verbs (PEFT/aLoRA path) + from_catalog() (Epic #929 Phase 2) #1141 said yes. One of them is wrong.
nothing more than what PR feat(backends): LocalFileBinding implements verbs (PEFT/aLoRA path) + from_catalog() (Epic #929 Phase 2) #1454 already did (accurate docstring, clearer error)
plus a decision about whether a fresh binding should be able to claim a
released name — which is the case that actually bites.
add_adapterneeds an inverse.That is a change to the mixin verb contract, which feat(backends): EmbeddedBinding implements apply_activation (Granite Switch path); remove render_controls + set_request_adapter (Epic #929 Phase 2) #1142 and add support for granite-switch / embedded adapters on our huggingface backend #1018 also build
on, so it should not be done incidentally.
Why it matters for #1465
#1465 routes intrinsic generation through
adapter_scope. If that work ends uppreparing a binding per call rather than once per session, it hits this
immediately — the second call cannot register. Worth resolving before #1465 picks a
lifetime for its bindings, even if the resolution is "terminal is correct, prepare
once".
Scope
WeightsBinding.release()is strictly terminal, and reconcile theABC docstring with feat(backends): LocalFileBinding implements verbs (PEFT/aLoRA path) + from_catalog() (Epic #929 Phase 2) #1141's text so they no longer contradict.
qualified_nameshould become re-claimable by a freshbinding, and if so add the inverse of
add_adapterto the mixin contract.release works, or that it fails with a clear, accurate error.
Not in scope
Changing
unload_peft_adapter's own semantics — it correctly manages the loadedset. The gap is the absent registered-set counterpart.
References
release(), corrected its docstring and the misleading"Backend refused to register" message to point here
release()cleanly unregisters"; its"
release()+prepare()cycle" line contradicts the merged ABC