Results
Frozen test set of 2,929 xLAM questions, greedy decoding, scored by the same code for base and fine-tuned model.
Table with columns: Metric, Fine-tuned, 95% CI| Metric | Fine-tuned | 95% CI |
|---|
| exact_match | 78.0% | 76.5–79.4 |
| function_match | 97.3% | 96.7–97.8 |
| argument_f1 | 90.3% | 89.5–91.1 |
| schema_valid | 99.4% | 99.0–99.6 |
Exact match: base 61.6% → fine-tuned 78.0% (592 questions fixed, 112 broken, McNemar p < 0.001).
Table with columns: Call pattern, n, Exact match| Call pattern | n | Exact match |
|---|
| single | 1,386 | 81.8% |
| parallel_same_tool | 530 | 80.4% |
| multi_distinct_tools | 936 | 71.3% |
| mixed | 77 | 74.0% |
The model was trained on this exact format. It is not Qwen's native <tool_call> format, and it does not read OpenAI-style tools= parameters.
System:
You are a function-calling assistant. Your task is to select the appropriate tool and provide the arguments requiredto answer the user's request. Return ONLY valid JSON. The output must be a JSON array of tool calls in this format: [ { "name": "function_name", "arguments": { "argument_name": "value" } }] If none of the available tools can answer the request, return an empty array: [] Do not explain your answer.Do not output markdown.Do not invent tools.
User:
Available tools: <tools as a JSON list: name, description, parameters> User request: <the request> Return the required tool call(s) as JSON.
Assistant: [{"name": "get_weather", "arguments": {"city": "Pune"}}]
Usage
import jsonfrom transformers import AutoModelForCausalLM, AutoTokenizer repo = "SwapniL-pr1117/qwen2.5-0.5b-instruct-fc"tok = AutoTokenizer.from_pretrained(repo)model = AutoModelForCausalLM.from_pretrained(repo, dtype="auto", device_map="auto") SYSTEM_PROMPT = """<copy the system prompt above>"""tools = [{"name": "get_weather", "description": "Current weather for a city.", "parameters": {"city": {"type": "str", "description": "City name"}}}]user = (f"Available tools:\n\n{json.dumps(tools, indent=2)}\n\n" f"User request:\n\nWhat's the weather in Pune?\n\n" f"Return the required tool call(s) as JSON.") messages = [{"role": "system", "content": SYSTEM_PROMPT}, {"role": "user", "content": user}]inputs = tok.apply_chat_template(messages, add_generation_prompt=True, return_tensors="pt", return_dict=True).to(model.device)out = model.generate(**inputs, max_new_tokens=256) # greedy is the defaultprint(tok.decode(out[0][inputs["input_ids"].shape[1]:], skip_special_tokens=True))
vLLM (OpenAI-compatible server)
vllm serve SwapniL-pr1117/qwen2.5-0.5b-instruct-fc --max-model-len 4096
Send the same two messages to /v1/chat/completions with temperature=0, then json.loads the reply.
Ollama (GGUF, Q8_0)
ollama run Avahan/qwen2.5_0.5b-instruct-fc-Chat
No system prompt is baked in: send the system prompt above yourself (plain ollama run gives the chat behaviour described below).
Decoding
Use greedy decoding. generation_config.json already sets do_sample=False; with OpenAI-compatible
servers pass temperature=0. Sampling and repetition penalties hurt JSON accuracy.
How it behaves
- With the system prompt above: always answers with a JSON array of tool calls. It's a tool-calling specialist, not a chatbot.
- Without it (plain chat): answers in normal text. In our checks 0% of plain chat messages turned into tool calls.
Chat quality is that of a 0.5B model, further degraded by fine-tuning (it gets basic facts wrong): don't use it as a chatbot.
- It does not execute anything. It only writes the call; your code runs the tool. Validate the JSON against your tool
schemas before running it, and ask the user before running tools with side effects.
Limitations
- Doesn't abstain: when no tool fits, the right answer is
[], but it returned [] in 0% of such cases.
It picks the closest tool and may invent argument values. Guard against this (e.g. check arguments appear in the request).
- Unseen tools: almost every tool in the test set also appears in training (only a handful are new), so the score measures
new requests for familiar tools. Accuracy on completely new tool schemas may be lower.
- Most errors are wrong argument values (19% of questions), e.g. formats or units, not wrong tools.
- Single turn only: it picks the call; it doesn't read tool results or write a final natural-language answer.
- English only; trained on xLAM's API-style tools.
Training
QLoRA (4-bit base) with Unsloth, r=16, alpha=32, all linear layers, 1 epoch on ~48.7k xLAM examples,
effective batch 16, lr 0.0002, max length 1536, loss on the answer only.
LoRA merged into the bf16 base model.