[AI | GPT] GPT 3.5 파인튜닝 with python(1) - 데이터 준비

한시삼십사분·2024년 3월 28일
0

AI

목록 보기
1/3
post-thumbnail

농사 게임 프로젝트에서 AI를 활용해 농산물 퀴즈 미니게임 기능을 개발해야 했다.
처음에는 SKT의 KoGPT2 모델을 파인튜닝하는 형태로 개발하려고 했고, 약 일주일간 시도를 했지만 원하는 수준의 결과물을 뽑아내지 못해서 결국 기각... GPT 3.5파인튜닝 하기로 방향을 바꿨다.
(프로젝트 종료 후 약 일주일 정도 여유있을 것 같아서 다시 시도해볼 예정)

데이터를 준비하고, 파인튜닝 하고, 추론 그리고 Fast API + AWS를 활용해 배포까지의 과정을 총 3개의 글로 정리하려고 한다.

파인튜닝 꼭 해야할까...?


(근데 우유 6개 사와야 하는거 아닌가...?)

위의 사진과 같이 멍청(?)한 GPT는 GPT 4.0의 등장으로 옛말이 되었다. 사실 프롬프트를 조금만 잘 작성해도 생각보다 고수준의 요구에도 답변을 잘 생성한다.

GPT한테 배추에 관한 퀴즈를 만들어줘!라는 요청을 보냈을 때 생각보다 퀴즈를 잘 만들어준다. 그럼에도 내가 파인튜닝을 진행한 이유는 답변 형식의 일관화이다. 서비스 기간 동안 많은 요청이 있을텐데 그 요청마다 질문, 답변, 오답(사지선다 형태의 문제를 필요로 했다)을 담고있는 response의 형식이 달라진다면 프론트 입장에서 사용하는데 불편함을 느낄 것이다.

이외에도 OpenAI가 제시한 use case에서

  • Improved steerability(지시를 잘 따르게 한다)
  • Reliable output formatting(일관성있는 답변)
  • Custom tone(커스텀된 톤으로 응답한다)

같은 경우에서 높은 성능을 낸다고 말한다.

데이터셋 선택

AI 학습의 시작이자 끝, 데이터셋을 준비해야 한다.
나는 KorQuAD 1.0 데이터셋을 가공해서 활용했다.

KorQuAD 1.0은 한국어 Machine Reading Comprehension을 위해 만든 데이터셋입니다. 모든 질의에 대한 답변은 해당 Wikipedia article 문단의 일부 하위 영역으로 이루어집니다. Stanford Question Answering Dataset(SQuAD) v1.0과 동일한 방식으로 구성되었습니다.

위 사진과 같이, 위키백과의 제목(title), 내용(context), 내용을 바탕으로 생성된 질문(question), 질문에 대한 답변(answers)로 이루어져 있다.

내가 여기서 필요한 데이터는 context, question, answers 였다.
이제 이 데이터를 GPT가 요구하는 형식에 맞춰야한다.

데이터 가공

