Qwen2.5-VL

Qwen2.5-VL

**Qwen2.5-VL**은 Qwen 팀의 비전-언어 모델 시리즈로, 이해·추론·멀티모달 처리에서 이전 세대보다 크게 개선되었어요.

출처: 문서

본문

1. Model Introduction

**Qwen2.5-VL**은 Qwen 팀의 비전-언어 모델 시리즈로, 전작 대비 이해, 추론, 멀티모달 처리에서 크게 개선되었어요.

주요 특징:

  • 시각적 이해: 꽃, 새, 물고기, 곤충 같은 일반 객체를 인식하는 데 능숙하며, 이미지 내 텍스트, 차트, 아이콘, 그래픽, 레이아웃을 분석하는 데 매우 뛰어나요.
  • 더 에이전틱: 추론하고 도구를 동적으로 지시할 수 있는 시각 에이전트 역할을 하며, 컴퓨터 사용과 휴대폰 사용이 가능해요.
  • 긴 비디오 이해 및 이벤트 포착: 1시간 이상의 비디오 이해를 지원하며, 이번에는 관련 비디오 세그먼트를 정확히 짚어 이벤트를 포착하는 새로운 능력이 있어요.
  • 다양한 형식의 시각적 위치화: bounding boxes나 points를 생성해 이미지 내 객체를 정확히 위치화하고, 좌표와 속성에 대해 안정적인 JSON 출력을 제공할 수 있어요.
  • 구조화된 출력 생성: 콘텐츠의 구조화된 출력을 지원하며, 금융·상거래 등에서 인보이스, 양식, 표 스캔 같은 데이터에 유용해요.
  • 비디오 이해를 위한 동적 해상도 및 프레임 레이트 트레이닝: 동적 FPS 샘플링을 채택해 동적 해상도를 시간 차원으로 확장하고, 다양한 샘플링 레이트의 비디오를 이해할 수 있게 해요. 이에 따라 mRoPE를 시간 차원에서 ID와 절대 시간 정렬로 업데이트해 모델이 시간 순서와 속도를 학습하고, 결국 특정 순간을 정확히 짚는 능력을 얻도록 해요.
  • 다양한 크기: 3B, 7B, 32B, 72B 변형으로 제공되어 다양한 배포 요구에 맞춥니다.
  • ROCm 지원: SGLang을 통해 AMD MI300X, MI325X, MI355X GPU와 호환(검증됨).

자세한 내용은 공식 Qwen2.5-VL GitHub 저장소를 참조하세요.

2. SGLang Installation

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

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

SGLang CPU 설치에 대해서는 CPU 버전 설치 가이드를 참조하세요.

3. Model Deployment

이 섹션은 AMD MI300X, MI325X, MI355X와 Intel Xeon CPU 하드웨어 플랫폼 및 다양한 사용 사례에 최적화된 배포 구성을 제공해요.

3.1 Basic Configuration

Qwen2.5-VL 시리즈는 다양한 크기의 모델을 제공해요. 아래 구성은 AMD MI300X, MI325X, MI355X GPU와 Intel Xeon CPU에서 검증되었어요.

대화형 명령 생성기: 아래 구성 선택기를 사용해 하드웨어 플랫폼과 모델 크기에 맞는 배포 명령을 자동 생성하세요.

3.2 Configuration Tips

  • 메모리 관리: MI300X/MI325X/MI355X의 72B 모델은 --context-length 128000으로 성공적인 배포를 검증했어요. 필요하면 더 작은 컨텍스트 길이로 메모리 사용을 줄일 수 있어요.
  • 멀티 GPU 배포: 텐서 병렬 처리(--tp)를 사용해 여러 GPU에 걸쳐 확장하세요. 예를 들어 MI300X/MI325X/MI355X에서 72B 모델은 --tp 8, 32B 모델은 --tp 2를 사용하세요.
  • Xeon CPU 서비스 구성: SGLang CPU 서버 문서의 serving engine 실행 섹션에서 Notes 부분을 참조해 TP(텐서 병렬) 및 NUMA 바인딩 설정을 올바르게 구성하는 방법을 이해하세요.

4. Model Invocation

4.1 Basic Usage

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

4.2 Advanced Usage

4.2.1 Multi-Modal Inputs

Qwen2.5-VL은 이미지 입력을 지원해요. 단일 이미지 입력의 기본 예시:

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": "Read all the text in the image."
            }
        ]
    }
]

