DeepSeek V3

DeepSeek V3

이 문서는 DeepSeek이 개발한 대규모 Mixture-of-Experts(MoE) 언어 모델인 DeepSeek V3를 SGLang으로 배포하고 호출하는 방법을 설명해요. 강력한 범용 추론, 코딩, 도구 보강 능력과 함께 높은 훈련·추론 효율을 제공해요. 원문 페이지에는 하드웨어 플랫폼과 배포 전략을 골라 명령을 자동 생성해 주는 대화형 선택기가 포함되어 있어요.

출처: 문서

본문

1. 모델 소개

DeepSeek V3는 DeepSeek이 개발한 대규모 Mixture-of-Experts(MoE) 언어 모델로, 높은 훈련·추론 효율로 강력한 범용 추론, 코딩, 도구 보강 능력을 제공하도록 설계되었어요. DeepSeek 모델 계열의 최신 세대로서, DeepSeek V3는 체계적인 아키텍처와 훈련 혁신을 도입해 경쟁력 있는 연산 비용을 유지하면서도 추론, 수학, 코딩, 장문 맥락 이해 전반의 성능을 크게 개선했어요.

주요 하이라이트는 다음과 같아요:

  • 효율적인 MoE 아키텍처 (Efficient MoE architecture): DeepSeek V3는 많은 수의 전문가와 희소 활성화를 사용하는 세분화된 Mixture-of-Experts 설계를 채택해, 추론·훈련 비용을 감당할 수 있는 수준으로 유지하면서도 높은 모델 용량을 제공해요.
  • 고급 추론 및 코딩 (Advanced reasoning and coding): 이 모델은 개선된 데이터 큐레이션과 훈련 전략 덕분에 수학적 추론, 논리 추론, 실제 코딩 벤치마크에서 강력한 성능을 보여줘요.
  • 장문 맥락 능력 (Long-context capability): DeepSeek V3는 확장된 컨텍스트 길이를 지원해 긴 문서, 복잡한 다단계 추론, 에이전트 스타일 워크플로우를 더 효과적으로 처리할 수 있어요.
  • 도구 사용 및 함수 호출 (Tool use and function calling): 이 모델은 구조화된 출력과 도구 호출을 지원하도록 훈련되어, 추론 중 외부 도구 및 에이전트 프레임워크와의 원활한 통합을 가능하게 해요.

2. SGLang 설치

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

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

SGLang CPU 설치는 CPU 버전 설치 가이드를 참고하세요.

3. 모델 배포

이 섹션은 빠른 배포에서 성능 최적화까지 이어지는 점진적인 가이드를 제공하며, 다양한 수준의 사용자에게 적합해요.

3.1 기본 설정

대화형 명령 생성기 (Interactive Command Generator): 아래 설정 선택기를 사용해 하드웨어 플랫폼, 모델 변형, 배포 전략, 사고 능력에 맞는 배포 명령을 자동으로 생성할 수 있어요. (대화형 위젯은 원문 페이지에서 동작하므로, 기본 설정 기준 명령은 다음과 같아요.)

python -m sglang.launch_server \
  --model-path deepseek-ai/DeepSeek-V3 \
  --tp 8

3.2 설정 팁

가중치 유형별 권장 GPU 설정:

가중치 유형 지원 하드웨어
FP8 (권장) 8× H200, 8× B200, 8× MI300X, 2×8× H100/H800/H20
BF16 (FP8에서 upcast) 2×8× H200, 2×8× MI300X, 4×8× H100/H800, 4×8× A100/A800
INT8 16× A100/A800, 32× L40S, Xeon 6980P CPU, 4× Ascend A3 Series
W4A8 / AWQ / MXFP4 / NVFP4 8× H20/H100, 4× H200; 8× H100/A100; 8/4× MI355X/MI350X; 8/4× B200

공식 DeepSeek-V3 체크포인트는 이미 FP8 형식이에요 — 서빙할 때 --quantization fp8추가하지 마세요.

DeepGEMM 사전 컴파일 (NVIDIA Hopper / Blackwell): 첫 서버 실행 전에 GEMM 커널을 사전 컴파일해 JIT 오버헤드(약 10분)를 피하세요:

python3 -m sglang.compile_deep_gemm --model deepseek-ai/DeepSeek-V3 --tp 8 --trust-remote-code

DeepGEMM은 Hopper/Blackwell에서 기본적으로 활성화되며 SGLANG_ENABLE_JIT_DEEPGEMM=0으로 비활성화할 수 있어요.

