Laguna-S-2.1
Laguna-S-2.1
Laguna-S-2.1은 poolside가 만든 오픈 가중치 118B 파라미터 하이브리드 sliding-window-attention MoE 모델(토큰당 약 8B 활성화)로, 에이전틱 코딩과 장기 지평 소프트웨어 엔지니어링을 위해 만들어졌어요. Laguna 패밀리에서 Laguna XS 2.1(33B/3B 활성)과 Laguna M.1(222B/23B 활성) 사이에 위치해요.
출처: 문서
본문
Deployment
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)에서는 모든 양자화가 --tp 8로 실행돼요. 4-GPU GB300 노드는 전체적으로 --tp 4를 사용해요. NVFP4는 Blackwell 전용(B300 / GB300만)이에요.
Playground
Playground는 검증된 매트릭스를 넘어 SGLang 기능을 실험하는 곳이에요. 위 Deploy 패널은 승인된 조합만 생성하며, Playground는 Deploy 패널이 현재 표시 중인 셀 위에 추가 노브(TP 정도, 파서)를 켤 수 있게 해 줘요.
1. Model Introduction
Laguna-S-2.1은 poolside가 만든 오픈 가중치 118B 파라미터 하이브리드 sliding-window-attention MoE 모델(토큰당 약 8B 활성화)로, 에이전틱 코딩과 장기 지평 소프트웨어 엔지니어링을 위해 만들어졌어요. Laguna 패밀리에서 Laguna XS 2.1(33B/3B 활성)과 Laguna M.1(222B/23B 활성) 사이에 위치해요.
주요 특징:
- 희소 MoE: 48개 레이어, 256개 라우팅 전문가, top-10 라우팅, 플러스 공유 전문가 1개.
- 하이브리드 attention: 36개 sliding-window 레이어(window 512)와 12개 full-attention 레이어가 interleave(1:3 global-to-SWA 비율); 8 KV heads, head dim 128; 레이어 유형별 rotary 스케일을 가진 per-head sigmoid 출력 게이팅.
- 긴 컨텍스트: 1,048,576 토큰.
- DFlash drafts: 낮은 지연 서빙을 위해 양자화마다 일치하는 draft 모델 제공.
- 하이브리드 추론:
thinking… response를chat_template_kwargs={"enable_thinking": …}으로 요청마다 토글.
사용 가능한 양자화:
| Precision | Target model | Draft model |
|---|---|---|
| BF16 | poolside/Laguna-S-2.1 |
poolside/Laguna-S-2.1-DFlash |
| FP8 | poolside/Laguna-S-2.1-FP8 |
poolside/Laguna-S-2.1-DFlash-FP8 |
| NVFP4 | poolside/Laguna-S-2.1-NVFP4 |
poolside/Laguna-S-2.1-DFlash-NVFP4 |
| INT4 | poolside/Laguna-S-2.1-INT4 |
poolside/Laguna-S-2.1-DFlash-INT4 |
draft는 작은 BF16 모델로, 각각 자기 양자화된 타깃에 맞춰 보정돼요 — 항상 타깃과 일치하는 draft를 짝지으세요(정밀도를 섞으면 accept-length가 저하됨).
라이선스: OpenMDW-1.1
리소스: Hugging Face · Technical report · API platform
2. Configuration Tips
Attention backend
High-throughput 셀에서는 --attention-backend을 설정하지 않은 채로 두세요 — 자동 선택이 올바르기 때문이에요(Hopper에서 fa3, Blackwell에서 trtllm_mha). DFlash가 활성화되면 자동 선택은 대신 flashinfer로 폴백하는데, 이 하이브리드-SWA 모델을 Blackwell의 tp ≥ 4에서 망가뜨려요(Laguna-XS-2.1에서 재현, greedy GSM8K 76% → 28%), 그래서 Low-latency 명령은 타깃 백엔드를 명시적으로 고정해요. --speculative-draft-attention-backend은 설정하지 않은 채 두세요. 다른 attention 백엔드 선택은 Laguna에서 완전히 검증되지 않았으니 기본값을 유지하세요.
H200의 BF16 메모리
H200의 BF16은 FP8/INT4보다 CUDA-graph 캡처와 NCCL 할당에 여유가 적어요. High-throughput BF16 명령은 --mem-fraction-static 0.80을 담아요. FP8, INT4, 그리고 모든 B300/GB300 셀은 기본 휴리스틱을 사용해요.
FP8 공유 전문가
SGLANG_SHARED_EXPERT_TP1=1은 모든 하드웨어에서 FP8 셀에 필요해요 — H200(TP=8)과 GB300(TP=4) 모두에서 확인. FP8 체크포인트는 공유 전문가(128×128 스케일)를 블록 양자화하는데, S-2.1에서 두 TP 정도 모두에서 깨끗하게 TP-샤드될 수 없어요. 이 환경 변수는 공유 전문가를 샤딩하는 대신 복제해요. INT4는 공유 전문가를 BF16으로 유지(플래그 없음); BF16은 비양자화. 참고: 이는 TP=4에서 플래그가 필요 없는 Laguna-XS-2.1과 다르며, 제약은 아키텍처별이에요.
FP8 및 NVFP4 DFlash drafts
2026-07-21에 업스트림 수정: 모든 DFlash draft 설정이 이제 평평한 최상위 rope_theta를 사용해요(rope_parameters 블록은 제거됨). draft 모델 로드 시 KeyError: 'rope_theta' 오류로 서버가 중단되면 2026-07-21 이전에 캐시된 draft 체크포인트를 제공하고 있는 것이므로 재다운로드하세요(예: hf download poolside/Laguna-S-2.1-DFlash-FP8)로 수정된 설정을 받으세요.
DFlash 메모리
Low-latency 셀은 --mem-fraction-static 0.7을 담아요(H200의 BF16에도 충분). Dense 셀은 기본 휴리스틱을 사용해요(위의 H200 BF16 제외).
BF16 추론 길이
BF16은 FP8/INT4보다 약 2배 더 길게 추론해요(AIME25에서 중앙값 34.8k 대 16.9k 토큰), max_tokens=64000에서 일관되게 잘려요. FP8/INT4는 약 2%에서 잘려요. 유효한 BF16 AIME25 점수를 원하면 max_tokens ≥ 131072로 서빙하세요(모델은 1M 컨텍스트 윈도우 지원).
Chat template
transformers ≥ 5.10에서는 독립 chat_template.jinja가 자동 로드돼요 — 플래그 불필요(서버가 Auto-detected template features: reasoning_parser=poolside_v1, ...을 기록). 더 오래된 transformers(≤ 약 5.8)에서는 --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-S-2.1, 또는 -FP8 / -NVFP4 / -INT4 id)과 일치해야 해요.
3. Advanced Usage
3.1 DFlash Speculative Decoding
DFlash는 블록 단위 추측 디코더예요: draft가 토큰 블록 하나를 제안하고 타깃이 전체 블록을 단일 forward pass로 검증해요 — 출력 품질은 구조상 타깃의 것. 속도 레버는 accept-length, 즉 타깃 단계당 검증을 통과하는 draft 토큰 수예요.
대화형 / 소수 스트림 서빙에 가장 좋아요. 배치가 가득 찬 부하에서는 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-S-2.1", messages=[{"role": "user", "content": "What is 15% of 240? Explain briefly."}], max_tokens=4096, 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>
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-S-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}")