우리가 자주 사용하는 카카오톡 에서는 대화 내용을 text 형태로 내보낼 수 있는 기능을 제공 합니다.
카카오톡 대화 내용으로 Language Model 을 Fine Tuning 해보면서 AI safety와 개인정보의 중요성에 대해 같이 한번 이야기해보려고 합니다.
데이터는 개인의 카카오톡에서 저장한 파일과 colab (무료 버전의 GPU) 환경에서 진행해보겠습니다.
이번에 학습해보려는 Model 의 목적은 아래 대화 내용처럼 “라이언” 이 메세지를 보내면 “무지” 처럼 대답을 하는 ChatBot 을 만들어보는것입니다.
1. Dataset 구성
먼저 카카오톡 대화방 설정에서 대화 내용 저장을( 모바일의 경우 메일로 전송) 하게 되면 아래와 같은 csv 파일이 생성됩니다.
그럼 이제 csv 파일을 import 해서 본격적으로 Model 을 학습하기 위한 데이터셋을 구성해보겠습니다.
Colab의 파일 업로드 기능을 활용하여 대화내용이 저장된 csv 파일을 upload 합니다.
1 2 |
from google.colab import files uploaded = files.upload() |
전처리 작업을 위해 upload 된 csv 파일을 pandas 의 Dataframe 으로 변환합니다.
Date 컬럼의 경우 제거하지 않아도 문제되지 않지만, 이번 작업에서는 활용하지 않을 예정이므로, 제거 하고 넘어가겠습니다.
1 2 3 |
import pandas as pd df = pd.read_csv('{upload된 파일명}') df.drop('Date',axis=1,inplace=True) |
DataFrame 을 살펴보면 시간 순으로 대화 내용이 나열된 구조입니다.
Data를 라이언/무지 컬럼으로 DataFrame 을 재구성해서, 라이언 1번 / 무지 1번 씩 나타나는 대화 형식의 Data로 만들어보겠습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
new_df = pd.DataFrame(columns=['User', 'Message']) current_user = None current_message = "" # 같은 User 가 연속으로 나타날 경우 한개의 Row로 처리 for index, row in df.iterrows(): if current_user is None: current_user = row['User'] current_message += row['Message'] elif current_user != row['User']: new_df = new_df.append({'User': current_user, 'Message': current_message}, ignore_index=True) current_user = row['User'] current_message = row['Message'] else: current_message += "\n" + row['Message'] # 마지막 행 추가 if current_user is not None: new_df = new_df.append({'User': current_user, 'Message': current_message}, ignore_index=True) # me = new_df[new_df.User =='라이언'].reset_index().Message you = new_df[new_df.User =='무지'].reset_index().Message data = pd.DataFrame({'me':me , 'you' : you}) |
재구성된 data를 확인해보겠습니다.
“무지” 처럼 대답하는 chatBot을 만드는게 목적이기 때문에 “라이언”은 me 가 되고, “무지”는 you 가 되어 row 별로 me 와 you 가 한번씩 대화 하는 구조가 생성되었습니다.
2. 사전 학습된 Model Fine tuning
“무지”처럼 대답하는 서비스를 만들어보기 위해 사용할 Model 은 SKT 에서 21년 공개한 GPT2 base 의 KoGPT2 모델입니다.( https://github.com/SKT-AI/KoGPT2 )
최근 다양한 아키텍쳐를 반영한 다양한 크기의 모델들이 나오고 있지만, 단순 대화 내용을 Fine tuning 하기 위해서는 한국어 능력을 가진 Model 이면 가능할 것이라고 보고 KoGPT2 를 선정하였습니다.
1 2 3 4 5 6 7 8 9 |
import torch from transformers import PreTrainedTokenizerFast checkpoint = 'skt/kogpt2-base-v2' device = 'cuda' tokenizer = PreTrainedTokenizerFast.from_pretrained(checkpoint, bos_token='<s>', eos_token='</s>', unk_token='', pad_token='', mask_token='') |
SKT-AI github 에 있는 가이드 대로 Tokenizer 를 선언하고, 모델이 학습할 수 있도록 Dataset을 구성해보겠습니다.
기본적인 Prompt는 가장 간단하게 me 의 Message와 you 의 Message 형태로 구성합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
''' DataSet 구성 ### me : \n 오늘 저녁 뭐 먹을까?\n ### you : \n 나는 다 좋지. 너 먹고 싶은거 먹어 ''' from datasets import Dataset dataset = Dataset.from_pandas(data).map( lambda x: {'text': f"### Me: {x['me']}\n### You: {x['you']}" } #end token ).train_test_split(test_size=0.1) #kogpt2 의 경우 max length 가 1024로 1024 이상의 길이는 Truncate 해야줘야 합니다. dataset = dataset.map(lambda x: tokenizer(x["text"] , truncation=True, max_length=1024, padding="max_length"), batched=True) |
모델을 load 한 후 huggingface 의 trainer 를 사용해서 3 epochs 정도만 학습을 진행합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
from transformers import GPT2LMHeadModel model = GPT2LMHeadModel.from_pretrained(checkpoint).to(device) from transformers import TrainingArguments, Trainer , DataCollatorForLanguageModeling tokenizer.pad_token = tokenizer.eos_token training_args = TrainingArguments(output_dir="test_trainer", evaluation_strategy="epoch", per_device_train_batch_size=4, gradient_accumulation_steps=4, num_train_epochs=3, save_total_limit = 1 ) trainer = Trainer( model=model, args=training_args, train_dataset=dataset['train'], eval_dataset=dataset['test'], data_collator=DataCollatorForLanguageModeling(tokenizer, mlm=False) ) trainer.train() |
3. 모델 평가
질문 : 오늘 뭐 먹을까?
생성된 답변 :
ㅡㅜ
나 오늘 밥 먹구 카페 갈깡
엄청 피곤
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
result = model.generate( **tokenizer( f"### Me: 오늘 뭐 먹을까?\n### You: ", return_tensors='pt', return_token_type_ids=False ).to(device), max_length=32, pad_token_id=tokenizer.pad_token_id, eos_token_id=tokenizer.eos_token_id, bos_token_id=tokenizer.bos_token_id, use_cache=True, early_stopping=True, do_sample=True, temperature=0.7, top_k=30, top_p=0.80 ) print(tokenizer.decode(result[0]).split('### You: ')[1]) |
생성된 메세지는 기존 koGPT2 와 전혀 다른 메세지로 파인튜닝된 데이터를 반영하여 실제 대화와 같은 결과를 생성합니다.
4. 마무리
영화 “Her” 같은 세상이 진짜로 올까요? 라는 질문에 대해 이제 많은 사람들이 “네” 라고 답할지도 모르겠습니다.
사전 학습된 LLM 은 단순한 fine tuning 작업만으로 우리가 원하는 방향으로 AI 모델을 학습시킬 수 있는 세상을 열어 주었습니다.
다만, “우리가 원하는 방향” 이라는것이 무서운 것 같습니다.
이번에는 재미로 카카오톡 대화 내용을 바탕으로 나만의 Language Model 을 만들어 보았지만,
어떤 목적에 따라 준비된 데이터셋이 Model 을 의도적으로 특정 방향으로 학습시킨다면 AI 기술이 사회에 어떤 영향을 줄지 두려움도 있습니다.
그런점에서 최근 공개되는 llama나 gemma 같은 모델을 보면 AI safety 가이드( https://llama.meta.com/responsible-use-guide , https://ai.google.dev/responsible?hl=ko )를 제시하고 있습니다.
Language Model 을 활용해서 서비스를 개발하는 주체와 AI 서비스를 사용하는 사용자 모두 AI Safety 에 대한 인식과 논의가 필요하지 않을까 생각합니다.
또한, 카카오톡 대화를 기반으로한 ChatBot 모델처럼 이제는 우리의 개인정보가 주민등록번호, 주소, 전화번호 처럼 이전에 중요하게 생각했던 개인 정보외에,
대화 이력, 인터넷에 업로드 된 글, 사진 등 디지털 발자국 또한 중요한 개인정보임을 인지하고 관리해야할것 같습니다.
AI 시대는 점점 더 빨리 오고 있는것 같습니다.
기술의 발전만큼 우리 사회도 새로운 시대에 대한 고민이 필요할 것 같습니다.
출처
https://github.com/SKT-AI/KoGPT2
https://llama.meta.com/responsible-use-guide
https://ai.google.dev/responsible?hl=ko]
이 글은 SK 그룹의 개발자 모임 Devocean 에 동일하게 작성된 글입니다.