Model Summary: Granite Switch 4.1 3B Preview is a modular LLM built on IBM Granite 4.1 3B with embedded adapters from the Granite Libraries collection. A single checkpoint supports multiple specialized capabilities — RAG, safety, explainability, and more — that are activated on demand via control tokens in the chat template.
For full details on model composition and adapter configuration, see BUILD.md.
Base Model:ibm-granite/granite-4.1-3b (3B params, 128K context)
Adapters: 12 adapters from granitelib-rag-r1.0, granitelib-core-r1.0, and granitelib-guardian-r1.0
Motivation:
Traditional multi-task LLM deployments require either separate model copies per capability (multiplying memory and compute) or weight merging that permanently blends adapters and destroys task specialization. Granite Switch takes a different approach: independently trained activated LoRA adapters are embedded in a single checkpoint and dynamically selected at inference time via control tokens. KV cache normalization ensures adapters share no internal KV cache state as each adapter sees prior tokens only through the base model's representation. That way, adapters can build on each other's outputs, but never through another adapter's cached activations. This allows adapters to be developed independently and composed without accuracy loss. This makes it possible to implement LLM capabilities very efficiently and very accurately.
Mellea is the preferred way to run Granite Switch adapters in applications. It standardizes the interface for building with adapters like answerability checking, hallucination detection, requirement checker and harmful language detection easily and reliably. Constrained decoding and input/output pre-processing are handled automatically, improving accuracy and reliability. When running Granite Switch models through Mellea, embedded adapters function as high-level API calls. This allows you to use direct operations instead of raw prompt engineering.
pip install mellea
Answerability check
python
1from mellea.backends.openai import OpenAIBackend
2from mellea.formatters import TemplateFormatter
3from mellea.stdlib.components import Document, Message
4from mellea.stdlib.components.intrinsic import rag
5from mellea.stdlib.context import ChatContext
67SWITCH_MODEL_ID ="ibm-granite/granite-switch-4.1-3b-preview"89backend = OpenAIBackend(10 model_id=SWITCH_MODEL_ID,11 formatter=TemplateFormatter(model_id=SWITCH_MODEL_ID),12 base_url="http://localhost:8000/v1",13 api_key="EMPTY",14 load_embedded_adapters=True,15)1617context = ChatContext().add(Message("assistant","Hello there, how can I help you?"))18question ="What is the square root of 4?"19documents =[Document("The square root of 4 is 2.")]2021result = rag.check_answerability(question, documents, context, backend)22print(f"Answerability: {result}")
Requirement check
python
1from mellea.stdlib.components.intrinsic import core
23context = ChatContext().add(4 Message("user","Invite for an IBM office party.")5).add(6 Message("assistant","Dear Team, you are cordially invited to a team social...")7)89result = core.requirement_check(context, backend, requirement="Use a professional tone.")10print(f"Requirements Satisfied: {result}")# float between 0.0 and 1.0
Guardian core (safety detection)
python
1from mellea.stdlib.components.intrinsic import guardian
23context = ChatContext().add(4 Message("user","How can I hack my friend's email?")5)67score = guardian.guardian_check(context, backend, criteria="harm", target_role="user")8verdict ="Risk detected"if score >=0.5else"Safe"9print(f"Score: {score:.4f} ({verdict})")
See the mellea examples/ directory for more examples, including manual adapter loading.
The following examples demonstrate low-level adapter invocation via the HuggingFace and vLLM backends directly. Check Granite Switch For additional tutorials.
HuggingFace Inference
python
1import granite_switch.hf # Register the model architecture23from transformers import AutoModelForCausalLM, AutoTokenizer
45model = AutoModelForCausalLM.from_pretrained("ibm-granite/granite-switch-4.1-3b-preview", device_map="auto")6tokenizer = AutoTokenizer.from_pretrained("ibm-granite/granite-switch-4.1-3b-preview")
Activate an adapter via the chat template
python
1messages =[2{"role":"assistant","content":"Hello there, how can I help you?"},3{"role":"user","content":"What is the square root of 4?"},4]5documents =[{"doc_id":"1","text":"The square root of 4 is 2."}]67prompt = tokenizer.apply_chat_template(8 messages,9 documents=documents,10 adapter_name="answerability",# activate the answerability adapter11 add_generation_prompt=True,12 tokenize=False,13)1415outputs = model.generate(**tokenizer(prompt, return_tensors="pt").to(model.device))16print(tokenizer.decode(outputs[0], skip_special_tokens=True))17# => "answerable"
1from openai import OpenAI
23client = OpenAI(base_url="http://localhost:8000/v1", api_key="unused")45response = client.chat.completions.create(6 model="ibm-granite/granite-switch-4.1-3b-preview",7 messages=[8{"role":"assistant","content":"Hello there, how can I help you?"},9{"role":"user","content":"What is the square root of 4?"},10],11 extra_body={12"documents":[{"doc_id":"1","text":"The square root of 4 is 2."}],13"chat_template_kwargs":{"adapter_name":"answerability"},14},15 max_completion_tokens=6,16)17print(response.choices[0].message.content)18# => "answerable"
Or with curl:
bash
1curl -s http://localhost:8000/v1/chat/completions \2 -H "Content-Type: application/json"\3 -d '{
4 "model": "ibm-granite/granite-switch-4.1-3b-preview",
5 "messages": [
6 {"role": "assistant", "content": "Hello there, how can I help you?"},
7 {"role": "user", "content": "What is the square root of 4?"}
8 ],
9 "documents": [{"doc_id": "1", "text": "The square root of 4 is 2."}],
10 "chat_template_kwargs": {"adapter_name": "answerability"},
11 "max_completion_tokens": 6
12 }'
Model Artifacts:
File
Description
model.safetensors
Full model with embedded adapters
config.json
GraniteSwitchConfig
tokenizer.json / tokenizer_config.json
Tokenizer with control tokens
adapter_index.json
Adapter-to-control-token mapping
io_configs/
Original io.yaml for each adapter
chat_template.jinja
Jinja template with adapter activation logic
BUILD.md
Composed model details and adapter configuration
Requirements:
Dependency
Version
Python
>= 3.9
PyTorch
>= 2.0.0
Transformers
>=5.5.1
vLLM (optional)
>= 0.19.1, < 0.21.0
How It Works
Granite Switch uses coarse-grained expert switching — one adapter is active across all layers for a contiguous span of tokens. A lightweight switch layer (standard attention) detects control tokens in the input and produces per-position adapter indices that tell every decoder layer which LoRA weights to apply.
Each adapter is activated by passing its name to the chat template using an argument. The template inserts the appropriate control token automatically — callers just pass adapter_name.
Ethical Considerations and Limitations
This model inherits the safety profile of the base Granite 4.1 model. The Guardian Library adapters (guardian core, factuality detection/correction, policy guardrails) provide additional safety layers but are not a substitute for application-level safety testing. Deployers should:
Test adapter behavior on their specific use cases before production deployment
Apply appropriate content filtering for their domain
Monitor adapter outputs, especially for safety-critical applications
Use the uncertainty adapter to assess model confidence on important decisions
Model Signing
The model.sig file contains a signature over all model artifacts to ensure integrity and provenance.
To verify the integrity of a downloaded adapter, use the model-signing tool:
bash
1# First obrain the model weights2hf download ibm-granite/granite-switch-4.1-3b-preview --local-dir granite-switch-4.1-3b-preview
34# Install the model signing verification tool5pip install'model-signing==v1.1.1'67# Verify all artifacts in an adapter's lora/ directory8model_signing verify sigstore \9 --signature granite-switch-4.1-3b-preview/model.sig \10 --ignore-git-paths \11 --ignore-paths granite-switch-4.1-3b-preview/README.md \12 --identity Granite-sign@ibm.com \13 --identity_provider https://sigstore.verify.ibm.com/oauth2 \14 granite-switch-4.1-3b-preview
The "Verification succeeded" message confirms that the model has not been tampered with after release.
License
Granite Switch has an Apache-2.0 license, as found in the LICENSE file.
Citation
bibtex
1@software{granite_switch,
2 title = {Granite Switch: Coarse-Grained Expert Switching for LLMs},
3 author = {IBM Research},
4 year = {2026},
5 url = {https://github.com/generative-computing/granite-switch}
6}