Instructions to use iromu/LFM2.5-230M-tools with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use iromu/LFM2.5-230M-tools with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="iromu/LFM2.5-230M-tools") messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# pip install -U transformers accelerate # Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("iromu/LFM2.5-230M-tools") model = AutoModelForCausalLM.from_pretrained("iromu/LFM2.5-230M-tools", device_map="auto") messages = [ {"role": "user", "content": "Who are you?"}, ] inputs = tokenizer.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=256) print(tokenizer.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use iromu/LFM2.5-230M-tools with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "iromu/LFM2.5-230M-tools" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "iromu/LFM2.5-230M-tools", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/iromu/LFM2.5-230M-tools
- SGLang
How to use iromu/LFM2.5-230M-tools with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "iromu/LFM2.5-230M-tools" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "iromu/LFM2.5-230M-tools", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "iromu/LFM2.5-230M-tools" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "iromu/LFM2.5-230M-tools", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use iromu/LFM2.5-230M-tools with Docker Model Runner:
docker model run hf.co/iromu/LFM2.5-230M-tools
LFM2.5-230M-tools
Merged BF16 weights of the LoRA tool-calling fine-tune of LiquidAI/LFM2.5-230M-Base,
trained so the model emits tool calls for agentic workflows in the LFM2.5 wire format.
This is the smallest model in the family line, and the one whose tool calls are not
OpenAI-shaped. Read the Tool-call format section before using it in a runtime that
expects tool_calls in a JSON envelope.
Base model
This model was fine-tuned from:
LiquidAI/LFM2.5-230M-Base
Tool-call format
The chat template is the model's contract, and it is not the OpenAI one. A call renders as a bracketed list between two markers:
<|tool_call_start|>[search_files(path="src/", query="load"), read_file(path="src/app.py")]<|tool_call_end|>
- Argument values render in a Python-like form: strings single-quoted, mappings as JSON.
- A tool's arguments must be a mapping, not a JSON-encoded string; the template calls
items()on them. - The assistant span is the trainable one, and the schema list is rendered into the system turn rather than into a separate tool block.
Anything that parses this output has to know the format. A scorer that looks for an
OpenAI tool_calls array will report no call on every row, which reads like a model
that never learned to call tools. This model's own evaluation declares the format and
parses it, so its numbers are measured against what the model actually emits.
Training
Supervised fine-tuning with LoRA, run with NeMo-RL, assistant-turn-masked cross-entropy over the tool-calling logs.
- LoRA: dim
32, alpha32, dropout0.05, target modules*.proj - Max sequence length:
4096 - Precision:
bfloat16 - Optimizer: AdamW, lr
5e-5, weight decay0.01 - Schedule: 15-step linear warmup, then cosine decay to
1e-6 - Global batch size:
64(micro batch2) - Training steps:
336(validation every84) - Loss masked to assistant turns via the chat template's
generationkeyword
Dataset
Training used the sft_tools split of the
r0b0tlab/qwen3.8-max-glm5.2-kimi-k3-distillation dataset (OpenAI messages
format; assistant turns carry tool_calls). The rows are the same corpus the Qwen
tool-callers trained on, rendered through this family's template.
Intended use
- Structured tool / function calling in a very small footprint (230M parameters)
- Agent-style multi-step interactions where the runtime understands the LFM2.5 format
- On-device and edge deployment
It is not intended to be a general-purpose assistant, and it is not a drop-in for a runtime that assumes the OpenAI tool-call envelope.
Sibling artifacts
- GGUF quantizations:
iromu/LFM2.5-230M-tools-GGUF
Usage
Load the merged BF16 model with transformers:
from transformers import AutoModelForCausalLM, AutoTokenizer
model = AutoModelForCausalLM.from_pretrained(
"iromu/LFM2.5-230M-tools", torch_dtype="bfloat16", device_map="auto"
)
tokenizer = AutoTokenizer.from_pretrained("iromu/LFM2.5-230M-tools")
Render a prompt with tools and decode greedily:
prompt = tokenizer.apply_chat_template(
messages, tools=tools, add_generation_prompt=True, tokenize=False
)
Validation
| Model | Quant | Cap | n | Tool call emitted | Names match | Exact args match | Δ exact vs BASE (gated) |
|---|---|---|---|---|---|---|---|
| LiquidAI/LFM2.5-230M-Base | BF16 | 384 tok | 272 | 0/272 (0.0%) | 0/272 (0.0%) | 0/272 (0.0%) | (no predecessor) |
| LFM2.5-230M-tools | BF16 | 384 tok | 272 | 43/272 (15.8%) | 17/272 (6.2%) | 4/272 (1.5%) | +1.5pp |
Both rows were scored at the same 384-token generation cap, under the same declared tool-call grammar, on the same 274-row split, through the same scorer and the same decoding path. That is what makes the delta admissible: a comparison between two rows that differ in cap or backend measures the harness, not the weights.
The base model produced no parseable tool call on any of the 272 gradable rows, so every delta against it is the fine-tune's absolute number rather than a gain over something the base could already do. Of 274 rows, 272 expect a tool call and were gradable.
Compare this against the Qwen line only with care: these are the same 274 tasks, but this model was trained to a different wire format than every other model in this line.
- Downloads last month
- 84