Skip to content

feat(intrinsics): introduce Adapter/Identity/IOContract/WeightsBinding scaffolding (Epic #929 Phase 0) #1134

Closed

Description

@planetf1

Correction (2026-05-26): the name AdapterBasedComponent is the
chosen name for the user-facing component class. References to "placeholder"
below are design-tracker language only — they record that, if IBM later
chooses a different upstream term, a rename is scheduled in issue 4.1. The
source code itself asserts the name without hedging. Please disregard the
"placeholder" framing when reviewing the implementation.


Parent epic: #929
Design proposal: PR #1080
Phase: 0 (Wave 1 — file immediately, no dependencies)
Blocks: 1.A, 2.1, 2.2, 2.3, and #1111 (needs AdapterSchemaMismatchError)


Problem

Today's adapter hierarchy (IntrinsicAdapter / EmbeddedIntrinsicAdapter / CustomIntrinsicAdapter + abstract Adapter ABC) leaks the weights-location distinction into every caller via isinstance branching. Seven recent fix-up commits (8b6b8d55, c57aba1d, 8577d092, 4d372b0e, 0617bd96, 75465d29, 1734900d) trace directly to this structure. Adding new realities requires new branches everywhere (blocks #1018).

Separately, IBM is retiring the term "Intrinsic" but has not confirmed the replacement. Mellea uses AdapterBasedComponent as a placeholder.

Agreed design

Replace the four-class hierarchy with a single Adapter composed of three parts plus a pluggable binding:

Adapter
├── identity      — name, adapter_type (lora|alora), optional role
├── io_contract   — builds prompt + parses output (delegates to granite-common/formatters)
└── weights       — pluggable WeightsBinding: LocalFile / Embedded / ServerMediated

Types to introduce:

  • Adapter — dataclass with identity, io_contract, weights
  • Identity — dataclass: name: str, adapter_type: Literal["lora", "alora"], role: str | None = None
  • IOContract — ABC: build_prompt(...) -> Component and parse(raw: str) -> dict; parse raises AdapterSchemaMismatchError only on contract-breaking failures (not benign additions)
  • WeightsBinding — ABC with four verbs: prepare, activate, deactivate, release
  • Three stub subclasses raising NotImplementedError: LocalFileBinding, EmbeddedBinding, ServerMediatedBinding
  • AdapterSchemaMismatchError exception: attributes name, observed_keys, expected_keys; message format: "Adapter '{name}' output cannot satisfy declared contract. Observed keys: {observed_keys}; expected: {expected_keys}."

Placeholder module (AdapterBasedComponent):

  • New: mellea.stdlib.components.adapter_based_component re-exporting today's Intrinsic as AdapterBasedComponent
  • Old import mellea.stdlib.components.intrinsic stays valid
  • Module docstring notes placeholder rationale

KNOWN_ROLES advisory registry:

  • mellea/backends/adapters/roles.py — KNOWN_ROLES: frozenset[str] with initial role strings
  • Identity warns (UserWarning) when role not in KNOWN_ROLES; does not reject

⚠️ Critical: naming collision

The existing Adapter ABC at mellea/backends/adapters/adapter.py:24 shares the name with the proposed new Adapter dataclass. The implementer must either:

  • (a) Introduce the new type under a different module path, re-export as Adapter in the public surface, OR
  • (b) Move the old ABC to a private name

The chosen resolution must be documented in the PR description. Both approaches are acceptable; pick one and commit. Until 4.1 removes the shims, both must coexist.

Scope

  • mellea/backends/adapters/_core.py (or equivalent) — new types
  • mellea/backends/adapters/roles.py — KNOWN_ROLES
  • mellea/stdlib/components/adapter_based_component/__init__.py — placeholder re-export
  • Import new types + KNOWN_ROLES into mellea/backends/adapters/__init__.py
  • Existing classes (IntrinsicAdapter, etc.) not modified — that's 1.A

Out of scope

Any caller migration (1.A), binding verb implementations beyond NotImplementedError (Phase 2), shim removal (4.1), catalogue pinning (0.2), IBM rename.

Acceptance criteria

  • Adapter, Identity, IOContract, WeightsBinding importable from mellea.backends.adapters
  • IOContract ABC enforces both build_prompt and parse as abstract
  • WeightsBinding ABC enforces all four verbs as abstract
  • LocalFileBinding, EmbeddedBinding, ServerMediatedBinding raise NotImplementedError on each verb
  • AdapterSchemaMismatchError has correct attributes and message format
  • from mellea.stdlib.components.adapter_based_component import AdapterBasedComponent works
  • AdapterBasedComponent is Intrinsic evaluates True (same class object)
  • Old import mellea.stdlib.components.intrinsic still works
  • Naming-collision resolution documented in PR description
  • KNOWN_ROLES importable; Identity(role="unknown-role") emits UserWarning; Identity(role="answerability") does not
  • All existing tests pass unchanged
  • ruff format, ruff check, mypy clean

Test plan

test/backends/adapters/test_core_types.py:

  • test_adapter_dataclass_construction
  • test_identity_validation — adapter_type literal enforcement
  • test_io_contract_abc_enforcement
  • test_weights_binding_abc_enforcement
  • test_stub_binding_subclasses_raise_not_implemented
  • test_adapter_schema_mismatch_error_format

test/stdlib/components/test_adapter_based_component.py:

  • test_adapter_based_component_is_intrinsic
  • test_both_import_paths_work

test/backends/adapters/test_roles.py:

  • test_known_roles_is_frozenset
  • test_unknown_role_warns
  • test_known_role_does_not_warn
  • test_none_role_does_not_warn

Breaking changes

None for end users. Implementers importing the old Adapter ABC directly may need to update depending on the chosen naming-collision resolution — document in PR.

References

Activity

  1. self-assigned this
    on May 22, 2026
  2. added
    area/backendsProvider-specific work: Ollama, HF, LiteLLM, OpenAI, Bedrock, vLLM
    area/adapter-functionsGranite adapter functions: framework and adaptiers including RAG, Guardian, Core
    on May 22, 2026
  3. added this to the Release 0.6.0 milestone on May 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area/adapter-functionsGranite adapter functions: framework and adaptiers including RAG, Guardian, Corearea/backendsProvider-specific work: Ollama, HF, LiteLLM, OpenAI, Bedrock, vLLMenhancementNew feature or request

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions