GLM-4.5V

GLM-4.5V

이 문서는 ZhipuAI의 최첨단 멀티모달 비전-언어 모델 GLM-4.5V를 SGLang으로 배포하고 호출하는 방법을 설명해요. 차세대 플래그십 텍스트 기반 모델 GLM-4.5-Air(106B 파라미터, 12B 활성) 위에 구축됐으며, 42개 공개 비전-언어 벤치마크에서 같은 규모의 모델 중 SOTA 성능을 달성했어요. 효율적인 하이브리드 훈련을 통해 실제 사용성을 중점으로 다양한 시각 콘텐츠 유형에 걸친 전원 스펙트럼 비전 추론을 가능하게 해요. 원문 페이지에는 하드웨어 플랫폼과 배포 전략을 골라 명령을 자동 생성해 주는 대화형 선택기가 포함되어 있어요.

출처: 문서

본문

1. 모델 소개

GLM-4.5V은 ZhipuAI의 최첨단 멀티모달 비전-언어 모델로, 차세대 플래그십 텍스트 기반 모델 GLM-4.5-Air(106B 파라미터, 12B 활성) 위에 구축됐어요. 42개 공개 비전-언어 벤치마크에서 같은 규모의 모델 중 SOTA 성능을 달성해요. 효율적인 하이브리드 훈련을 통해 GLM-4.5V는 실제 사용성을 중점으로 다양한 시각 콘텐츠 유형에 걸친 전원 스펙트럼 비전 추론을 가능하게 해요.

하드웨어 지원: NVIDIA B200/H100/H200, AMD MI300X/MI325X/MI355X

GLM-4.5V는 여러 핵심 기능을 도입해요:

  • 이미지 추론 및 그라운딩 (Image Reasoning & Grounding) — 장면 이해, 복잡한 다중 이미지 분석, 정밀한 시각 요소 위치 파악을 통한 공간 인식. 정규화 좌표(0-1000)를 사용한 정확한 객체 감지를 위한 bounding box 예측을 지원해요.
  • 비디오 이해 (Video Understanding) — 긴 비디오 분할과 이벤트 인식, 확장된 비디오 시퀀스에 걸친 종합적인 시간적 분석 지원.
  • GUI 에이전트 작업 (GUI Agent Tasks) — 에이전트 기반 애플리케이션을 위한 화면 읽기, 아이콘 인식, 데스크톱 조작 지원. 그래픽 사용자 인터페이스와의 자연스러운 상호작용을 가능하게 해요.
  • 복잡한 차트 및 장문 문서 파싱 (Complex Chart & Long Document Parsing) — 텍스트, 차트, 표, 그림이 있는 문서에서 연구 보고서 분석 및 정보 추출. 최대 64K 토큰의 멀티모달 컨텍스트를 처리해요.
  • 사고 모드 전환 (Thinking Mode Switch) — 빠른 응답과 심층 추론 사이의 균형을 허용. 사용자는 작업 요구 사항에 따라 Chain-of-Thought 추론을 켜고 끌 수 있어 정확도와 해석 가능성이 개선돼요.

2. SGLang 설치

SGLang은 여러 설치 방법을 제공해요. 하드웨어 플랫폼과 요구 사항에 가장 적합한 설치 방법을 선택할 수 있어요.

설치 지침은 공식 SGLang 설치 가이드를 참고하세요.

3. 모델 배포

이 섹션은 서로 다른 하드웨어 플랫폼과 사용 사례에 최적화된 배포 설정을 제공해요.

3.1 기본 설정

GLM-4.5V는 다양한 크기와 아키텍처의 모델을 제공하며, 서로 다른 하드웨어 플랫폼에 최적화되어 있어요. 권장 실행 설정은 하드웨어와 모델 크기에 따라 달라져요.

대화형 명령 생성기 (Interactive Command Generator): 아래 대화형 설정 생성기를 사용해 배포 설정을 맞춤화하세요. 하드웨어 플랫폼, 모델 크기, 양자화 방법 등을 선택해 적절한 실행 명령을 생성하세요. (대화형 위젯은 원문 페이지에서 동작하므로, 기본 설정 기준 명령은 다음과 같아요.)

python -m sglang.launch_server \
  --model-path zai-org/GLM-4.5V \
  --host 0.0.0.0 \
  --port 30000

3.2 설정 팁

  • TTFT 최적화: SGLANG_USE_CUDA_IPC_TRANSPORT=1을 설정해 CUDA IPC로 멀티모달 특성을 전송하면 TTFT가 크게 개선돼요. 이는 추가 메모리를 소비하므로 --mem-fraction-static 및/또는 --max-running-requests를 조정해야 할 수 있어요. (추가 메모리는 이미지 크기 × 현재 실행 중 요청의 이미지 수에 비례해요.)
  • TP=8 설정: 텐서 병렬화(TP) 8을 사용할 때 비전 attention의 12개 헤드를 균등하게 나눌 수 없어요. --mm-enable-dp-encoder를 추가해 해결할 수 있어요.
  • 빠른 모델 로딩: 큰 모델(106B 버전 같은)에서는 --model-loader-extra-config='{"enable_multithread_load": "true","num_threads": 64}'를 사용해 모델 로딩을 빠르게 할 수 있어요.
  • 하드웨어 참고 사항:
    • H100 (FP8): 최상의 메모리 효율을 위해 FP8 체크포인트를 사용하세요.
    • A100 / H100 (BF16): 처리량과 GPU 메모리 사용량을 관리하려면 표준 멀티모달 파라미터를 사용하세요.
    • H200 / B200: 기본 상태로 실행되며, 전체 컨텍스트 길이 + 동시 이미지 및 비디오 처리를 지원해요.
  • 추가 멀티모달 파라미터:
    • --mm-attention-backend fa3: 멀티모달 attention 백엔드(Flash Attention 3) 지정.
    • --mm-feature-transport=cuda_ipc: 멀티모달 데이터 전송에 CUDA IPC 공유 메모리를 사용해 D2H 메모리 복사를 피하고 E2E 지연 시간을 크게 개선.

전체 멀티모달 최적화가 포함된 예시:

SGLANG_USE_CUDA_IPC_TRANSPORT=1 \
SGLANG_VLM_CACHE_SIZE_MB=0 \
python -m sglang.launch_server \
  --model-path zai-org/GLM-4.5V \
  --host 0.0.0.0 \
  --port 30000 \
  --trust-remote-code \
  --tp-size 8 \
  --enable-cache-report \
  --log-level info \
  --max-running-requests 64 \
  --mem-fraction-static 0.65 \
  --chunked-prefill-size 8192 \
  --attention-backend fa3 \
  --mm-attention-backend fa3 \
  --mm-enable-dp-encoder \
  --enable-metrics

4. 모델 호출

4.1 기본 사용법

기본 API 사용법과 요청 예시는 다음을 참고하세요:

4.2 고급 사용법

4.2.1 멀티모달 입력

GLM-4.5V는 이미지와 비디오 입력을 모두 지원해요. 이미지 입력의 기본 예시:

import time
from openai import OpenAI

client = OpenAI(
    api_key="EMPTY",
    base_url="http://localhost:30000/v1",
    timeout=3600
)

messages = [
    {
        "role": "user",
        "content": [
            {
                "type": "image_url",
                "image_url": {
                    "url": "https://ofasys-multimodal-wlcb-3-toshanghai.oss-accelerate.aliyuncs.com/wpf272043/keepme/image/receipt.png"
                }
            },
            {
                "type": "text",
                "text": "Describe this image in detail."
            }
        ]
    }
]

start = time.time()
response = client.chat.completions.create(
    model="zai-org/GLM-4.5V",
    messages=messages,
    max_tokens=2048
)
print(f"Response costs: {time.time() - start:.2f}s")
print(f"Generated text: {response.choices[0].message.content}")

출력 예시:

Response costs: 3.37s
Generated text: Auntie Anne's

CINNAMON SUGAR
1 x 17,000                    17,000

SUB TOTAL                    17,000

GRAND TOTAL                  17,000

CASH IDR                     20,000

CHANGE DUE                  3,000

다중 이미지 입력 예시:

GLM-4.5V는 단일 요청에서 여러 이미지를 처리해 비교하거나 분석할 수 있어요:

import time
from openai import OpenAI

client = OpenAI(
    api_key="EMPTY",
    base_url="http://localhost:30000/v1",
    timeout=3600
)

messages = [
    {
        "role": "user",
        "content": [
            {
                "type": "image_url",
                "image_url": {
                    "url": "https://www.civitatis.com/f/china/hong-kong/guia/taxi.jpg"
                }
            },
            {
                "type": "image_url",
                "image_url": {
                    "url": "https://cdn.cheapoguides.com/wp-content/uploads/sites/7/2025/05/GettyImages-509614603-1280x600.jpg"
                }
            },
            {
                "type": "text",
                "text": "Compare these two images and describe the differences in 100 words or less. Focus on the key visual elements, colors, textures, and any notable contrasts between the two scenes. Be specific about what you see in each image."
            }
        ]
    }
]

start = time.time()
response = client.chat.completions.create(
    model="zai-org/GLM-4.5V",
    messages=messages,
    max_tokens=2048
)
print(f"Response costs: {time.time() - start:.2f}s")
print(f"Generated text: {response.choices[0].message.content}")

출력 예시:

Response costs: 3.86s
Generated text: The first image shows a close - up of a few red taxis on a street with storefronts in the background. The taxis are in a line, and the scene has an urban, busy feel with visible shop displays. The second image is an aerial view of a large taxi parking area with numerous red and green taxis, some with hoods open. The scene is more open, with a parking lot layout, and includes elements like a bridge and grassy areas. Key differences: number of taxis (few vs many), perspective (close - up vs aerial), color variety (mostly red vs red and green), and setting (street with shops vs parking lot).

비디오 입력 예시:

GLM-4.5V는 비디오 URL을 처리해 비디오 이해를 지원해요:

import time
from openai import OpenAI

client = OpenAI(
    api_key="EMPTY",
    base_url="http://localhost:30000/v1",
    timeout=3600
)

messages = [
    {
        "role": "user",
        "content": [
            {
                "type": "video_url",
                "video_url": {
                    "url": "https://videos.pexels.com/video-files/4114797/4114797-uhd_3840_2160_25fps.mp4"
                }
            },
            {
                "type": "text",
                "text": "Describe what happens in this video."
            }
        ]
    }
]

start = time.time()
response = client.chat.completions.create(
    model="zai-org/GLM-4.5V",
    messages=messages,
    max_tokens=2048
)
print(f"Response costs: {time.time() - start:.2f}s")
print(f"Generated text: {response.choices[0].message.content}")

참고:

  • 비디오 처리를 위해 충분한 컨텍스트 길이(최대 64K 토큰)가 구성되었는지 확인하세요
  • 비디오 처리는 더 많은 메모리를 요구할 수 있으므로 --mem-fraction-static을 그에 맞게 조정하세요
  • file:// 프로토콜을 사용해 로컬 파일 경로를 제공할 수도 있어요

출력 예시:

Response costs: 3.89s
Generated text: A person wearing blue gloves is using a microscope. They are adjusting the focus knob with one hand while holding a pipette with the other, suggesting they are preparing or examining a sample on the slide beneath the objective lens. The microscope's 40x objective lens is positioned over the slide, indicating a high-magnification observation. The person carefully manipulates the slide and the microscope controls, likely to achieve a clear view of the specimen.

4.2.2 사고 모드 (Thinking Mode)

GLM-4.5V는 향상된 추론을 위한 사고 모드를 지원해요. 배포 중 사고 모드를 활성화하세요:

python -m sglang.launch_server \
  --model-path zai-org/GLM-4.5V \
  --reasoning-parser glm45 \
  --tp 4 \
  --host 0.0.0.0 \
  --port 30000

사고 과정이 포함된 스트리밍:

from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:30000/v1",
    api_key="EMPTY"
)

# Enable streaming to see the thinking process in real-time
response = client.chat.completions.create(
    model="zai-org/GLM-4.5V",
    messages=[
        {"role": "user", "content": "Solve this problem step by step: What is 15% of 240?"}
    ],
    temperature=0.7,
    max_tokens=2048,
    stream=True
)

# Process the stream
has_thinking = False
has_answer = False
thinking_started = False

for chunk in response:
    if chunk.choices and len(chunk.choices) > 0:
        delta = chunk.choices[0].delta

        # Print thinking process
        if hasattr(delta, 'reasoning_content') and delta.reasoning_content:
            if not thinking_started:
                print("=============== Thinking =================", flush=True)
                thinking_started = True
            has_thinking = True
            print(delta.reasoning_content, end="", flush=True)

        # Print answer content
        if delta.content:
            # Close thinking section and add content header
            if has_thinking and not has_answer:
                print("\n=============== Content =================", flush=True)
                has_answer = True
            print(delta.content, end="", flush=True)

print()

참고: reasoning parser는 모델의 단계별 사고 과정을 캡처해 모델이 결론에 도달하는 방식을 볼 수 있게 해줘요.

사고 모드 비활성화:

특정 요청에서 사고 모드를 비활성화하려면:

response = client.chat.completions.create(
    model="zai-org/GLM-4.5V",
    messages=[{"role": "user", "content": "What is the capital of France?"}],
    extra_body={"chat_template_kwargs": {"enable_thinking": False}}
)

4.2.3 도구 호출 (Tool Calling)

GLM-4.5V는 도구 호출 기능을 지원해요. tool call parser를 활성화하세요:

python -m sglang.launch_server \
  --model-path zai-org/GLM-4.5V \
  --reasoning-parser glm45 \
  --tool-call-parser glm45 \
  --tp 4 \
  --host 0.0.0.0 \
  --port 30000