데이터 병렬화 어텐션 (--enable-dp-attention): 큰 배치 크기의 높은 처리량 시나리오에 권장돼요. TP 랭크 간 KV-cache 중복을 줄여줘요. 단일 8-GPU 노드에서는 --enable-dp-attention --tp 8 --dp 8을 사용하세요. 저지연·소배치 워크로드에는 권장되지 않아요.

NCCL 타임아웃: 모델 로딩이 느리고 NCCL 타임아웃이 발생하면 늘리세요: --dist-timeout 3600.

Xeon CPU 서비스 설정: SGLang CPU 서버 문서의 서빙 엔진 실행 부분에 있는 Notes 항목을 참고해 인자, 특히 TP(텐서 병렬) 및 NUMA 바인딩 설정을 이해하세요.

4. 모델 호출

4.1 기본 사용법

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

4.2 고급 사용법

4.2.1 추론 파서 (Reasoning Parser)

DeepSeek-V3는 추론 모드를 지원해요. 배포 중 reasoning parser를 활성화해 thinking 섹션과 content 섹션을 분리하세요:

python -m sglang.launch_server \
  --model deepseek-ai/DeepSeek-V3 \
  --reasoning-parser deepseek-v3 \
  --tp 8

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

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="deepseek-ai/DeepSeek-V3",
    messages=[
        {"role": "user", "content": "Solve this problem step by step: What is 15% of 240?"}
    ],
    temperature=0.7,
    max_tokens=2048,
    extra_body = {"chat_template_kwargs": {"thinking": True}},
    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()

출력 예시:

=============== Thinking =================
To determine 15% of a number, follow these steps:

**Step 1: Understand the Problem**
You need to find 15% of a given number. Let's assume the number is 240 for this example.

**Step 2: Convert the Percentage to a Decimal**
To work with percentages in calculations, convert the percentage to its decimal form. To do this, divide the percentage by 100.

\[ 15\% = \frac{15}{100} = 0.15 \]

**Step 3: Multiply the Decimal by the Number**
Now, multiply the decimal form of the percentage by the number you want to find the percentage of.

\[ 0.15 \times 240 \]

**Step 4: Perform the Multiplication**
Calculate the product:

\[ 0.15 \times 240 = 36 \]

**Step 5: Conclusion**
Therefore, 15% of 240 is:

\boxed{36}

The answer is 36. To find 15% of 240, we multiply 240 by 0.15, which equals 36.

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

4.2.2 도구 호출 (Tool Calling)

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

배포 명령:

python -m sglang.launch_server \
  --model deepseek-ai/DeepSeek-V3 \
  --tool-call-parser deepseekv3 \
  --reasoning-parser deepseek-v3 \
  --chat-template ./examples/chat_template/tool_chat_template_deepseekv3.jinja \
  --tp 8 \
  --host 0.0.0.0 \
  --port 30000

빠른 테스트 (curl):

curl "http://127.0.0.1:30000/v1/chat/completions" \
  -H "Content-Type: application/json" \
  -d '{
    "temperature": 0,
    "max_tokens": 100,
    "model": "deepseek-ai/DeepSeek-V3",
    "tools": [{"type": "function", "function": {"name": "query_weather", "description": "Get weather of a city", "parameters": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]}}}],
    "messages": [{"role": "user", "content": "How's the weather in Beijing today?"}]
  }'

낮은 temperature(예: 0)를 사용하면 더 일관된 도구 호출 결과를 얻을 수 있어요. 위의 --chat-template 플래그는 도구 사용을 위한 개선된 통합 프롬프트를 제공해요.

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="deepseek-ai/DeepSeek-V3",
    messages=[
        {"role": "user", "content": "What's the weather in Beijing?"}
    ],
    tools=tools,
    extra_body = {"chat_template_kwargs": {"thinking": True}},
    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()

출력 예시:

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

참고:

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

도구 호출 결과 처리:

아래 코드 블록을 이전 Python 스크립트에 붙이세요.

# 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="deepseek-ai/DeepSeek-V3",
    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.3 다중 토큰 예측 (Multi-Token Prediction, EAGLE 추측 디코딩)

SGLang은 EAGLE speculative decoding을 기반으로 DeepSeek V3 Multi-Token Prediction(MTP)을 구현해요. 이 최적화 덕분에 H200 TP8에서 배치 크기 1일 때 디코딩 속도가 최대 1.8배, 배치 크기 32일 때 1.5배 향상돼요.

활성화 방법:

python3 -m sglang.launch_server \
  --model-path deepseek-ai/DeepSeek-V3-0324 \
  --speculative-algorithm EAGLE \
  --trust-remote-code \
  --tp 8

기본 설정은 --speculative-num-steps 3 --speculative-eagle-topk 1 --speculative-num-draft-tokens 4이에요. bench_speculative.py로 워크로드에 가장 좋은 값을 찾으세요. 최소 실행 가능 설정은 --speculative-num-steps 1 --speculative-eagle-topk 1 --speculative-num-draft-tokens 2이에요.

큰 배치 크기(>48)의 경우 MTP에 대해 --max-running-requests를 기본값 48보다 늘리세요. 또한 --cuda-graph-bs-decode를 설정해 대상 배치 크기를 포함하세요(추측 디코딩의 기본 캡처 크기: 48).

spec-v2 overlap 스케줄러는 기본적으로 활성화돼요. 이는 draft 단계와 verification 단계를 겹쳐 성능을 개선해요. 비활성화하려면 --disable-overlap-schedule을 전달하세요.

4.2.4 MLA 최적화

DeepSeek V3는 추론 효율을 개선하는 어텐션 메커니즘인 Multi-head Latent Attention (MLA)를 사용해요. SGLang은 여러 최적화를 구현해요:

  • Weight Absorption: 디코딩 단계 효율을 개선하기 위해 행렬 곱셈 순서를 재정렬해요.
  • MLA Attention Backends: FA3, Flashinfer, FlashMLA, TRTLLM MLA (Blackwell), Triton. FA3가 기본이에요.
  • FP8 Quantization: W8A8 FP8과 KV Cache FP8, 그리고 FP8에서 weight-absorbed MLA를 위한 BMM 연산자.
  • CUDA Graph & Torch.compile: MLA와 MoE 모두 CUDA Graph와 Torch.compile을 지원해 디코딩 지연 시간을 줄여요.
  • Chunked Prefix Cache: 장문 시퀀스 chunked prefill의 처리량을 높여요 (FlashAttention3 backend 전용).

전반적으로 이러한 최적화는 기준선 대비 최대 7배의 출력 처리량 개선을 달성해요.

참고: 자세한 내용은 SGLang v0.3 블로그슬라이드를 참고하세요.

4.2.5 다중 노드 배포

다중 노드 서빙 및 하드웨어별 예시는 다음을 참고하세요:

대규모 배포를 위한 블로그 참고 자료:

5. 벤치마크

5.1 속도 벤치마크

테스트 환경:

  • 하드웨어: AMD MI300X GPU (8x)
  • 모델: DeepSeek-V3
  • 텐서 병렬화(Tensor Parallelism): 8
  • sglang 버전: 0.5.7

ShareGPT_Vicuna_unfiltered 데이터셋에 대해 SGLang 내장 벤치마킹 도구로 성능 평가를 수행했어요. 이 데이터셋은 실제 대화 데이터를 포함해 실제 사용 시나리오의 성능을 더 잘 반영해요. 실제 사용 패턴을 시뮬레이션하기 위해 각 요청을 1024개의 입력 토큰과 1024개의 출력 토큰으로 구성했어요.

5.1.1 지연 시간 민감 벤치마크

  • 모델 배포 명령:
python3 -m sglang.launch_server \
  --model-path deepseek-ai/DeepSeek-V3 \
  --tp 8 \
  --dp 8 \
  --enable-dp-attention \
  --speculative-algorithm EAGLE \
  --speculative-num-steps 3 \
  --speculative-eagle-topk 1 \
  --speculative-num-draft-tokens 4 \
  --host 0.0.0.0 \
  --port 8000
  • 벤치마크 명령:
python3 -m sglang.bench_serving \
  --backend sglang \
  --host 127.0.0.1 \
  --port 8000 \
  --model deepseek-ai/DeepSeek-V3 \
  --random-input-len 1024 \
  --random-output-len 1024 \
  --num-prompts 10 \
  --max-concurrency 1
  • 테스트 결과:
