Qwen3-1.7B Tool-Calling Fine-Tune v4

Function-calling fine-tune of unsloth/Qwen3-1.7B, trained with Unsloth + TRL + PyTorch DDP on Kaggle 2× Tesla T4. 300 training steps, LoRA r=16, effective batch 32.

  • Training: 14,574 s (~4 h 3 min) end-to-end; 13,948 s in the training loop
  • BFCL v4: Non-Live AST 72.56% · Live AST 58.62%
  • NexusRaven: Overall F1 0.8485 strict / 0.8764 lenient
  • Disclosure: All benchmark runs were performed locally using the official bfcl-eval AST scorer and a custom NexusRaven harness. None were submitted to a public leaderboard.

Model Details

  • Fine-Tuned by: pmrccs
  • Type: Causal LM with merged LoRA adapter, tuned for function calling
  • Base model: unsloth/Qwen3-1.7B — 28 layers, 32,768 native context
  • Merged size: 3.44 GB (safetensors)
  • Standalone LoRA adapter: 69.8 MB
  • Precision: fp16 (T4 does not support bf16)
  • License: cc-by-nc-4.0
  • Output format: <tool_call> XML tags, compatible with the Qwen3 native chat template
  • Special tokens: <tool_call>, </tool_call>, <tool_response>, </tool_response>, <|im_start|>, <|im_end|>

Uses

Intended: single-tool invocation, tool selection from 2–4 candidates, short multi-turn agent loops, Python-schema APIs.

Out of scope (documented limitations, not defects):

Limitation Why Workaround
Parallel calls bundled in one response Hermes func_calling_singleturn is single-call by design Sequential multi-turn execution
Java / JavaScript schemas Not in training data Use Python-schema APIs
no_call sentinel token Model refuses in natural language instead Parse any non-<tool_call> output as refusal
Strict enum adherence Trained on free-text entity values Clamp to closest schema member downstream
Cross-session state No persistent memory implemented Session-level state management

Bias, Risks, Limitations

Issue Severity Evidence
Training-distribution lock-in High Accuracy drops 25–40 pts on Java/JS or parallel calls
Refusal calibration Medium 74.17% offline / 59.84% live irrelevance; may fire nearby-wrong tool on hard negatives
Type-format drift Medium "limit": "2" vs "limit": 2 — lenient scoring hides this
Date format variance Low 2023-04-15, 04/15/2023, 2023.4.15 all observed
Recursive-schema dumps Low Rare; treat as no_call in post-processing

Inherits biases of the Qwen3 base and the Hermes/xLAM corpora. No bias-specific evaluation was performed. Do not deploy as a standalone tool dispatcher; wrap in schema validation and human-in-the-loop for side-effecting actions.

Training Details

Data Mix

85% positive / 15% negative.

Source Config / subset Ratio Role Notes
NousResearch/hermes-function-calling-v1 func_calling_singleturn ~55% Positive Single-turn tool-call pairs
NousResearch/hermes-function-calling-v1 glaive_func_calling ~30% Positive Multi-turn, nested calls
MadeAgents/xlam-irrelevance-7.5k full 15% Negative Mapped to natural-language refusals

Preprocessing normalizes Python dict-repr tool calls to real JSON, strips <tool_response> wrappers to avoid double-wrapping under Qwen3's chat template, and reformats xLAM negatives into the same <tools> + <tool_call> structure used at inference.

Hyperparameters

  • Schedule: 300 steps · learning rate 5e-5 · cosine decay · 15-step warmup (5%).
  • Batch: per-device 1 · grad-accum 16 · effective batch 32 across 2 GPUs via Unsloth Multi-GPU Fine-Tuning.
  • LoRA: r=16, α=32, dropout=0.05. Target modules: q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj.
  • Optimizer: adamw_8bit · weight decay 0.05.
  • Sequence: max length 4096, matching the Qwen3 native chat template.
  • Precision: fp16.
  • Seed: 42.

Wall-clock breakdown