Python 예시 (사고 과정 포함):

from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:30000/v1",
    api_key="EMPTY"
)

# Define available tools
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"],
                        "description": "Temperature unit"
                    }
                },
                "required": ["location"]
            }
        }
    }
]

# Make request with streaming to see thinking process
response = client.chat.completions.create(
    model="zai-org/GLM-4.5V",
    messages=[
        {"role": "user", "content": "What's the weather in Beijing?"}
    ],
    tools=tools,
    temperature=0.7,
    stream=True
)

# Process streaming response
thinking_started = False
has_thinking = False
tool_calls_accumulator = {}

for chunk in response:
    if chunk.choices and len(chunk.choices) > 0:
        delta = chunk.choices[0].delta

        # Print thinking process
        if hasattr(delta, 'reasoning_content') and delta.reasoning_content:
            if not thinking_started:
                print("=============== Thinking =================", flush=True)
                thinking_started = True
            has_thinking = True
            print(delta.reasoning_content, end="", flush=True)

        # Accumulate tool calls
        if hasattr(delta, 'tool_calls') and delta.tool_calls:
            # Close thinking section if needed
            if has_thinking and thinking_started:
                print("\n=============== Content =================\n", flush=True)
                thinking_started = False

            for tool_call in delta.tool_calls:
                index = tool_call.index
                if index not in tool_calls_accumulator:
                    tool_calls_accumulator[index] = {
                        'name': None,
                        'arguments': ''
                    }

                if tool_call.function:
                    if tool_call.function.name:
                        tool_calls_accumulator[index]['name'] = tool_call.function.name
                    if tool_call.function.arguments:
                        tool_calls_accumulator[index]['arguments'] += tool_call.function.arguments

        # Print content
        if delta.content:
            print(delta.content, end="", flush=True)

# Print accumulated tool calls
for index, tool_call in sorted(tool_calls_accumulator.items()):
    print(f"🔧 Tool Call: {tool_call['name']}")
    print(f"   Arguments: {tool_call['arguments']}")

print()

출력 예시:

=============== Thinking =================
The user is asking about the weather in Beijing. I need to use the get_weather function to retrieve this information.
I should call the function with location="Beijing".
=============== Content =================

🔧 Tool Call: get_weather
   Arguments: {"location": "Beijing", "unit": "celsius"}

참고:

  • reasoning parser는 모델이 도구를 어떻게 사용하기로 결정하는지 보여줘요
  • 도구 호출은 함수 이름과 인자로 명확하게 표시돼요
  • 그런 다음 함수를 실행하고 결과를 다시 보내 대화를 이어갈 수 있어요

도구 호출 결과 처리:

# After getting the tool call, execute the function
def get_weather(location, unit="celsius"):
    # Your actual weather API call here
    return f"The weather in {location} is 22°{unit[0].upper()} and sunny."

# Send tool result back to the model
messages = [
    {"role": "user", "content": "What's the weather in Beijing?"},
    {
        "role": "assistant",
        "content": None,
        "tool_calls": [{
            "id": "call_123",
            "type": "function",
            "function": {
                "name": "get_weather",
                "arguments": '{"location": "Beijing", "unit": "celsius"}'
            }
        }]
    },
    {
        "role": "tool",
        "tool_call_id": "call_123",
        "content": get_weather("Beijing", "celsius")
    }
]

final_response = client.chat.completions.create(
    model="zai-org/GLM-4.5V",
    messages=messages,
    temperature=0.7
)

print(final_response.choices[0].message.content)
# Output: "The weather in Beijing is currently 22°C and sunny."

4.2.4 사고 예산 (Thinking Budget)

전체 추론 모드 활성화/비활성화(4.2.2절) 외에도 CustomLogitProcessor로 사고 토큰 수를 제한할 수 있어요. --enable-custom-logit-processor로 실행하고 요청에 Glm4MoeThinkingBudgetLogitProcessor를 전달하세요:

import openai
from sglang.srt.sampling.custom_logit_processor import Glm4MoeThinkingBudgetLogitProcessor

client = openai.Client(base_url="http://127.0.0.1:30000/v1", api_key="*")
response = client.chat.completions.create(
    model="zai-org/GLM-4.5V",
    messages=[{"role": "user", "content": "Describe this image briefly."}],
    max_tokens=1024,
    extra_body={
        "custom_logit_processor": Glm4MoeThinkingBudgetLogitProcessor().to_str(),
        "custom_params": {"thinking_budget": 512},
    },
)
print(response)

5. 벤치마크

5.1 정확도 벤치마크

표준 벤치마크에서 모델 정확도를 문서화하세요.