LFM2 is a new generation of hybrid models developed by Liquid AI, specifically designed for edge AI and on-device deployment. It sets a new standard in terms of quality, speed, and memory efficiency.
We're releasing the weights of our first MoE based on LFM2, with 8.3B total parameters and 1.5B active parameters.
LFM2-8B-A1B is the best on-device MoE in terms of both quality (comparable to 3-4B dense models) and speed (faster than Qwen3-1.7B).
Code and knowledge capabilities are significantly improved compared to LFM2-2.6B.
Quantized variants fit comfortably on high-end phones, tablets, and laptops.
Find more information about LFM2-8B-A1B in our blog post.
📄 Model details
Due to their small size, we recommend fine-tuning LFM2 models on narrow use cases to maximize performance.
They are particularly suited for agentic tasks, data extraction, RAG, creative writing, and multi-turn conversations.
However, we do not recommend using them for tasks that are knowledge-intensive or require programming skills.
Generation parameters: We recommend the following parameters:
temperature=0.3
min_p=0.15
repetition_penalty=1.05
Chat template: LFM2 uses a ChatML-like chat template as follows:
<|startoftext|><|im_start|>system
You are a helpful assistant trained by Liquid AI.<|im_end|>
<|im_start|>user
What is C. elegans?<|im_end|>
<|im_start|>assistant
It's a tiny nematode that lives in temperate soil environments.<|im_end|>
You can automatically apply it using the dedicated .apply_chat_template() function from Hugging Face transformers.
Tool use: It consists of four main steps:
Function definition: LFM2 takes JSON function definitions as input (JSON objects between <|tool_list_start|> and <|tool_list_end|> special tokens), usually in the system prompt
Function call: LFM2 writes Pythonic function calls (a Python list between <|tool_call_start|> and <|tool_call_end|> special tokens), as the assistant answer.
Function execution: The function call is executed and the result is returned (string between <|tool_response_start|> and <|tool_response_end|> special tokens), as a "tool" role.
Final answer: LFM2 interprets the outcome of the function call to address the original user prompt in plain text.
Here is a simple example of a conversation using tool use:
<|startoftext|><|im_start|>system
List of tools: <|tool_list_start|>[{"name": "get_candidate_status", "description": "Retrieves the current status of a candidate in the recruitment process", "parameters": {"type": "object", "properties": {"candidate_id": {"type": "string", "description": "Unique identifier for the candidate"}}, "required": ["candidate_id"]}}]<|tool_list_end|><|im_end|>
<|im_start|>user
What is the current status of candidate ID 12345?<|im_end|>
<|im_start|>assistant
<|tool_call_start|>[get_candidate_status(candidate_id="12345")]<|tool_call_end|>Checking the current status of candidate ID 12345.<|im_end|>
<|im_start|>tool
<|tool_response_start|>[{"candidate_id": "12345", "status": "Interview Scheduled", "position": "Clinical Research Associate", "date": "2023-11-20"}]<|tool_response_end|><|im_end|>
<|im_start|>assistant
The candidate with ID 12345 is currently in the "Interview Scheduled" stage for the position of Clinical Research Associate, with an interview date set for 2023-11-20.<|im_end|>
You can directly pass tools as JSON schema or Python functions with .apply_chat_template() as shown in this page to automatically format the system prompt.
Architecture: Hybrid model with multiplicative gates and short convolutions: 18 double-gated short-range LIV convolution blocks and 6 grouped query attention (GQA) blocks.
Pre-training mixture: Approximately 75% English, 20% multilingual, and 5% code data sourced from the web and licensed materials.
Training approach:
Very large-scale SFT on 50% downstream tasks, 50% general domains
Custom DPO with length normalization and semi-online datasets
Iterative model merging
🏃 How to run LFM2
Transformers.js
If you haven't already, you can install the Transformers.js JavaScript library from NPM using:
npm i @huggingface/transformers
You can then use the model as follows:
js
1import{ pipeline,TextStreamer}from"@huggingface/transformers";23// Create a text generation pipeline4const generator =awaitpipeline(5"text-generation",6"onnx-community/LFM2-8B-A1B-ONNX",7{dtype:"q4f16",device:"webgpu"},8);910// Define the list of messages11const messages =[12{role:"user",content:"What's the capital of France?"},13];1415// Generate a response16const output =awaitgenerator(messages,{17max_new_tokens:512,18do_sample:false,19streamer:newTextStreamer(generator.tokenizer,{20skip_prompt:true,21skip_special_tokens:true,22}),23});24console.log(output[0].generated_text.at(-1).content);
The following plots showcase the performance of different models under int4 quantization with int8 dynamic activations on the AMD Ryzen AI 9 HX 370 CPU, using 16 threads. The results are obtained using our internal XNNPACK-based inference stack, and a custom CPU MoE kernel.