Instructions to use BasselNashaat/SmolLM3-3B-banking77 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use BasselNashaat/SmolLM3-3B-banking77 with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="BasselNashaat/SmolLM3-3B-banking77") messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# pip install -U transformers accelerate # Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("BasselNashaat/SmolLM3-3B-banking77") model = AutoModelForCausalLM.from_pretrained("BasselNashaat/SmolLM3-3B-banking77", 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=256) print(tokenizer.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use BasselNashaat/SmolLM3-3B-banking77 with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "BasselNashaat/SmolLM3-3B-banking77" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "BasselNashaat/SmolLM3-3B-banking77", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/BasselNashaat/SmolLM3-3B-banking77
- SGLang
How to use BasselNashaat/SmolLM3-3B-banking77 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 "BasselNashaat/SmolLM3-3B-banking77" \ --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": "BasselNashaat/SmolLM3-3B-banking77", "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 "BasselNashaat/SmolLM3-3B-banking77" \ --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": "BasselNashaat/SmolLM3-3B-banking77", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use BasselNashaat/SmolLM3-3B-banking77 with Docker Model Runner:
docker model run hf.co/BasselNashaat/SmolLM3-3B-banking77
SmolLM3-3B-banking77
HuggingFaceTB/SmolLM3-3B fine-tuned to sort online-banking customer messages into the 77 intents of BANKING77. Made as a final project of the Hugging Face smol-course.
Results
All 3080 messages of the BANKING77 test split, which training never used. The model writes the intent name, and an answer that isn't exactly one of the 77 names counts as wrong.
| Model | Accuracy | Macro precision | Macro recall | Macro F1 | Valid intent name |
|---|---|---|---|---|---|
| Untrained | 46.9% | 64.0% | 46.9% | 46.2% | 98.9% |
| This model (SFT) | 93.3% | 93.5% | 93.3% | 93.3% | 100.0% |
DPO was also tried after SFT but made validation accuracy worse, so it was dropped and never used on the test (see Training). The published model is the SFT model.
Change in accuracy compared with the untrained model: +46.3% (95% range about ±1.8%).
The untrained model already saw the full list of intent names in its prompt, so this compares the same prompt before and after training.
Most common mix-ups
| Right intent | What the model said | Times |
|---|---|---|
| beneficiary_not_allowed | failed_transfer | 6 |
| pending_transfer | balance_not_updated_after_bank_transfer | 5 |
| reverted_card_payment | declined_card_payment | 5 |
| card_arrival | card_delivery_estimate | 4 |
| card_delivery_estimate | card_arrival | 4 |
| top_up_reverted | top_up_failed | 4 |
| card_payment_not_recognised | compromised_card | 4 |
| topping_up_by_card | pending_top_up | 4 |
Training
- Data: 6992 training messages for SFT, 2000 for DPO and 1000 for validation, all from the BANKING77 training split. Messages repeated in the test split were removed.
- Step 1, SFT + LoRA (r=16, alpha=32, all linear layers): only the intent name counts towards the loss. It stopped at its 3.5-hour time limit, after 1,619 of 1,748 planned updates, while validation was still improving slightly. The version with the best validation accuracy (update 1,600) was kept.
- Step 2, DPO + LoRA on 2000 pairs. The rejected answer was the SFT model's own mistake (147 pairs) or, when it was right, the intent most often confused with the right one (1853 pairs).
- DPO decision: Not kept. On validation it newly got 10 messages right and 52 wrong compared with SFT (-4.2%, ±1.5%), which isn't a clear gain. The published model is the SFT model.
- The best versions were chosen using validation only, and thinking mode was off.
Validation accuracy rose from 44.7% to 93.7% during SFT. DPO then lowered it to 85.8%, so DPO was dropped. DPO's own loss kept falling while its accuracy fell, which is why real answers were scored at every check.
Limits
- It knows only these 77 intents, for one online bank's kind of messages, in English. A message about anything else still gets one of the 77.
- The prompt must list the intents, as in the example below.
- BANKING77 is licensed CC BY 4.0.
How to use it
from transformers import AutoModelForCausalLM, AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("BasselNashaat/SmolLM3-3B-banking77")
model = AutoModelForCausalLM.from_pretrained("BasselNashaat/SmolLM3-3B-banking77", device_map="auto")
intents = ["activate_my_card", "age_limit", "apple_pay_or_google_pay", "atm_support", "automatic_top_up", "balance_not_updated_after_bank_transfer", "balance_not_updated_after_cheque_or_cash_deposit", "beneficiary_not_allowed", "cancel_transfer", "card_about_to_expire", "card_acceptance", "card_arrival", "card_delivery_estimate", "card_linking", "card_not_working", "card_payment_fee_charged", "card_payment_not_recognised", "card_payment_wrong_exchange_rate", "card_swallowed", "cash_withdrawal_charge", "cash_withdrawal_not_recognised", "change_pin", "compromised_card", "contactless_not_working", "country_support", "declined_card_payment", "declined_cash_withdrawal", "declined_transfer", "direct_debit_payment_not_recognised", "disposable_card_limits", "edit_personal_details", "exchange_charge", "exchange_rate", "exchange_via_app", "extra_charge_on_statement", "failed_transfer", "fiat_currency_support", "get_disposable_virtual_card", "get_physical_card", "getting_spare_card", "getting_virtual_card", "lost_or_stolen_card", "lost_or_stolen_phone", "order_physical_card", "passcode_forgotten", "pending_card_payment", "pending_cash_withdrawal", "pending_top_up", "pending_transfer", "pin_blocked", "receiving_money", "Refund_not_showing_up", "request_refund", "reverted_card_payment?", "supported_cards_and_currencies", "terminate_account", "top_up_by_bank_transfer_charge", "top_up_by_card_charge", "top_up_by_cash_or_cheque", "top_up_failed", "top_up_limits", "top_up_reverted", "topping_up_by_card", "transaction_charged_twice", "transfer_fee_charged", "transfer_into_account", "transfer_not_received_by_recipient", "transfer_timing", "unable_to_verify_identity", "verify_my_identity", "verify_source_of_funds", "verify_top_up", "virtual_card_not_working", "visa_or_mastercard", "why_verify_identity", "wrong_amount_of_cash_received", "wrong_exchange_rate_for_cash_withdrawal"]
message = "I still haven't received my new card"
question = ("Customer message: " + message + "\n\nWhich one of these intents does the message have?\n"
+ "\n".join(intents) + "\n\nReply with the intent name only, exactly as written.")
text = tokenizer.apply_chat_template([{"role": "user", "content": question}], tokenize=False,
add_generation_prompt=True, enable_thinking=False)
inputs = tokenizer(text, return_tensors="pt", add_special_tokens=False).to(model.device)
output = model.generate(**inputs, max_new_tokens=20, do_sample=False)
print(tokenizer.decode(output[0][inputs["input_ids"].shape[1]:], skip_special_tokens=True))
- Downloads last month
- 173



