Hugging Face Transformers GGUF 지원

Hugging Face는 transformers 라이브러리에 GGUF (GPT-Generated Unified Format) 모델 지원을 통합하여, 사용자가 원래 llama.cpp용으로 설계된 양자화된 체크포인트를 익숙한 PyTorch 및 Transformers API를 사용하여 로드하고 실행할 수 있도록 했습니다. 이 통합을 통해 기본 ggml 커널을 활용하여 전용 로컬 추론 엔진에 가까운 성능을 유지하면서 Apple Silicon에서 효율적인 로컬 추론이 가능해졌습니다.

GGUF 형식 및 양자화

GGUF는 llama.cpp 팀이 개발한 파일 형식으로, 모델 가중치, 토크나이저 정보, 선택적 채팅 템플릿을 단일 파일로 패키징합니다. 주요 장점은 다양한 양자화 수준을 지원한다는 점이며, 이를 통해 사용자는 정밀도를 일부 희생하는 대신 모델의 메모리 사용량을 줄일 수 있습니다.

예를 들어, Unsloth의 Qwen3.5-4B 모델을 사용할 경우 메모리 요구 사항은 양자화 변형에 따라 다음과 같이 달라집니다:

GGUF 변형 파일 크기 트레이드오프
BF16 8.42 GB 비양자화 참조
Q6_K 3.53 GB 높은 정밀도
Q5_K_M 3.14 GB 크기와 정밀도의 균형
Q4_K_M 2.74 GB 로컬 추론을 위한 실용적인 시작점

기술적 구현: ggml 커널 및 생성 루프

llama.cpp와 유사한 성능 수준을 달성하기 위해 Hugging Face는 ggml 커널 재사용과 generate 루프 간소화라는 두 가지 주요 기술적 최적화를 구현했습니다.

ggml Metal 커널 통합

transformers는 모델을 별도의 런타임으로 교체하는 대신 kernels 라이브러리를 사용하여 PyTorch에서 직접 호환되는 ggml Metal 커널을 호출합니다. 이를 통해 무거운 연산은 특수 GPU 프로그램이 처리하는 동안 모델은 Python 상태를 유지할 수 있습니다:

  • ggml-quantization: 행렬 연산을 위해 패킹된 양자화 가중치를 읽어, 각 디코드 연산 전에 가중치 행렬을 확장할 필요가 없습니다.
  • ggml-norm: Qwen3.5 및 Qwen3.8에서 사용되는 제로 중심 RMSNorm을 포함한 정규화 연산을 통합합니다.
  • ggml-attn: 프롬프트 처리 및 토큰 디코딩 모두를 위해 ggml의 Metal 플래시 어텐션을 구현합니다.
  • ggml-gated-delta-net: Qwen3.5 및 Qwen3.8 하이브리드 아키텍처의 선형 어텐션 레이어를 가속화합니다.
  • topk: MoE(Mixture-of-Experts) 모델에서 전문가 선택을 최적화하기 위한 맞춤형 Metal 구현입니다.

생성 루프 최적화

Hugging Face는 GPU가 계속해서 가동되도록 generate 함수에서 CPU-GPU 동기화 오버헤드를 줄였습니다. 두 가지 주요 변경 사항이 도입되었습니다:

  1. 어텐션 마스크 최적화: 패딩이 없는 디코더 전용 입력의 경우, 생성 시작 시 모든 값이 1인 패딩 마스크를 제거하여 어텐션 코드가 마스크를 반복적으로 검사하는 것을 방지합니다.
  2. 지연된 중단 검사: 중단 결정이 비동기적으로 복사되어, GPU가 현재 단계를 실행하는 동안 CPU가 작업을 계속 예약할 수 있도록 합니다.

성능 및 벤치마크

MacBook Pro M2 Max (32 GB 통합 메모리)에서 수행된 벤치마크에서 transformers는 소형 밀집 모델, 대형 밀집 모델, MoE 모델 전반에 걸쳐 llama.cpp에 근접한 처리량을 보여주었습니다. 특히 transformers 측정값에는 프리필(prefill)이 포함되었으며, llama.cpp의 llama-bench 결과는 디코드 전용 처리량에 초점을 맞추었습니다.

사용 및 배포

GGUF 모델 로드

사용자는 from_pretrained에서 gguf_file 매개변수를 사용하여 Hugging Face Hub에서 GGUF 모델을 로드할 수 있습니다:

import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

model_id = "unsloth/Qwen3.5-4B-GGUF"
filename = "Qwen3.5-4B-Q4_K_M.gguf"

tokenizer = AutoTokenizer.from_pretrained(model_id, gguf_file=filename)
model = AutoModelForCausalLM.from_pretrained(model_id, gguf_file=filename)

OpenAI 호환 API를 통한 서빙

모델은 transformers serve CLI를 사용하여 서빙할 수 있으며, 이는 Jan이나 Pi와 같은 클라이언트와의 통합을 위해 OpenAI 호환 API를 노출합니다:

pip install -U "transformers[serving] @ git+https://github.com/huggingface/transformers.git" kernels

transformers serve "unsloth/Qwen3.5-4B-GGUF:Qwen3.5-4B-Q4_K_M.gguf"

전략적 의미 및 제한 사항

순수 로컬 추론 효율성 측면에서는 llama.cpp가 여전히 권장되는 엔진이지만, 이번 통합을 통해 개발자는 다음과 같은 작업을 위해 PyTorch 생태계 내에서 GGUF 체크포인트를 사용할 수 있습니다:

  • 프로토타이핑: 훅(hook)을 사용하여 중간 활성화 값을 검사하거나 순전파(forward pass)를 수정.
  • 평가: 기존 transformers 워크플로우를 사용하여 양자화된 모델 품질 측정.
  • 검증: 원본 체크포인트와 GGUF 변환본을 비교하여 양자화 오류 확인.
  • 파인튜닝: GgufConfig(dequantize=True)를 통해 가중치를 역양자화하여 표준 학습 워크플로우 계속 진행.

현재 제한 사항

  • 하드웨어: 패킹된 추론 경로는 현재 MPS(Apple Silicon)로 제한됩니다.
  • 배칭: 패딩된 배치는 현재 성능이 낮으며, MPS에서 generate_batch에 대한 최적화가 진행 중입니다.
  • 아키텍처: 초기 지원은 Qwen3.5 밀집 및 MoE 아키텍처(Qwen3.8 포함)로 제한됩니다.

향후 전망

Hugging Face는 현재 llama.cpp에서 지원하지 않는 아키텍처에도 ggml의 성능을 제공하는 것을 목표로 합니다. ggml 커널을 PyTorch에 통합함으로써 transformers는 새로운 아키텍처마다 전체 llama.cpp 구현을 요구하지 않고도 새로운 연구 모델과 맞춤형 변형 모델을 가속화할 수 있게 될 것입니다.

Sources