Intern-S2-Mobius

Intern-S2-Mobius

Intern-S2-Mobius는 InternLM의 35B 과학 멀티모달 파운데이션 모델로, Mobius-v0 아키텍처를 기반으로 해요(Qwen3.5-35B에서 지속 사전학습 후 SFT와 RL 후학습). 기존 Transformer처럼 지식 저장과 추론 계산을 레이어별로 묶는 대신, Mobius는 지식을 전역 공유 Memory로 구성하고 여러 Reasoner가 반복적으로 질의해서 네이티브한 두 가지 능력을 만들어내요.

출처: 문서

본문

1. Model Introduction

Intern-S2-Mobius는 InternLM의 35B 과학 멀티모달 파운데이션 모델로 Mobius-v0 아키텍처를 기반으로 해요(Qwen3.5-35B에서 지속 사전학습 후 SFT·RL 후학습). 기존 Transformers처럼 지식 저장과 추론 계산을 레이어별로 묶는 대신, Mobius는 지식을 전역 공유 Memory로 구성하고 여러 Reasoner가 그것을 반복적으로 질의해서 두 가지 네이티브 능력을 만들어내요:

  • Backward Residual Connection — 얕고 깊은 추론 단계가 순방향 레이어별 흐름에만 의존하지 않고 모델 전반의 지식에 도달할 수 있게 해요.
  • Dynamic Latent Reasoning — 반복적 잠재 반복이 디코딩 전에 은닉 상태를 정제해서, 숙고 과정의 일부를 내면화하고 가시적 chain-of-thought를 줄여줘요. 보고된 결과는 Qwen3.5-35B 기준선 대비 약 4× 종단간 추론 속도 향상이면서도 일반 추론 벤치마크에서 비슷한 점수를 유지하고 과학 작업(Biology-Instructions, Mol-Instructions, MolecularIQ)에서는 개선돼요.

서빙 측면에서 이 모델은 하이브리드예요: 40개 트랜스포머 레이어 중 30개가 GDN (Gated Delta Net) 선형 어텐션(kimi-linear 계열)을 사용하고, 4번째 레이어마다 full-attention 레이어(full_attention_interval: 410개 full-attention 레이어)가 있으며, 스택 하단은 MoE로 라우팅돼요(2,560 라우팅 전문가 × 512 중간, 토큰당 8 활성). 별도의 MoE-256 / top-8 MTP (NEXTN) 레이어가 스페큘레이티브 디코딩에 공급돼요. 비전 타워를 통해 이미지를 받고 표준 <|vision_start|>…<|vision_end|> + <|image_pad|> 마커를 인식해요. 컨텍스트 길이는 262,144 토큰이에요.

Variant Architecture Context License
Intern-S2-Mobius Mobius-v0 · GDN ×30 + full ×10 · MoE-2560 / top-8 · MTP · BF16 262,144 Apache-2.0
Intern-S2-Mobius-FP8 Mobius-v0 · GDN ×30 + full ×10 · MoE-2560 / top-8 · MTP · FP8 E4M3 262,144 Apache-2.0

권장 생성 설정: temperature=0.8, top_p=1.0, top_k=50, min_p=0.0model card가 권장하는 값이에요. 두 체크포인트 모두 generation_config.json에 다른 값(temperature=1.0, top_p=0.95, top_k=20)을 담아 배포하며, SGLang은 기본적으로 그 파일을 적용해요(--sampling-defaults model) — 그 권장 값을 쓰고 싶다면 요청마다 명시적으로 보내세요.

리소스: HuggingFace (BF16) · HuggingFace (FP8) · GitHub (InternLM/Intern-S2-Mobius).

