본문 바로가기
NLP

실전 데이터를 활용한 LLM Fine-tunning, RAG 적용해보기 (EXAONE Finetuning) - (1)

by AI미남홀란드 2024. 8. 22.
728x90

 

요즘 회사에서는 LLM과 관련된 업무를 하지는 않지만 LLM 에 대한 꾸준한 포스팅을 해보려고 합니다. Dacon 에서 대회를 하고 있는데 마침 RAG 스터디를 하기도 했고, Advanced RAG 를 막상적용할 도메인이 마땅하지 않다고 생각한 차에 좋은 대회가 있어서 해보게 되었습니다.

 

재정정보 AI 검색 알고리즘 경진대회 - DACON

분석시각화 대회 코드 공유 게시물은 내용 확인 후 좋아요(투표) 가능합니다.

dacon.io

글쓰는 날 기준으로 대회가 끝나가긴 하지만 그동안 이 대회를 해보면서 다양한 공부도 하였고, 다시 LLM 을 파인튜닝 해볼 기회가 생겨서 정리할겸 써봅니다.

 

현재 저는 순위자체는 10위 ~ 20위권 왔다갔다하고 있습니다. 아무래도 평가지표가 F1 Score 로 submission 을 제출한 문자열에 대해서 score 를 매기는것 같은데 그렇다면 주최사가 정답으로 생각하는 답 쪽으로 모델링을 해야할거같단 생각이 들긴했습니다. 물론 RAG 성능 또한 중요합니다.

 

Dataset Info.

train_source [폴더]
16개의 PDF 파일
Source에서 여러 질문-답변 쌍을 추출


test_source [폴더]
9개의 PDF 파일
Source에서 여러 질문-답변 쌍을 추출하여, Inference를 위한 질문만 제공


train.csv [파일] 
SAMPLE_ID : 샘플 별 식별 ID
Source : 질문-답변의 원천이 되는 Source PDF 파일명
Source_path : 질문-답변의 원천이 되는 Source PDF 파일 경로
Question : Source로부터 추출된 질문
Answer : Source로부터 추출된 질문에 대한 정답(답변)


test.csv [파일]
SAMPLE_ID : 샘플 별 식별 ID
Source : 질문-답변의 원천이 되는 Source PDF 파일명
Source_path : 질문-답변의 원천이 되는 Source PDF 파일 경로
Question : Source로부터 추출된 질문


sample_submission.csv [파일] - 제출 양식
SAMPLE_ID : 샘플 별 식별 ID
Answer : 질문에 대해 생성된 정답(답변)

 

학습데이터

train.csv  -QA pair , 참조한 pdf source

 

테스트 데이터

test.csv - Question, 참조한 pdf source

 

위와 같이 구성이 되어있고, test pdf 를 통해서 RAG를 적용해볼 수 있습니다. 

 

일단 저는 가용 가능한 자원을 활용해서 LLaMA3.1-70B + Advanced RAG 조합을 활용해서 상위 점수에 있습니다. 코드는 대회가 끝나면 공개하겠습니다.

 

그냥 순위에 연연하지 말고 RAG는 많이 시도를 해보았으니 이건 튜닝의 영역이다 생각이 들었고, llama70b 는 어찌어찌 돌릴 수 있었지만, 튜닝은 무리일것 같아서 sLLM 으로 눈이 갔습니다. 사실 이 대회 본 시점 딱 LG AI Research 에서 엑사원 모델을 공개했고 실행을 해봤는데 그땐 그냥 (?) 별 생각이 없었습니다. 그리고 Ollama 로 Mac 으로 서빙을 해서 써봤는데 확실히 한국어토종모델이라 예전에 sLLM 을 사용하다보면 한국어튜닝안한 모델 같은 경우는 아랍어 영어 섞어서 출력되던 그런점이 없어서 신기했습니다. 근데 이친구가 자기의 주체를 GPT-4라고해서?? 뭐지 하다가 넌 누가만들었어 하니깐 엘지관련된 이야기가 나와서 헤프닝으로 지나갔습니다. 대회가 끝나갈 즈음 그래도 아쉬우니 튜닝이라도 해보자 이생각으로 모델을 Choice 하다가 Gemma-9b가 확실히 성능이 좋은거같은데? 생각을 했지만 그냥 Colab 으로 돌릴 수 있는 모델로 해보자 생각이 들었고 llama7b 정도를 4bit 로 LoRA 튜닝을 하면 가능 할 것 같아서 이왕이면 토종모델로 해보자 생각이 들어서 엑사원을 다시 예토전생시켰습니다.

 

 

