Inkling-Small
Inkling-Small
Inkling-Small은 Thinking Machines의 오픈 가중치(아래 BF16과 NVFP4 체크포인트) Mixture-of-Experts 모델로, Inkling과 같은 아키텍처 제품군이에요. 텍스트, 이미지, 오디오 입력을 네이티브로 처리하며, 지연 시간·비용과 답변 품질을 맞바꾸는 가변 reasoning-effort 제어를 제공해요. 이 페이지는 SGLang에서 Inkling-Small을 서빙하는 방법, MTP 추측 디코딩 경로, 장문 컨텍스트 prefix 캐싱(통합 radix cache + HiCache)을 다뤄요.
출처: 문서
본문
Deployment
Install SGLang
모든 설치 방법과 하드웨어 플랫폼은 공식 SGLang 설치 가이드를 참조하세요.
Python (pip / uv):
Inkling-Small은 main에 병합됐지만 아직 pip 릴리스에 없어요 — 소스에서 설치하세요:
pip install --upgrade pip
pip install 'git+https://github.com/sgl-project/sglang.git#subdirectory=python'
그다음 아래 명령 패널의 Python 출력을 실행하세요.
Docker:
Note: Inkling-Small 이미지가
lmsysorg/sglang에 게시되고 있어요 — 태그 목록에서 상태를 확인하세요.
두 개의 multi-arch (amd64 / arm64) CUDA 빌드와 ROCm 빌드가 있어요. CUDA 빌드는 GPU가 아닌 CUDA 버전으로 선택하세요. DGX Spark (GB10)는 전용 arm64 CUDA 13 이미지를 사용해요:
docker pull lmsysorg/sglang:dev-inkling-dspark # CUDA 13
docker pull lmsysorg/sglang:dev-cu12-inkling-dspark # CUDA 12 (final build; lane retired)
docker pull lmsysorg/sglang:dev-inkling-small-dgx-spark # DGX Spark (GB10 / SM121)
docker pull lmsysorg/sglang-rocm:dev-rocm720-mi35x-inkling-dspark # AMD MI350X / MI355X
이미지 실행 방법은 Install → Method 3: Using Docker을 참고하세요. 안쪽 sglang serve ...를 아래 명령 생성기가 만들어 주는 것으로 바꿔 끼우세요.
하드웨어를 골라 실행 명령을 생성하세요. 각 플랫폼은 Balanced 레시피와 함께 MTP 및 DSpark(추측 디코딩) 계층, 그리고 검증된 곳에서 Long Context (MXFP8 KV) 계층을 제공해요. LoRA 변형은 동결된 베이스 모델 위에서 어댑터를 서빙해요. MAX_LORAS를 서빙하는 서로 다른 어댑터 수로 설정하세요(단일 어댑터 서빙에는 1이 가장 빠름).
패널 컨트롤 (명령 상자 상단):
- ⧉ Copy — 현재 명령을 클립보드로 복사.
- $ cURL — 서버가 떠 있는지 확인하는
localhost:30000대상 샘플 요청. - ⚙ Env — 명령과 cURL이 공유하는 플레이스홀더(
HOST_IP,PORT,NODE_RANK,NODE0_IP) 편집. - Verified / Not Verified 배지 —
(hw, variant, quant, strategy, nodes)콤보가 실제 하드웨어에서 end-to-end로 실행됐으면 초록, 이웃에서 자동 파생되어 아직 재확인되지 않았으면 노랑.
Playground
Playground는 검증된 매트릭스를 넘어선 SGLang 기능을 실험하는 곳이에요. Deploy 패널은 승인된 조합만 방출하고, Playground는 Deploy 패널이 현재 보여주는 셀 위에 추가 노브를 켤 수 있어요. 베이스는 Deploy 선택에서 실시간으로 읽어오며, 당신의 오버라이드만 변경돼요.
초록으로 강조된 줄은 오버라이드로 추가된 것, 빨간 취소선 줄은 검증된 베이스에 있었지만 오버라이드가 제거한 것이에요. 변경은 새 구성이 end-to-end로 실행될 때까지 배지를 Not Verified로 바꿔요.
1. 모델 소개
Inkling-Small은 Thinking Machines의 Mixture-of-Experts 모델로, Inkling과 같은 아키텍처 제품군의 오픈 가중치(아래 BF16과 NVFP4 체크포인트) 모델이에요. 텍스트, 이미지, 오디오 입력을 네이티브로 처리하고, 지연 시간·비용과 답변 품질을 맞바꾸는 가변 reasoning-effort 제어를 노출해요. 이 페이지는 MTP 추측 디코딩 경로와 장문 컨텍스트 prefix 캐싱(통합 radix cache + HiCache)을 포함해 SGLang에서 Inkling-Small을 서빙하는 방법을 다뤄요.
리소스: HuggingFace — Inkling-Small (BF16) · Inkling-Small-NVFP4.
2. 구성 팁
멀티모달. 레시피는 --enable-multimodal을 전달해 텍스트와 함께 이미지·오디오 입력을 서버가 받아들이게 해요 — 텍스트 전용 서빙에서는 빼세요.
DGX Spark (2× GB10). 검증된 셀은 ConnectX-7(노드당 1 GPU)로 두 Spark에 걸쳐 TP=2 NVFP4를 실행해요. dev-inkling-small-dgx-spark 이미지, Triton attention + Marlin FP4/MoE, --disable-prefill-cuda-graph를 사용하세요. Docker 명령은 이미 ConnectX-7 플래그 --ulimit memlock=-1:-1 --cap-add IPC_LOCK --device /dev/infiniband를 담고 있어요.
메모리 풀 비율. --swa-full-tokens-ratio와 --mamba-full-memory-ratio(둘 다 기본 0.1)가 SWA와 Mamba/sconv 상태 풀 크기를 결정해요. 워크로드 사용량에 맞게 튜닝하세요.
MTP는 --enable-multi-layer-eagle이 필요해요. MTP 레시피는 Inkling-Small의 다중 레이어 draft 헤드를 구동해요. 이 플래그가 없으면 표준 EAGLE 워커가 그에 맞서 실행되어 쓰레기 출력을 내요.
Reasoning effort. reasoning_effort를 아래 명명된 수준 중 하나로 전달하세요. 이를 생략한 요청은 기본적으로 high가 되고, max가 가장 강해요. 각 수준은 내부 effort 값에 매핑돼요(max는 0.99):
| reasoning_effort | value |
|---|---|
none |
0.0 |
minimal |
0.1 |
low |
0.2 |
medium |
0.7 |
high |
0.9 |
xhigh |
0.99 |
max |
0.99 |
3. 고급 사용
3.1 추론
inkling reasoning parser를 활성화해(위 Playground의 Parsers 카드에서 Reasoning Parser 토글) thinking과 최종 답변을 reasoning_content vs content로 분리하세요.
추론 예제 (Python)
from openai import OpenAI
client = OpenAI(base_url="http://localhost:30000/v1", api_key="EMPTY")
resp = client.chat.completions.create(
model="thinkingmachines/Inkling-Small-NVFP4",
messages=[{"role": "user", "content": "What is 17 times 24?"}],
extra_body={"chat_template_kwargs": {"thinking": True}},
)
msg = resp.choices[0].message
print("Reasoning:", getattr(msg, "reasoning_content", None))
print("Answer:", msg.content)
예제 출력
Reasoning: The user is asking for the product of 17 and 24. Let me calculate that.
17 × 24
I can break this down:
17 × 20 = 340
17 × 4 = 68
340 + 68 = 408
Alternatively:
24 × 10 = 240
24 × 7 = 168
240 + 168 = 408
So the answer is 408.
Answer: 17 times 24 is **408**.
Here's a quick breakdown:
- 17 × 20 = 340
- 17 × 4 = 68
- 340 + 68 = **408**
3.2 툴 호출
inkling 툴 호출 파서를 활성화해(위 Playground의 Parsers 카드에서 Tool Call Parser 토글) message.tool_calls를 통해 구조화된 툴 호출을 노출하세요.
툴 호출 예제 (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"}},
"required": ["location"],
},
},
}
]
resp = client.chat.completions.create(
model="thinkingmachines/Inkling-Small-NVFP4",
messages=[{"role": "user", "content": "What's the weather in Beijing?"}],
tools=tools,
)
msg = resp.choices[0].message
print("Reasoning:", getattr(msg, "reasoning_content", None))
print("Content:", msg.content)
print("Tool calls:", msg.tool_calls)
예제 출력
Reasoning: The user is asking for the weather in Beijing. I have a tool called `get_weather` that can get the current weather for a location. Let me call it with "Beijing" as the location.
Content:
Tool calls: [ChatCompletionMessageFunctionToolCall(id='call_98f772f3a0044f45b80c5ba5', function=Function(arguments='{"location": "Beijing"}', name='get_weather'), type='function', index=0)]
3.3 멀티모달 입력 (이미지 + 오디오)
Inkling-Small은 멀티모달이에요. 단일 사용자 메시지가 텍스트, 이미지, 오디오를 섞을 수 있어요. 각 미디어 항목을 자체 content part로 전달하세요 — 이미지는 image_url, 오디오는 audio_url, url은 HTTP(S) 링크 또는 base64 data: URI로 설정. 오디오는 OpenAI의 input_audio part로도 보낼 수 있어요. data에 base64 바이트를, format은 wav 또는 mp3로 함께 담아요. 서버는 --enable-multimodal로 시작해야 해요(위 모든 레시피에 이미 포함).
이미지 + 오디오 예제 (Python)
from openai import OpenAI
client = OpenAI(base_url="http://localhost:30000/v1", api_key="EMPTY")
with open("image.png", "rb") as f:
image_b64 = base64.b64encode(f.read()).decode()
with open("audio.wav", "rb") as f:
audio_b64 = base64.b64encode(f.read()).decode()
resp = client.chat.completions.create(
model="thinkingmachines/Inkling-Small-NVFP4",
messages=[
{
"role": "user",
"content": [
{"type": "image_url", "image_url": {"url": f"data:image/png;base64,{image_b64}"}},
{"type": "audio_url", "audio_url": {"url": f"data:audio/wav;base64,{audio_b64}"}},
{"type": "text", "text": "Describe the image, then transcribe the audio."},
],
}
],
max_tokens=1024,
)
print(resp.choices[0].message.content)
Note: 이미지와 오디오는 base64 대신 공개 HTTP(S) URL로 보낼 수 있어요 — 예:
{"type": "image_url", "image_url": {"url": "https://.../photo.jpg"}}. 미디어 항목당 content part 하나를 사용하고, 컨텍스트 예산이 허용하는 만큼 섞으세요.
3.4 LoRA (어댑터 서빙)
LoRA 배포 변형은 동결된 베이스 모델 위에서 어댑터를 서빙해요. 실행 명령이 --enable-lora --lora-paths lora0={{ADAPTER_PATH}} --max-loras-per-batch {{MAX_LORAS}}를 추가해요 — 각 어댑터는 = 왼쪽의 이름으로 등록돼요(여기서는 lora0). 어댑터는 POST /load_lora_adapter 엔드포인트로 런타임에도 추가/제거할 수 있어요. 여러 어댑터를 서빙하려면 실행 시 여러 --lora-paths name=path를 전달하고 각각을 이름으로 참조하세요.
요청 시 그 이름으로 어댑터를 선택하세요 — model 필드에 base-model:adapter 구문으로(권장) 또는 extra_body에서 lora_path로 명시적으로:
LoRA 예제 (Python)
from openai import OpenAI
client = OpenAI(base_url="http://localhost:30000/v1", api_key="EMPTY")
# Option A (recommended): "<model>:<adapter-name>" in the model field
resp = client.chat.completions.create(
model="thinkingmachines/Inkling-Small-NVFP4:lora0",
messages=[{"role": "user", "content": "Summarize the changelog."}],
)
# Option B: explicit lora_path via extra_body
resp = client.chat.completions.create(
model="thinkingmachines/Inkling-Small-NVFP4",
messages=[{"role": "user", "content": "Summarize the changelog."}],
extra_body={"lora_path": "lora0"},
)
print(resp.choices[0].message.content)
Note: 요청당 어댑터 하나 —
:adapter접미사(그리고lora_path)를 생략하면 베이스 모델을 hits해요. 같은 배치의 서로 다른 요청은 서로 다른 어댑터를 사용할 수 있어요. 배치에 공존하는 서로 다른 어댑터 수는--max-loras-per-batch(MAX_LORAS필드, 기본1)로 제한돼요.model:adapter와lora_path둘 다 제공되면model접미사가 우선해요.
3.5 HiCache (계층적 KV 캐싱)
Inkling-Small은 SGLang의 통합 radix cache에서 서빙돼요. 역사적으로 분리된 full-attention, SWA, Mamba/sconv 캐시가 타입 컴포넌트와 함께 하나의 radix 트리로 결합되고, 네이티브 HiCache가 콜드 prefix 페이지를 계층에 걸쳐(GPU HBM → 호스트 DRAM → 디스크/원격) 오프로드해요. 이렇게 하면 멀티 턴과 장문 컨텍스트 워크로드의 유효 prefix 캐시 용량이 확장돼요.
HiCache를 활성화하려면 위 Playground의 HiCache 카드를 열고 Enable을 켠 뒤 L3 계층용 스토리지 백엔드(file / mooncake / nixl)를 고르세요. Write 정책은 기본적으로 write_through예요.
3.6 Long Context (MXFP8 KV)
Long Context 배포 전략은 Balanced 레시피 위에 --kv-cache-dtype mxfp8을 추가해요. KV 항목이 BF16이 아닌 block-scaled MXFP8로 저장되므로, 같은 GPU에서 SWA + Mamba/sconv 메모리 풀이 대략 2배 토큰을 담아요. 컨텍스트 또는 동시성에 제약이 있을 때 사용하세요.
Blackwell 전용. MXFP8 KV 캐시는 Blackwell(B200 / B300 / GB200 / GB300)이 필요하고 Hopper(H200)에서는 제공되지 않아요.
트레이드오프는 BF16 KV 대비 추가 양자화/역양자화 작업에서 오는 ~5% decode 지연 시간 패널티뿐만 아니라, MXFP8로 KV를 저장하면 장문 컨텍스트 길이에서 약간의 정확도 손실도 생겨요. 용량 레버로 취급하고 속도 레버로는 취급하지 마세요. 메모리 풀에 여유가 있고 더 낮은 지연이나 최대 출력 품질만 원하면 Balanced에 머무르세요.
시도해 보려면 Deploy 패널에서 NVFP4 셀에 대해 Long Context 전략을 선택하세요. 패널이 --kv-cache-dtype mxfp8을 넣은 실행 명령을 재생성해요. B200, B300, GB300에서 end-to-end 검증됨.
3.7 DSpark (추측 디코딩)
DSpark 배포 전략은 Inkling-Small의 두 번째 추측 디코딩 경로예요. Inkling-Small의 자체 다중 레이어 draft 헤드를 구동하는 MTP와 달리, DSpark는 별도의 draft 체크포인트 — RadixArk/Inkling-Small-DSpark — 를 NVFP4 타겟과 함께 양자화 없이 서빙해요.
DSpark 지원은 §1에 나열된 이미지에 들어 있어요(CUDA 13은 dev-inkling-dspark, CUDA 12는 dev-cu12-inkling-dspark — 해당 lane이 은퇴했으므로 최종 빌드), 별도 빌드가 필요 없어요. B200(TP=8, NVFP4)에서 end-to-end 검증됨.