Repository navigation
add support for granite-switch / embedded adapters on our huggingface backend #1018
Description
Parent epic: #929
Phase: 3 (scope research / acceptance criteria before implementation)
Depends on: #1142
Blocks: #1144
⚠️ Thinly specified — scope research required before starting.
The Granite Switch HF path has not been mapped against the newEmbeddedBindingAPI.
Scope research is now unblocked. Do not begin implementation until items 1–3 below are resolved and the implementer has read the
granite-switch HF examples
against the new binding interface.
Problem
EmbeddedBinding.apply_activation (implemented in #1142) teaches the OpenAI backend
how to activate an embedded adapter by writing chat_template_kwargs["adapter_name"]
into the outgoing request.
LocalHFBackend has no equivalent path. Loading and running a Granite Switch model
locally via the HF backend today requires the caller to replicate the activation logic
manually — nothing in LocalHFBackend knows how to route an EmbeddedBinding through
its generation path.
This means a user who has a Granite Switch checkpoint locally cannot use adapter functions
through the standard Adapter(weights=EmbeddedBinding.from_base_model(backend)) pattern —
the backend simply ignores the binding.
Scope
- Teach
LocalHFBackendto callbinding.apply_activation(request, identity)on the
generation path when the active adapter's binding is anEmbeddedBinding. - Verify that the
chat_template_kwargs/ request-field mechanism that works for
OpenAIBackend(via the Granite Switch API) also works for HF local inference — or
document why it differs and what the HF-specific activation field is. - Add
LocalHFBackendto the backend × reality matrix in
docs/docs/advanced/intrinsics.md(introduced by feat(backends): EmbeddedBinding implements apply_activation (Granite Switch path); remove render_controls + set_request_adapter (Epic #929 Phase 2) #1142) once the path is confirmed.
Out of scope
LocalFileBinding(PEFT path) — already handled by feat(backends): LocalFileBinding implements verbs (PEFT/aLoRA path) + from_catalog() (Epic #929 Phase 2) #1141.- Output-contract parsing — that is refactor(intrinsics): resolve the adapter's output contract from the adapter, not a parallel argument (Epic #929 Phase 2) #1516.
ServerMediatedBinding(no backend currently targets this).- Training or uploading embedded adapters (
m aloraCLI).
Research required before writing acceptance criteria
- Read granite-switch HF inference examples
and map the activation field againstLocalHFBackend's generation entry point. - Confirm whether
apply_activationas designed in feat(backends): EmbeddedBinding implements apply_activation (Granite Switch path); remove render_controls + set_request_adapter (Epic #929 Phase 2) #1142 produces the right request
shape for HF local inference, or whether HF needs a different field name/location. - Determine whether the existing
EmbeddedIntrinsicAdaptercode path in the OpenAI
backend (pre-feat(backends): EmbeddedBinding implements apply_activation (Granite Switch path); remove render_controls + set_request_adapter (Epic #929 Phase 2) #1142) has any HF-equivalent that would need to be removed.
Once (1)–(3) are answered, replace this section with concrete acceptance criteria,
a test plan, and a breaking-changes note following the format of #1141 / #1142.
References
- feat(backends): EmbeddedBinding implements apply_activation (Granite Switch path); remove render_controls + set_request_adapter (Epic #929 Phase 2) #1142 —
EmbeddedBinding.apply_activation; must merge first - refactor(backends): AdapterMixin verb rename/narrow + resolve_model_options + IntrinsicMetricsPlugin (Epic #929 Phase 2) #1140 —
AdapterMixinverb set; merged - granite-switch repo — HF examples
- PR feat: add embedded adapters (granite switch) to openai backend #881 — Reality B added to OpenAI backend; the original embedded adapter implementation
Activity
docs: second round review edits (generative-computing#929)
planetf1 commentedon May 26, 2026
Closing as superseded by #1142 (feat(backends): EmbeddedBinding implements verbs — Granite Switch path + OTel spans), which is tracked as part of the adapter lifecycle epic #929. Will be addressed when Phase 2 of that epic lands.
jakelorocco commentedon May 26, 2026
@planetf1, the linked issue (#1142) explicitly lists this issue as out of scope. We should ensure that this work does get done (even if it happens after the epic / major refactor).
planetf1 commentedon May 26, 2026
@jakelorocco — you're right. #1142 explicitly defers this; closing it as superseded was wrong. Reopening as a follow-on blocked on #1142.
planetf1 commentedon Jun 19, 2026
Assessment: scope, sequencing, and what remains
Researched this against the current codebase and the granite-switch repo to clarify what work is actually needed here.
What Granite Switch embedded adapters are
Granite Switch composes multiple adapter functions (answerability, query-rewrite, hallucination detection, etc.) into a single HF-compatible checkpoint. Adapters are activated via control tokens injected by the model's own chat template — there is no separate PEFT file to load at runtime and no
set_adapter()call. This is theEmbeddedBinding/ "Reality B" path in Epic #929's design.Current state
OpenAIBackendalready supports this fully (PR #881):load_embedded_adapters=True, and_generate_from_intrinsicinjectschat_template_kwargs["adapter_name"]to activate the control token.LocalHFBackenddoes not._generate_from_intrinsic(huggingface.py:594) raises:There is no
load_embedded_adaptersflag, nochat_template_kwargs["adapter_name"]injection on the local generate path, andadd_adapteris typed forLocalHFAdapteronly.Relationship to Phase 2 (#1140, #1142)
This issue is not covered by #1140 or #1142 — both explicitly list
#1018in their Out of scope sections. #1142 portsEmbeddedBindingthrough the new binding abstraction but only on the OpenAI path.#1018 is the distinct follow-on: wiring the (refactored)
EmbeddedBindingandrender_controlsverb intoLocalHFBackend. It depends on #1140 and #1142 and should land after both merge, before docs consolidation (Phase 4 / #1144).Scope of this issue
load_embedded_adapters=Truesupport toLocalHFBackend— mirror the OpenAI registration path inmellea/backends/adapters/_util.py; reuseEmbeddedIntrinsicAdapter.from_source/from_hub.render_controlsonLocalHFBackend: injectchat_template_kwargs["adapter_name"]intotransformers.generate(); skip the PEFTload_adapter/set_adapterpath and theobtain_loracall (Epic Epic: Fix Adapter Function Lifecycle & Consistency in Mellea #929 item 1.b)._generate_from_intrinsic(or the post-feat(backends): EmbeddedBinding implements apply_activation (Granite Switch path); remove render_controls + set_request_adapter (Epic #929 Phase 2) #1142EmbeddedBinding.activatepath) through this new path instead of raisingTypeError.IntrinsicsRewriter/IntrinsicsResultProcessorI/O transform (already used by the OpenAI path).LocalHFBackend × EmbeddedBindingintegration test (@integration,@hf,@slow) against a Granite Switch checkpoint.Out of scope: the OpenAI embedded path (#1142), the local PEFT/aLoRA
LocalFileBindingpath (#1141).Key files
mellea/backends/huggingface.py:509-594_generate_from_intrinsic— where theTypeErrorlivesmellea/backends/huggingface.py:1800add_adapter— typedLocalHFAdapteronlymellea/backends/openai.py:638-647mellea/backends/adapters/adapter.py:311EmbeddedIntrinsicAdapter(already exists)mellea/backends/adapters/_core.py:195EmbeddedBindingstubmellea/stdlib/components/intrinsic/_util.py:122-128_uses_embedded_adaptersregistration hook to mirrorAcceptance criteria
LocalHFBackend(load_embedded_adapters=True)registers embedded adapters from a Granite Switch sourcechat_template_kwargs["adapter_name"]; no PEFT load /obtain_loraon this pathLocalHFBackend × EmbeddedBindingintegration test passesIntrinsicsResultProcessor(shared with OpenAI path)ruff/mypycleanBlocked by: #1140, #1142
refactor(backends): shrink _generate_with_adapter_lock to its standar…
docs(backends): frame apply_activation as generative-computing#1018/g…
fix(backends): route intrinsic generation through adapter_scope, fix …
fix(backends): serialize resolve_adapter() registration under the act…
feat(backends): reuse exact token id prefixes under intrinsics
feat(backends): reuse exact token id prefixes under intrinsics
feat(backends): reuse exact token id prefixes under intrinsics