LGAI-EXAONE/EXAONE-3.0-7.8B-Instruct · Hugging Face

EXAONE-3.0-7.8B-Instruct 👋👋 We have revised our license for revitalizing the research ecosystem.👋👋 Introduction We introduce EXAONE-3.0-7.8B-Instruct, a pre-trained and instruction-tuned bilingual (English and Korean) generative model with 7.8

huggingface.co

 

 

벤치마크만 보더라도 압도적이긴합니다 한국어성능은!! 근데 인퍼런스단계에서 Dacon 점수는 오히려 많이 떨어졌습니다(?) 그래서 저 Train 데이터셋 450개정도의 QA pair 를 SFT 를 해보자 생각이었습니다. 엑사원은 ExaoneForCausalLM 구조로 레이어가 쌓여있는데요 이걸 LLamA로 바꿔주어야 우리가 평소에 했던 튜닝들을 쉽게 할 수 있었습니다. 

 

마침 maywell님이 또 만들어 주셔서.. 그저 빛✨

그냥 로드하고 함수만 돌리면 되는 간편한 구조 였습니다.

 

 

maywell/EXAONE-3.0-7.8B-Instruct-Llamafied · Hugging Face

maywell/EXAONE-3.0-7.8B-Instruct-Llamafied Llamafy Script import torch import gc from transformers import LlamaConfig, LlamaForCausalLM, AutoModelForCausalLM, AutoTokenizer from tqdm import tqdm def unload_model(model): """Clear memory by deleting a model

huggingface.co



전체적으로 LLaMA 포맷으로 바꿔주고, 구조 가중치를 복사해주고, 전체 아키텍처를 변환을 해줍니다. use_auth_token="yourkey" 를 넣어주어야 엑사원이 로드가 됩니다 먼저 허깅페이스로그인하고 엑사원 모델 사용동의를 얻어야합니다.

 

 

 

 

위처럼 llamafied 로 바뀐 exaone 모델입니다. 이제 취향에 따라 코드로 파인튜닝을 해도 되고 Unsloth , LLamaFactory 등 다양하게 튜닝을 해보아도 됩니다. 그전에 데이터셋을 만들어야 합니다! Alpacadataset 을 활용해서 만들어 볼 예정입니다. 어차피 데이터셋은 SFT 튜닝할떄 Instruction, Output 을 활용해서 QA 페어를 만들기 때문에

 

위와같이 CSV 를 로드해서 만들었습니다. exaone 학습 템플레이트에 맞춰서 데이터셋을 변경해줘야 합니다.

 

 

|system| , |user| , |assistant|, |endofturn| 위와 같은 포맷팅을 적용해야합니다.

 

 

GitHub - hiyouga/LLaMA-Factory: Efficiently Fine-Tune 100+ LLMs in WebUI (ACL 2024)

Efficiently Fine-Tune 100+ LLMs in WebUI (ACL 2024) - hiyouga/LLaMA-Factory

github.com

 

LLaMA-Factory 를 활용해서 finetunning 을 해보려고한다. 친절하게 튜닝하는방법이 있다 ㅎㅎ 요즘은 문서화가 다들 GPT로 하는지 잘되어있어서 편한 것 같다.

 

 

Finetune-Llama3-with-LLaMA-Factory.ipynb

Colab notebook

colab.research.google.com

 

git clone 을 해주고, llama factory 의 데이터셋을 적용하기 위해 급하게.. input"" 처리 하였습니다. 상관은없을거같긴한데 일단 괜히 에러못잡을것같아서 그전에 일단바꿔주었습니다.

import json

args = dict(
  stage="sft",                        # do supervised fine-tuning
  do_train=True,
  model_name_or_path="모델 주소", 
  dataset="나의 데이터",             
  template="exaone 템플릿",                   
  finetuning_type="lora",                   # use LoRA adapters to save memory
  lora_target="all",                     # attach LoRA adapters to all linear layers
  output_dir="exaone_lora",                  # the path to save LoRA adapters
  per_device_train_batch_size=2,               # the batch size
  gradient_accumulation_steps=4,               # the gradient accumulation steps
  lr_scheduler_type="cosine",                 # use cosine learning rate scheduler
  logging_steps=10,                      # log every 10 steps
  warmup_ratio=0.1,                      # use warmup scheduler
  save_steps=1000,                      # save checkpoint every 1000 steps
  learning_rate=5e-5,                     # the learning rate
  num_train_epochs=3.0,                    # the epochs of training
  max_samples=500,                      # use 500 examples in each dataset
  max_grad_norm=1.0,                     # clip gradient norm to 1.0
  quantization_bit=4,                     # use 4-bit QLoRA
  loraplus_lr_ratio=16.0,                   # use LoRA+ algorithm with lambda=16.0
  fp16=True,                         # use float16 mixed precision training
)

json.dump(args, open("train_exaone.json", "w", encoding="utf-8"), indent=2)

%cd /content/LLaMA-Factory/

!llamafactory-cli train train_exaone.json

 

파라미터는 알맞게 설정해주시면 됩니다. LLM 튜닝이 어렵다고 느껴지는게 수많은 파라미터에 따라 달라지기도 하고 너무시간이 오래걸리는점이 진짜어려운 것 같습니다. 이렇게 무지성으로 튜닝을 실행하는 순간 error 가 범벅이게 되고 보니깐 Template 관련설정이 누락되어서 src -> data -> template.py 에서 exaone 전용 template 를 만들어주어야했습니다.

 

위코드를 보고 엑사원에 맞게 수정해주었습니다.

_register_template(
    name="exaone",
    format_user=StringFormatter(
        slots=[
            (
                "|user| {{content}} |endofturn|\n"
                "|assistant| "
            )
        ]
    ),
    format_assistant=StringFormatter(
        slots=["{{content}} |endofturn|\n"]
    ),
    format_system=StringFormatter(
        slots=["|system| {{content}} |endofturn|\n"]
    ),
    format_observation=StringFormatter(
        slots=[
            (
                "|assistant| Observation: {{content}} |endofturn|\n"
                "|assistant| "
            )
        ]
    ),
    format_prefix=EmptyFormatter(slots=[{"bos_token"}]),
    stop_words=["|endofturn|"],
    replace_eos=True,
)

 

format_observation 은 tool 을 활용할때 쓰는 포맷이라고하니 굳이 안해도 되고 빼고 라마팩토리 소스에 추가해주시면 됩니다. 이런식으로 py 파일에 적용해주면 됩니다. 그럼 위에서 cli code 에서 exaone 으로 수정을 해주고 돌려주면 됩니다.

 

 

일단 Colab에선 터져서.. 아마 긴급하게 4090 수혈을 해야하지 않을까 싶습니다. 아마 기존 엑사원 용량과 변환된 엑사원 용량 초과로 인해서 디스크부족이 뜨더니 터져버렸습니다. 나약한 코랩놈 디스크를 지우면서 최적화 코드를 짜야하지 않을까 싶습니다. 일단 제가 가지고있는 rtx4090으로 시도를 먼저해보고 다른 GPU 가 로드가능하면 추가적으로 Advanced RAG 코드설명과 함께 게시물 포스팅하겠습니다.

728x90