Laguna-XS-2.1
Laguna-XS-2.1
Laguna-XS-2.1은 poolside가 만든 오픈 가중치 33B 파라미터 하이브리드 sliding-window-attention MoE 모델(토큰당 약 3B 활성화)로, 에이전틱 코딩과 장기 지평 소프트웨어 엔지니어링을 위해 만들어졌어요 — Laguna-M.1의 초소형 형제 모델이에요.
출처: 문서
본문
Deployment
모델은 Hub에 커스텀 config 코드를 실어 보내므로 --trust-remote-code가 필요해요(실행 명령에 포함).
git clone https://github.com/sgl-project/sglang.git
cd sglang
uv pip install --prerelease=allow -e python
```
그런 다음 해당 환경에서 아래 명령 패널의 **Python** 출력을 실행하세요.
</Tab>
<Tab title="Docker">
```bash
docker pull lmsysorg/sglang:latest
```
이미지 실행 방법은 [Install → Method 3: Using Docker](../../../docs/get-started/install#method-3-using-docker)를 참고하세요. 안쪽의 `sglang serve ...`를 아래 명령 생성기가 만들어 내는 것으로 대체하세요.
</Tab>
하드웨어 + 양자화 + 전략을 선택해 실행 명령을 생성하세요. 두 가지 서빙 전략이 일반적인 동작 포인트를 다룹니다:
- Low-latency — 일치하는 draft 모델이 있는 DFlash 추측 디코딩. 채팅과 대화형 에이전트에 선택하세요.
- High-throughput — 일반 서빙. 배치 워크로드에 가장 적합하며, 추측의 draft + 거부 오버헤드가 절약보다 더 비싼 경우예요.
8-GPU HGX 플랫폼(H200 / B300)에서 BF16과 NVFP4는 일반 --tp 8로 실행돼요. FP8과 INT4는 양자화 스케일이 MoE를 8-way로 샤드할 수 없어 --tp 8 --ep-size 8로 실행돼요(Configuration Tips 참조). 4-GPU GB300 노드는 전체적으로 일반 --tp 4를 사용해요.
Playground
Playground는 검증된 매트릭스를 넘어 SGLang 기능을 실험하는 곳이에요. 위 Deploy 패널은 승인된 조합만 생성하며, Playground는 Deploy 패널이 현재 표시 중인 셀 위에 추가 노브(TP 정도, 파서)를 켤 수 있게 해 줘요.
1. Model Introduction
Laguna-XS-2.1은 poolside의 오픈 가중치 33B 파라미터 하이브리드 sliding-window-attention MoE 모델(토큰당 약 3B 활성화)로, 에이전틱 코딩과 장기 지평 소프트웨어 엔지니어링을 위해 만들어졌어요 — Laguna-M.1의 초소형 형제 모델.
주요 특징:
- 희소 MoE: 40개 레이어, 256개 라우팅 전문가, top-8 라우팅.
- 하이브리드 attention: 30개 sliding-window 레이어(window 512)와 10개 full-attention 레이어가 interleave; 48 Q / 8 KV heads.
- 긴 컨텍스트: 262,144 토큰(full-attention 레이어에 RoPE + YaRN).
- DFlash drafts: 양자화마다 일치하는 draft 모델(5-레이어, 약 0.9 GB) 제공으로 낮은 지연 서빙.
- 하이브리드 추론:
thinking… response를chat_template_kwargs={"enable_thinking": …}으로 요청마다 토글.
사용 가능한 양자화:
| Precision | Target model | Draft model |
|---|---|---|
| BF16 | poolside/Laguna-XS-2.1 |
poolside/Laguna-XS-2.1-DFlash |
| FP8 | poolside/Laguna-XS-2.1-FP8 |
poolside/Laguna-XS-2.1-DFlash-FP8 |
| NVFP4 | poolside/Laguna-XS-2.1-NVFP4 |
poolside/Laguna-XS-2.1-DFlash-NVFP4 |
| INT4 | poolside/Laguna-XS-2.1-INT4 |
poolside/Laguna-XS-2.1-DFlash-INT4 |
draft 자체는 작은 bf16 모델로, 각각 자기 양자화된 타깃에 맞춰 보정돼요 — 항상 타깃과 일치하는 draft를 짝지으세요(정밀도를 섞으면 accept-length가 저하됨).
라이선스: Apache 2.0
리소스: Hugging Face · Release blog post · API platform.
2. Configuration Tips
Attention backend
High-throughput 셀에서는 --attention-backend을 설정하지 않은 채 두세요 — 자동 선택이 올바르기 때문이에요(Hopper에서 fa3, Blackwell에서 trtllm_mha). DFlash가 활성화되면 자동 선택은 대신 flashinfer로 폴백하는데, 이 하이브리드-SWA 모델을 Blackwell의 tp ≥ 4에서 망가뜨려요(greedy GSM8K 76% → 28%), 그래서 Low-latency 명령은 타깃 백엔드를 명시적으로 고정해요. --speculative-draft-attention-backend은 설정하지 않은 채 두세요. Laguna에는 triton attention을 절대 사용하지 마세요(GSM8K 13%).
양자화 체크포인트는 일반 TP를 4로 제한
moe_intermediate_size=512에 FP8 블록 [128,128] / INT4 group_size=128 스케일은 8-way로 샤드될 수 없어요(512/8 = 64 < 128 granularity): FP8은 가중치 생성 시 실패하고, INT4는 모든 하드웨어에서 Marlin 커널에서 충돌해요. 따라서 생성된 8-GPU FP8/INT4 명령은 --tp 8 --ep-size 8을 사용해요 — 전문가 병렬 처리는 랭크당 전문가 전체를 유지하므로 한 인스턴스에서 8개 GPU를 모두 사용합니다. FP8은 추가로 SGLANG_SHARED_EXPERT_TP1=1이 필요해요(그 공유 전문가도 블록 양자화되고; INT4는 bf16으로 유지). 대안: 일반 --tp 4, 또는 --tp 4 --dp-size 2. 정확도는 평가 노이즈 내에서 병렬 처리와 무관해요(GB300에서 tp1 ≡ tp4, H200에서 tp4 ≡ tp8+ep8로 검증).
DFlash 메모리
Low-latency 셀은 --mem-fraction-static 0.7을 담아요: 기본 비율은 GB300의 tp 4에서 draft vocab all-gather가 OOM 나요. Dense 셀은 기본 휴리스틱을 사용해요.
INT4는 혼합 정밀도
INT4 체크포인트는 MoE 레이어를 혼합 4-bit / 8-bit 구성 그룹으로 양자화해요. PR #29761보다 오래된 빌드는 로드 시 KeyError: 'Linear'로 충돌해요.
Chat template
transformers ≥ 5.10에서는 독립 chat_template.jinja가 자동 로드돼요 — 플래그 불필요(서버가 Auto-detected template features: reasoning_parser=poolside_v1, ...을 기록). 더 오래된 transformers(≤ 약 5.8)에서는 tokenizer_config.json의 {% include %} 스텁이 해석되지 못해 서버가 조용히 일반 템플릿으로 폴백해요 — 거기서는 --chat-template <model-dir>/chat_template.jinja를 명시적으로 전달하세요.
Thinking
기본적으로 꺼짐; 요청마다 extra_body={"chat_template_kwargs": {"enable_thinking": True}}로 옵트인하세요. 템플릿은 enable_thinking에 게이트하며, 일반 thinking 키는 무시돼요.
Served model id
서버는 --model-path에 전달한 대로 모델을 등록하며, 클라이언트의 model 필드가 그것(poolside/Laguna-XS-2.1, 또는 -FP8 / -NVFP4 / -INT4 id)과 일치해야 해요.
3. Advanced Usage
3.1 DFlash Speculative Decoding
DFlash는 블록 단위 추측 디코더예요: 5-레이어 draft가 토큰 블록 하나를 제안하고 타깃이 전체 블록을 단일 forward pass로 검증하므로 타깃이 승인한 토큰만 생성돼요 — 출력 품질은 구조상 타깃의 것(모든 양자화에서 GSM8K가 noise 내에서 dense와 일치). 속도 레버는 accept-length, 즉 타깃 단계당 검증을 통과하는 draft 토큰 수예요:
tp 1에서 약 6 토큰/단계,tp 4에서 약 4(greedy GSM8K, 일치 정밀도 쌍; 혼합 reasoning-heavy 트래픽에서 약 3; FP8은 H200의tp 8 + ep 8에서 6.75 달성) — dense의 1 토큰/단계 대비.- 대화형 / 소수 스트림 서빙에 가장 좋아요. 배치가 가득 찬 부하에서는 High-throughput을 선호하세요: GPU가 compute-bound가 되면 draft + 거부 토큰 오버헤드가 총 처리량을 깎아요.
- 생성된 명령은 항상 선택한 타깃 정밀도에 맞게 보정된 draft를 짝지워요.
3.2 Reasoning
--reasoning-parser poolside_v1로 실행하세요(모든 생성 명령에 내장). Reasoning은 enable_thinking=True로 옵트인하며, thinking 트레이스는 message.content의 최종 답과 분리되어 message.reasoning_content에 들어가요.
client = OpenAI(base_url="http://localhost:30000/v1", api_key="EMPTY")
response = client.chat.completions.create( model="poolside/Laguna-XS-2.1", messages=[{"role": "user", "content": "What is 15% of 240? Explain briefly."}], max_tokens=2048, extra_body={"chat_template_kwargs": {"enable_thinking": True}}, )
message = response.choices[0].message print("=============== Reasoning ===============") print(message.reasoning_content) print("=============== Answer ==================") print(message.content)
</Accordion>
<Note>
XS-2.1은 초소형 모델이에요 — thinking을 활성화하면 넉넉한 `max_tokens`를 주세요
(어려운 문제는 정기적으로 수천 토큰을 추론함), 짧은 형식 작업에는 thinking을 꺼 두세요.
</Note>
### 3.3 Tool Calling
`--tool-call-parser poolside_v1`로 실행하세요(모든 생성 명령에 내장). 파서는 Laguna의 `<tool_call>` 출력을 표준 OpenAI `tool_calls` 구조로 변환해요. 도구 호출은 reasoning이 꺼진 상태에서도(기본값) 작동해요.
<Accordion title="Tool Calling Example (Python)">
```python
from openai import OpenAI
client = OpenAI(base_url="http://localhost:30000/v1", api_key="EMPTY")
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a location",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "The city name"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
},
"required": ["location"],
},
},
}
]
response = client.chat.completions.create(
model="poolside/Laguna-XS-2.1",
messages=[{"role": "user", "content": "What's the weather in Beijing?"}],
tools=tools,
)
message = response.choices[0].message
if message.tool_calls:
for call in message.tool_calls:
print(f"Tool: {call.function.name}")
print(f"Args: {call.function.arguments}")