start = time.time()
response = client.chat.completions.create(
    model="Qwen/Qwen2.5-VL-7B-Instruct",
    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: 2.31s
Generated text: Auntie Anne's

CINNAMON SUGAR
1 x 17,000
SUB TOTAL
17,000

GRAND TOTAL
17,000

CASH IDR
20,000

CHANGE DUE
3,000

다중 이미지 입력 예시:

Qwen2.5-VL은 비교 또는 분석을 위해 단일 요청에서 여러 이미지를 처리할 수 있어요:

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."
            }
        ]
    }
]

start = time.time()
response = client.chat.completions.create(
    model="Qwen/Qwen2.5-VL-7B-Instruct",
    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: 13.79s
Generated text: The first image shows a single red taxi driving on a street with a few other taxis in the background. The second image shows a large number of taxis parked in a lot, with some appearing to be in various states of repair. The first image has a single taxi with a visible license plate, while the second image has multiple taxis with different license plates. The first image has a clear view of the street and surrounding area, while the second image is taken from an elevated perspective, showing a wider view of the parking lot and the surrounding area.

참고:

  • file:// 프로토콜을 사용해 로컬 파일 경로도 제공할 수 있어요.
  • 더 큰 이미지에는 더 많은 메모리가 필요할 수 있으므로 --mem-fraction-static을 그에 맞게 조정하세요.

5. Benchmark

5.1 Speed Benchmark

테스트 환경:

  • 하드웨어: AMD MI300X GPU (8x)
  • 모델: Qwen2.5-VL-72B-Instruct
  • 텐서 병렬 처리(Tensor Parallelism): 8
  • SGLang 버전: 0.5.6

SGLang의 내장 벤치마킹 도구를 임의 이미지와 함께 사용해 성능 평가를 수행해요. 실제 사용을 시뮬레이션하려면 각 요청에 대해 서로 다른 입력 및 출력 길이를 지정할 수 있어요. 예를 들어 각 요청이 128개의 입력 토큰, 두 장의 720p 이미지, 1024개의 출력 토큰을 가질 수 있어요.

5.1.1 Latency-Sensitive Benchmark

  • 모델 배포 명령:
python -m sglang.launch_server \
  --model Qwen/Qwen2.5-VL-72B-Instruct \
  --tp 8 \
  --host 0.0.0.0 \
  --port 30000
  • 벤치마크 명령:
python3 -m sglang.bench_serving \
  --backend sglang-oai-chat \
  --host 127.0.0.1 \
  --port 30000 \
  --model Qwen/Qwen2.5-VL-72B-Instruct \
  --dataset-name image \
  --image-count 2 \
  --image-resolution 720p \
  --random-input-len 128 \
  --random-output-len 1024 \
  --num-prompts 10 \
  --max-concurrency 1

5.1.2 Throughput-Sensitive Benchmark

  • 모델 배포 명령:
python -m sglang.launch_server \
  --model Qwen/Qwen2.5-VL-72B-Instruct \
  --tp 8 \
  --host 0.0.0.0 \
  --port 30000
  • 결과:
============ Serving Benchmark Result ============
Backend:                                 sglang-oai-chat
Traffic request rate:                    inf
Max request concurrency:                 1
Successful requests:                     10
Benchmark duration (s):                  37.99
Total input tokens:                      24781
Total input text tokens:                 821
Total input vision tokens:               23960
Total generated tokens:                  4220
Total generated tokens (retokenized):    2365
Request throughput (req/s):              0.26
Input token throughput (tok/s):          652.26
Output token throughput (tok/s):         111.07
Peak output token throughput (tok/s):    128.00
Peak concurrent requests:                2
Total token throughput (tok/s):          763.34
Concurrency:                             1.00
----------------End-to-End Latency----------------
Mean E2E Latency (ms):                   3797.61
Median E2E Latency (ms):                 3140.90
P90 E2E Latency (ms):                    6545.54
P99 E2E Latency (ms):                    7939.56
---------------Time to First Token----------------
Mean TTFT (ms):                          504.45
Median TTFT (ms):                        510.93
P99 TTFT (ms):                           521.78
-----Time per Output Token (excl. 1st token)------
Mean TPOT (ms):                          7.82
Median TPOT (ms):                        7.82
P99 TPOT (ms):                           7.84
---------------Inter-Token Latency----------------
Mean ITL (ms):                           10.07
Median ITL (ms):                         7.90
P95 ITL (ms):                            15.79
P99 ITL (ms):                            15.93
Max ITL (ms):                            23.60
==================================================
  • 벤치마크 명령:
python3 -m sglang.bench_serving \
  --backend sglang-oai-chat \
  --host 127.0.0.1 \
  --port 30000 \
  --model Qwen/Qwen2.5-VL-72B-Instruct \
  --dataset-name image \
  --image-count 2 \
  --image-resolution 720p \
  --random-input-len 128 \
  --random-output-len 1024 \
  --num-prompts 1000 \
  --max-concurrency 100
============ Serving Benchmark Result ============
Backend:                                 sglang-oai-chat
Traffic request rate:                    inf
Max request concurrency:                 100
Successful requests:                     1000
Benchmark duration (s):                  454.68
Total input tokens:                      2481865
Total input text tokens:                 85865
Total input vision tokens:               2396000
Total generated tokens:                  510855
Total generated tokens (retokenized):    296466
Request throughput (req/s):              2.20
Input token throughput (tok/s):          5458.50
Output token throughput (tok/s):         1123.55
Peak output token throughput (tok/s):    5004.00
Peak concurrent requests:                106
Total token throughput (tok/s):          6582.05
Concurrency:                             98.63
----------------End-to-End Latency----------------
Mean E2E Latency (ms):                   44844.92
Median E2E Latency (ms):                 42866.15
P90 E2E Latency (ms):                    82798.20
P99 E2E Latency (ms):                    106306.30
---------------Time to First Token----------------
Mean TTFT (ms):                          4507.79
Median TTFT (ms):                        1180.83
P99 TTFT (ms):                           39975.22
-----Time per Output Token (excl. 1st token)------
Mean TPOT (ms):                          80.26
Median TPOT (ms):                        82.38
P99 TPOT (ms):                           152.89
---------------Inter-Token Latency----------------
Mean ITL (ms):                           100.66
Median ITL (ms):                         13.26
P95 ITL (ms):                            428.45
P99 ITL (ms):                            1393.35
Max ITL (ms):                            31943.26
==================================================

5.2 Accuracy Benchmark

5.2.1 MMMU Benchmark

MMMU 데이터셋을 사용해 모델의 정확도를 평가할 수 있어요:

  • 벤치마크 명령:
python3 benchmark/mmmu/bench_sglang.py \
    --port 30000 \
    --concurrency 64
Benchmark time: 97.75084622902796
answers saved to: ./answer_sglang.json
Evaluating...
answers saved to: ./answer_sglang.json
{'Accounting': {'acc': 0.633, 'num': 30},
 'Agriculture': {'acc': 0.5, 'num': 30},
 'Architecture_and_Engineering': {'acc': 0.367, 'num': 30},
 'Art': {'acc': 0.767, 'num': 30},
 'Art_Theory': {'acc': 0.9, 'num': 30},
 'Basic_Medical_Science': {'acc': 0.7, 'num': 30},
 'Biology': {'acc': 0.467, 'num': 30},
 'Chemistry': {'acc': 0.433, 'num': 30},
 'Clinical_Medicine': {'acc': 0.733, 'num': 30},
 'Computer_Science': {'acc': 0.567, 'num': 30},
 'Design': {'acc': 0.833, 'num': 30},
 'Diagnostics_and_Laboratory_Medicine': {'acc': 0.467, 'num': 30},
 'Economics': {'acc': 0.767, 'num': 30},
 'Electronics': {'acc': 0.433, 'num': 30},
 'Energy_and_Power': {'acc': 0.467, 'num': 30},
 'Finance': {'acc': 0.533, 'num': 30},
 'Geography': {'acc': 0.633, 'num': 30},
 'History': {'acc': 0.7, 'num': 30},
 'Literature': {'acc': 0.867, 'num': 30},
 'Manage': {'acc': 0.633, 'num': 30},
 'Marketing': {'acc': 0.733, 'num': 30},
 'Materials': {'acc': 0.333, 'num': 30},
 'Math': {'acc': 0.533, 'num': 30},
 'Mechanical_Engineering': {'acc': 0.433, 'num': 30},
 'Music': {'acc': 0.367, 'num': 30},
 'Overall': {'acc': 0.62, 'num': 900},
 'Overall-Art and Design': {'acc': 0.717, 'num': 120},
 'Overall-Business': {'acc': 0.66, 'num': 150},
 'Overall-Health and Medicine': {'acc': 0.693, 'num': 150},
 'Overall-Humanities and Social Science': {'acc': 0.775, 'num': 120},
 'Overall-Science': {'acc': 0.553, 'num': 150},
 'Overall-Tech and Engineering': {'acc': 0.443, 'num': 210},
 'Pharmacy': {'acc': 0.833, 'num': 30},
 'Physics': {'acc': 0.7, 'num': 30},
 'Psychology': {'acc': 0.767, 'num': 30},
 'Public_Health': {'acc': 0.733, 'num': 30},
 'Sociology': {'acc': 0.767, 'num': 30}}
eval out saved to ./val_sglang.json
Overall accuracy: 0.62

더 알아보기