Granite 4.2

Granite 4.2

Granite 4.2은 IBM이 만든 dense decoder-only 언어 모델 제품군으로, 3B·8B·30B 세 가지 체크포인트를 제공해요. 각 체크포인트는 BF16 가중치를 사용하고 구성된 컨텍스트 길이는 131,072 토큰이며, chat template을 통해 기본 thinking(default thinking)·non-thinking·low-effort thinking·구조화된 tool call을 모두 지원해요. 저장소들은 Apache-2.0 라이선스를 선언하고 있어요.

출처: 문서

본문

1. Model introduction

Granite 4.2는 IBM의 dense decoder-only 언어 모델 제품군으로 3B, 8B, 30B 체크포인트를 제공해요. 각 체크포인트는 BF16 가중치를 사용하고 구성된 컨텍스트 길이가 131,072 토큰이며, chat template을 통해 default thinking, non-thinking, low-effort thinking, 그리고 구조화된 tool call을 지원해요. 저장소들은 Apache-2.0 라이선스를 선언하고 있어요.

Variant Total params Position in family
Granite 4.2 3B 3B Smallest checkpoint
Granite 4.2 8B 8B Mid-size checkpoint
Granite 4.2 30B 30B Largest checkpoint

권장 생성 설정: IBM은 일반 채팅·추론·tool calling에서 temperature=1.0top_p=0.95를 권장해요. 릴리스 체크포인트는 이 값들을 generation_config.json에 담아 배포하며, 명시적으로 지정하고 싶다면 요청마다 함께 보내면 돼요.

리소스: Granite 4.2 3B · Granite 4.2 8B · Granite 4.2 30B.

2. Configuration tips

  • Thinking은 기본으로 활성화돼요. 바로 답을 얻고 싶다면 chat_template_kwargs.enable_thinkingfalse로 설정해요. 더 짧은 추론 과정을 원한다면 enable_thinkinglow_efforttrue로 설정해요.
  • Thinking에 충분한 토큰을 주세요. temperature=1.0에서 기본 thinking 모드는 다단계 문제에서 1,000 토큰을 넘길 수 있어요. thinking 요청에는 답이 잘리지 않도록 max_tokens를 최소 2,048로 설정해요.
  • Reasoning parser. --reasoning-parser auto로 시작하면 이 체크포인트들에서 nemotron_3로 해석되어, OpenAI 호환 응답이 추론을 message.reasoning_content로, 답을 message.content로 분리해줘요. parser 플래그가 없으면 reasoning 마크업이 message.content 안에 인라인으로 남아요.
  • Tool-call parser. --tool-call-parser auto로 시작하면 이 체크포인트들에서 qwen3_coder로 해석되어 tool 요청이 message.tool_calls로 반환돼요. 없으면 raw <tool_call> 마크업이 message.content에 남아요.
  • 단일 GPU 크기 설계. 세 BF16 체크포인트 모두 H200 한 대와 B200 한 대에서 --tp 1 --mem-fraction-static 0.8로 로드되고 채팅 요청을 완료했어요. 새 토폴로지를 검증한 후에만 TP를 높이세요.
  • 이미지 선택. 검증된 경로는 lmsysorg/sglang:dev를 사용해요. 검증 중 테스트된 안정 이미지는 모델 로딩 전에 호환되지 않는 의존성 세트를 가졌기 때문에, 더 새로운 태그 릴리스가 확인될 때까지 레시피의 이미지를 사용하세요.

3. Advanced usage

아래 출력은 검증된 서버에서 Granite 4.2 3B를 캡처한 그대로의 결과예요. 샘플링은 확률적이라 같은 요청을 반복해도 다른 문구가 나올 수 있어요.

3.1 Thinking modes

nemotron_3 reasoning parser는 reasoning과 최종 콘텐츠를 별도 필드로 유지해요. Granite 4.2는 세 가지 chat-template 모드를 지원해요: default thinking, non-thinking, low-effort thinking.

from openai import OpenAI

client = OpenAI(base_url="http://localhost:30000/v1", api_key="EMPTY")
model = "ibm-granite/granite-4.2-3b"

modes = {
    "thinking": {"enable_thinking": True},
    "non-thinking": {"enable_thinking": False},
    "low-effort": {"enable_thinking": True, "low_effort": True},
}

for name, chat_template_kwargs in modes.items():
    response = client.chat.completions.create(
        model=model,
        messages=[
            {"role": "user", "content": "What is 17 * 23? Answer briefly."}
        ],
        extra_body={"chat_template_kwargs": chat_template_kwargs},
    )
    message = response.choices[0].message
    print(f"[{name}]")
    print("Reasoning:", getattr(message, "reasoning_content", None))
    print("Answer:", message.content)
[thinking]
Reasoning: Okay, the user asked "What is 17 * 23? Answer briefly." I need to calculate 17 multiplied by 23.

Let me do the multiplication. 17 times 23.

I can break it down: 17 * 20 = 340, and 17 * 3 = 51. Then add them: 340 + 51 = 391.

Alternatively, 23 * 17: 23*10=230, 23*7=161, 230+161=391. Same result.

So the answer is 391.

The user wants a brief answer, so just state the number.

Answer:
391
[non-thinking]
Reasoning: None
Answer: 391
[low-effort]
Reasoning: Compute 17*23 = 17*20=340, plus 17*3=51 => 391.

Answer:
391

3.2 Tool calling

qwen3_coder parser는 모델의 tool 마크업을 OpenAI 호환 구조화 호출로 변환해요.

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 city.",
        "parameters": {
            "type": "object",
            "properties": {
                "city": {"type": "string", "description": "The city name"},
            },
            "required": ["city"],
        },
    },
}]

response = client.chat.completions.create(
    model="ibm-granite/granite-4.2-3b",
    messages=[{"role": "user", "content": "What is the weather in Boston right now?"}],
    tools=tools,
    tool_choice="auto",
)

choice = response.choices[0]
message = choice.message
print("Reasoning:", getattr(message, "reasoning_content", None))
print("Content:", message.content)
for call in message.tool_calls or []:
    print("Tool:", call.function.name)
    print("Arguments:", call.function.arguments)
print("Finish reason:", choice.finish_reason)
Reasoning: Okay, the user is asking for the weather in Boston right now. I need to use the available tool called get_weather. The tool requires the city parameter. Since the user specified Boston, I'll call get_weather with city set to Boston.

Content: None
Tool: get_weather
Arguments: {"city": "Boston"}
Finish reason: tool_calls