Haru's 개발 블로그

[LLM]LLM 파일 형식 GGML & GGUF이란? 본문

머신러닝 & 딥러닝/LLM

[LLM]LLM 파일 형식 GGML & GGUF이란?

Haru_29 2024. 3. 7. 19:57

현재 LLM에서 혁신적인 파일 형식이 등장하였는데 GGML과 GGUF를 소개하고자 합니다. 

 

GGML 개요

GGML은 기계학습 분야에서 중요한 역할을 하는 텐서 라이브러리입니다. 이는 크기가 큰 모델과 다양한 하드웨어 환경에서 높은 성능을 발휘합니다.

 

장점

  • GPT 모델용 파일 형식으로 처음 시도된 사례입니다.
  • 하나의 파일로 모델을 쉽게 공유하는 것이 가능합니다.
  • 다양한 사용자가 CPU에서도 GGML 파일 실행하는 것이 가능합니다.

단점

  • 모델의 추가적인 정보를 입력하는 것이 어렵습니다.
  • 새로운 기능 추가 시 기존 모델과의 호환 문제가 생깁니다.
  • 사용자가 수동적으로 설정을 변경해야 하는 어려움이 있습니다.

GGML 유형

  • GGML_TYPE_Q2_K - 16개의 블록을 포함하는 수퍼 블록의 "유형 1" 2비트 양자화, 각 블록은 16개의 가중치를 가집니다. 블록 스케일과 최소값은 4비트로 양자화됩니다. 이는 결국 가중치당 2.5625비트(bpw)를 효과적으로 사용하게 됩니다.
  • GGML_TYPE_Q3_K - 각 블록에 16개의 가중치가 있는 16개의 블록을 포함하는 수퍼 블록의 "type-0" 3비트 양자화. 스케일은 6비트로 양자화됩니다. 이것은 3.4375bpw를 사용하게 됩니다.
  • GGML_TYPE_Q4_K - 8개의 블록을 포함하는 수퍼 블록의 "유형 1" 4비트 양자화, 각 블록에는 32개의 가중치가 있습니다. 스케일과 최소값은 6비트로 양자화됩니다. 이것은 4.5bpw를 사용하여 끝납니다.
  • GGML_TYPE_Q5_K - "유형 1" 5비트 양자화. GGML_TYPE_Q4_K와 동일한 슈퍼 블록 구조로 5.5bpw
  • GGML_TYPE_Q6_K - "type-0" 6비트 양자화. 16개의 블록이 있는 슈퍼 블록, 각 블록에는 16개의 가중치가 있습니다. 스케일은 8비트로 양자화됩니다. 이것은 6.5625bpw를 사용하여 끝납니다.
  • GGML_TYPE_Q8_K - "type-0" 8비트 양자화. 중간 결과를 양자화하는 데만 사용됩니다. 기존 Q8_0과의 차이점은 블록 크기가 256이라는 것입니다. 이 양자화 유형에 대해 모든 2-6비트 내적이 구현됩니다.

이는 다음과 같이 다양한 "양자화 혼합"을 정의하는 llama.cpp 양자화 유형을 통해 노출됩니다.

  • LLAMA_FTYPE_MOSTLY_Q2_K -tention.vw 및 feed_forward.w2 텐서에는 GGML_TYPE_Q4_K를 사용하고 다른 텐서에는 GGML_TYPE_Q2_K를 사용합니다.
  • LLAMA_FTYPE_MOSTLY_Q3_K_S - 모든 텐서에 GGML_TYPE_Q3_K 사용
  • LLAMA_FTYPE_MOSTLY_Q3_K_M -tention.wv,tention.wo 및 feed_forward.w2 텐서에 GGML_TYPE_Q4_K를 사용하고 그렇지 않으면 GGML_TYPE_Q3_K를 사용합니다.
  • LLAMA_FTYPE_MOSTLY_Q3_K_L -tention.wv,tention.wo 및 feed_forward.w2 텐서에 GGML_TYPE_Q5_K를 사용하고 그렇지 않으면 GGML_TYPE_Q3_K를 사용합니다.
  • LLAMA_FTYPE_MOSTLY_Q4_K_S - 모든 텐서에 GGML_TYPE_Q4_K 사용
  • LLAMA_FTYPE_MOSTLY_Q4_K_M -tention.wv 및 feed_forward.w2 텐서의 절반에 대해 GGML_TYPE_Q6_K를 사용하고 그렇지 않으면 GGML_TYPE_Q4_K를 사용합니다.
  • LLAMA_FTYPE_MOSTLY_Q5_K_S - 모든 텐서에 GGML_TYPE_Q5_K 사용
  • LLAMA_FTYPE_MOSTLY_Q5_K_M -tention.wv 및 feed_forward.w2 텐서의 절반에 대해 GGML_TYPE_Q6_K를 사용하고 그렇지 않으면 GGML_TYPE_Q5_K를 사용합니다.
  • LLAMA_FTYPE_MOSTLY_Q6_K- 모든 텐서에 대해 6비트 양자화(GGML_TYPE_Q8_K) 사용

