This example demonstrates how to fine-tune Google's Gemma 270m model for tool calling using the TRL (Transformer Reinforcement Learning) library form Hugginface
This example of training pipeline includes:
- Synthetic Dataset Creation: 10 examples covering weather queries, calculations, web searches, and regular conversation.
- Completion-Only Training: Only compute loss on assistant responses.
You can use all command environment managers: uv, pip, or conda
Example for pip (prepend uv for using uv):
pip install -r requirements.txtThe training data uses a simple format with special tokens:
<|user|>
What's the weather in Paris?
<|assistant|>
<tool_call>get_weather(location='Paris', unit='celsius')</tool_call>
For regular conversations without tool calls:
<|user|>
Hello, how are you?
<|assistant|>
I'm doing well, thank you! How can I help you today?
- get_weather: Get the current weather for a given location.
- correct_grammar: Correct the given sentence.
- generate_image: Generate an image from a given description.
- speech_synthesis: Generate speech based on a given text input.
- search_web: Search the web for information relevant to the given prompt.
To verify the tool-call conversations you created, please run the verifier for sanity
python3 tools/validate_tools.py tools/data/example.jsonlThe training is rooted in train.py.
python train.pyTo see how to parse arguments use:
python train.py --helpIn the Trainer you can parse in: report_to="wandb" which will prompt you with the necessary steps to log your loss and potentially your accuracy and rewards - if you use that in your project.
Example configuration:
- Model: google/gemma-3-270m-it (instruction-tuned)
- Batch Size: 2 (with gradient accumulation of 4)
- Learning Rate: 2e-4
- Epochs: 30
- Optimizer: adamw
We encourage students to explore different settings and new parameters! E.g., look into other optimizers, LR-Schedulars; even adjusting batch-size can help performance.
After training, the model should be able to:
- Recognize when to call tools vs respond normally.
- Format tool calls properly.
- Extract correct parameters from user queries.
- Handle multiple tool calls in one response.
After training, you'll find:
.gemma-270m-tool-calling/checkpoint-<STEPS>: Checkpoints during training..gemma-270m-tool-calling: Final trained model with.
from transformers import AutoTokenizer, AutoModelForCausalLM
from peft import PeftModel
# Load base model
base_model = AutoModelForCausalLM.from_pretrained("gemma-270m-tool-calling")
tokenizer = AutoTokenizer.from_pretrained("gemma-270m-tool-calling")
# Inference
prompt = "<|user|>\nWhat's the weather in Tokyo?\n<|assistant|>\n"
inputs = tokenizer(prompt, return_tensors="pt")
outputs = model.generate(**inputs, max_new_tokens=50)
print(tokenizer.decode(outputs[0]))- Increase dataset size: 100-1000 or even more examples work much better.
- Add variety: Include edge cases, ambiguous queries, and multi-turn conversations.
- Balance dataset: Ensure equal distribution of tool calls vs regular responses.
- Train longer: More epochs or larger datasets need more training.
- Tune hyperparameters: Experiment with learning rate, batch size, optimizer, and other details of the training.
It it the students tasks to exstend and improve the dataset both in size and diversity to work better and generalize to an arbitrary conversation with a user. Note that, right now, this boilerplate does not even include a validation dataset. You are quite free to think out of the box regarding the data (e.g. conversations etc), but you must keep the format of the messages (the so-called chat-template), so we later on can parse the outputs of all your models to test accuracy.
tools = [
{
"name": "get_weather",
"description": "Get current weather for a location",
"parameters": {
"location": {"type": "string", "description": "City name"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
}
},
{
"name": "correct_grammar",
"description": "Correct grammatical errors in text using GEC API",
"parameters": {
"text": {"type": "string", "description": "Text to check and correct"}
}
},
{
"name": "generate_image",
"description": "Generate an image from a text description",
"parameters": {
"prompt": {"type": "string", "description": "Description of the image to generate"},
"style": {"type": "string", "description": "Art style (optional)"}
}
},
{
"name": "text_to_speech",
"description": "Convert text to speech audio",
"parameters": {
"text": {"type": "string", "description": "Text to convert to speech"},
"voice": {"type": "string", "description": "Voice type (male/female/neutral)"}
}
},
{
"name": "search_web",
"description": "Search the web for information",
"parameters": {
"query": {"type": "string", "description": "Search query"}
}
}
]Out of Memory: Reduce batch size or increase gradient accumulation steps. Poor performance: Add more diverse training examples. Model not calling tools: Ensure balanced dataset with both tool and non-tool examples.
Install an inference engine like vLLM or SGLang. This means you can use optimizations like dynamic batching (look it up!). See vLLM installation guide here. Installing it with uv is faster and often more stable.
When working on remote compute instances (such as those on uCloud), it is often necessary to run programs that take a long time to finish. If you run these programs in a normal terminal session, they will stop if your connection drops or if you close the terminal.
To avoid this, you can run your work inside a detachable terminal session. Tools such as tmux, screen, and byobu allow you to create persistent terminal sessions that continue running even after you disconnect. You can later reconnect to the same session and continue exactly where you left off.
The typical workflow is:
- Start a detachable session.
- Run commands inside it.
- Detach from the session while the processes continue running.
- Reattach later to check progress or continue working.
In this guide we will use tmux, which is one of the most widely used tools for this purpose.
Start a tmux Session
Start a new tmux session:
tmuxIt is usually better to give the session a name:
tmux new -s mysessionYou are now inside a tmux session. Any processes started here will keep running even if you disconnect.
Move to the next window:
Ctrl + b, then n
Move to the previous window:
Ctrl + b, then p
Jump to a specific window:
Ctrl + b, then <number>
Example:
Ctrl + b, then 2
To see all windows in the current session:
Ctrl + b, then w
This opens an interactive menu where you can select a window.
You can leave the tmux session without stopping the programs running inside it.
Detach from the session with:
Ctrl + b, then d
You will return to the normal terminal while the tmux session continues running in the background.
To see all active tmux sessions:
tmux lsExample output:
mysession: 2 windows (created Fri Mar 6 10:00:00 2026)
To reconnect to a running session:
tmux attach -t mysessionYou will return to the session exactly as you left it.
Start a new session:
tmux new -s trainingCreate a second window for monitoring:
Ctrl + b, then c
In the first window, run a long job:
python train_model.pySwitch to another window:
Ctrl + b, then 0
Run a monitoring tool:
htopDetach from the session:
Ctrl + b, then d
Later, reconnect to the session:
tmux attach -t trainingAll windows and running processes will still be active.
Using tmux allows you to:
- Run long jobs safely on remote machines
- Keep processes alive even if your connection drops
- Work with multiple terminal windows in one session
- Reattach to your work at any time
This makes tmux an essential tool when working on remote servers, HPC clusters, or cloud computing platforms such as uCloud.

