Instructions to use drstupidity/granite-3.3-2b-customer-support with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use drstupidity/granite-3.3-2b-customer-support with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="drstupidity/granite-3.3-2b-customer-support") messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("drstupidity/granite-3.3-2b-customer-support") model = AutoModelForCausalLM.from_pretrained("drstupidity/granite-3.3-2b-customer-support", device_map="auto") messages = [ {"role": "user", "content": "Who are you?"}, ] inputs = tokenizer.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=40) print(tokenizer.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use drstupidity/granite-3.3-2b-customer-support with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "drstupidity/granite-3.3-2b-customer-support" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "drstupidity/granite-3.3-2b-customer-support", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/drstupidity/granite-3.3-2b-customer-support
- SGLang
How to use drstupidity/granite-3.3-2b-customer-support with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "drstupidity/granite-3.3-2b-customer-support" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "drstupidity/granite-3.3-2b-customer-support", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "drstupidity/granite-3.3-2b-customer-support" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "drstupidity/granite-3.3-2b-customer-support", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use drstupidity/granite-3.3-2b-customer-support with Docker Model Runner:
docker model run hf.co/drstupidity/granite-3.3-2b-customer-support
Customer Support Assistant (granite-3.3-2b)
LoRA fine-tune of ibm-granite/granite-3.3-2b-instruct on the
Bitext customer-support dataset,
trained to answer customer-support requests in a helpful support register.
Prompt template
Training, evaluation and serving all use this exact format. Use the model's own chat template
with add_generation_prompt=True.
System prompt:
You are a customer support assistant. Read the customer's message, understand what they need, and reply accurately and helpfully in a professional, empathetic tone. Give concrete next steps when they apply, and never invent account details, order numbers, or policies you were not given.
from transformers import AutoModelForCausalLM, AutoTokenizer
MODEL = "drstupidity/granite-3.3-2b-customer-support"
tok = AutoTokenizer.from_pretrained(MODEL)
model = AutoModelForCausalLM.from_pretrained(MODEL, dtype="bfloat16", device_map="auto")
messages = [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": "I need to cancel order 12345"},
]
prompt = tok.apply_chat_template(
messages, tokenize=False, add_generation_prompt=True
)
inputs = tok(prompt, return_tensors="pt").to(model.device)
out = model.generate(**inputs, max_new_tokens=512, do_sample=False)
print(tok.decode(out[0][inputs.input_ids.shape[1]:], skip_special_tokens=True))
The model was trained with a 15% system-prompt dropout, so it also behaves sensibly with a different system prompt or none at all.
These weights are the model, not the served stack
Everything above is all you need. The repository also runs a guardrail layer in front of the model at serve time (NeMo Guardrails plus a local out-of-domain embedding check), but none of it is baked into these weights and none of it is required to run them. Loading the checkpoint as shown gives you the model alone.
That separation is deliberate. The rails divert a small fraction of requests to predefined text
instead of generating -- measured at 0.27% of real validation queries, and 9.4% on a deliberately
adversarial probe set. If those fired during someone else's evaluation, the scores would describe
the rails rather than the model. So the serving layer exposes an ungated /v1/completions route
for exactly that purpose, and the rails can be turned off entirely with CSBOT_GUARDRAILS=0.
Training
| method | LoRA (r=16, alpha=32, dropout=0.05) |
| target modules | q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj |
| learning rate | 0.0002 |
| schedule | cosine, warmup 0.03 |
| effective batch | 32 |
| max seq len | 640 |
| train rows | 31,343 |
| guardrail rows | 1,235 synthetic "when not to help" examples |
| loss | completion-only (assistant tokens) |
| hardware | NVIDIA GeForce RTX 5060 Laptop GPU, peak 3.47 GB |
| final eval loss | 0.6328 |
Data was split by near-duplicate cluster, not by row: the source dataset is 27 intents with roughly a thousand generated paraphrases each, so a random split leaks near-identical text across the train/test boundary. See the project repository for the leakage audit, evaluation design and base-vs-tuned results.
Why there are synthetic "decline" examples in the training data
Every one of the 23,453 Bitext rows is "customer asks -> agent helpfully assists". There is not a single example of declining. Fine-tuning on that alone taught the model always help, which is right inside the domain and wrong the moment a query leaves it: measured against a held-out behavioural probe set, its off-topic redirect rate dropped from 0.800 (base model) to 0.350.
Blending in a 5% slice of examples that decline off-topic requests, refuse instruction overrides, ask for clarification when a message is uninformative, and decline to invent account data brought that to 0.850 -- past the base model -- at no measurable in-domain cost (validation loss 0.6461 vs 0.6436 for an otherwise identical control run).
Limitations
- Trained on synthetic, English, single-turn support data. It has no multi-turn conversation training and no access to real account systems.
- It must not be relied on for account-specific facts; it is trained never to invent order numbers, policies or contact details, but that is a tendency, not a guarantee.
- Non-English input is out of distribution for the training data.
- Downloads last month
- 187
Model tree for drstupidity/granite-3.3-2b-customer-support
Base model
ibm-granite/granite-3.3-2b-base