빅웨이브에이아이 기술블로그

Mergekit, LLM을 한번 합쳐보자! 본문

기술 블로그

Mergekit, LLM을 한번 합쳐보자!

빅웨이브 이현상 2024. 2. 21. 17:55
빅웨이브 이현상 님이 작성한 기술 리뷰입니다.

Mergekit?

  • LLM을 합칠 수 있는 툴킷
  • 주소 링크
  • GitHub - arcee-ai/mergekit: Tools for merging pretrained large language models.
  • 특징
    1. LLAMA, MISTRAL, GPT-NeoX, StableLM 등 지원
    2. Linear, SLERP, Task Arithmetic 등 다양한 병합 방법 사용 가능
    3. VRAM 8GB 수준의 GPU 가속화 가능
    4. 텐서 지연 로딩으로 메모리 사용 낮게 가능
    5. 가중치 값에 대한 보간 그래디언트 적용
    6. Piecewise 형태로 LLM 모델 레이어를 병합시킴
  • 최근에 Kyujin이라는 사람이 SOLAR랑 본인 모델 Mergekit해서 EN, KO 둘 다 1등함
  • ML 모델 앙상블이랑 유사한 개념이긴 한데, 조금 더 효율적이고 효과적

기능 및 구성 소개

  • 사용법 - argument 사용, jupyter notebook 둘다 가능
mergekit-yaml path/to/your/config.yml ./output-model-directory [--cuda] [--lazy-unpickle] [--allow-crimes] [... other options]
  • 좋은 모델 나오면 허킹페이스에 업로드 가능
# log in to huggingface with an access token (must have write permission)
huggingface-cli login
# upload your model
huggingface-cli upload your_hf_username/my-cool-model ./output-model-directory .
  • yaml 파일 구성
    1. merge_method: 모델 병합 방법 설정
    2. slices: 모델의 레이어 슬라이스 정의
    3. models: 병합에 쓸 전체 모델 정의
    4. base_model: 기본 모델 정의
    5. parameters: 다양한 파라미터 가중치 설정
    6. dtype: 병합할 때 데이터 유형
    7. tokenizer_source: 토크나이저 뭐 쓸지?
  • 병합 방법론 유형

  • Linear: 그냥 가중치를 평균함, 정규화 기능 지원
  • slerp: 하나를 기본 모델로 설정해서 구면 보간 수행, 가장 성능이 좋다고 알려져 있음
    • 구면 보간: 데이터 포인트를 구면상의 점으로 간주해서 smooth한 곡선 혹은 곡면을 그리는 방식으로 없는 값 채워 넣음
    • 기본 모델의 가중치 값과 다른 모델의 가중치 값을 합칠 때 smooth한 곡선 혹은 곡면 형태가 나타나도록 보간 함수로 조정
    • 모델 2개일때만 돌릴 수 있음
  • task_arithmetic: 다른 모델의 가중치에서 기본 모델의 가중치를 빼 작업 벡터(편차)를 생성한 후, 이를 선형적으로 병합(여러 개일 때)하고 기본 모델을 다시 더하는 방식
    • 병합할 모델이 여러 개일 때 적용할 수 있는 방법론
  • ties: 작업 벡터를 희소화(sparsify, 작은 값은 0처)하고 부호 합의(값의 부호 확인, 불일치 시 희소화) 알고리즘을 통해 모델 간 간섭을 해소
  • dare: 작업 벡터를 희소화하고 새로운 재조정 기법을 적용하여 모델 간 간섭을 줄임, task_arithmetic과 ties와 붙일 수 있음
  • passthrough: 입력 텐서를 변경하지 않고 그대로 전달하여 레이어 병합에 사용되며, 특히 하나의 입력 모델만 있는 경우 유용함
  • yaml 파일 구성 예시

 

slices:
  - sources:
      - model: psmathur/orca_mini_v3_13b #오르카 미니 LLM, 허깅페이스에서 불러옴
        layer_range: [0, 40] #레이어 개수에 따라서 설정
      - model: garage-bAInd/Platypus2-13B #플래티푸스2 LLM, 허깅페이스에서 불러옴
        layer_range: [0, 40] #레이어 개수에 따라서 설정

merge_method: slerp #병합 방법 중 slerp 방법론 활용
base_model: psmathur/orca_mini_v3_13b #기본 모델 설정
parameters:
  t:
    - filter: self_attn #어텐션 스코어 가중치
      value: [0, 0.5, 0.3, 0.7, 1] # 가능한 조합들
    - filter: mlp #최종 분류 로짓값 가중치
      value: [1, 0.5, 0.7, 0.3, 0]
    - value: 0.5 # 기본 모델이 얼마나 가중치를 가질 것인지
dtype: float16 #저장된 가중치 dtype
  • 3개 모델도 병합 가능
