Instructions to use lxyuan/FunctionGemma-270M-banking77-router with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use lxyuan/FunctionGemma-270M-banking77-router with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="lxyuan/FunctionGemma-270M-banking77-router") messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("lxyuan/FunctionGemma-270M-banking77-router") model = AutoModelForCausalLM.from_pretrained("lxyuan/FunctionGemma-270M-banking77-router", 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 lxyuan/FunctionGemma-270M-banking77-router with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "lxyuan/FunctionGemma-270M-banking77-router" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "lxyuan/FunctionGemma-270M-banking77-router", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/lxyuan/FunctionGemma-270M-banking77-router
- SGLang
How to use lxyuan/FunctionGemma-270M-banking77-router 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 "lxyuan/FunctionGemma-270M-banking77-router" \ --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": "lxyuan/FunctionGemma-270M-banking77-router", "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 "lxyuan/FunctionGemma-270M-banking77-router" \ --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": "lxyuan/FunctionGemma-270M-banking77-router", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use lxyuan/FunctionGemma-270M-banking77-router with Docker Model Runner:
docker model run hf.co/lxyuan/FunctionGemma-270M-banking77-router
FunctionGemma 270M BANKING77 Router
This is a full fine-tune of
google/functiongemma-270m-it that turns an
English banking request into one of ten structured support tool calls. It is a
learning experiment, not a production banking system.
What was trained?
BANKING77 is normally a classification dataset with text, integer label,
and human-readable label_text fields. This experiment does not add a
classification head. It converts label_text into the expected assistant tool
call and fine-tunes FunctionGemma to generate that native structure.
{
"text": "My card is gone. I think it was stolen.",
"label_text": "lost_or_stolen_card"
}
becomes a target call to handle_lost_or_stolen_card.
Tool schema
Every tool receives the original customer message. One complete schema is:
{
"type": "function",
"function": {
"name": "handle_lost_or_stolen_card",
"description": "Handle a card reported lost or stolen.",
"parameters": {
"type": "object",
"properties": {
"customer_message": {
"type": "string",
"description": "The original customer support message."
}
},
"required": [
"customer_message"
]
},
"return": {
"type": "string"
}
}
}
| Function | Intended request |
|---|---|
handle_card_arrival |
Handle questions about when a newly ordered card will arrive. |
handle_card_not_working |
Handle reports that a physical bank card does not work. |
handle_cash_withdrawal_not_recognised |
Handle an unrecognized cash withdrawal. |
handle_change_pin |
Handle requests to change a card PIN. |
handle_compromised_card |
Handle reports that card details may be compromised. |
handle_lost_or_stolen_card |
Handle a card reported lost or stolen. |
handle_pending_card_payment |
Handle a card payment that is still pending. |
handle_terminate_account |
Handle requests to close a bank account. |
handle_transfer_not_received_by_recipient |
Handle a transfer the recipient has not received. |
handle_verify_my_identity |
Handle questions about completing identity verification. |
Use the model
import re
from transformers import AutoModelForCausalLM, AutoTokenizer
MODEL_ID = "lxyuan/FunctionGemma-270M-banking77-router"
TOOL_DESCRIPTIONS = {
"handle_card_arrival": "Handle questions about when a newly ordered card will arrive.",
"handle_card_not_working": "Handle reports that a physical bank card does not work.",
"handle_cash_withdrawal_not_recognised": "Handle an unrecognized cash withdrawal.",
"handle_change_pin": "Handle requests to change a card PIN.",
"handle_compromised_card": "Handle reports that card details may be compromised.",
"handle_lost_or_stolen_card": "Handle a card reported lost or stolen.",
"handle_pending_card_payment": "Handle a card payment that is still pending.",
"handle_terminate_account": "Handle requests to close a bank account.",
"handle_transfer_not_received_by_recipient": "Handle a transfer the recipient has not received.",
"handle_verify_my_identity": "Handle questions about completing identity verification."
}
def make_tool(name: str, description: str) -> dict:
return {
"type": "function",
"function": {
"name": name,
"description": description,
"parameters": {
"type": "object",
"properties": {
"customer_message": {"type": "string"},
},
"required": ["customer_message"],
},
"return": {"type": "string"},
},
}
tools = [make_tool(name, description) for name, description in TOOL_DESCRIPTIONS.items()]
model = AutoModelForCausalLM.from_pretrained(MODEL_ID, device_map="auto")
tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
message = "My card was stolen last night"
inputs = tokenizer.apply_chat_template(
[
{
"role": "developer",
"content": "You route customer requests by calling exactly one banking support tool.",
},
{"role": "user", "content": message},
],
tools=tools,
add_generation_prompt=True,
return_tensors="pt",
return_dict=True,
).to(model.device)
output = model.generate(**inputs, max_new_tokens=64, do_sample=False)
generated = tokenizer.decode(
output[0, inputs["input_ids"].shape[1] :],
skip_special_tokens=False,
)
match = re.search(
r"<start_function_call>call:([a-z0-9_]+).*?<end_function_call>",
generated,
re.DOTALL,
)
if match is None:
raise ValueError(f"No complete function call: {generated!r}")
print({"tool": match.group(1), "raw_call": match.group(0)})
The model selects a call; it does not execute the tool. Validate arguments and dispatch through an explicit allow-listed handler map.
Observed held-out examples
| Customer input | First generated tool |
|---|---|
I am sick of this damn company and want to close out my account. |
handle_terminate_account |
My card doesn't work. |
handle_card_not_working |
My card is gone I think it was stolen |
handle_lost_or_stolen_card |
There is a withdrawal that isn't mind in the app. |
handle_cash_withdrawal_not_recognised |
When will I get my card? |
handle_card_arrival |
Can i change my PIN at the ATM? |
handle_change_pin |
Input: I am sick of this damn company and want to close out my account.
Output: <start_function_call>call:handle_terminate_account{customer_message:<escape>I am sick of this damn company and want to close out my account.<escape>}<end_function_call>
Loss function
This run uses TRL SFTTrainer with loss_type="chunked_nll". This is the
standard causal-language-model next-token negative log-likelihood, or
cross-entropy, computed in memory-saving chunks:
loss = mean(-log P(correct next token | previous tokens))
assistant_only_loss=False, and this is a conversational language-modeling
dataset rather than a prompt-completion dataset. Therefore every non-padding
token in the rendered developer prompt, tool declarations, user message, and
assistant call contributes. Padding labels use -100 and are ignored. Exact
generated tool accuracy is a separate application metric and is not the
differentiable loss. Chunking does not alter this token selection; the label
mask controls which tokens contribute, while loss_type controls how the same
calculation is held in memory. See the
TRL 1.12 SFT documentation.
Results
| Metric | Value |
|---|---|
| Base-model exact first-tool accuracy | 51.00% |
| Fine-tuned exact first-tool accuracy | 97.00% |
| Generated evaluation examples | 100 |
| Final evaluation loss | 0.0492 |
| Mean training loss | 0.0959 |
Training loss can continue falling while validation loss rises because the model becomes more confident on repeated training rows without improving equally on unseen rows. Cross-entropy can increase from a few confidently wrong tokens even when average token accuracy changes little.
TensorBoard event files, trainer_state.json, and training_metrics.json are
included in this repository for inspecting the training curves and recorded
results.
Training configuration
| Setting | Value |
|---|---|
| Training examples | 800 |
| Evaluation examples | 200 |
| Epochs | 4 |
| Learning rate | 5e-05 |
| Effective batch size | 8 |
| Maximum sequence length | 1024 |
| Loss | chunked_nll, full rendered sequence except padding |
| Warmup | 0.1 steps in the reference run (effectively no warmup) |
| Seed | 42 |
Software:
datasets==5.0.1tensorboard==2.20.0torch==2.11.0+cu128transformers==5.16.1trl==1.12.0
Precision and limitations
Load the saved FP32 checkpoint without forcing all weights to FP16. The verified FP32 Hub reload produced a valid function call, while forced pure FP16 on a T4 produced padding-only output. Training used FP16 autocast around FP32 master weights.
- Only ten BANKING77 intents are supported, not all 77.
- There is no out-of-scope or refusal route.
- Argument quality was not scored separately from tool-name selection.
- Ambiguous, adversarial, multilingual, or unrelated requests may route incorrectly.
- Do not use this model for financial decisions without production privacy, safety, monitoring, fallback, and human-review controls.
The BANKING77 mirror describes the dataset as CC BY 4.0. FunctionGemma weights remain subject to the Gemma terms.
- Downloads last month
- -
Model tree for lxyuan/FunctionGemma-270M-banking77-router
Base model
google/functiongemma-270m-itDataset used to train lxyuan/FunctionGemma-270M-banking77-router
Evaluation results
- Exact first-tool accuracy on BANKING77 ten-intent held-out slicetest set self-reported0.970