위에서 명시적으로 언급되지 않은 것은 이 PR을 사용하면 모든 양자화 변형이 output.weight 텐서에 6비트 양자화를 사용한다는 사실입니다. 이는 예를 들어 Q4_0의 perplexity를 7B에서 약 0.03만큼 낮춥니다.

유의사항, GGML 파일 유형은 언제든 변경이 될 수 있으므로 확인 필수!입니다.

 

GGUF 소개

GGUF는 2023년 8월에 나온 새로운 파일 형식인데 대형 모델 언어(LLM)에서 저장과 처리에 큰 발전을 이루었습니다.

  • 새로운 기능을 추가하여도 기존 모델과의 호환성을 가집니다.
  • 새로운 버전으로 전환이 용이합니다.
  • Llama 모델을 포함하여 다양한 모델을 제공합니다.

GGUF 구조

llm에서 GGUF는 단일 파일이기 때문에 모델의 Weight 값과 메타데이터가 들어있는 Key-Value 형식으로 저장되어 있습니다.

여기서 다른 ML라이브러리와는 다르게 8-bit, 6-bit, 5-bit, 4-bit, 3-bit 그리고 2-bit 양자 텐서타입까지 지원을 하고 있습니다.(다만, 언제 업데이트 되는지는 모르기 때문에 항시 체크하는 것이 좋습니다.)

저는 주로 llama.cpp 를 자주 사용하는데 여기서는 다양한 모델들을 양자화 변환을 하여 GGUF 파일로 제공합니다.

 

GGUF 파일에는 두 가지 정보가 기록되어 있습니다.

 

1. 모델의 Weight Tensor 값과 텐서 정보

  • Tensor의 이름
  • Tensor의 차원 수
  • Tensor의 Shape
  • Tensor의 데이터 타입
  • Tensor 데이터가 위치한 Offset

2. Key-Value 형식의 메타데이터

Key는 ASCII 문자와 '.'으로 계층을 표시합니다.

예를 들어 llama.attention.head_count_kv로 표현이 가능합니다.

 

먼저 모델의 세부 정보들을 포함 시켜야 합니다.

  • 입력 토큰 길이
  • 임베딩 크기
  • 피드 포워드 길이

여기에 더해서 Tokenizer 정보도 포함시켜야 합니다.

  • bos token id
  • eos token id
  • uknown token id
  • seperate token id
  • padding token id
  • Vocab 파일

이외에도 추론기에 이 값을 활용하는 기능이나 필요한 정보가 있다면 구현이 되어있어야 합니다.

magic                                   =  0x46554747
version                                 =  3
tensor_count                            =  291
metadata_kv_count                       =  16
general.architecture                    =  llama
general.name                            =  LLaMA
llama.context_length                    =  2048
llama.embedding_length                  =  4096
llama.block_count                       =  32
llama.feed_forward_length               =  11008
llama.rope.dimension_count              =  128
llama.attention.head_count              =  32
llama.attention.head_count_kv           =  32
llama.attention.layer_norm_rms_epsilon  =  9.999999974752427e-07
general.file_type                       =  10
tokenizer.ggml.model                    =  llama
tokenizer.ggml.tokens                   =  ['<unk>', '<s>', '</s>', '<0x00>', '<0x01>', '<...
tokenizer.ggml.scores                   =  [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0...
tokenizer.ggml.token_type               =  [2, 3, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6...
general.quantization_version            =  2

 

여기서 GGUF는 크게 세 분류로 나뉘어 지는데 1) Header 2) Tensor Info 3) Tensor Data Header에 메타데이터가 저장되어 있습니다. 그리고 Tensor Info와 Tensor Data 부분에 모델의 Weight Tensor 정보가 기록되어 있습니다.

GGUF - Header
GGUF - Tensor Info (Tensor Data는 이진수이기에 생략)

 

다음 장에서는 추론기로  많이 사용하는 llama.cpp 실행 방법에 알아보도록 하겠습니다.

Comments