Skip to main content
From public conversations to an evaluated fine-tune: the data recipe has Beam rewrite them in one shot with token-efficient reasoning and builds train.jsonl; this recipe trains Gemma 4 on it and evaluates before and after. This recipe is the right half of the path; the tool-calling reasoning data recipe in this cookbook is the left half. Same prompt, same tools, thinking on: the stock E4B generates 444 tokens, the fine-tune 205, and both make the same two tool calls. The mechanism is Gemma 4’s own thinking channel. The stock model deliberates in numbered lists before every call; the fine-tune keeps the channel and replaces the habit with a short thought that names the function and justifies each argument. Nothing else changes: same tokenizer, same template, same serving stack. <details> <summary>Both generations in full, as decoded from the model (greedy, thinking on)</summary> Stock Gemma 4 E4B, 444 tokens in 19.5 s:
After this recipe, 205 tokens in 8.8 s:
On the simpler prompt “What’s the weather forecast for Paris on 2026-11-03?” the stock model generates 326 tokens and the fine-tune 127, again with the same call. </details>
Note on the benchmark. We ran BFCL v4 without its web-search category, which needs a search API key. BFCL’s overall formula counts a missing category as zero, so the overall scores on this page are lower than a full run would give, for the stock models and the fine-tunes alike. The before-and-after deltas are unaffected, because both sides were scored the same way.

What you’ll build

BFCL v4 overall and output tokens for E2B, E4B and 12B, stock against this recipe: accuracy up on the two small models, tokens down 45 to 64 percent on all three. A Gemma 4 E4B checkpoint that writes a short thought before every tool call and keeps acting through multi-step tasks, exported in Hugging Face format and ready to serve with SGLang. The same data, settings and scripts, with only BASE_MODEL changed, take the E2B from 30.98 to 33.30 at 54% fewer output tokens and hold the 12B at 48.32 against 49.98 at 64% fewer, so what you learn on the E4B carries to the other sizes. Every row was measured with thinking on and the model’s own thoughts kept in the chat history; tokens are the model’s output summed over the 4,906 scored entries. <details> <summary>The numbers behind the chart</summary> The 12B row is one seed; three seeds of the same recipe average 47.1, and run-to-run variance at this learning rate is about plus or minus 3 points overall, plus or minus 8 on multi-turn and plus or minus 15 on memory. </details>

What you’ll learn

Label masking: the system prompt, user turns and tool results are masked; the thought, the tool calls, the reply and the end-of-turn token are trained.
  • A thought on every turn, trained only on the model’s own spans. Gemma 4’s template renders a thought only on tool-call turns and the last round; the recipe opens it on every assistant turn, and the labels cover the thought, the calls, the reply and the closing token.
Accuracy against output tokens on the 12B for three thought styles: purpose-style thoughts match verbose ones within a point at 25 percent fewer tokens; concise thoughts lose five points.
  • Why the thoughts are this length. On the 12B, verbose thoughts score 47.70 at 4.21M tokens, the recipe’s purpose-style thoughts 47.13 at 3.16M (three-seed mean; the served seed 48.32 at 2.54M), concise thoughts 42.38 at 2.32M. The prompt asks for enough to justify the decision and each argument, and nothing more.
  • One epoch at 3e-6. Higher rates over-fit the data’s habits and cost the 12B multi-turn accuracy; a second epoch helps the small models by about a point and hurts the 12B.
  • Compare fairly. One handler for the stock model and the fine-tune, thinking on, thoughts kept in history; compare multi-turn and memory across seeds, not single runs.

What you need

  • Pinned by download.sh and requirements.txt: the three Gemma 4 instruction-tuned checkpoints, which are public, and the training stack of our runs on Python 3.12 with CUDA 13.0 wheels for torch.
  • train.jsonl from the tool-calling reasoning data recipe in this cookbook; its LIMIT=20 mode gives a small file for a dry run. The evaluation needs BFCL, which eval_install.sh installs, and an SGLang build with Gemma 4 support.

Run it

Train

train.sh renders the conversations with the thinking gate open on every assistant turn and masks everything the model did not generate, fine-tunes for one epoch at a learning rate of 3e-6 under FSDP, and exports the epoch checkpoint behind the generation gate. It refuses a RUN_DIR that already holds checkpoints. The last line of a successful run:
Training loss per logged step of the E4B run, from 1.51 at step 5 to 0.55 at step 115, and the held-out loss of 0.528 after the epoch. The held-out loss is the signal that the training works: the loss on 200 conversations the model never trains on. It lands near 0.53 for the E4B with this data, near 0.51 for the 12B and near 0.63 for the E2B. <details> <summary>The full transcript of our E4B run (paths shortened, progress bars and library warnings removed)</summary>
A step took about 6 seconds and the epoch 19 minutes. loss is the training loss of the logged step, which jumps from step to step because every step sees different conversations; mean_token_accuracy is the share of trained tokens the model predicts correctly. The run folder holds dataset/ and dataset_val/, checkpoints/checkpoint-117/ with trainer_state.json and train_info.json beside it, export/ with SMOKE_OK, and the filled-in fsdp.yaml. </details> Then print the losses and check the export:
<details> <summary>Full output of check_run.py</summary>
</details>

Evaluate before and after

Score the stock model first, so the baseline is your own, then the fine-tune, under one handler: thinking on, and the model’s own thoughts kept in the chat history. BFCL v4 scores six sections over 4,906 entries.
Then the fine-tune, served under its own name into a second project root, and the comparison:
E4B section deltas, recipe minus stock: relevance up 25 points, multi-turn up 11.4, single-turn live up 10.9, memory up 5.2, single-turn non-live up 1.4, irrelevance down 14.4. Relevance up 25 points and multi-turn up 11 are the recipe’s gains: the model reaches for a tool when one fits and keeps going through multi-step tasks. Irrelevance down 14 is its cost on the E4B: a model that reaches for tools more readily also reaches for them a few times when none fits. <details> <summary>Output of eval_analyze.py for our E4B reference runs</summary>
Sections are unweighted means of their categories; the overall number is BFCL’s own formula, read from score/data_overall.csv, with the web-search category counted as zero on both sides. The diagnostics count multi-turn entries that hit BFCL’s step limit, repeated the same call three times in a row, or ended in an inference error. Tokens and latency sum the server’s usage over every call of an entry, excluding the 111 memory prerequisite entries that BFCL does not score. </details> The same eval_serve.sh serves the export for your own use, with Gemma 4’s tool-call and reasoning parsers on.

Common fixes

COMMON_FIXES.md lists the symptoms we hit, their causes and the fix for each: out of memory in the first steps, a chat template the recipe does not know, an export that prints SMOKE_FAIL, a serving image that cannot load the exported config, a transformers that predates Gemma 4, a held-out loss that does not fall, inference errors in the analysis, and a registry entry that breaks the overall number.

Next steps

  • Train on your own data. One conversation per line as {"id": ..., "tools": [...], "messages": [...]}, with OpenAI-style tools, a reasoning_content field on every assistant message and structured tool_calls where the assistant calls a tool. Keep a thought on every assistant turn, including text replies, and hold a few hundred conversations out.
  • Change the dose with care. Higher learning rates over-fit the data’s habits; a second epoch helps the small models by about a point and hurts the 12B.
  • Compare seeds, not single runs, when a difference is within a few points on multi-turn or memory; those sections move by 8 to 15 points between seeds of the same recipe.
Last modified on October 20, 2026