Adapter functions
Prerequisites: pip install "mellea[hf]" for LocalHFBackend (GPU or Apple
Silicon Mac recommended), or pip install mellea for OpenAIBackend with a
Granite Switch model served via vLLM.
Adapter functions are adapter-accelerated operations for RAG quality checks. They use LoRA/aLoRA adapters loaded directly into the Hugging Face backend — faster and more reliable than prompting a general-purpose model for these specialized micro-tasks.
Backend note: Adapter functions work with two backends:
- LocalHFBackend — loads LoRA/aLoRA adapters from the catalog at runtime. All adapter functions are available. Requires a GPU or Apple Silicon Mac.
- OpenAIBackend — uses a Granite Switch model served via vLLM with
load_embedded_adapters=True. Only adapter functions embedded in the model are available — check the model'sadapter_index.jsonfor the list. Seedocs/docs/examples/granite-switch/README.mdAdapter functions do not work with Ollama or other remote backends.
Set up the backend once and reuse it across adapter function calls:
# Requires: mellea[hf]
# Returns: LocalHFBackend
from mellea.backends.huggingface import LocalHFBackend
backend = LocalHFBackend(model_id="ibm-granite/granite-4.1-3b")
Or, with a Granite Switch model via the OpenAI backend:
from mellea.backends.openai import OpenAIBackend
from mellea.backends.model_ids import IBM_GRANITE_SWITCH_4_1_3B_PREVIEW
from mellea.formatters import TemplateFormatter
backend = OpenAIBackend(
model_id=IBM_GRANITE_SWITCH_4_1_3B_PREVIEW.hf_model_name,
formatter=TemplateFormatter(model_id=IBM_GRANITE_SWITCH_4_1_3B_PREVIEW.hf_model_name),
base_url="http://localhost:8000/v1", # vLLM server
api_key="EMPTY",
load_embedded_adapters=True,
)
Answerability
Check whether a set of retrieved documents can answer a given question:
# Requires: mellea[hf]
# Returns: bool
from mellea.backends.huggingface import LocalHFBackend
from mellea.stdlib.components import Document, Message
from mellea.stdlib.components.intrinsic import rag
from mellea.stdlib.context import ChatContext
backend = LocalHFBackend(model_id="ibm-granite/granite-4.1-3b")
context = ChatContext().add(Message("assistant", "Hello! How can I help you?"))
question = "What is the square root of 4?"
docs_answerable = [Document("The square root of 4 is 2.")]
docs_not_answerable = [Document("The square root of 8 is approximately 2.83.")]
print(rag.check_answerability(question, docs_answerable, context, backend)) # True
print(rag.check_answerability(question, docs_not_answerable, context, backend)) # False
Context relevance
check_context_relevance() is deprecated and will be removed in a future release.
The underlying adapter is Granite 4.0 only and will not receive a Granite 4.1 version.
There is no direct adapter replacement. check_answerability() addresses a
related but different question — it asks whether a set of documents can collectively
answer a question (binary result), while check_context_relevance() scores a single
document on a three-way scale. They operate at different stages of a RAG pipeline and
are not interchangeable.
For per-document relevance filtering, use a @generative function with any current
Granite backend:
from mellea import generative
@generative
def is_relevant(document: str, question: str) -> bool:
"""Determine whether the document contains information relevant to the question."""
See Build a RAG pipeline for a full example.
Assess whether a document is relevant to a question:
# Requires: mellea[hf]
# Returns: str
from mellea.backends.huggingface import LocalHFBackend
from mellea.stdlib.components import Document
from mellea.stdlib.components.intrinsic import rag
from mellea.stdlib.context import ChatContext
# NOTE: no context_relevance adapter for Granite 4.1 — use granite-4.0-micro
backend = LocalHFBackend(model_id="ibm-granite/granite-4.0-micro")
context = ChatContext()
question = "Who is the CEO of Microsoft?"
document = Document(
"Microsoft Corporation is an American multinational corporation "
"headquartered in Redmond, Washington."
)
result = rag.check_context_relevance(question, document, context, backend)
print(result) # 'partially relevant' — doc is about Microsoft but not its CEO
Hallucination detection
Flag sentences in an assistant response that are not grounded in the source documents:
# Requires: mellea[hf]
# Returns: list[str]
from mellea.backends.huggingface import LocalHFBackend
from mellea.stdlib.components import Document, Message
from mellea.stdlib.components.intrinsic import rag
from mellea.stdlib.context import ChatContext
backend = LocalHFBackend(model_id="ibm-granite/granite-4.1-3b")
context = (
ChatContext()
.add(Message("assistant", "Hello! How can I help you?"))
.add(Message("user", "Tell me about yellow fish."))
)
response = "Purple bumble fish are yellow. Green bumble fish are also yellow."
documents = [
Document(doc_id="1", text="The only type of fish that is yellow is the purple bumble fish.")
]
result = rag.flag_hallucinated_content(response, documents, context, backend)
print(result)
# Flags "Green bumble fish are also yellow." as hallucinated
Answer relevance rewriting
Rewrite a vague or incomplete answer to be more grounded in the source documents:
# Requires: mellea[hf]
# Returns: str
from mellea.backends.huggingface import LocalHFBackend
from mellea.stdlib.components import Document, Message
from mellea.stdlib.components.intrinsic import rag
from mellea.stdlib.context import ChatContext
backend = LocalHFBackend(model_id="ibm-granite/granite-4.1-3b")
context = ChatContext().add(Message("user", "Who attended the meeting?"))
documents = [
Document("Meeting attendees: Alice, Bob, Carol."),
Document("Meeting time: 9:00 am to 11:00 am."),
]
original = "Many people attended the meeting."
result = rag.rewrite_answer_for_relevance(original, documents, context, backend)
print(result)
# A more specific, grounded answer — output will vary