mtlm-7m-tools β a 7M-parameter assistant that talks English and calls tools, trained end-to-end in machin
Fine-tune of javimosch/mtlm-7m-base that decides between answering in
plain English and emitting a one-line JSON tool call, over 14 generic tools (weather, calculator, web search, time, read/write
file, HTTP GET, email, translate, shell, unit conversion, reminders, notes, wikipedia). Served by
anvil, it speaks the OpenAI chat-completions protocol including tool_calls.
Everything except the synthesis of the fine-tuning text is pure machin (MFL): the base pretraining, the chat-template tokenizer, the fine-tune, the int8 export and the server. The text corpus was produced by a templated Python script from the tool catalog (no LLM teacher).
Honest numbers
| base | mtlm-7m-base (7.2M params, TinyStories, val loss 1.916) |
| fine-tune data | 40k synthetic conversations (76% plain-English assistant turns, 24% tool calls), 6.2M tokens, plus 15% TinyStories mixed into every batch |
| schedule | 2,000 steps Γ 32 Γ 256, lr 2e-4, warmup 50, cosine; 6.2 h on a shared 6-core CPU |
| held-out loss | 0.222 (step 100) β 0.088 (step 2,000) |
Probes on the exported int8 model (temperature 0.3), probes.txt has the raw output:
| prompt | output |
|---|---|
| what is the weather in Lyon? | {"tool_call":{"name":"get_weather","arguments":{"city":"Lyon"}}} |
| hello, who are you? | Hi! What can I do for you? |
| what is 123 plus 456? | {"tool_call":{"name":"calculator","arguments":{"expression":"123 + 456"}}} |
| send an email to lily@example.com with subject Hello saying See you at 10. | send_email with to, subject, body all correct |
| tell me a very short story about a cat | a fluent five-sentence story (about a girl, not a cat) |
| how do you say good morning in Spanish? | {"tool_call":{"name":"translate","arguments":{"text":"good morning","to":"Spanish"}}} |
| (tool result: Lyon, 18 Β°C, cloudy) | "In Lyon it is cloudy with -4 degrees." β right form, wrong number |
Known limits: numbers are sometimes misquoted when summarizing a tool result; the tool set is fixed at fine-tune time (the model does not read tool schemas from the prompt β that is the point: 256 tokens of context, tools baked in); only the 14 tools above; English only; no knowledge beyond children's stories.
Chat format
anvil's Zephyr-style template at the token level: <s> then for each message <|role|>\n{content} </s> \n, and
<|assistant|>\n to start generation. Tool results are rendered as a user message Tool result: {...}. A tool call is a
single line {"tool_call":{"name":...,"arguments":{...}}} followed by </s>.
Run it as an OpenAI-compatible server
ANVIL_TOOLS_INJECT=0 anvil-serve models/m7tool2.bin 8097 # tools are baked in; do not paste schemas into the prompt
curl -s localhost:8097/v1/chat/completions -d '{
"model": "mtlm", "temperature": 0.2,
"messages": [
{"role":"system","content":"You are a helpful assistant. You can call tools. When a tool is needed, reply with only the JSON tool call. Otherwise answer in plain English."},
{"role":"user","content":"what is the weather in Lyon?"}],
"tools": [{"type":"function","function":{"name":"get_weather","parameters":{"type":"object","properties":{"city":{"type":"string"}}}}}]}'
returns "tool_calls":[{"type":"function","function":{"name":"get_weather","arguments":"{\"city\":\"Lyon\"}"}}] with
finish_reason: "tool_calls"; the same request with "hello, who are you?" returns plain text. Use the system prompt above:
it is the one the model was trained with.
Files
m7tool2.mtlmβ fp32 checkpoint (mtlm1layout).m7tool2.binβ llama2.c v2 int8 export, group size 32 (the model width, 288, is not a multiple of 64), 8.0 MB.tokenizer.binβ llama2.c tokenizer format, 4096 pieces.train_log.jsonl,probes.txtβ the run log and the raw probe/server outputs above.
Model tree for javimosch/mtlm-7m-tools
Base model
javimosch/mtlm-7m-base