refactor(adapters): decouple KNOWN_CAPABILITIES from catalog entry names (#1186)#1266
Conversation
…mes (generative-computing#1186) Add an optional `capability` field to `IntriniscsCatalogEntry` and an `effective_capability` property (returns `capability` or falls back to `name`). Derive `KNOWN_CAPABILITIES` from `effective_capability` instead of `name`, so the capability vocabulary survives upstream adapter renames. Set explicit underscore capabilities on the six hyphenated catalog entries (context-attribution, requirement-check, policy-guardrails, guardian-core, factuality-detection, factuality-correction). All other entries default to their name unchanged. Closes generative-computing#1186. Part of Epic generative-computing#929 Phase 0. Assisted-by: Claude Code Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
Add three extra assertions to catch future regressions: - no hyphenated names can leak into KNOWN_CAPABILITIES - count of capabilities must equal count of catalog entries (no duplicates) - every catalog entry's effective_capability is non-empty Assisted-by: Claude Code Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
f488e62 to
a83e2fe
Compare
|
Will actually review later, but there were a few non-blocking optional things that an AI review put forward (so treat them as such):
|
Address two structural gaps raised in PR review: - Add field_validator on `capability` rejecting empty/whitespace strings, making the effective_capability "guaranteed non-empty" docstring true rather than conventional. - Add module-level uniqueness check so duplicate effective_capability values raise ValueError at import time, not just at test time. Assisted-by: Claude Code Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
|
Thanks @psschwei. 1 and 2 are fixed in the latest commit: now rejects empty/whitespace strings via a field validator, and the catalog asserts uniqueness of values at import time rather than relying on the test alone. 3 (the class name misspelling) is tracked in #1268. Deferred to a standalone PR after #1256 and this one merge — both have open diffs against the same files and adding a rename now would create unnecessary conflict for one of them. |
psschwei
left a comment
There was a problem hiding this comment.
lgtm outside of the things @ajbozarth already mentioned
…uarantee true Add _check_name validator rejecting empty/whitespace strings on IntriniscsCatalogEntry.name. The effective_capability fallback path returns name unchanged, so without this validator the "guaranteed non-empty" docstring was only honoured when capability was explicitly set. Now both branches are guarded and the guarantee holds for any constructed entry. Consistent with the existing validators on capability and revision. Assisted-by: Claude Code Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
…, revision Extend all three string token validators to be consistent: empty/whitespace- only strings were already rejected; now leading or trailing whitespace is rejected too. Silent normalisation (strip-and-return) is deliberately not used — the codebase convention is validators raise, they do not mutate. Covers _check_name, _check_capability (both new in this PR), and the pre-existing validate_revision. Update docstrings and Raises entries accordingly. Assisted-by: Claude Code Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
Move the inline `from mellea.backends.adapters.catalog import _INTRINSICS_CATALOG_ENTRIES` from inside two test functions to the module-level import block in each file. No logic change. Assisted-by: Claude Code Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
e1fce6d
…mputing#1266 content) Two HuggingFace references in docstrings were introduced by the generative-computing#1186 capability-decoupling work (generative-computing#1266) after the original sweep's branch point — not caught until rebase. Brought in line with the rest of the brand name corrections. Assisted-by: Claude Code Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
…nerative-computing#1192) (generative-computing#1256) * chore(terminology): adopt agreed Granite Switch / Mellea glossary (generative-computing#1192) Sweeps the five Phase 0 adapter files, AGENTS.md, and the reference glossary to use the canonical terms agreed under Epic generative-computing#929: - "adapter function" replaces "intrinsic" / "intrinsic function" in prose - "aLoRA" replaces "Activated LoRA" / "activated-LoRA" - "Granite Switch" replaces "Project Granite Switch" - "cache hit/miss" framing in the aLoRA glossary entry (never "cache rewrite") Python symbol names (IntrinsicAdapter, fetch_intrinsic_metadata, etc.) and import paths are untouched — those renames are Phase 1 (generative-computing#1136) / Phase 4 (generative-computing#1144). Also adds the full agreed glossary set to docs/docs/reference/glossary.md: Adapter function, Adapter, Capability, Checkpoint, Granite Libraries, Granite Switch, Granite Switch composer, Mellea, and a References section. Fixes the duplicate ## 13 heading in AGENTS.md (→ ## 14). Assisted-by: Claude Code Signed-off-by: Nigel Jones <jonesn@uk.ibm.com> * fixup! chore(terminology): adopt agreed Granite Switch / Mellea glossary (generative-computing#1192) Address code review findings: - adapter.py: fix four missed prose descriptions in EmbeddedIntrinsicAdapter and CustomIntrinsicAdapter (intrinsic_name param docs, __init__ docstring) - adapter.py:202: lands → is merged (second TODO comment missed by replace-all) - adapter.py:335: fix clunky doubled noun in EmbeddedIntrinsicAdapter init doc - glossary.md aLoRA entry: rewrite to centre base-model KV-cache reuse / single-token activation (the fundamental mechanism), keep multi-adapter Granite Switch throughput benefit as secondary paragraph - glossary.md: move ## Mellea above ## MelleaSession (alphabetical order) Assisted-by: Claude Code Signed-off-by: Nigel Jones <jonesn@uk.ibm.com> * chore(terminology): extend glossary sweep to docstrings, backends, and integration docs - Fix Adapter / Adapter function glossary entry ordering (alphabetical) - Replace "Guardian Intrinsic function" with "Guardian adapter function" in all four Guardian glossary entries and the GuardianCheck deprecation note - Replace "Intrinsic function(s)" with "Adapter function(s)" in module and function docstrings: core.py, rag.py, guardian.py - Replace "activated LoRAs" / "ALoras" with "aLoRA adapters" in backend error messages and docstrings: huggingface.py, litellm.py, watsonx.py, ollama.py; fix double-"support" typo in watsonx.py and ollama.py error messages - Replace "ALora" with "aLoRA" in requirement.py comment - Replace "intrinsic functions" / "intrinsic wrappers" / "intrinsics" prose in integration docs: openai.md, huggingface.md, lora-and-alora-adapters.md Assisted-by: Claude Code Signed-off-by: Nigel Jones <jonesn@uk.ibm.com> * chore(terminology): sweep Guardian Intrinsics → Guardian adapter functions Replaces all remaining "Guardian Intrinsics" / "Guardian intrinsics" prose with "Guardian adapter functions" across 13 doc pages and one deprecation warning in guardian.py. Not covered by Phase 1 (generative-computing#1136, symbol-only) or Phase 4 (generative-computing#1144, deferred page rewrite) — safe to fix in this sweep. Also fixes 7 bare [Intrinsics](path) cross-doc links (missing .md suffix, violating CONTRIBUTING_DOCS.md) by adding the extension and updating link text to "Adapter functions". No page slugs are renamed; the intrinsics.md page stays in place until Phase 4. Assisted-by: Claude Code Signed-off-by: Nigel Jones <jonesn@uk.ibm.com> * chore(terminology): address review findings from generative-computing#1256 Four user-facing error strings in adapter.py still said "intrinsic" as prose, directly violating issue generative-computing#1192 criterion generative-computing#4 ("Done when: no 'intrinsic' prose remains in the five Phase 0 files"). Sweep the four f-strings: - "Intrinsic '{name}' not available as an adapter of type …" - "io.yaml for intrinsic '{name}' …" - "No adapter found for intrinsic '{name}' in {path}" (×2) Sweep remaining user-visible prose in two other files: - openai.py:582 — "has no adapter for processing intrinsic: …" - rag.py:206 — "Citation generation intrinsic failed: …" Fix openai.md section heading ("## Intrinsics with Granite Switch" → "## Adapter functions with Granite Switch") — body was swept in prior commit but heading was missed, leaving the section self-contradictory. Sweep intrinsics.md page title and body prose (title, opening paragraph, backend-note callout, reuse-note, Direct-usage heading, catalog reference) to use "adapter functions" throughout. File slug rename is deferred to Phase 4 (generative-computing#1144); the page content is swept here to keep it consistent with the cross-references that now point to it as "Adapter functions". Fix three remaining safety-guardrails links without .md suffix in common-errors.md and the lora-and-alora-adapters link in prefix-caching-and-kv-blocks.md. Assisted-by: Claude Code Signed-off-by: Nigel Jones <jonesn@uk.ibm.com> * test: update error message assertion after terminology sweep test_filter_nonexistent_intrinsic matched the old "No adapter found for intrinsic" string; update to match the swept form "No adapter found for adapter function". Assisted-by: Claude Code Signed-off-by: Nigel Jones <jonesn@uk.ibm.com> * docs: fix broken tutorial link in safety-guardrails See also The .md suffix added in the terminology sweep made Docusaurus validate the link, revealing it pointed to the wrong filename. The tutorial file is 04-making-agents-reliable.md, not making-agents-reliable.md. Assisted-by: Claude Code Signed-off-by: Nigel Jones <jonesn@uk.ibm.com> * docs: correct HuggingFace → Hugging Face brand name in prose 'Hugging Face' is the correct two-word brand name. URLs (huggingface.co), Python symbols (huggingface_hub, LocalHFBackend), and file slugs are intentionally unchanged — only prose references are corrected. 14 files, 25 occurrences. 9 of these files were already in the PR diff; the remaining 5 (context-and-sessions, installation, quickstart, smolagents, faq) are included since the work was already underway. No page slugs change and no redirects are needed — Docusaurus derives URL slugs from file paths, not page titles. Assisted-by: Claude Code Signed-off-by: Nigel Jones <jonesn@uk.ibm.com> * docs: correct HuggingFace → Hugging Face in catalog.py (generative-computing#1266 content) Two HuggingFace references in docstrings were introduced by the generative-computing#1186 capability-decoupling work (generative-computing#1266) after the original sweep's branch point — not caught until rebase. Brought in line with the rest of the brand name corrections. Assisted-by: Claude Code Signed-off-by: Nigel Jones <jonesn@uk.ibm.com> * chore(terminology): thorough sweep of remaining intrinsic prose and HuggingFace brand catalog.py: effective_capability docstring said "for this intrinsic"; corrected to "adapter function" (Phase 0 file, missed in original sweep). rag.py: three docstrings and two internal comments still referenced "find_citations intrinsic" / "passed to intrinsics"; swept to "adapter function". adapter.py, huggingface.py, openai.py, guardian.py: HuggingFace brand name corrected to "Hugging Face" in docstrings and comments across all four Python files that were already in the PR diff. Note: docstrings that describe _generate_from_intrinsic() by name (openai.py, huggingface.py) are deliberately left — they are tied to that Python symbol and will be swept naturally in Phase 1 (generative-computing#1136). Out of scope for this PR (noted for follow-up): docs/examples/ READMEs not in this diff, and Python files outside the sweep perimeter (backend.py, tools.py, model_ids.py, etc.). Assisted-by: Claude Code Signed-off-by: Nigel Jones <jonesn@uk.ibm.com> --------- Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
Fixes #1186. Part of Epic #929 Phase 0 (adapter lifecycle refactor).
Background
Epic #929 is a multi-phase refactor of how Mellea loads and identifies adapters (LoRA/aLoRA fine-tuned modules). Phase 0 (
#1134,#1135, this PR) lays the scaffolding; later phases wire it into the live loading paths.This PR fixes a coupling introduced in
#1134:KNOWN_CAPABILITIESwas built directly from catalog entrynamefields, so the capability vocabulary was tied to the names HuggingFace uses for their adapters. When an upstream adapter gets renamed, Mellea capability strings break too. Therequirement-check/requirement_checkmismatch (hyphens vs underscores) had already forced several edits.Change
Before — capability vocabulary = upstream adapter names:
After — capability vocabulary is declared independently:
effective_capabilityreturnscapabilitywhen set, falling back toname— so entries whose name is already a clean identifier (answerability,citations, etc.) need no explicitcapabilityfield.The six hyphenated catalog entries (Core + Guardian groups) get explicit underscore capabilities. The seven underscore-named RAG entries are unchanged.
The issue also called out updating call sites that hardcode adapter names as capabilities. There are none:
Identityis Phase 0 scaffolding not yet wired into production adapter loading — nothing in production code constructsIdentityobjects today. That migration is Phase 1/2 work.Validation hardening
As part of ensuring
effective_capabilitygenuinely guarantees a non-empty, clean token, this PR extends validation consistently across all three string token fields onIntriniscsCatalogEntry:name,capability, andrevisionall now reject empty strings, whitespace-only strings, and strings with leading or trailing whitespacemellea/validate_revision(pre-existing, exported) updated to matchRelationship to #1256
Independent of #1256 (terminology sweep) — can merge in either order. Both touch
catalog.pyandcapabilities.pybut in different lines. Whoever merges second needs a one-line docstring rebase.Test plan
60 tests pass. Key assertions:
"requirement_check" in KNOWN_CAPABILITIES,"requirement-check" not in KNOWN_CAPABILITIESKNOWN_CAPABILITIES(regression guard)len(KNOWN_CAPABILITIES) == len(_INTRINSICS_CATALOG_ENTRIES)(no duplicates)name,capability,revisionall reject empty, whitespace-only, and leading/trailing whitespace