slices:
  - sources:
      - model: psmathur/orca_mini_v3_13b
        layer_range: [0, 40]
      - model: garage-bAInd/Platypus2-13B
        layer_range: [0, 40]
merge_method: slerp
base_model: psmathur/orca_mini_v3_13b
parameters:
  t:
    - filter: self_attn
      value: [0, 0.5, 0.3, 0.7, 1]
    - filter: mlp
      value: [1, 0.5, 0.7, 0.3, 0]
    - value: 0.5 # fallback for rest of tensors
dtype: float16
name: gradient-slerp
---
models:
  - model: gradient-slerp
    parameters:
      density: [1, 0.7, 0.1] # density gradient
      weight: 1.0
  - model: WizardLM/WizardMath-13B-V1.0
    parameters:
      density: 0.33
      weight:
        - filter: mlp
          value: 0.5
        - value: 0
merge_method: ties
base_model: TheBloke/Llama-2-13B-fp16
parameters:
  normalize: true
  int8_mask: true
dtype: float16
name: gradient-slerp-ties

Setting

# Dev Container GPU 세팅
# - devcontainer.json
"runArgs": [
		"--gpus",
		"all"
	]

# 깃 클론
git clone <https://github.com/cg123/mergekit.git>
# 경로 설정
cd mergekit
# jupyter notebook 출력 위젯 설치
pip install ipywidgets
# 깃에 세팅된 패키지 설치
pip install -e .
  • CUDA 붙여져 있으면 pip 설치할 때 pytorch gpu 붙음. 가속화 사용 가능

실행

  • argument를 활용해도 되지만, jupyter notebook으로도 실행 예제 제공
# 변수 세팅
OUTPUT_PATH = "./merged"  # 저장될 경로
LORA_MERGE_CACHE = "/tmp"  # 로라 병합 캐시 저장 경로
CONFIG_YML = "./examples/gradient-slerp.yml"  # config(설정) yml 파일 경로 
COPY_TOKENIZER = True  # 토크나이저 있는거 쓰기
LAZY_UNPICKLE = True  # 실험적인 저용량 모델 로더 기능 활성화
LOW_CPU_MEMORY = True  # 서버 성능 좋으면 True 하면 됨
# 패키지 임포트
import torch
import yaml

from mergekit.config import MergeConfiguration
from mergekit.merge import MergeOptions, run_merge

# yml 파일 설정값 불러오기
with open(CONFIG_YML, "r", encoding="utf-8") as fp:
    merge_config = MergeConfiguration.model_validate(yaml.safe_load(fp))

run_merge(
    merge_config,
    out_path=OUTPUT_PATH,
    options=MergeOptions(
        lora_merge_cache=LORA_MERGE_CACHE,
        cuda=torch.cuda.is_available(), # GPU 세팅
        copy_tokenizer=COPY_TOKENIZER, # 토크나이저
        lazy_unpickle=LAZY_UNPICKLE, 
        low_cpu_memory=LOW_CPU_MEMORY,
    ),
)
print("Done!")

  • LAZY_UNPICKLE, LOW_CPU_MEMORY False로 하니까 커널 crash 발생.…
  • True로 하니까 해결!
  • 기본적으로 GPU 가속화 활용하더라도 시간이 꽤 걸림 20~30분

 

결과

  • ./merged 경로에 병합된 모델 및 관련 정보들이 자동으로 저장됨

  • 커스텀 테스트로 한국어 open-KoLLM 리더보드 1등(Solar), 2등(DataVortexS) 병합해봤는데 코드 잘 돌아감

  • 병합된 모델 로드해서 간단하게 로컬에서 추론 시연해보려 했으나, 로컬 서버 메모리 문제로 테스트는 실패..
  • 결론

    • 최근 Open-Ko-LLM 리더보드에서 SOLAR + DPO + Mergekit을 활용한 모델들이 상위권 유지 중
    • llama-cpp(로컬 LangChain)로도 돌릴려고 해봤는데, merge된 local safetensors를 GGUF(llama-cpp 지원 확장자)로 변환하는게 현재 지원이 안됨
    • Mergekit을 활용하여 허깅페이스에서 공개된 모델들을 아주 쉽게 병합할 수 있음
    • Mergekit에서 병합 모델을 가장 사용하기 쉬운 구조는 허깅페이스에 업로드해서 쓰는 것으로 보임
    • 실제 허깅페이스에 모델 업로드 해놓음, 바로 Langchain 붙일 수 있음

https://huggingface.co/coolwin20/merged_solar_vortexS

 

coolwin20/merged_solar_vortexS · Hugging Face

merged2 This is a merge of pre-trained language models created using mergekit. Merge Details Merge Method This model was merged using the SLERP merge method. Models Merged The following models were included in the merge: Configuration The following YAML co

huggingface.co

Mergekit을 활용하여  쉽게 허깅페이스 업로드 및 활용 가능

Comments