From 513b5e1c637f5793f0bdc32ccaa53efa13fdc053 Mon Sep 17 00:00:00 2001 From: Leonie Monigatti Date: Fri, 10 Jul 2026 17:21:11 +0200 Subject: [PATCH] fix review findings and additional clean up --- guides/migration-guide.mdx | 202 +++--------------- lfm/key-concepts/chat-template.mdx | 11 +- lfm/key-concepts/tool-use.mdx | 7 +- snippets/key-concepts/chatml-example.mdx | 10 + .../key-concepts/tool-call-token-example.mdx | 5 + 5 files changed, 52 insertions(+), 183 deletions(-) create mode 100644 snippets/key-concepts/chatml-example.mdx create mode 100644 snippets/key-concepts/tool-call-token-example.mdx diff --git a/guides/migration-guide.mdx b/guides/migration-guide.mdx index 32f9b6ee..f5452999 100644 --- a/guides/migration-guide.mdx +++ b/guides/migration-guide.mdx @@ -3,7 +3,10 @@ title: "Migration Guide" description: "Move from Qwen, Llama, or Gemma to LFMs while avoiding the common migration pitfalls." --- -This guide is for teams already running Qwen, Llama, or Gemma who want to evaluate Liquid Foundation Models as replacements. LFMs load and serve through the same frameworks you already use, so most migrations are a model ID and config change. The details that usually matter are sampling defaults, chat templates, tool-call parsing, and LoRA module names. +import { ChatMLExample } from "/snippets/key-concepts/chatml-example.mdx"; +import { ToolCallTokenExample } from "/snippets/key-concepts/tool-call-token-example.mdx"; + +This guide is for teams already running Qwen, Llama, or Gemma who want to evaluate Liquid Foundation Models (LFMs) as replacements. LFMs load and serve through the same frameworks you already use, so most migrations are a model ID and configuration change. The details that usually matter are deployment runtime choice (see [Deployment runtimes](#deployment-runtimes)), chat templates (see [Chat Template](#chat-template)), sampling configuration (see [Sampling Configuration](#sampling-configuration)), tool-call parsing (see [Tool Use](#tool-use)), and LoRA module names (see [Fine-tuning](#fine-tuning)). Use this alongside [Use Case Evaluation](/guides/use-case-evaluation) for model selection and benchmarking methodology. @@ -13,143 +16,30 @@ Pick the LFM in the same deployment class as your current model. Compare within | If you run | Evaluate | Notes | | --- | --- | --- | -| Qwen3-0.6B, Llama-3.2-1B, Gemma-3-270M/1B | [LFM2.5-350M](https://huggingface.co/LiquidAI/LFM2.5-350M) | Classification, extraction, routing. Also consider LFM2.5-230M. | -| Qwen3-1.7B, Llama-3.2-3B, Gemma-3-4B | [LFM2.5-1.2B-Instruct](https://huggingface.co/LiquidAI/LFM2.5-1.2B-Instruct) | The default dense workhorse. | -| Qwen3-4B/8B, Llama-3.1-8B, Gemma-3-12B | [LFM2.5-8B-A1B](https://huggingface.co/LiquidAI/LFM2.5-8B-A1B) | MoE with 8B total and 1.5B active parameters. | -| Qwen3-14B/32B and larger dense models | [LFM2-24B-A2B](https://huggingface.co/LiquidAI/LFM2-24B-A2B) | 24B total and roughly 2.3B active parameters. | -| Qwen3 thinking mode or DeepSeek distills | [LFM2.5-1.2B-Thinking](https://huggingface.co/LiquidAI/LFM2.5-1.2B-Thinking) | Reasoning traces at 1.2B. | +| Qwen3-0.6B, Llama-3.2-1B, Gemma-3-270M/1B | [LFM2.5-230M](https://huggingface.co/LiquidAI/LFM2.5-230M) or [LFM2.5-350M](https://huggingface.co/LiquidAI/LFM2.5-350M) | Smallest text models for classification, extraction, routing, and tight memory budgets. | +| Qwen3-1.7B, Llama-3.2-3B, Gemma-3-4B, reasoning models in this latency class | [LFM2.5-1.2B-Instruct](https://huggingface.co/LiquidAI/LFM2.5-1.2B-Instruct) or [LFM2.5-1.2B-Thinking](https://huggingface.co/LiquidAI/LFM2.5-1.2B-Thinking) | Choose the Thinking variant when reasoning quality is worth the added latency. | +| Qwen3-4B/8B, Llama-3.1-8B, Gemma-3-12B | [LFM2-2.6B](https://huggingface.co/LiquidAI/LFM2-2.6B) or [LFM2.5-8B-A1B](https://huggingface.co/LiquidAI/LFM2.5-8B-A1B) | Compare in your latency and memory budget; 8B-A1B is an MoE model with 1.5B active parameters. | +| Qwen3-14B/32B and larger dense models | [LFM2-24B-A2B](https://huggingface.co/LiquidAI/LFM2-24B-A2B) | Largest LFM option for higher-capability text workloads. | | Qwen2.5-VL-3B/7B, Llama-3.2-Vision, Gemma-3 vision | [LFM2.5-VL-450M](https://huggingface.co/LiquidAI/LFM2.5-VL-450M) or [LFM2.5-VL-1.6B](https://huggingface.co/LiquidAI/LFM2.5-VL-1.6B) | Use `-Extract` variants for image to strict JSON. | | Whisper plus separate TTS | [LFM2.5-Audio-1.5B](https://huggingface.co/LiquidAI/LFM2.5-Audio-1.5B) | ASR, TTS, and speech-to-speech in one model. | See the [Complete Model Library](/lfm/models/complete-library) for the full catalog. -LFM2.5 dense models support 32K context, and LFM2.5-8B-A1B supports 128K. If you rely on 128K context in a small dense Qwen or Llama model, check your production context distribution before assuming this is a blocker. Most sub-8B deployments do not exceed 8K tokens. - -## Runtime-by-runtime migration - -Minimum versions: - -- `transformers >= 5.2.0` -- vLLM `>= 0.23.0` - - - - Change the model ID and use the model's chat template: - - ```python - from transformers import AutoModelForCausalLM, AutoTokenizer - - model_id = "LiquidAI/LFM2.5-1.2B-Instruct" - model = AutoModelForCausalLM.from_pretrained( - model_id, - dtype="bfloat16", - device_map="auto", - ) - tokenizer = AutoTokenizer.from_pretrained(model_id) - - inputs = tokenizer.apply_chat_template( - [{"role": "user", "content": "What is C. elegans?"}], - add_generation_prompt=True, - return_tensors="pt", - return_dict=True, - ).to(model.device) - - out = model.generate( - **inputs, - max_new_tokens=512, - do_sample=True, - temperature=0.1, - top_k=50, - repetition_penalty=1.05, - ) - ``` - - Do not reuse literal Llama-style or Gemma-style prompt strings. They will usually run, but quality will degrade. - - See [Transformers](/deployment/gpu-inference/transformers). - - - - Serve the model behind an OpenAI-compatible endpoint: - - ```bash - vllm serve LiquidAI/LFM2.5-1.2B-Instruct - ``` - - Your OpenAI-client code stays mostly unchanged: - - ```python - client.chat.completions.create( - model="LiquidAI/LFM2.5-1.2B-Instruct", - messages=messages, - temperature=0.1, - extra_body={"top_k": 50, "repetition_penalty": 1.05}, - ) - ``` - - If you use OpenAI-style `tools=[...]`, configure the LFM tool-call parser before switching traffic. See [Tool calling](#tool-calling) below and the [vLLM guide](/deployment/gpu-inference/vllm). - - - - Serve the model through SGLang's OpenAI-compatible API and keep your client integration mostly unchanged: - - ```bash - sglang serve --model-path LiquidAI/LFM2.5-1.2B-Instruct --tool-call-parser lfm2 - ``` - - Use LFM sampling defaults and configure the LFM tool-call parser if your evaluation includes tools. - - See [SGLang](/deployment/gpu-inference/sglang). - +## Deployment runtimes - - Pull the official GGUF and choose the quantization level you plan to deploy: +Across runtimes, avoid carrying over hand-written Qwen, Llama, or Gemma prompt templates. Use the model-provided chat template, and configure the `lfm2` tool-call parser in vLLM or SGLang when tool use is in scope. - ```bash - llama-server -hf LiquidAI/LFM2.5-1.2B-Instruct-GGUF:Q4_K_M - ``` +For GPU inference, see [Transformers](/deployment/gpu-inference/transformers), [vLLM](/deployment/gpu-inference/vllm), or [SGLang](/deployment/gpu-inference/sglang). - The GGUF embeds the correct chat template. Do not override it with an old Qwen or Llama template. +For edge and on-device inference, see [llama.cpp](/deployment/on-device/llama-cpp), [Ollama](/deployment/on-device/ollama), [LM Studio](/deployment/on-device/lm-studio), [MLX](/deployment/on-device/mlx), [ONNX](/deployment/on-device/onnx), or the [LEAP SDK](/deployment/on-device/sdk/quick-start). - See [llama.cpp](/deployment/on-device/llama-cpp). - - - - Use the official GGUF artifact and keep the embedded chat template: - - ```bash - ollama run hf.co/LiquidAI/LFM2.5-1.2B-Instruct-GGUF:Q4_K_M - ``` - - If you are using LM Studio, select the matching GGUF quantization and avoid overriding the prompt template with a previous Qwen, Llama, or Gemma template. - - See [Ollama](/deployment/on-device/ollama) and [LM Studio](/deployment/on-device/lm-studio). - - - - Per-precision repos exist for each model, including `-MLX-4bit` through `-MLX-8bit` and `-ONNX`. Swap the repo ID in `mlx-lm` or your ONNX Runtime pipeline. - - See [MLX](/deployment/on-device/mlx) and [ONNX](/deployment/on-device/onnx). - - - - The [LEAP SDK](/deployment/on-device/sdk/quick-start) gives iOS and Android apps a supported runtime with function calling and constrained generation included. - - - -## Chat template and sampling +## Chat Template LFMs use a ChatML-style format: -```text -<|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 -``` + -Roles are `system`, `user`, `assistant`, and `tool`. Vision-language models use an `` sentinel. See [Chat template](/lfm/key-concepts/chat-template). +Roles are `system`, `user`, `assistant`, and `tool`. Vision-language models use an `` sentinel. Migration notes: @@ -157,36 +47,33 @@ Migration notes: - **From Llama:** replace `<|begin_of_text|>` and `<|start_header_id|>` prompt builders. - **From Gemma:** replace `` builders. LFMs support a real `system` role. -Recommended starting sampling values: +See [Chat Template](/lfm/key-concepts/chat-template) and Hugging Face's [`apply_chat_template` guide](https://huggingface.co/docs/transformers/main/en/chat_templating#using-applychattemplate) for the full formatting workflow. -| Param | LFM2.5 recommendation | Common carry-over mistake | -| --- | --- | --- | -| `temperature` | `0.1` | `0.6` to `0.7`, which can cause drift | -| `top_k` | `50` | disabled | -| `repetition_penalty` | `1.05` | `1.0` | +## Sampling Configuration -For deterministic classification, extraction, and structured output, use greedy decoding. See [Text generation and prompting](/lfm/key-concepts/text-generation-and-prompting). +Generation parameters are model-specific. Tune on your task instead of carrying over defaults from Qwen, Llama, or Gemma. -## Tool calling +See the [Prompting Guide](/lfm/key-concepts/text-generation-and-prompting) for recommended sampling configurations by model. + +## Tool Use LFMs natively emit a Pythonic tool-call list, not OpenAI-style JSON: -```text -<|tool_call_start|>[get_candidate_status(candidate_id="12345")]<|tool_call_end|> -``` + If you swap an agent to an LFM and let a generic JSON parser run, tool calls can appear broken. The format is different. What to do: -1. Pass tools through `tokenizer.apply_chat_template(messages, tools=[...])` or the serving runtime's supported tool mechanism. +1. Pass tools through [`tokenizer.apply_chat_template(messages, tools=[...])`](https://huggingface.co/docs/transformers/main/en/chat_templating#using-applychattemplate) or the serving runtime's supported tool mechanism. 2. Parse the Pythonic call list between `<|tool_call_start|>` and `<|tool_call_end|>`. -3. On vLLM or SGLang, configure the LFM tool-call parser instead of a generic JSON parser. +3. On vLLM or SGLang, configure the `lfm2` tool-call parser instead of a generic JSON parser. 4. Return results as `tool` role messages, with JSON content if useful. -5. For strict schemas, use constrained decoding. See [Constrained Generation](/deployment/on-device/sdk/constrained-generation). -6. If you fine-tune for tool calling, train on the native Pythonic format and convert to any internal DSL after parsing. +5. If you fine-tune for tool calling, train on the native Pythonic format and convert to any internal domain-specific language after parsing. + +See [Tool Use](/lfm/key-concepts/tool-use) for the full tool-calling workflow. -## Migrating your fine-tuning pipeline +## Fine-tuning LFMs are standard Hugging Face causal LMs, so TRL and Unsloth-style pipelines carry over with two LFM-specific corrections. @@ -196,7 +83,7 @@ First, update LoRA `target_modules`. LFM2 and LFM2.5 use a conv-attention hybrid # LFM2 / LFM2.5 target_modules = ["w1", "w2", "w3", "q_proj", "k_proj", "v_proj", "out_proj", "in_proj"] -# Llama/Qwen/Gemma configs are wrong for LFMs: +# Llama/Qwen/Gemma configurations are wrong for LFMs: # o_proj/gate_proj/up_proj/down_proj do not exist. ``` @@ -204,36 +91,9 @@ Before a long run, call `model.print_trainable_parameters()`. You should see mil Second, format training examples with the LFM chat template. Training data formatted with your previous model's template creates a silent distribution mismatch. -Everything else transfers directly: - -- [LEAP Finetune](https://github.com/Liquid4All/leap-finetune) for SFT, LoRA, DPO, GRPO, text, VLM, MoE, local, SLURM, Kubernetes, Modal, and GGUF export workflows -- Existing [TRL](/lfm/fine-tuning/trl) or [Unsloth](/lfm/fine-tuning/unsloth) setups -- Starting LoRA recipe: `r=16`, `alpha=32`, learning rate around `2e-4` to `3e-4`, 3 to 5 epochs, bf16 - -## Migration checklist - -### Serving swap - -- Runtime meets minimum version requirements -- Model ID swapped -- Chat template comes from the model -- Sampling updated for LFM defaults -- Tool parser configured if tool calling is in scope -- Context length validated against production p95 - -### Evaluation - -- Comparison stays within the same deployment class -- Latency and throughput measured at production prompt lengths and concurrency -- Quantized artifact evaluated if you plan to ship quantized - -### Fine-tuning +Everything else transfers directly. Use [LEAP Finetune](/lfm/fine-tuning/leap-finetune), [TRL](/lfm/fine-tuning/trl), or [Unsloth](/lfm/fine-tuning/unsloth) depending on your existing workflow. -- LoRA `target_modules` updated to LFM names -- Trainable-parameter count sanity-checked -- Training data reformatted with the LFM chat template -- Tool-call training data uses the native Pythonic format -- Held-out eval set frozen before training +See [Fine-tuning Overview](/lfm/fine-tuning/overview) for the main fine-tuning workflow. ## Related docs diff --git a/lfm/key-concepts/chat-template.mdx b/lfm/key-concepts/chat-template.mdx index 2f8ea9cd..c0590fff 100644 --- a/lfm/key-concepts/chat-template.mdx +++ b/lfm/key-concepts/chat-template.mdx @@ -3,14 +3,9 @@ title: "Chat Template" description: "The chat template defines how conversations are structured using special tokens and roles. LFM2 uses a ChatML-like chat template to structure conversations 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|> -``` +import { ChatMLExample } from "/snippets/key-concepts/chatml-example.mdx"; + + Conversations are formatted using special tokens: diff --git a/lfm/key-concepts/tool-use.mdx b/lfm/key-concepts/tool-use.mdx index 34f52db1..59941067 100644 --- a/lfm/key-concepts/tool-use.mdx +++ b/lfm/key-concepts/tool-use.mdx @@ -3,6 +3,8 @@ title: "Tool Use" description: "LFM2.5 and LFM2 models support tool use (function calling), enabling models to interact with APIs, databases, and external services to provide accurate, up-to-date information." --- +import { ToolCallTokenExample } from "/snippets/key-concepts/tool-call-token-example.mdx"; + ## Overview The tool use workflow follows four steps: @@ -124,10 +126,7 @@ response = tokenizer.decode( The model outputs a tool call wrapped in special tokens: -``` -<|tool_call_start|>[get_candidate_status(candidate_id="12345")]<|tool_call_end|> -Checking the current status of candidate ID 12345. -``` + Parse the tool call and execute the function externally. Here we use a mock function that simulates what would typically be an API call to your recruitment system: diff --git a/snippets/key-concepts/chatml-example.mdx b/snippets/key-concepts/chatml-example.mdx new file mode 100644 index 00000000..ccb25684 --- /dev/null +++ b/snippets/key-concepts/chatml-example.mdx @@ -0,0 +1,10 @@ +export const ChatMLExample = () => ( + +{`<|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|>`} + +); diff --git a/snippets/key-concepts/tool-call-token-example.mdx b/snippets/key-concepts/tool-call-token-example.mdx new file mode 100644 index 00000000..806342ab --- /dev/null +++ b/snippets/key-concepts/tool-call-token-example.mdx @@ -0,0 +1,5 @@ +export const ToolCallTokenExample = () => ( + +{`<|tool_call_start|>[get_candidate_status(candidate_id="12345")]<|tool_call_end|>`} + +);