Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Ollama 벤치마크

온프레미스로 띄운 사후 훈련 모델이 실제 과제를 얼마나 잘 푸는지는 벤치마크로 잽니다. Ollama API를 그대로 활용해 서버에 문항을 하나씩 POST /api/chat으로 보내 채점하면, 추가 라이브러리 없이 로컬 모델의 외재적 성능을 바로 확인할 수 있습니다. Qwen3·Gemma 같은 최신 모델은 추론(thinking)이 기본으로 켜져 있어 답하기 전에 생각을 전개하는데, 이 생각 과정이 점수를 크게 좌우하므로 끄지 않습니다 — 끄면 특히 수학·과학에서 성능이 급락합니다. 긴 추론이 잘리지 않도록 문맥 길이(num_ctx)를 넉넉히 줍니다.

import os, re, requests
from datasets import load_dataset

OLLAMA_BASE_URL = os.environ.get("OLLAMA_HOST", "http://localhost:11434")

def 풀이_요청(모델, 질문, 문맥=32768, 생성=24576):
    옵션 = {"num_ctx": 문맥, "num_predict": 생성, "seed": 0}
    답 = requests.post(f"{OLLAMA_BASE_URL}/api/chat",
                       json={"model": 모델,
                             "messages": [{"role": "user", "content": 질문}],
                             "stream": False, "options": 옵션},
                       timeout=1200).json()["message"]
    return 답.get("thinking", ""), 답.get("content", "")        # 추론 과정, 최종 답

think 인자를 따로 주지 않으면 모델의 기본값(추론 켜짐)을 따릅니다. 응답에서 추론은 thinking, 최종 답은 content로 분리되어 오므로, 답만 골라 채점하기 쉽습니다.

GSM8K(초등 수준 수리)로 채점하는 예입니다.

데이터 = load_dataset("gsm8k", "main", split="test").select(range(30))

def 정수(글):
    숫자 = re.findall(r"-?\d+", 글.replace(",", ""))
    return 숫자[-1] if 숫자 else None

맞힘 = 0
for 문항 in 데이터:
    정답 = 정수(문항["answer"].split("####")[-1])
    _, 최종답 = 풀이_요청("qwen3:latest",
                          문항["question"] + "\n\n최종 정수 답을 '#### ' 뒤에 적으세요.")
    맞힘 += (정수(최종답) == 정답)

print(f"{맞힘} / {len(데이터)}")
30 / 30

같은 방식을 더 어려운 벤치마크와 다른 모델에도 적용해, 두 계열의 소형 사후 훈련 모델을 비교합니다.

벤치마크 (난이도)qwen3:latestgemma4:e4b
GSM8K — 초등 수리100%100%
GPQA-Diamond — 전문가급 과학40%53%
AIME 2025 — 경시 수학60%36%

(GSM8K 15문항, GPQA·AIME 각 30문항, Ollama 양자화 모델, 추론 켜짐, seed 고정 — 절대 수치보다 경향을 봅니다.)

세 가지가 드러납니다. 첫째, GSM8K는 포화됐습니다 — 두 모델 모두 만점이어서 변별이 되지 않습니다. 요즘 모델에는 너무 쉬워, 상위권을 가르려면 GPQA·AIME 같은 더 어려운 과제가 필요합니다. 둘째, 과제 성격에 따라 강자가 갈립니다 — Gemma는 전문가급 과학 추론(GPQA)에서, Qwen은 경시 수학(AIME)에서 앞섭니다. '어느 모델이 더 낫다’는 단일 점수로 답할 수 없고, 쓰려는 과제에 맞춰 골라야 합니다. 셋째, 추론에 들인 시간이 성능과 맞닿습니다 — AIME에서 Qwen은 문항당 평균 130초를 생각해 60%를 맞혔고, Gemma는 48초로 36%였습니다. 어려운 문제일수록 더 길게 생각하는 모델이 유리합니다.

1규모를 키우면 — 매개변수와 벤치마크

같은 계열에서 매개변수 수를 키우며 GPQA-Diamond를 재 보면, 규모가 능력으로 이어지는 모습을 볼 수 있습니다.

계열모델(크기 증가순)정확도
Qwen30.6B20%
1.7B20%
4B80%
8B (qwen3:latest)50%
Gemmae2b30%
e4b55%
12b70%
26b75%
31b80%

(각 20문항, 모든 모델이 같은 문항, 추론 켜짐, Ollama 양자화.)

두 가지가 보입니다. 첫째, 작은 모델(약 2B 이하)은 GPQA에서 무작위(25%) 수준에 머뭅니다 — 전문가급 과학 추론은 일정 규모를 넘어서야 풀리기 시작합니다. 규모가 커지면 정답률이 뚜렷이 올라, Gemma 계열은 30% → 55% → 70% → 75% → 80%로 다섯 단계에 걸쳐 일관되게 증가합니다. 둘째, 곡선이 늘 매끄럽지는 않습니다 — Qwen3는 4B에서 80%로 치솟지만 8B에서 50%로 도로 내려갑니다. 같은 20문항을 풀었는데도 이런 역전이 나오는 건 표본이 20개로 작아 분산이 크기 때문입니다(한 문항이 5%p). 신뢰할 수 있는 규모 곡선을 그리려면 수백~수천 문항이 필요하며, 이렇게 작은 표본의 절대 수치는 경향의 참고로만 봐야 합니다.

규모와 손실(perplexity)의 매끄러운 거듭제곱 관계는 더 큰 표본으로 규모의 법칙 장에서 다룹니다.

2같은 점수, 다른 비용 — 속도와 메모리

품질만 보면 큰 모델을 고르면 그만이지만, 로컬 서빙에서는 속도와 메모리가 똑같이 중요합니다. 앞의 GPQA 점수에 같은 RTX 3090에서 잰 디코드 속도와 VRAM 점유를 나란히 놓으면, 비용의 축이 드러납니다.

모델구조디코드(tok/s)VRAM(GB)GPQA
e2b탄력적 (effective ~2B)871.830%
e4b탄력적 (effective ~4B)1283.355%
12b밀집 (dense)318.170%
26bMoE (전문가 128개 중 8개 활성)12317.475%
31b밀집 (dense)3720.380%

(디코드 속도 = 생성 토큰 수 ÷ 생성 시간, Ollama 양자화(Q4_K_M), VRAM은 /api/ps의 적재량. 단발 측정이라 경향으로 봅니다.)

속도가 크기 순서를 따르지 않는 점이 눈에 띕니다 — e4b(128)와 26b(123)가 빠르고, 그 사이의 12b(31)는 오히려 느립니다. gemma4 계열이 세 가지 아키텍처를 섞어 쓰기 때문입니다.

핵심은 디코드 속도는 토큰마다 실제로 계산하는 활성(active) 매개변수에, VRAM은 적재해야 하는 전체(total) 매개변수에 좌우된다는 점입니다. MoE인 26b가 그 둘을 분리한 전형입니다 — 4B만큼만 계산해 빠르지만, 전문가 전체를 메모리에 올려야 해 17GB를 씁니다. 따라서 모델 선택은 단일 점수가 아니라 품질·속도·메모리의 삼각 절충입니다 — 에지·실시간이면 e4b, 품질이 최우선이면 31b, 둘의 균형점이면 MoE인 26b가 후보입니다.