Skip to content

feat(backends): support embedded adapters on LocalHFBackend - #1593

Open
planetf1 wants to merge 6 commits into
generative-computing:mainfrom
planetf1:issue-1018
Open

feat(backends): support embedded adapters on LocalHFBackend#1593
planetf1 wants to merge 6 commits into
generative-computing:mainfrom
planetf1:issue-1018

Conversation

@planetf1

@planetf1 planetf1 commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Pull Request

Issue

Fixes #1018

Description

Before this change, a Mellea user with a Granite Switch checkpoint could use its
embedded adapter functions only through a vLLM deployment and OpenAIBackend.
They could not point LocalHFBackend at the checkpoint and use the existing
adapter-function helpers locally.

After installing mellea[hf], a user can construct
LocalHFBackend(..., load_embedded_adapters=True) around a local Granite Switch
checkpoint and call the same adapter-function helpers. Mellea discovers the
embedded functions, renders the selected control token through the checkpoint's
chat template, and parses the result. No separate adapter weights need to be
downloaded, loaded, or activated through PEFT.

Existing LocalHF runtime LoRA/aLoRA behaviour is unchanged: the Granite Switch
dependency and registration import run only when
load_embedded_adapters=True is selected.

What changes

  1. LocalHFBackend(load_embedded_adapters=True) discovers embedded adapter functions from a local checkpoint or Hugging Face source.
  2. Embedded calls run EmbeddedBinding.apply_activation() after request rewriting. The resulting adapter_name is forwarded into tokenizer.apply_chat_template().
  3. Embedded calls use the generation lock, clear any stale PEFT selection, and never download, load, or activate PEFT weights or enter adapter_scope().
  4. The shared Transformers request converter forwards safe template kwargs and rejects attempts to overwrite framework-owned values.
  5. Local paths and unqualified model IDs now derive a valid base model name during embedded registration.
  6. The adapter-functions how-to and Granite Switch examples document the
    mellea[hf] local install path and include a runnable local example.

Granite Switch dependency compatibility

The local checkpoint path installs through mellea[hf], which imports
the Granite Switch HF registration package only when embedded adapter functions
are requested. Granite Switch 0.1.0 currently declares a Transformers range
that excludes Mellea's resolved version, even though the consolidated local 3B
e2e passes on that version. Mellea therefore records an explicit resolver
override and emits a one-time warning while the installed Granite Switch
metadata still excludes the resolved Transformers version. The warning
automatically disappears when Granite Switch publishes widened metadata.

Current runtime warning:

UserWarning: granite-switch declares a Transformers range that excludes 5.10.2;
Mellea is using its explicit compatibility override for local Granite Switch
support. This warning will disappear once Granite Switch publishes widened metadata.

Follow-up: validate the wider range with the Granite Switch maintainers before
the next release.

Effect

Users can run adapter functions against a local Granite Switch checkpoint through LocalHFBackend. Only adapter functions listed in that checkpoint's adapter_index.json are available; the existing runtime LoRA/aLoRA path is unchanged.

Deliberately out of scope

Testing

  • uv run pytest test/backends/test_huggingface_unit.py -q — 98 passed

  • uv run mypy mellea/backends/huggingface.py mellea/backends/adapters/adapter.py test/backends/test_huggingface_unit.py

  • uv run ruff check and uv run ruff format --check on changed Python files

  • npx markdownlint-cli2 "docs/docs/advanced/intrinsics.md"

  • uv run pytest test/backends/test_huggingface_embedded.py -q -rs — real
    3B LocalHF e2e passed on Apple Silicon (1 passed, 30.93 s)

  • Same targeted e2e on a Linux GPU runner (1 passed, 60.18 s), including
    the assertion that the Switch template changes when adapter_name is set

  • uv sync --extra hf followed by the new local example —
    returned Answerability: answerable

  • Markdownlint plus API-doc build and 100% docstring-quality audit

  • uv run pytest test/ -m "not qualitative" — 4,130 passed, 1 failed. The unrelated test_matplotlib_agg_injected timed out while creating its isolated matplotlib environment; its requested targeted rerun passed.

  • Tests added to the respective file if code was changed

  • New code has 100% coverage if code was added

  • Ensure existing tests and github automation passes (a maintainer will kick off the github automation when the rest of the PR is populated)

Attribution

  • AI coding assistants used

Adding a new component, requirement, sampling strategy, or tool?

  • Component
  • Requirement
  • Sampling Strategy
  • Tool

NOTE: Please ensure you have an issue that has been acknowledged by a core contributor and routed you to open a pull request against this repository. Otherwise, please open an issue before continuing with this pull request.

@github-actions github-actions Bot added the enhancement New feature or request label Aug 27, 2026
Assisted-by: Codex
Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
Assisted-by: Codex
Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
Assisted-by: Codex
Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
Assisted-by: Codex
Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
Assisted-by: Codex
Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
Assisted-by: Codex
Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
@planetf1
planetf1 marked this pull request as ready for review August 28, 2026 10:45
@planetf1
planetf1 requested a review from a team as a code owner August 28, 2026 10:45

@AngeloDanducci AngeloDanducci left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally LGTM, one small thing to change WRT the dependencies.

Comment thread pyproject.toml
# granite-switch 0.1.0 declares transformers<5.10.0. Mellea's local Granite
# Switch e2e passes on 5.10.2; retain Mellea's tested HF range until upstream
# publishes widened Granite Switch metadata.
override-dependencies = ["transformers>5.5.0,<6.0.0"]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think [tool.uv] override-dependencies is only an uv workspace configuration — it is not part of [project] requires-dist and is never written into the built wheel/sdist. It only affects resolution inside this repo.

Should probably be moved to [project] somewhere.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

add support for granite-switch / embedded adapters on our huggingface backend

2 participants