2. Configuration Tips

  • 원격 코드 신뢰가 필요해요. Intern-S2-Mobius는 HF 저장소에 커스텀 configuration_interns2_mobius.py / modeling_interns2_mobius.py를 배포하며, 모든 레시피가 --trust-remote-code를 추가해요.
  • FP8은 H200 한 대를 사용해요. FP8 체크포인트는 128×128 블록 스케일의 E4M3 가중치와 동적 활성화 양자화를 저장해요. 검증된 H200 레시피는 TP=1, deep_gemm, --mem-fraction-static 0.6, prefill CUDA 그래프 비활성화, batch size 16까지의 디코드 그래프를 사용해요. 더 높은 메모리 분율이나 기본 그래프 범위는 DeepGEMM 워밍업 중 H200 메모리를 소진했어요; 실행 중인 MTP 서버는 약 99 GB를 사용했어요.
  • 스페큘레이티브 디코딩 일정. 체크포인트는 MTP 레이어 한 개를 배포해요. 가장 낮은 지연 시간(--speculative-algorithm NEXTN --speculative-num-steps 3 --speculative-eagle-topk 1 --speculative-num-draft-tokens 4)을 위해 MTP를 켜요. 8K-in / 1K-out에서 accept-length ~3.9/4 드래프트 토큰을 측정했으며, 단일 스트림 디코드 속도가 약 3배 빨라졌어요(중앙값 TPOT 9.79 ms → 3.13 ms at conc=1, 14.26 ms → 6.84 ms at conc=16), 중간 동시성 총 처리량은 약 2배(conc=16에서 9358 → 18029 tokens/s, conc=64에서 21395 → 26033 tokens/s). 고처리량 레시피는 스페큘레이티브를 끄는데, 넓게 배칭할 수 있게 되면 그 포화점이 더 높기 때문이에요(conc=256에서 34786 tokens/s 대 스펙 레시피의 conc=64 최고점).
(위의 추론·툴·비전 실행 산출물은 원문과 동일하게 별도 코드 섹션에서 재현)
  • Mamba pool 크기 조정. GDN 레이어는 별도의 Mamba 상태 풀에 있어요. --mamba-full-memory-ratio(기본 0.9)는 10개 full-attention 레이어의 KV 풀과 30개 GDN 레이어의 conv+SSM 상태 풀 사이의 분할을 제어해요. 기본 분할은 2×H200 노드에서 conc=64를 편안하게 처리해요; 워크로드에서 --max-running-requests가 허용하는 것보다 더 높은 동시성이 필요하면 --mamba-full-memory-ratio를 살짝 올리세요(각각 +1% mamba 비율은 full-attn KV를 소모해요).
  • 비전 입력. 이미지는 표준 image_url 채팅 메시지 타입으로 받아요. 비전 토큰은 프롬프트에 포함되고(prompt_tokens_details.image_tokens가 개수를 보여줌), 모델은 <|vision_start|> / <|vision_end|> 경계를 정확히 존중해요.
  • B200 크기 조정. B200(192 GB HBM)은 BF16 가중치 + KV + Mamba 풀을 --tp 1단일 GPU에 맞춰요. FP8 B200 셀은 검증된 H200 TP=1 레시피를 상속하지만 검증되지 않았으므로 Blackwell 측정이 나올 때까지 시작점으로 취급하세요.

3. Advanced Usage

아래 출력은 라이브 서버(체크포인트 generation_config.json에 따른 샘플링, temperature 1.0)에서 캡처한 그대로의 결과예요. 같은 요청을 다시 실행하면 의미적으로 동일하지만 텍스트가 다른 trace가 나와요 — 대표값으로 취급하고 결정론적으로 보지 마세요.

3.1 Reasoning

InternS2-Mobius는 하이브리드 reasoning 모델로, thinking trace가 최종 답 앞에 "Thinking Process:"로 시작해요. qwen3 reasoning parser를 켜면(PlaygroundParsers 카드의 Reasoning Parser 토글) thinking을 message.reasoning_content로, 답을 message.content로 분리해줘요.

from openai import OpenAI

client = OpenAI(base_url="http://localhost:30000/v1", api_key="EMPTY")
resp = client.chat.completions.create(
    model="internlm/Intern-S2-Mobius",
    messages=[{"role": "user", "content": "What is 15% of 240?"}],
)
msg = resp.choices[0].message
print("Reasoning:", getattr(msg, "reasoning_content", None))
print("Answer:", msg.content)
Reasoning: Thinking Process:

