LFM2.5-24B-A2B, 24B 중 2.45B만 일하는 에이전트 모델

로컬에서 에이전트를 돌릴 때마다 같은 고민을 한다. 작은 모델은 도구 호출이 자주 틀리고, 큰 모델은 노트북에서 너무 느리다. 리퀴드 AI가 2026년 10월 13일(현지시간) 오픈웨이트로 공개한 LFM2.5-24B-A2B가 이 고민을 정면으로 겨냥한다. 전체 파라미터는 24.0B인데, 토큰 하나를 만들 때 실제로 계산하는 파라미터는 2.45B뿐이다. 회사가 내세운 목표도 분명하다. 개인정보 보호와 응답 속도를 앞세운 '온디바이스 AI 에이전트'다.
이 모델로 230M부터 24B까지 이어지는 LFM2.5 제품군이 다 갖춰졌다. Base 모델과 사후학습 모델 모두 Hugging Face에 올라와 있다.
핵심 해설: 무엇이 달라졌나
먼저 구조부터 본다(모델 카드 기준).
항목내용전체 / 활성 파라미터24.0B / 2.45B층 구성40층 = 이중 게이트 단(短) 컨볼루션 30 + GQA 어텐션 10MoE블록마다 전문가 64개, top-4 라우팅컨텍스트131,072 토큰어휘128,000라이선스lfm1.0언어한국어 포함 16개
이전 LFM2-24B-A2B와 비교하면 컨텍스트는 32,768에서 131,072토큰으로 네 배가 됐다. 어휘는 약 65K에서 128K로, 사전학습 데이터는 약 17조에서 33조 토큰으로 늘었다. 참고로 모델 카드는 총 학습량을 "36조 토큰"으로 따로 적고 있다. 사전학습 33조에 중간 학습 등이 더해진 숫자로 읽힌다.
24B 중 2.45B만 일한다
활성 비율은 이렇다.
$$ \frac{N_{\text{active}}}{N_{\text{total}}} = \frac{2.45\text{B}}{24.0\text{B}} \approx 10.2\% $$
MoE 블록에서는 라우터가 토큰마다 전문가 64개 중 점수가 높은 4개만 고른다.
$$ y = \sum_{i \in \text{Top4}(g(x))} \operatorname{softmax}(g(x))_i \cdot E_i(x), \qquad \frac{4}{64} = 6.25\% $$
전문가 쪽 비율(6.25%)이 전체 활성 비율(10.2%)보다 낮다. 컨볼루션 · 어텐션 · 임베딩처럼 모든 토큰이 함께 쓰는 부분이 있기 때문이다.
여기서 꼭 짚을 점이 있다. 연산은 2.45B급이지만, 메모리에는 24B 전체가 올라가야 한다. 어떤 전문가가 뽑힐지 미리 알 수 없어서다. 그래서 이 모델은 "작은 GPU용"이라기보다 "메모리는 넉넉하지만 연산은 약한 기기용"에 가깝다. 통합 메모리를 쓰는 Apple Silicon이나 AMD Ryzen AI Max 계열이 바로 그런 기기다.
어텐션은 10층뿐
40개 층 가운데 어텐션은 10개뿐이다. 이 구조가 긴 컨텍스트에서 유리한 이유는 KV 캐시에 있다. 어텐션 층은 지나간 토큰의 K · V를 모두 쌓아 두므로 메모리가 컨텍스트 길이에 비례해서 커진다. 반면 짧은 컨볼루션은 정해진 창 크기만큼의 상태만 들고 간다.
$$ \text{KV 메모리} \propto L_{\text{attn}} \times n_{\text{ctx}} $$
다른 조건이 같다고 하면, 40층 모두 어텐션인 모델에 비해 KV 캐시가 개념적으로 $10/40 = 1/4$로 줄어든다. 131K 컨텍스트를 노트북에서 감당할 수 있게 해 주는 핵심이 여기에 있다. 실제 GB 수치는 공개 자료에 없어서 여기서는 비율로만 적는다.
직접 돌려 보기
transformers
모델 카드의 예제를 거의 그대로 옮겼다. 권장 생성 설정은 temperature 0.1, top_k 50, repetition_penalty 1.05다.
from transformers import AutoModelForCausalLM, AutoTokenizer, TextStreamer
model_id = "LiquidAI/LFM2.5-24B-A2B"
model = AutoModelForCausalLM.from_pretrained(
model_id, device_map="auto", dtype="bfloat16",
)
tokenizer = AutoTokenizer.from_pretrained(model_id)
streamer = TextStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True)
input_ids = tokenizer.apply_chat_template(
[{"role": "user", "content": "MoE 라우팅을 한 문단으로 설명해 줘."}],
add_generation_prompt=True, return_tensors="pt", tokenize=True,
)["input_ids"].to(model.device)
model.generate(
input_ids, do_sample=True,
temperature=0.1, top_k=50, repetition_penalty=1.05,
max_new_tokens=1024, streamer=streamer,
)
vLLM · llama.cpp
서버로 띄울 때는 모델 카드의 명령 한 줄이면 된다.
vllm serve "LiquidAI/LFM2.5-24B-A2B"
노트북에서는 GGUF 버전(LFM2.5-24B-A2B-GGUF)과 llama.cpp 조합이 현실적이다. 아래는 -hf 옵션으로 받아서 띄우는 예시이고, 나는 아직 직접 돌려 보지 않았다. 양자화 태그는 저장소에서 확인하고 고르길 권한다.
# 예시 (직접 실행해 보지 않음)
llama-server -hf LiquidAI/LFM2.5-24B-A2B-GGUF \
--temp 0.1 --top-k 50 --repeat-penalty 1.05 -c 32768
MLX, SGLang, ONNX도 지원한다.
파이썬식 tool call로 에이전트 루프 만들기
이 모델은 기본적으로 JSON이 아니라 파이썬 함수 호출 모양으로 도구를 부른다(시스템 프롬프트로 JSON 형식을 쓰게 할 수도 있다).
<|tool_call_start|>[function_name(param="value")]<|tool_call_end|>
이 형식은 ast로 안전하게 파싱할 수 있어서 편하다. 아래는 그 아이디어를 보여 주는 예시 코드로, 실제 모델과 연결해 검증하지는 않았다. generate()는 위의 transformers 코드나 vLLM 호출로 바꿔 끼우면 된다.
# 예시 코드 (직접 돌려 보지 않음)
import ast, re
TOOLS = {
"get_weather": lambda city: f"{city}: 맑음, 18도",
}
CALL_RE = re.compile(r"<\|tool_call_start\|>(.*?)<\|tool_call_end\|>", re.S)
def parse_calls(text):
m = CALL_RE.search(text)
if not m:
return []
tree = ast.parse(m.group(1).strip(), mode="eval") # [f(a="b"), ...]
calls = []
for node in tree.body.elts:
name = node.func.id
kwargs = {k.arg: ast.literal_eval(k.value) for k in node.keywords}
calls.append((name, kwargs))
return calls
def agent(messages, generate, max_steps=5):
for _ in range(max_steps):
reply = generate(messages)
messages.append({"role": "assistant", "content": reply})
calls = parse_calls(reply)
if not calls:
return reply # 도구 호출이 없으면 최종 답
for name, kwargs in calls:
result = TOOLS[name](**kwargs) # eval 은 쓰지 않는다
messages.append({"role": "tool", "content": str(result)})
return reply
포인트는 eval을 쓰지 않는 것이다. ast.parse로 구조만 읽고, 인자는 literal_eval로 리터럴만 받는다. 도구 결과를 어떤 role로 넣을지는 모델의 채팅 템플릿을 확인해서 맞추는 게 좋다.
벤치마크 읽는 법
아래 점수는 모두 리퀴드 AI가 직접 측정한 것이다. 비교 상대는 Qwen3.6-35B-A3B이고, 모델 카드에는 Gemma-4-26B-A4B도 함께 나온다.
벤치마크LFM2.5-24B-A2BQwen3.6-35B-A3BLiveClaw48.0938.19AutomationBench27.698.72ToolSandbox80.7175.02IFEval96.7593.06MATH-50096.0496.73
AutomationBench에서는 3배가 넘게 차이 난다. 하지만 AI타임스 보도에 따르면 에이전트 · 도구 사용 벤치마크 8개 가운데 앞서거나 비슷한 것은 5개다. 나머지 3개에서는 뒤졌다는 뜻이다. MATH-500에서도 근소하게 뒤진다.
속도도 회사가 발표한 숫자다.
Apple M5 Max: 초당 184토큰
AMD Ryzen AI Max+ 395: 초당 114토큰
NVIDIA B300 한 장, 고부하 조건: 합계 초당 21,000 출력토큰 이상
API 가격은 100만 토큰당 입력 $0.10, 출력 $1.00이다.
내 생각: 개발자에게 주는 의미
첫째, "로컬 에이전트"가 실험에서 선택지로 바뀌고 있다. 활성 2.45B라는 연산량과 131K 컨텍스트가 만나면, 저장소 하나를 통째로 넣고 도구를 여러 번 부르는 작업도 노트북 안에서 해 볼 만하다. 코드나 사내 문서를 밖으로 보내기 곤란한 팀이라면 특히 그렇다.
둘째, 메모리 계산을 헷갈리면 안 된다. "A2B"라는 이름만 보고 2B 모델처럼 생각하면 안 된다. 메모리 요구량은 24B 모델 그대로이고, 빠른 것은 연산뿐이다. 그래서 VRAM이 작은 외장 GPU보다 통합 메모리가 큰 기기가 더 잘 맞는다.
셋째, 벤치마크는 내 작업으로 다시 재야 한다. 제조사가 직접 잰 점수이고, 에이전트 벤치마크는 프롬프트 형식에 민감하다. 파이썬식 tool call은 기존 JSON 기반 툴링과 바로 맞물리지 않으니, 파서와 템플릿을 맞추는 비용도 따져 봐야 한다. 라이선스가 Apache 같은 표준 라이선스가 아닌 "lfm1.0"이라는 점도 상용으로 쓰기 전에 꼭 읽어 볼 대목이다.
정리
LFM2.5-24B-A2B는 전체 24.0B, 활성 2.45B인 MoE 모델이다. 전문가 64개 중 4개를 고르는 top-4 라우팅을 쓴다.
40층 중 30층이 컨볼루션이고 어텐션은 10층뿐이라 KV 캐시 부담이 작다. 덕분에 131K 컨텍스트를 노릴 수 있다.
transformers · vLLM · llama.cpp(GGUF) · MLX로 바로 돌려 볼 수 있다. 권장 설정은 temp 0.1, top_k 50, repetition_penalty 1.05다.
에이전트 벤치마크에서 Qwen3.6-35B-A3B보다 앞선 항목이 많다. 다만 모두 회사가 직접 측정한 수치이니 내 작업으로 다시 확인해야 한다.