OpenAI가 제공하는 문서를 확인해보면 파인튜닝을 위한 데이터의 형식을 제공한다. (파인튜닝하고자 하는 모델의 종류에 따라 데이터 형식이 다르니 주의!)

  • gpt-3.5-turbo
{"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What's the capital of France?"}, {"role": "assistant", "content": "Paris, as if everyone doesn't know that already."}]}
{"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "Who wrote 'Romeo and Juliet'?"}, {"role": "assistant", "content": "Oh, just some guy named William Shakespeare. Ever heard of him?"}]}
{"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "How far is the Moon from Earth?"}, {"role": "assistant", "content": "Around 384,400 kilometers. Give or take a few, like that really matters."}]}
  • babbage-002, davinci-002
{"prompt": "<prompt text>", "completion": "<ideal generated text>"}
{"prompt": "<prompt text>", "completion": "<ideal generated text>"}
{"prompt": "<prompt text>", "completion": "<ideal generated text>"}

나는 gpt-3.5-turbo 모델을 파인튜닝했기 때문에 위의 형식에 데이터를 맞춰보았다.

총 3개의 message 형태로 구성된다.

  • 모델의 성격을 정의하는 message
  • 사용자의 입력 예시 message
  • gpt의 답변 예시 message

각 message는 role, content로 구성되며 role은 system, user, assistant 순서로 고정된 값이다. 우리는 각 message의 content만 알맞게 맞춰주면 된다.

1.모델의 성격을 정의하는 message

모델의 성격을 정의한다. 위의 예시에서는

{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}

와 같이 너는 Marv라는 사실적이고 냉소적인 챗봇이야와 같은 역할을 부여한다.

2. 사용자의 입력 예시 message

사용자가 프롬프트에 입력하는 예시를 정의한다.

{"role": "user", "content": "What's the capital of France?"}

프랑스의 수도가 어디야?라는 프롬프트 예시를 입력한다.

3. gpt의 답변 예시 message

2번 사용자의 프롬프트에 대한 답변을 정의한다.

{"role": "assistant", "content": "Paris, as if everyone doesn't know that already."}

다들 모르겠지만 파리야.라는 1번에서 정의한 것과 같이 냉소적인 답변을 입력한다.

데이터셋 변환

이제 내가 들고있는 KorQuAD 1.0 데이터셋을 위의 형식에 맞게 변환한다.

  • 사용자 -> GPT
    정보를 주면서 이 문맥에 대해 퀴즈를 생성해줘라는 요청을 한다.

  • GPT -> 사용자
    퀴즈답변을 제시한다.

이 규칙을 바탕으로 데이터셋의 첫번째 데이터에 대해 변환해보자.

  • 모델 성격 정의
{"role": "system", "content": "You are the best quiz generator."}

너는 최고의 퀴즈 생성자야.라는 성격을 정의했다.

  • 사용자의 입력
{"role": "user", "content": "1839년 바그너는 ... 의견도 있다.<sep>generate question with context"}

데이터셋의 context를 입력하고 <sep>이라는 구분자를 활용해 구분해준 후 generate question with context를 통해 이 문맥을 바탕으로 질문을 생성해줘라는 요청을 한다.

  • gpt의 답변
{"role": "assistant", "content": "question : 바그너는 괴테의 파우스트를 읽고 무엇을 쓰고자 했는가?, answer : 교향곡}]}

데이터셋의 questionanswer를 구분해서 입력한다.

❗ 하지만 나는 사지선다의 형식을 원한다. 즉 3개의 오답이 필요하다. 이를 위해 gpt에게 context, question, answer를 알려주면서 오답 3개를 생성해달라는 요청을 통해 오답 데이터를 생성했다.(이 과정에서 GPT4가 3번이나 일시적으로 사용이 중단되었다... 2시간 정도 기다리면 다시 사용 가능)

이를 통해 생성된 오답 3개를 <sep>을 통해 구분하여 데이터 뒤에 붙여주었다.

다음과 같은 형태가 된다.

{"role": "assistant", "content": "question : 바그너는 괴테의 파우스트를 읽고 무엇을 쓰고자 했는가?, answer : 교향곡, wrong: 오페라<sep>서곡<sep>소나타"}]}

최종적으로 3개의 message를 합친 데이터의 형태는 다음과 같다.

{"messages": [{"role": "system", "content": "You are the best quiz generator."}, {"role": "user", "content": "1839년  ... 있다.<sep>generate question with context"}, {"role": "assistant", "content": "question : 바그너는 괴테의 파우스트를 읽고 무엇을 쓰고자 했는가?, answer : 교향곡, wrong: 오페라<sep>서곡<sep>소나타"}]}

KorQuAD 1.0은 약 6만개의 데이터가 있지만 나는 500개train_data, 100개validation_data로 분리하여 사용했다.

👍 마무리

GPT 파인튜닝을 위한 데이터 준비 과정을 알아봤다.
다음 글에서 OpenAI API KEY를 발급받고 python을 활용해 파인튜닝하는 과정을 정리하겠다.

profile
인간은 망각의 동물이라지만 이건 너무한 거 아니냐고

0개의 댓글