LFM2.5
LFM2.5
LFM2.5는 Liquid AI의 온디바이스 배포용 하이브리드 모델 제품군으로, LFM Open License v1.0로 공개됐어요. LFM2 아키텍처를 확장한 사전학습(dense 모델은 10T → 28T 토큰, 8B-A1B MoE는 12T → 38T 토큰)과 대규모 강화 학습을 기반으로 해요. 이 제품군은 적은 수의 GQA 블록과 gated short convolution 블록을 인터리브한 하이브리드 구조로, 엣지 지연 시간·메모리 예산에서 CPU에서도 비슷한 크기 모델보다 최대 2배 빠른 prefill·decode를 제공해요.
출처: 문서
본문
1. Model Introduction
LFM2.5는 Liquid AI의 온디바이스 배포용 하이브리드 모델 제품군으로, LFM Open License v1.0로 공개됐어요. LFM2 아키텍처에 확장된 사전학습(dense 모델 10T → 28T 토큰, 8B-A1B MoE 12T → 38T 토큰)과 대규모 강화 학습을 적용했어요.
백본은 gated short convolution 블록과 소수의 grouped query attention (GQA) 블록을 인터리브해요. 각 convolution 블록은 depthwise short convolution 주변에 입력 의존적 곱셈 게이팅을 적용해서 낮은 연산·메모리 비용으로 빠른 로컬 믹싱을 제공해요. GQA 블록은 전역 컨텍스트와 장문 검색을 처리해요.
이 최소 하이브리드 배치는 엣지 지연 시간과 메모리 예산 하에서 hardware-in-the-loop 아키텍처 탐색으로 선택됐어요. CPU에서는 비슷한 크기 모델보다 최대 2배 빠른 prefill과 decode를 제공해요(LFM2 Technical Report 참조).
주요 특징:
- 하이브리드 gated short conv + GQA 배치: 1.2B / 350M dense 모델은 16 레이어(10 conv + 6 GQA); 8B-A1B MoE는 24 레이어(18 conv + 6 GQA). 모델당 어텐션 레이어가 6개뿐이라 긴 컨텍스트에서도 KV cache가 작게 유지돼요.
- 블록 세부: kernel size 3의 depthwise convolution; 8 KV 그룹·head size 64·RoPE·QK-Norm의 GQA; 전역에 pre-norm RMSNorm과 SwiGLU MLP.
- Sparse MoE (8B-A1B): 총 8.3B / 활성 1.5B 파라미터. 처음 두 레이어를 제외한 모든 레이어가 dense MLP를 32-전문가 MoE 블록으로 교체; 각 토큰은 정규화된 sigmoid router(적응형 bias 로드 밸런싱 포함)로 top-4 SwiGLU 전문가에 라우팅돼요.
- 2.5의 새로운 점 (8B-A1B): 블록은 LFM2-8B-A1B와 동일하지만 컨텍스트 윈도우가 32K에서 128K로 늘어나고(RoPE base-θ 증가 + long-context midtraining) 어휘가 65,536에서 128,000 토큰으로 두 배가 되어 비라틴계 토큰화가 더 효율적이에요.
- Pythonic tool calling: 함수 호출이
<|tool_call_start|>와<|tool_call_end|>토큰 사이의 Python 리스트로 출력돼요.lfm2tool-call parser가 이를 표준message.tool_calls로 표면화해요. - Reasoning 변형: 8B-A1B와 1.2B-Thinking 체크포인트는 답보다 먼저 명시적 chain-of-thought를 항상 내보내는 reasoning 전용 모델이에요. MoE의 1.5B 활성 파라미터는 그 reasoning 토큰을 저렴하게 유지해요.
- 다국어: JP 체크포인트를 제외한 모든 모델이 최소 영어·아랍어·중국어·프랑스어·독일어·일본어·한국어·스페인어를 다뤄요(일부 변형은 더 추가). 전용 JP 채팅 체크포인트는 일본어(일본어 + 영어만)에 집중해요.
- 비전: LFM2.5-VL-1.6B는 1.2B 언어 백본을 SigLIP2 So400M NaFlex 인코더와 짝지어 OCR·문서 이해·다국어 비전을 지원해요. LFM2.5-VL-450M은 350M 백본에 SigLIP2 Base-86M 인코더를 짝지어 엣지 크기의 캡셔닝·객체 검출을 지원해요; bounding-box grounding과 function calling은 2.5 릴리스에서 새로 추가됐어요.
이용 가능한 모델:
| Model | Parameters | Context | Role |
|---|---|---|---|
| LFM2.5-8B-A1B | 8.3B total / 1.5B active (MoE) | 128K | Reasoning-tuned, agentic / tool use |
| LFM2.5-1.2B-Instruct | 1.17B (dense) | 32K | General instruct, RAG, data extraction |
| LFM2.5-1.2B-Thinking | 1.17B (dense) | 32K | Reasoning (always-on chain-of-thought) |
| LFM2.5-350M | 350M (dense) | 32K | Compact instruct, structured output |
| LFM2.5-230M | 230M (dense) | 32K | Most compact; data extraction, structured output |
| LFM2.5-1.2B-JP-202606 | 1.17B (dense) | 32K | Japanese chat (latest) |
| LFM2.5-1.2B-JP | 1.17B (dense) | 32K | Japanese chat (original) |
| LFM2.5-VL-1.6B | 1.2B LM + SigLIP2 400M | 32K | Vision-language (OCR, docs, multi-image) |
| LFM2.5-VL-450M | 350M LM + SigLIP2 86M | 32K | Compact vision-language (captioning, object detection) |
| LFM2.5-1.2B-Base | 1.17B (dense) | 32K | Pre-trained base (no post-training) |
위 Deploy 패널은 여덟 개 서빙 변형을 다뤄요; LFM2.5-1.2B-JP(원본 — --tool-call-parser 없이 시작)와 Base 저장소(사전학습 전용, 후학습 없음 — §3.5 참조)는 모델 경로만 바꿔 같은 방식으로 시작해요.
변형 선택:
- 8B-A1B — agentic·tool-calling 워크로드의 플래그십; 유일한 128K-컨텍스트 옵션.
- 1.2B-Thinking — reasoning 중심 작업: 수학, tool 사용, 프로그래밍.
- 1.2B-Instruct — 채팅과 창작 글쓰기에 권장.
- 350M — tool 사용, 데이터 추출, 구조화 출력; 수학·코드·창작 글쓰기에는 비권장.
- 230M — 가장 컴팩트한 체크포인트; 350M과 같은 용도, 수학·코드·창작 글쓰기용 아님.
라이선스: LFM Open License v1.0.
리소스: LFM2.5 announcement, LFM2.5-8B-A1B blog, LFM docs, LFM2 Technical Report (arXiv:2511.23404).
2. Configuration Tips
- Reasoning parser: LFM2.5 reasoning 모델은 chain-of-thought를
thinking... response태그로 감싸요. 명령 생성기는 8B-A1B용으로--reasoning-parser qwen3(명시적 시작thinking출력)를, 1.2B-Thinking용으로--reasoning-parser qwen3-thinking(상시 reasoning)를 전달해요. 이는 thinking 과정을reasoning_content로 분리하며, 없으면 chain-of-thought가content에 인라인으로 남아요. - Tool calling:
--tool-call-parser lfm2는 LFM2.5의 Pythonic<|tool_call_start|>[...]<|tool_call_end|>호출을 표준message.tool_calls로 표면화해요. 원본 1.2B-JP는 tool calling을 노출하지 않으며, Base는 후학습이 없어요(§3.5 참조). - Blackwell (B200/sm100)의 어텐션 백엔드: SGLang은 sm100에서
trtllm_mha백엔드를 기본으로 하며, dense 텍스트 모델에 가장 빠르다. 8B-A1B는 page-size-1 백엔드에서 동작하는 mamba-style 상태 캐시를 사용하므로 생성기는--attention-backend flashinfer를 선택해요. VL 언어 모델도 같은 상태 캐시를 사용하며 두 백엔드를 제공해요:--attention-backend flashinfer(prefix/radix 캐싱 유지 — 생성기가 내보내는 것), 또는--attention-backend trtllm_mha --disable-radix-cache(Blackwelltrtllm_mha어텐션에서 언어 모델 실행 —--disable-radix-cache는 page-size-1 요구를 풀지만 prefix 캐싱을 희생). 둘 다 비전 타워용--mm-attention-backend fa4와 짝지을 수 있어요. - VL 비전 타워 (
--mm-attention-backend): sm100에서trtllm_mha기본값은 텍스트에 가장 빠르지만 이미지 토큰에 causal 어텐션을 적용해요. VL 모델에서는 B200/B300에--mm-attention-backend fa4(또는 H100/H200에fa3)를 전달해 양방향 이미지 토큰 어텐션과 전체 비전 품질을 복원해요. - VL 멀티모달 피처 전송: 생성기는 VL 모델을
SGLANG_USE_CUDA_IPC_TRANSPORT=1 SGLANG_USE_IPC_POOL_HANDLE_CACHE=1로 시작해요. 첫 번째는 processor→scheduler 이미지 피처 핸드오프를 프로세스 간 텐서 직렬화 대신 CUDA IPC로 옮기고, 두 번째는 pool 핸들을 전달해 scheduler가 요청마다 per-item 핸들을 여는 대신 한 번 열고 캐시하게 해요. 이미지 서빙 워크로드(1 이미지 @ 720p, VL-1.6B에서 H100과 B200으로 측정)에서 이 쌍은 없을 때보다 약 30–50% 더 높은 이미지 처리량과 30–40% 더 낮은 이미지 TTFT를 내며(VL-1.6B, H100·B200에서 측정), 디코드 속도(TPOT)는 영향이 없어요. - VL-450M 메모리 헤드룸 (
--mem-fraction-static 0.8): 기본 메모리 분율로는 450M의 작은 가중치 때문에 SGLang이 정적 KV/mamba 풀을 GPU의 거의 전체로 잡아 이미지 피처 텐서용 헤드룸이 남지 않아요 — 지속적인 동시 이미지 로드에서 scheduler가 radix-cache free 경로에서 CUDA OOM으로 충돌할 수 있어요. 생성기는 VL-450M에--mem-fraction-static 0.8으로 제한해요; 그래도 풀은 이 모델이 필요한 것보다 훨씬 크다. - Mamba 스케줄링: LFM2.5는 기본
no_buffermamba 스케줄러 전략으로 실행되며--mamba-radix-cache-strategy플래그가 필요 없어요.extra_buffer전략(일부 Gated-DeltaNet 하이브리드에 사용 가능한 overlap-scheduling 처리량 최적화)은 convolution 블록이mamba_chunk_size=1을 쓰는 LFM2.5에는 적용되지 않아요. - 하드웨어 요구사항: 모든 LFM2.5 모델은 Hopper 또는 Blackwell의 단일 GPU(TP=1)에서 실행돼요. 1.2B / 350M dense 모델은 몇 GB에 맞고, 8B-A1B MoE는 bf16 가중치 + KV cache에 약 16 GB가 필요해요. 어떤 변형에도 다중 GPU 텐서 병렬화는 필요하지 않아요.
권장 샘플링 파라미터 — 매 요청에 명시적으로 전달하세요. 일부 LFM2.5 체크포인트는 generation_config.json에 샘플링 기본값을 배포하지 않아서 서버가 대신 적용해주지 않아요. top_k, min_p, repetition_penalty는 표준 OpenAI chat.completions 필드가 아니므로 **extra_body**로 전달하면 SGLang이 sampler로 보내줘요. 출력을 제한하려는 게 아니라면 max_tokens를 설정하지 마세요 — 응답(또는 reasoning 모델의 chain-of-thought)을 도중에 잘라낼 수 있어요.
| Model | temperature | extra_body (sampler) |
|---|---|---|
| LFM2.5-8B-A1B | 0.2 | {"top_k": 80, "repetition_penalty": 1.05} |
| LFM2.5-1.2B-Instruct | 0.1 | {"top_k": 50, "repetition_penalty": 1.05} |
| LFM2.5-1.2B-Thinking | 0.05 | {"top_k": 50, "repetition_penalty": 1.05} |
| LFM2.5-350M | 0.1 | {"top_k": 50, "repetition_penalty": 1.05} |
| LFM2.5-230M | 0.1 | {"top_k": 50, "repetition_penalty": 1.05} |
| LFM2.5-1.2B-JP-202606 | 0.1 | {"top_k": 50, "repetition_penalty": 1.05} |
| LFM2.5-1.2B-JP | 0.3 | {"min_p": 0.15, "repetition_penalty": 1.05} |
| LFM2.5-VL-1.6B (text) | 0.1 | {"min_p": 0.15, "repetition_penalty": 1.05} |
| LFM2.5-VL-450M (text) | 0.1 | {"min_p": 0.15, "repetition_penalty": 1.05} |
| LFM2.5-1.2B-Base | 0.3 | {"min_p": 0.15, "repetition_penalty": 1.05} |
3. Advanced Usage
3.1 Basic Usage
권장 샘플링 사전설정을 모델별로 적용한 단일 클라이언트(다음 섹션의 예제들은 이 chat 헬퍼를 재사용):
from openai import OpenAI
client = OpenAI(base_url="http://localhost:30000/v1", api_key="EMPTY")
# Non-OpenAI fields (top_k / min_p / repetition_penalty) ride in extra_body.
SAMPLING = {
"LiquidAI/LFM2.5-8B-A1B": dict(temperature=0.2, extra_body={"top_k": 80, "repetition_penalty": 1.05}),
"LiquidAI/LFM2.5-1.2B-Instruct": dict(temperature=0.1, extra_body={"top_k": 50, "repetition_penalty": 1.05}),
"LiquidAI/LFM2.5-1.2B-Thinking": dict(temperature=0.05, extra_body={"top_k": 50, "repetition_penalty": 1.05}),
"LiquidAI/LFM2.5-350M": dict(temperature=0.1, extra_body={"top_k": 50, "repetition_penalty": 1.05}),
"LiquidAI/LFM2.5-230M": dict(temperature=0.1, extra_body={"top_k": 50, "repetition_penalty": 1.05}),
"LiquidAI/LFM2.5-1.2B-JP-202606": dict(temperature=0.1, extra_body={"top_k": 50, "repetition_penalty": 1.05}),
"LiquidAI/LFM2.5-VL-1.6B": dict(temperature=0.1, extra_body={"min_p": 0.15, "repetition_penalty": 1.05}),
"LiquidAI/LFM2.5-VL-450M": dict(temperature=0.1, extra_body={"min_p": 0.15, "repetition_penalty": 1.05}),
}
def chat(model, messages, **overrides):
cfg = SAMPLING[model]
body = cfg["extra_body"] | overrides.pop("extra_body", {})
return client.chat.completions.create(
model=model, messages=messages,
temperature=cfg["temperature"], extra_body=body, **overrides,
)
resp = chat(
"LiquidAI/LFM2.5-1.2B-Instruct",
[{"role": "user", "content": "What is C. elegans? Answer in one sentence."}],
)
print(resp.choices[0].message.content)
3.2 Reasoning
8B-A1B와 1.2B-Thinking 체크포인트는 chain-of-thought를 내장 동작으로 출력해요. Deploy 패널은 일치하는 --reasoning-parser로 시작하는데, 이는 thinking 과정을 reasoning_content로 분리해요:
resp = chat(
"LiquidAI/LFM2.5-8B-A1B",
[{"role": "user", "content": "If a train travels 60 km/h for 2.5 hours, how far does it go?"}],
)
msg = resp.choices[0].message
print("Reasoning:", msg.reasoning_content)
print("Answer:", msg.content)
3.3 Tool Calling
LFM2.5는 Pythonic tool call을 작성해요. --tool-call-parser lfm2(이미 시작 명령에 포함)로 표준 message.tool_calls로 표면화돼요:
resp = chat(
"LiquidAI/LFM2.5-1.2B-Instruct",
[{"role": "user", "content": "What's the weather in Paris?"}],
tools=[{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather for a location",
"parameters": {
"type": "object",
"properties": {"location": {"type": "string"}},
"required": ["location"],
},
},
}],
)
for call in resp.choices[0].message.tool_calls or []:
print(call.function.name, call.function.arguments)
Tool calling은 8B-A1B, 1.2B-Thinking, 1.2B-Instruct, 350M, 230M, 1.2B-JP-202606, VL-1.6B, VL-450M에서 지원돼요. VL 모델에서는 텍스트 턴 전용이에요 — 같은 턴에 이미지와 tool을 결합하지 마세요.
3.4 Vision Input
VL 모델(VL-1.6B와 VL-450M)은 표준 OpenAI 멀티모달 콘텐츠 블록으로 이미지를 받아요. Base64 data URI(data:image/jpeg;base64,...)가 URL 대신 동작해요:
resp = chat(
"LiquidAI/LFM2.5-VL-1.6B",
[{
"role": "user",
"content": [
{"type": "image_url", "image_url": {
"url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg"}},
{"type": "text", "text": "What is in this image?"},
],
}],
)
print(resp.choices[0].message.content)
3.5 Base Checkpoints
각 크기는 사전학습된 Base 저장소를 배포해요 — LFM2.5-230M-Base, LFM2.5-1.2B-Base, LFM2.5-350M-Base, LFM2.5-8B-A1B-Base — 파인튜닝과 지속 사전학습용이에요.
이 저장소들은 ChatML-스타일 채팅 템플릿을 배포하므로 chat.completions 요청이 정상적으로 포맷돼요. 다만 체크포인트에는 후학습이 없어서 지시 따르기를 기대하지 마세요. raw 텍스트 연속 생성:
comp = client.completions.create(
model="LiquidAI/LFM2.5-1.2B-Base",
prompt="The capital of France is",
temperature=0.3,
extra_body={"min_p": 0.15, "repetition_penalty": 1.05},
)
print(comp.choices[0].text)