1.  **Identify the core question:** The user is asking for 15% of 240.
2.  **Determine the calculation method:** To find a percentage of a
    number, multiply the number by the percentage expressed as a decimal
    or fraction.
    *   Percentage: 15%
    *   Decimal: 0.15
    *   Fraction: 15/100
3.  **Perform the calculation:** $240 \times 0.15$
    *   Method 1: $240 \times 0.10 = 24$ (10%) and
        $240 \times 0.05 = 12$ (5%). Then add them: $24 + 12 = 36$.
    *   Method 2: $240 \times 15 = 3600$. Divide by 100 -> 36.
4.  **Verify the result:** The calculation is correct.
5.  **Formulate the answer:** State the final number clearly.

Answer:

15% of 240 is **36**.

Here is the math:
$240 \times 0.15 = 36$

3.2 Tool Calling

qwen3_coder tool-call parser를 켜면(PlaygroundParsers 카드의 Tool Call Parser 토글) 구조화된 tool call이 message.tool_calls로 표면화돼요. Intern-S2-Mobius는 <tool_call>…<function=name>…<parameter=key>…value…</parameter>…를 내보내는데, 이는 정확히 qwen3_coder가 파싱하는 형식이에요; parser 없이는 호출이 content에 raw 텍스트로 남아요. 이 thinking 모드 모델에서는 턴이 reasoning_content도 채우므로 두 필드를 모두 출력하세요.

Auto-resolution이 기본으로 동작해요. Intern-S2-Mobius의 chat template에는 auto-detector가 사용하는 <function= / <parameter= 마커가 있어서, --reasoning-parser auto --tool-call-parser auto는 추가 설정 없이 qwen3 / qwen3_coder로 해석돼요(이 빌드에서 서버 로그의 "Auto-detected …" 줄 + 라이브 tools 요청으로 검증). 리터럴 qwen3_coder slug를 전달할 수도 있지만 그럴 필요는 없어요.

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="internlm/Intern-S2-Mobius",
    messages=[{"role": "user", "content": "What is the weather in Beijing?"}],
    tools=tools,
)
msg = resp.choices[0].message
print("Reasoning:", getattr(msg, "reasoning_content", None))
print("Tool calls:", msg.tool_calls)
Reasoning: The user is asking for the weather in Beijing. I have access
to a get_weather function that can get the current weather for a
location. The function requires a "location" parameter which should be
the city name. In this case, the user specified "Beijing", so I should
use that as the location parameter.

Tool calls: [
  {
    "id": "call_545b5956b4c3457286261490",
    "index": 0,
    "type": "function",
    "function": {"name": "get_weather", "arguments": "{\"location\": \"Beijing\"}"}
  }
]

finish_reason: tool_calls

3.3 Vision Input

Intern-S2-Mobius는 OpenAI 호환 image_url 콘텐츠 타입으로 이미지를 받아요. 비전 입력은 Deploy 패널이 만든 것과 같은 서버에서 동작하며, 모델별 추가 플래그는 필요 없어요.

from openai import OpenAI

client = OpenAI(base_url="http://localhost:30000/v1", api_key="EMPTY")
resp = client.chat.completions.create(
    model="internlm/Intern-S2-Mobius",
    messages=[{
        "role": "user",
        "content": [
            {"type": "image_url",
             "image_url": {"url": "https://raw.githubusercontent.com/open-mmlab/mmdeploy/main/tests/data/tiger.jpeg"}},
            {"type": "text", "text": "Describe this image in one sentence."},
        ],
    }],
)
msg = resp.choices[0].message
print("Reasoning:", getattr(msg, "reasoning_content", None))
print("Answer:", msg.content)
Reasoning: The user wants a one-sentence description of the image.
Key elements: Tiger, lying down, grass, looking at camera.
Drafting: A tiger is lying in the green grass looking directly at the
camera.
Refining for flow and detail: A majestic tiger with striking orange and
black stripes rests calmly on a bed of lush green grass, staring
intently directly at the viewer.

Answer:

A majestic tiger with striking orange and black stripes rests calmly on a
bed of lush green grass, staring intently directly at the viewer.