Nacho

[냉부] 👨‍🍳 레시피 AI 만드는 여정 (2) 본문

Toys

[냉부] 👨‍🍳 레시피 AI 만드는 여정 (2)

Nacho_13 2024. 11. 10. 16:27
반응형

Llama다 망할 AI야

 

본문에서는...

  • 끝까지 해결하지 못한 오류
  • OpenAi 한테 호구당한 이야기
  • Flask 서버
  • EC2
  • LLama3.1 파인튜닝
  • 웹 크롤링 (완료)

과 같은 내용을 다룹니다..


3. Llama 3.1 파인튜닝 

AI 학습에 있어 가장 중요한 역량이 있다. 이전엔 수학, 영어 등 학문적인 고민을 했지만 생각이 바뀌었다.

가장 중요한 요소는 "돈"이다. 이전 포스팅에 밝힌바 있지만, 

난 돈도 없고 능력도 없다.

 

LLM 깔짝 쓰고 싶은 나에게 저렴한 ai는 없다. 

 

따라서, 직접 만든다..!

 

(파인튜닝에 앞서 나는 Google Colab Pro 를 구독하여 사용하였다.)

A100 을 사용해야 GPU 메모리에 Llama가 간신히 올라간다..

 

!pip install -U accelerate==0.29.3 peft==0.10.0 trl==0.8.6 datasets==2.19.0
!pip install --upgrade transformers bitsandbytes

from google.colab import drive

drive.mount('/content/drive')	# 구글 드라이브 마운트

import os
import torch
import pandas as pd
from peft import LoraConfig
from trl import SFTTrainer
from datasets import Dataset

import huggingface_hub
huggingface_hub.login('Huggingface_KEY') # 본인의 Huggingface_KEY 입력 (로그인)

base_model = "meta-llama/Llama-3.1-8B-Instruct"	#Llama 모델
dataset = '/content/drive/MyDrive/data_path/recipe_questions_answers.csv' # 만개의 레시피 데이터
query_dataset = pd.read_csv(dataset) # 데이터 불러오기

 #데이터를 학습 형태에 맞게 변환
prompt = []
for index,row in query_dataset.iterrows():
  prompt.append({"text": 'Question: ' + row['Question']+'Answer : ' +row['Answer']}) 
  
train_dataset = Dataset.from_list(prompt)


from transformers import (AutoTokenizer,
                          AutoModelForCausalLM,
                          BitsAndBytesConfig,
                          TrainingArguments,
                          logging,
                          pipeline)
                          
# 4bit 양자화 설정 (모델이 너무 커서 잘라서 불러온다 생각하면 됨)
quant_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",  # 또는 "fp4"
    bnb_4bit_compute_dtype=torch.float16,  # 또는 torch.bfloat16
    bnb_4bit_use_double_quant=False
)

# 모델 로드
model = AutoModelForCausalLM.from_pretrained(
    base_model,
    quantization_config=quant_config,
    device_map="auto",
)
model.config.use_cache = False
model.config.pretraining_tp = 1

# 토크나이저 로드
tokenizer = AutoTokenizer.from_pretrained(
              base_model,
              trust_remote_code=True)
tokenizer.pad_token = tokenizer.eos_token
tokenizer.padding_side = "right"


peft_params = LoraConfig(
    lora_alpha=16,
    lora_dropout=0.1,
    r=64,
    bias="none",
    task_type="CAUSAL_LM",
)

# 성능을 위해 파라미터 변경 가능 (메모리 용량에 맞게 잘 설정)
training_params = TrainingArguments(
    output_dir="/results",
    num_train_epochs = 1,
    max_steps=5000, 
    per_device_train_batch_size=1,
    gradient_accumulation_steps=4,
    optim="paged_adamw_8bit",
    warmup_steps=0,
    warmup_ratio=0.03,
    learning_rate=2e-4,
    fp16=True,
    logging_steps=100,
    report_to='none',
)

# 파인튜닝
trainer = SFTTrainer(
    model=model,
    train_dataset=train_dataset,
    peft_config=peft_params,
    dataset_text_field="text",
    max_seq_length=None,
    tokenizer=tokenizer,
    args=training_params,
    packing=False,
)


trainer.train() #학습 시작

 

모델 저장 및 검증

repo_name = "USER_ID/repo_name"  # 사용자 이름과 리포지토리 이름으로 설정

# 업로드 (push_to_hub 메서드를 사용하여 모델과 토크나이저를 허깅페이스에 업로드)
model.push_to_hub(repo_name)
tokenizer.push_to_hub(repo_name)
logging.set_verbosity(logging.CRITICAL)

prompt = "김치, 감자, 파, 밀가루, 계란, 참기름, 삼겹살 로 할 수 있는 요리레시피 알려줘"
pipe = pipeline(task="text-generation", model=model, tokenizer=tokenizer, max_length=1024)
result = pipe(f"<s>[INST] {prompt} [/INST]")
print(result[0]['generated_text'])