Phase Duration
Setup (imports, dependency install, NCCL smoke test, train.py write) 138 s
Model + dataset load 206 s
Training loop (steps 1 → 300) 13,948 s
Post-loop evaluation + save 175 s
Merge LoRA + push to Hub 108 s
End-to-end 14,574 s

Training Metrics

Metric Value Step
Final training loss 0.97852 300
Best evaluation loss 0.61841 300
Final evaluation loss 0.61857 300
Initial training loss 2.54814 1
Initial evaluation loss 1.25769 25
Total training FLOPs 7.3865e+16 —
Peak learning rate 5.00e-05 18
Final learning rate 1.37e-08 300
Step Train loss Eval loss LR
1 2.54814 — 0.00e+00
25 1.59098 1.25769 4.99e-05
50 1.45040 0.85552 4.85e-05
75 1.12508 0.71383 4.52e-05
100 0.67489 0.66835 4.05e-05
125 0.98662 0.65285 3.45e-05
150 1.12018 0.64302 2.79e-05
175 1.23996 0.63248 2.10e-05
200 1.05181 0.62608 1.45e-05
225 1.13671 0.62162 8.69e-06
250 0.92527 0.61901 4.15e-06
275 1.32625 0.61857 1.18e-06
300 0.97852 0.61841 1.37e-08

loss curve

Eval loss saturates after step ~200. The final 100 steps contributed only ~0.008 of improvement — the model extracted essentially all signal this distribution provides. Further gains require a different data mix, not more steps.

Evaluation

Both benchmarks were run locally. BFCL used the official bfcl-eval AST scorer; NexusRaven used a custom harness. Not submitted to any public leaderboard.

BFCL v4 — Non-Live (offline, single-turn)

Category Acc Correct / Total What it measures Failure mode when wrong
simple_python 91.75% 367 / 400 Single tool, Python schema Omits optional params with defaults
simple_java 50.00% 50 / 100 Single tool, Java schema Type / enum-constant mismatch
simple_javascript 60.00% 30 / 50 Single tool, JS schema Python-style booleans in JS AST
multiple 88.50% 177 / 200 1 call from 2–4 candidates Wrong candidate
parallel 70.00% 140 / 200 N calls to same tool One call per turn, not bundled
parallel_multiple 64.50% 129 / 200 Coordinated multi-tool Single-call training gap
irrelevance 74.17% 178 / 240 Detect no match Fires nearby-wrong tool
Non-Live AST Overall 72.56% — Weighted Bounded by Java/JS

BFCL v4 — Live (production APIs)

Category Acc Correct / Total What it measures Failure mode when wrong
live_simple 64.34% 166 / 258 One call, messy prompts Conversational leakage
live_multiple 57.36% 604 / 1,053 Diverse candidate selection Enum / nesting errors
live_parallel 75.00% 12 / 16 Repeat API for N entities Rare multi-call framing
live_parallel_multiple 41.67% 10 / 24 Multi-action single turn Hardest category
live_irrelevance 59.84% 529 / 884 Refuse out-of-scope Natural-language refusals penalized by AST
live_relevance 87.50% 14 / 16 Fire a call when warranted —
Live AST Overall 58.62% — Weighted —

NexusRaven API Evaluation

318 queries across 65 APIs. Strict scoring rejects type mismatches ("2" ≠ 2); lenient scoring coerces.

Metric Metric type Lenient Strict Notes
Function Retrieval P Precision 0.8889 0.8889 No type sensitivity
Function Retrieval R Recall 0.8805 0.8805 —
Function Retrieval F1 F1 0.8847 0.8847 Best submetric
Argument Inference P Precision 0.8694 0.8287 Type drift
Argument Inference R Recall 0.8757 0.8348 Type drift
Argument Inference F1 F1 0.8725 0.8318 —
Overall P Precision 0.8755 0.8476 —
Overall R Recall 0.8772 0.8493 —
Overall F1 F1 0.8764 0.8485 —

Per-dataset (strict):