============ Serving Benchmark Result ============
Backend:                                 sglang
Traffic request rate:                    inf
Max request concurrency:                 1
Successful requests:                     10
Benchmark duration (s):                  81.27
Total input tokens:                      1972
Total input text tokens:                 1972
Total input vision tokens:               0
Total generated tokens:                  2784
Total generated tokens (retokenized):    2774
Request throughput (req/s):              0.12
Input token throughput (tok/s):          24.27
Output token throughput (tok/s):         34.26
Peak output token throughput (tok/s):    65.00
Peak concurrent requests:                2
Total token throughput (tok/s):          58.52
Concurrency:                             1.00
Accept length:                           2.61
----------------End-to-End Latency----------------
Mean E2E Latency (ms):                   8123.17
Median E2E Latency (ms):                 7982.65
---------------Time to First Token----------------
Mean TTFT (ms):                          1080.76
Median TTFT (ms):                        1248.82
P99 TTFT (ms):                           1896.37
-----Time per Output Token (excl. 1st token)------
Mean TPOT (ms):                          25.04
Median TPOT (ms):                        24.76
P99 TPOT (ms):                           32.09
---------------Inter-Token Latency----------------
Mean ITL (ms):                           25.41
Median ITL (ms):                         20.14
P95 ITL (ms):                            60.28
P99 ITL (ms):                            60.99
Max ITL (ms):                            61.49
==================================================

5.1.2 처리량 민감 벤치마크

  • 모델 배포 명령:
python3 -m sglang.launch_server \
  --model-path deepseek-ai/DeepSeek-V3 \
  --tp 8 \
  --ep 8 \
  --dp 8 \
  --enable-dp-attention \
  --host 0.0.0.0 \
  --port 8000
  • 벤치마크 명령:
python3 -m sglang.bench_serving \
  --backend sglang \
  --host 127.0.0.1 \
  --port 8000 \
  --model deepseek-ai/DeepSeek-V3 \
  --random-input-len 1024 \
  --random-output-len 1024 \
  --num-prompts 1000 \
  --max-concurrency 100
  • 테스트 결과:
============ Serving Benchmark Result ============
Backend:                                 sglang
Traffic request rate:                    inf
Max request concurrency:                 100
Successful requests:                     1000
Benchmark duration (s):                  406.16
Total input tokens:                      301701
Total input text tokens:                 301701
Total input vision tokens:               0
Total generated tokens:                  188375
Total generated tokens (retokenized):    187542
Request throughput (req/s):              2.46
Input token throughput (tok/s):          742.81
Output token throughput (tok/s):         463.80
Peak output token throughput (tok/s):    1299.00
Peak concurrent requests:                109
Total token throughput (tok/s):          1206.61
Concurrency:                             87.53
----------------End-to-End Latency----------------
Mean E2E Latency (ms):                   35552.98
Median E2E Latency (ms):                 21466.07
---------------Time to First Token----------------
Mean TTFT (ms):                          1521.51
Median TTFT (ms):                        476.80
P99 TTFT (ms):                           8329.50
-----Time per Output Token (excl. 1st token)------
Mean TPOT (ms):                          214.73
Median TPOT (ms):                        152.00
P99 TPOT (ms):                           1155.85
---------------Inter-Token Latency----------------
Mean ITL (ms):                           182.10
Median ITL (ms):                         79.18
P95 ITL (ms):                            398.60
P99 ITL (ms):                            1488.96
Max ITL (ms):                            43465.60
==================================================

5.2 정확도 벤치마크

5.2.1 GSM8K 벤치마크

  • 벤치마크 명령:
python3 -m sglang.test.few_shot_gsm8k --num-questions 200 --port 8000
  • 테스트 결과:
    • DeepSeek-V3
      Accuracy: 0.960
      Invalid: 0.000
      Latency: 32.450 s
      Output throughput: 614.211 token/s
      

5.2.2 MMLU 벤치마크

  • 벤치마크 명령:
cd sglang
bash benchmark/mmlu/download_data.sh
python3 benchmark/mmlu/bench_sglang.py --nsub 10 --port 8000
  • 테스트 결과:
    • DeepSeek-V3
      subject: abstract_algebra, #q:100, acc: 0.800
      subject: anatomy, #q:135, acc: 0.874
      subject: astronomy, #q:152, acc: 0.928
      subject: business_ethics, #q:100, acc: 0.880
      subject: clinical_knowledge, #q:265, acc: 0.928
      subject: college_biology, #q:144, acc: 0.965
      subject: college_chemistry, #q:100, acc: 0.670
      subject: college_computer_science, #q:100, acc: 0.840
      subject: college_mathematics, #q:100, acc: 0.800
      subject: college_medicine, #q:173, acc: 0.861
      Total latency: 58.339
      Average accuracy: 0.871