113 1 month ago

LFM2.5-8B-A1B Q8_0 with working tool calls — fixes the llama.cpp parser crash (#23838). Same weights, metadata-only fix.

tools thinking
ollama run pierreprudh/lfm2.5-8b-a1b

Details

1 month ago

04f6eaceed27 · 9.0GB ·

lfm2moe
·
8.47B
·
Q8_0
LFM Open License v1.0 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "
{ "stop": [ "<|startoftext|>", "<|im_start|>", "<|im_end|>", "<|

Readme

LFM2.5-8B-A1B — Q8_0 with working tool calls

LiquidAI’s LFM2.5-8B-A1B at full Q8_0 precision, repackaged so that tool calling actually works on Ollama. Identical weights to LiquidAI’s official GGUF — only the Ollama config metadata differs.

LFM2.5-8B-A1B is a hybrid MoE model (8.3B total / ~1.5B active parameters) built for on-device agentic use: fast, memory-efficient, strong at tool calling, with a 128K context window and reasoning (“thinking”) support.

Why this exists

If you pull the official GGUF directly from Hugging Face —

ollama pull hf.co/LiquidAI/LFM2.5-8B-A1B-GGUF:Q8_0

— tool calling is broken in a subtle, nasty way:

  • Turn 1 works. The model emits a clean native tool call; Ollama parses it into tool_calls.
  • The crash comes later, whenever a response contains bracket-heavy code while tools are enabled. The request fails with:
500: Failed to parse input at pos N: ...

The root cause is upstream: hf.co/... pulls route chat templating through llama.cpp’s Jinja path, whose LFM2.5 tool-call parser mis-detects the template and chokes on output that merely looks like its Pythonic tool-call format. LFM2.5 writes tool calls as a bracketed list ([get_weather(city="Paris")]), so ordinary code in an answer — say useEffect(() => { ... }, [activeIdx, tabs.length]); — trips the parser and kills the whole request.

This is deterministic and reproducible:

# fails on the raw HF pull, succeeds on this build
curl -s http://localhost:11434/api/chat -d '{
  "model": "pierreprudh/lfm2.5:8b-a1b-q8_0",
  "stream": false,
  "messages": [{"role": "user", "content": "Repeat exactly, in a code block: useEffect(() => { measure(); }, [activeIdx, tabs.length]);"}],
  "tools": [{"type":"function","function":{"name":"read_file","description":"Read a file","parameters":{"type":"object","properties":{"path":{"type":"string"}},"required":["path"]}}}]
}'

Tracked upstream as llama.cpp #23838, fixed by PR #24178 — but not yet vendored into an Ollama release at the time of publishing (Ollama 0.30.7).

For coding agents and IDE harnesses this bug is fatal: any answer that quotes code crashes the run. That’s exactly how it was found — debugging an agent harness in a local-first IDE where multi-turn runs died the moment the model started explaining code.

What this build changes

Nothing about the weights. The fix is two fields in the Ollama model config:

"renderer": "lfm2",
"parser": "lfm2-thinking"

These route prompt rendering and tool-call parsing through Ollama’s native Go implementation for the LFM2 family instead of the broken llama.cpp Jinja path — the same mechanism the official ollama.com/library/lfm2.5 build uses. The GGUF’s embedded Jinja template layer is dropped (the renderer replaces it); LiquidAI’s license and sampling parameters ship unchanged.

The official library build only offers Q4_K_M (5.2 GB). This is the same fix at Q8_0 (9.0 GB) for those who want near-lossless quantization — useful when the model is doing precise code work.

Verified

  • ✅ Single-turn native tool calls (streaming and non-streaming)
  • ✅ Multi-turn agent loops: tool call → role: "tool" result → follow-up reasoning → final answer
  • ✅ Code-heavy responses with tools enabled (the exact crash case above)
  • ✅ Thinking traces parsed into thinking separately from content
  • ✅ Round-trip: pulled back from this registry and re-tested after publishing

Usage

ollama pull pierreprudh/lfm2.5:8b-a1b-q8_0

Tool calling via the standard Ollama API:

import ollama

response = ollama.chat(
    model="pierreprudh/lfm2.5:8b-a1b-q8_0",
    messages=[{"role": "user", "content": "What files are in the current directory?"}],
    tools=[{
        "type": "function",
        "function": {
            "name": "list_dir",
            "description": "List files in a directory",
            "parameters": {
                "type": "object",
                "properties": {"path": {"type": "string"}},
                "required": ["path"],
            },
        },
    }],
    options={"num_ctx": 32768},
)
print(response.message.tool_calls)

Tip — set num_ctx. Ollama defaults to a 4096-token context regardless of what the model supports. Agentic prompts (system prompt + tool schemas + history) overflow that quickly and return a confusing 400: exceeds the available context size. The model handles up to 128K; 32768 is a good default for agent loops.

Requirements & lifespan

  • Requires Ollama ≥ 0.30.0 (the version that ships the native lfm2 renderer/parser).
  • This build becomes redundant once Ollama vendors llama.cpp’s fix — at that point the raw hf.co/LiquidAI/... pull will work as-is. Until then, this is the way to run LFM2.5 tool calling at Q8_0.

Credits

All model weights, training, and the LFM Open License v1.0 belong to Liquid AI. This is a metadata-only repackage of their official LFM2.5-8B-A1B-GGUF Q8_0 release. See the included license for terms.