Dataset N Function F1 Argument F1 Overall F1 Notes
emailrep 38 0.9737 0.9565 0.9634 Effectively solved
virustotal 151 0.8079 0.9415 0.9006 Function confusion on vt_get_* family
toolalpaca 51 0.9495 0.7965 0.8431 Occasional refusal on list functions
cve_cpe 78 0.9487 0.5977 0.7063 Missing limit / verbose, enum mismatches

The ~3-point strict-vs-lenient gap on argument inference reflects the model emitting string-typed values where the schema expects numeric or boolean types — "limit": "2" instead of "limit": 2.

Evaluation Artifacts

Raw evaluation outputs are available in the companion repository:

https://github.com/pmrccs/qwen3-1.7b-tool-calling-v4

Folder Contents
results/bfcl_v4/ Per-category JSONL outputs from the official bfcl-eval AST scorer (13 files)
results/nexusraven/ Per-query results, aggregate metrics, and raw decoder outputs
training/ Step-level training logs, trainer state, and final run summary

The artifacts contain every prediction the model made on both benchmarks. Any aggregate score in the tables above can be independently reproduced by running the official bfcl-eval scorer against the JSONL files in results/bfcl_v4/.

Design Decisions

Decision Value Rationale
Refusal format 5 natural-language sentences Human-facing deployment; BFCL AST already accepts plain-text refusals as equivalent to no_call
Negative ratio 15% 25% made the model "lazy" — refused valid queries
Java / JS training Excluded No clean public dataset at scale; risk to Python performance. Caps Non-Live Simple AST at ~67%
LoRA rank 16 Higher rank → higher sequential-fine-tune forgetting risk
Training distribution Single-call Hermes func_calling_singleturn is single-call by design; parallel calls were not part of the objective
Post-training normalization JSON tool calls + stripped <tool_response> Prevents parser errors and double-wrapping under Qwen3 chat template
Checkpoint policy Every 50 steps · keep last 2 · mirror to last-checkpoint branch Cross-session resume support

Production Post-Processing

Step Action Reason
1 Treat any non-<tool_call> output as a refusal Model uses natural-language refusals
2 Detect schema dumps ({"type","properties"} as arg value) → refusal Recursive-schema failure mode
3 Normalize booleans ("true" → True) and numeric strings ("2" → 2) Bridges strict/lenient scoring gap
4 Canonicalize dates to ISO 8601 Multiple formats observed
5 Rename x-apikey → x_apikey VirusTotal family typo
6 Clamp enums to closest schema member Enum-drift failure mode

Technical Specifications

Layer Component Version
Runtime PyTorch 2.10.0+cu128
Runtime CUDA 12.8
Model Transformers 5.5.0
Model TRL 0.24.0
Model Accelerate 1.15.0
Model Unsloth from source
Model bitsandbytes 0.50.2
Model huggingface_hub 1.33.0
Hardware GPU 2× Tesla T4 (15.6 GB each, SM75)
Hardware Topology PCIe-only (no NVLink)
Hardware Precision fp16
DDP NCCL_P2P_DISABLE 1
DDP NCCL_SHM_DISABLE 1
DDP Backend NCCL via torchrun

Both NCCL_* env vars must be set before import torch on the T4 PCIe topology.

Citation

@misc{vonwerra2022trl,
  title        = {{TRL: Transformer Reinforcement Learning}},
  author       = {Leandro von Werra and Younes Belkada and Lewis Tunstall and Edward Beeching and Tristan Thrush and Nathan Lambert and Shengyi Huang and Kashif Rasul and Quentin Gallou{\'e}dec},
  year         = 2020,
  journal      = {GitHub repository},
  publisher    = {GitHub},
  howpublished = {\url{https://github.com}}
}
Downloads last month
421
Safetensors
Model size
2B params
Tensor type
F16
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for pmrccs/qwen3-1.7b-tool-calling-v4

Finetuned
Qwen/Qwen3-1.7B
Adapter
(22)
this model

Datasets used to train pmrccs/qwen3-1.7b-tool-calling-v4