# OUTPUT
'''
<s>[INST] 김치, 감자, 파, 밀가루, 계란, 참기름, 삼겹살 로 할 수 있는 요리레시피 알려줘 [/INST] </s>
김치, 감자, 파, 밀가루, 계란, 참기름, 삼겹살
감자김치볶음에 더 맛있는 감자김치볶음 레시피!소면이나 밥과 함께 먹어도 맛있고, 밥에 비벼 먹어도 맛있는 감자김치볶음 레시피!
· 김치 전분을 제거하기 위해 찬물에 담궈 물기를 빼준 후에 사용
· 감자 껍질을 벗기고 얇게 채 썰어 찬물에 담궈 둔 후에 사용
· 파 길게 채 썰어 소금과 참기름을 넣은 후에 노릇하게 볶아준 후에 사용
· 삼겹살은 껍질을 벗기고 얇게 채 썰어 찬물에 담괙어 둔 후에 사용
· 참기름 2스푼을 두르고 김치와 감자를 5분간 볶아준 후에 파를 넣고 볶아준 후에
· 소금 1스푼을 넣고 김치가 살짝 투명해질 때까지 볶아준 후에
· 삼겹살을 넣고 약불에서 10분간 볶아준 후에
· 계란을 넣고 약불에서 1분간 볶아준 후에
· 참기름 1스푼을 넣고 중불에서 3분간 볶아주면 완성
감자김치볶음은 소면과 함께 먹어도 맛있고, 밥 비벼 먹어도 맛있어요. 감자김치볶음 맛있게 만드는 비법은 이대로 만들어 보세요~ 소면과 함께 먹어도 맛있고, 밥 비벼 먹어도 맛있어요.
'''

 

결과는..? 처참하다.

1시간 30분 정도 학습한 결과,

4bit 양자화 모델이라 그런지 성능은 꽝이고, 말도 이상하다.

그래도 어쩌겠나 하고 모델을 불러와서 프롬프팅을 하려고 할 때 문제가 발생한다..

 

 

4.  끝내 해결하지 못한 오류

Supplied state dict for model.layers.22.mlp.down_proj.weight does not contain bitsandbytes__* and possibly other quantized_stats components.

 

모델을 불러와서 다른 파일에서 사용할 때 겪은 오류이다.

StackOverFlow와 Github을 모두 뒤져도 같은 요류를 찾을 수 없었으나 비슷한 오류를 찾을 수 있었다.

https://stackoverflow.com/questions/79068298/valueerror-supplied-state-dict-for-layers-does-not-contain-bitsandbytes-an

 

valueError: Supplied state dict for layers does not contain `bitsandbytes__*` and possibly other `quantized_stats`(when load sav

We are trying to deploy a quantized Llama 3.1 70B model(from Huggingface, using bitsandbytes), quantizing part works fine as we check the model memory which is correct and also test getting predict...

stackoverflow.com

 

모델을 저장할 때 quantized weight 과 meta data가 shard 로 분할되어 저장되는데, 이를 불러올 때 Error가 생긴다는 내용이다.

 

그래서 다음과 같이 모델 저장 방식을 변경

# 모델 저장 경로 설정
output_dir = "/content/drive/MyDrive/model_path"

# 모델과 토크나이저를 하나의 파일로 저장 (shard 크기를 설정하여 shard 분할 방지)
model.save_pretrained(output_dir, max_shard_size="50GB")
tokenizer.save_pretrained(output_dir, legacy_format=False)


from transformers import AutoTokenizer, AutoModelForCausalLM

# 모델 경로
model_path = output_dir

# 토크나이저와 모델 불러오기
val_tokenizer = AutoTokenizer.from_pretrained(model_path)
val_model = AutoModelForCausalLM.from_pretrained(model_path)

# 필요한 경우 모델을 GPU로 이동
device = "cuda" if torch.cuda.is_available() else "cpu"
val_model.to(device)
val_tokenizer.pad_token = tokenizer.eos_token
val_tokenizer.padding_side = "right"


# 모델 검증 (간단한 텍스트 생성)
inputs = val_tokenizer("감자와 김치를 가지고 만들 수 있는 요리", return_tensors="pt").to(device)
outputs = val_model.generate(**inputs, max_length=256)
print(val_tokenizer.decode(outputs[0], skip_special_tokens=True))



# MODEL_OUTPUT
'''
감자와 김치를 가지고 만들 수 있는 요리
ainless IonicModule IonicModuleryn IonicModule 
IonicModule IonicModulechwitzramellu� IonicModule_REPLACEryn 
IonicModuleinousoinainlesseam IonicModuleirlreenreenryn_REPLACEchwitz 
IonicModule IonicModule IonicModule IonicModulechwitz_REPLACE 
IonicModuleaeperaeper_REPLACE IonicModuleaeper 
IonicModule IonicModule_REPLACE IonicModule IonicModulereenreenensed 
IonicModuleeam397 IonicModuleuien IonicModule� IonicModuleuienlluainless 
IonicModule IonicModule IonicModule IonicModule IonicModuleumbsainlessreenumbsuml 
IonicModule IonicModule IonicModule IonicModule IonicModuleirth 
IonicModuleasaluien IonicModule IonicModuleuienreenantityreen IonicModule 
IonicModuleeameam IonicModuleantity
'''

 

모델은 성공적으로 불러오나, tokenizer 가 말썽... ㅜㅜ

A100 모델을 통해 내 컴퓨팅 단위는 살살 녹았고, 여기서 중단..누군가에게 도움이 되었기를 바라며...(눈물)

(학습 결과도 구리고, 불러오는 것도 말썽)

 

다음 포스팅은 Openai_Api 를 사용한 방식을 소개하고자 한다.

반응형