Skip to content

refactor(backends): AdapterMixin verb rename/narrow + resolve_model_options + IntrinsicMetricsPlugin (Epic #929 Phase 2) #1140

@planetf1

Description

@planetf1

Parent epic: #929
Design proposal: PR #1080 §13, §16 Phase 2
Phase: 2 (Wave 3 — start after 1.A merges, in parallel with 1.B/1.C/1.D)
Depends on: 1.A
Blocks: 2.2, 2.3


Problem

Two related backend-surface concerns that touch the same files:

(a) Mixin verb mismatch. AdapterMixin (verified main mellea/backends/adapters/adapter.py:240) exposes five verbs: base_model_name, add_adapter, load_adapter, unload_adapter, list_adapters. The proposed design uses different verbs: load_peft_adapter, unload_peft_adapter, render_controls, set_request_adapter. This is a rename + introduce, not a pure rename.

(b) Per-call option merging. Each backend calls _simplify_and_merge on every adapter call. Duplicated logic and a known precedence bug source (PR #972 was a fix for this).

Agreed design

(a) AdapterMixin verb rename/narrow

AdapterMixin after this issue:

AdapterMixin:
  load_peft_adapter / unload_peft_adapter   # LocalFile reality
  render_controls                           # Embedded reality
  set_request_adapter                       # ServerMediated reality

Map existing implementations onto new verbs case-by-case. base_model_name and list_adapters: remove if unused after 1.A; otherwise relocate with documented justification. Bindings (2.2/2.3) call into these from their prepare/activate/etc.

Backends affected: LocalHFBackend, OpenAIBackend (the two adapter-supporting backends). Not affected: OllamaBackend, WatsonxBackend, LiteLLMBackend.

(b) Option resolution

New mellea/backends/_options.py:resolve_model_options — documents and implements precedence: caller-passed model_options= > helper defaults > backend defaults. Both adapter-supporting backends replace _simplify_and_merge with resolve_model_options on the adapter call path.

IntrinsicMetricsPlugin

New plugin at mellea/core/plugins/intrinsic_metrics.py. Three OTel metrics:

  • mellea.intrinsic.invocations — counter; labels: name, revision, binding_type, adapter_type, outcome (success/schema_error/error)
  • mellea.intrinsic.phase_duration_ms — histogram; labels: name, phase (prepare/activate/generate/parse/deactivate)
  • mellea.intrinsic.parse_failures — counter; labels: name, revision. Schema-drift detector: a climbing counter against (name, revision) means a breaking schema change was pushed upstream. Increments on each AdapterSchemaMismatchError.

Auto-wired via the existing TokenMetricsPlugin registration pattern.

Observability doc

New docs/dev/adapter_observability.md — span tree structure, metric labels, parse_failures schema-drift detector pattern, MELLEA_TRACE_CONTENT content-capture gate. Phases 2.2/2.3 add span emission details; this issue writes the structure.

Out of scope

Binding implementations (2.2, 2.3), span instrumentation (lives where verbs are implemented), HF embedded adapter support (#1018).

Acceptance criteria

  • AdapterMixin exposes exactly the four verbs above; old verbs removed or relocated with documented justification
  • LocalHFBackend and OpenAIBackend implement the new verb set
  • resolve_model_options exists, documented, tested
  • Both adapter-supporting backends use resolve_model_options instead of _simplify_and_merge on adapter call path
  • IntrinsicMetricsPlugin registerable like existing plugins
  • All three metrics registered with correct label sets
  • mellea.intrinsic.parse_failures increments on AdapterSchemaMismatchError
  • docs/dev/adapter_observability.md written; covers span tree, metric labels, parse_failures pattern, MELLEA_TRACE_CONTENT gate; markdownlint passes
  • Existing tests pass (precedence behaviour unchanged)
  • New unit tests cover precedence: caller > helper > backend
  • Test asserts AdapterMixin exposes exactly the four verbs (catches accidental re-additions)
  • Unit tests for IntrinsicMetricsPlugin using synthetic OTel exporter
  • ruff format, ruff check, mypy clean

Test plan

  • Existing backend tests pass
  • resolve_model_options precedence tests: each pair (caller-vs-helper, caller-vs-backend, helper-vs-backend)
  • Verb set test: assert AdapterMixin has exactly the four verbs
  • IntrinsicMetricsPlugin unit tests:
    • test_invocations_counter_emits_on_success
    • test_invocations_counter_emits_schema_error_outcome
    • test_parse_failures_counter_increments
    • test_phase_duration_histogram_emits_for_each_phase

Breaking changes

  • AdapterMixin verb rename — downstream backends extending AdapterMixin must update. Migration table (old → new verb names) in changelog.
  • _simplify_and_merge removal from adapter call path — internal API only.

References

Metadata

Metadata

Assignees

Labels

area/backendsProvider-specific work: Ollama, HF, LiteLLM, OpenAI, Bedrock, vLLMarea/intrinsicsGranite intrinsic adapters: RAG, Guardian, Corearea/telemetryOTel spans, metrics, tracing, semconvrefactor

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions