Skip to content

Tool calling: add LFM2 / LFM2.5 pythonic tool call parser + chat template - #464

Open
mpetruc wants to merge 1 commit into
theroyallab:mainfrom
mpetruc:feat/lfm2-tool-parser
Open

Tool calling: add LFM2 / LFM2.5 pythonic tool call parser + chat template#464
mpetruc wants to merge 1 commit into
theroyallab:mainfrom
mpetruc:feat/lfm2-tool-parser

Conversation

@mpetruc

@mpetruc mpetruc commented Sep 5, 2026

Copy link
Copy Markdown

Problem: LFM2 / LFM2.5 (Liquid AI) models emit tool calls as a Pythonic list wrapped in
<|tool_call_start|>[...]<|tool_call_end|> sentinels, not OpenAI-style JSON. Generic parsers misread this, so tool
calls appear broken whenever an agent is swapped onto an LFM.

Why add it: enables the LFM2 family for agents/tool-calling, mirroring vllm's lfm2 tool parser. Includes
templates/lfm2.jinja which steers fresh-session calls toward the sentinel format (the stock template lists tools but
never says how to emit a call, so output drifted to JSON).

Examples: raw model output

  <|tool_call_start|>[browser_navigate(url='/home/user1/workspace')]<|tool_call_end|>

parses to

  {"function": {"name": "browser_navigate", "arguments": "{\"url\": \"/home/user1/workspace\"}"}}

Validated against a live lfm2.5 server: non-streaming, streaming, parallel calls (index 0/1), and content-only
responses (no false positives). Registered as tool_format: lfm2 | lfm | lfm2_5.

Additional context: new module endpoints/OAI/utils/toolcall_formats/lfm2.py (ast-based, handles reserved-keyword
params and leading-zero ints), registration in tools.py, 11 tests in test_stream_parser.py, docs row/footnote,
.gitignore tunes to ship the template.

LFM2 / LFM2.5 (Liquid AI) models emit tool calls as a Pythonic list
wrapped in <|tool_call_start|> / <|tool_call_end|> sentinels rather than
OpenAI-style JSON. Register a new parser that converts those into standard
tool_calls.

- lfm2.py: parse the pythonic call list with ast (handles strings, nesting,
  negatives, unicode), turning each call into a ToolCall with JSON-encoded
  kwargs. Recovers reserved-keyword names (from=...) and leading-zero ints
  via string-safe rewrites.
- tools.py: register lfm2 / lfm / lfm2_5 in ALL_TOOLCALL_FORMATS.
- templates/lfm2.jinja: chat template that steers the model toward the
  sentinel format and escapes quotes/backslashes when rendering tool-call
  history (fresh-session calls otherwise drift to JSON).
- tests: Lfm2ToolcallFormatTests in test_stream_parser.py.
- docs: note the lfm2 format and template.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant