GPT Prompting
배경
Retrieval 수행 후 탐색한 문서에서 응답을 추출해야 한다. BERT 기반 모델을 사용하다가 이 아이를 Generation Based 기법을 사용하여 프롬프팅 하면 어떨까? 하는 생각을 했다.
팀원 중 다른 분께서 LLaMA를 튜닝해보고 싶다고 하셔서, 나는 GPT를 프롬프팅만으로 시도해보기로 했다.
프롬프트
GPT를 프롬프팅 할 수 있는 요소는 system
, assistant
, user
이렇게 세 가지이다.
system
: GPT가 수행해야 할 작업을 설명한다. 작업의 순서, 제한사항 및 주의사항 등을 지정할 수 있다.
assistant
: GPT가 응답해야 할 방식을 제공한다. few-shot prompting 등에 사용한다.
user
: 사용자가 하는 질문이나, 수행해야 하는 작업을 입력한다.
System Prompt
이전 프로젝트 때 팀원이 증강 시 수행했던 프롬프팅을 참고(여기)하여 총 세 가지 요소로 구분했다.
- GPT가 수행해야 할 작업(MRC)을 간단히 소개
- MRC 수행 방법을 단계별로 안내
- MRC를 수행함에 있어서 주의해야 할 사항을 안내
이때 명령형을 사용하고, ‘~하지마라’, ‘~하면 안 된다’와 같은 부정어보다 ‘~해야 한다’, ‘~해라’와 같은 긍정어로 구성하도록 하는 것이 중요하다. 이제 몇 가지 팁을 소개한다~
역할 소개
수행해야 하는 작업을 간단 명료하게 소개한다. 이미 많은 정보를 갖고 있는 모델이기 때문에 ‘기계 독해’와 같은 단어를 사용해도 잘 알아 듣는다. 부가 설명은 지시사항과 제한사항을 덧붙이는 것으로 해결한다.
지시사항
단계가 길다고 좋은 것은 아니다. 단순한 작업이라면 한 두 단계면 충분하다.
제한사항과 구분하여 해당 단계에서 일반적으로 준수해야 하는 사항을 추가로 달 수 있다.
제한사항
지시사항과 구분한 점은 일반적이지 않은 상황에 대해 추가적인 설명을 덧붙였다. 지시사항과 겹치는 부분도 있는데, 답변을 출력해본 후 말을 안 듣는 부분에 대해서 강조의 의미로 덧붙였다. 효과가 있긴 했으나, 100% 말을 듣는 것 같지는 않다. 그래도 없는 것보단 나으니..
그리하여 완성된 프롬프트는 아래와 같다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
system = '''당신은 기계 독해를 수행하는 전문가입니다. 질문을 보고 함께 제공된 지문에서 가장 명확한 답변을 추출하세요.
[지시사항]
1. 질문이 입력되면 함께 제공된 지문으로부터 가장 명확한 답변을 찾으세요.
2. 답변을 찾을 때:
- 답변이 여러 개인 경우, 질문과 지문의 문맥을 고려하여 가장 유사한 답변을 고르세요.
- 질문과 답변의 맥락을 고려했을 때 답변에 불필요하게 중복되는 단어가 없어야 합니다.
- 질문에 순서 정보가 명시되어 있을 경우 순서 또는 인과관계를 파악하여 답변을 추출해야 합니다.
[제한사항]
- 질문과 지문의 맥락을 파악하여 답변을 추출하세요.
- 추출한 답변은 반드시 지문에 명시된 글자들로만 구성되어야 합니다.
- 고유명사는 형태를 그대로 유지하세요.
- 추출한 답변에는 따옴표, 괄호와 같은 특수문자가 포함될 수 있습니다.
- 문장 형태의 답변을 피하고, 짧은 구나 구절을 선택하세요.'''
Few-Shot Prompt
지시사항에 해당하는 예시들을 입력한다. 수행해야 하는 작업이 생성형 기반 기계 독해라면 Zero-Shot도 충분히 가능하지만, 본 프로젝트는 추출형이기 때문에 지문에서 답변을 그대로 출력해야 한다. 따라서 어떤 형태로 답변을 추출해야 하는지에 대한 예시를 제공한다.
이때 답을 헷갈릴 만한 예시로만 구성하면 편향된 형태의 데이터들이기 때문에 일반적인 예시를 함께 제공해야 한다.
구성한 예시들은 다음과 같다.
- 일반적인 예시 두 개
- ‘두 번째’, ‘마지막’과 같이 사건의 순서를 고려해야 하는 예시
- 하나의 단어가 아니라 수식어가 포함되었지만, 그 기준이 정해진 예시
- 영어와 특수문자가 답변에 포함된 예시
3번의 경우, 제공 받은 데이터셋을 살펴본 결과 질문과 답변을 연결했을 때 겹치는 단어가 없는 한 답변의 수식어가 포함되는 형태로 출력해야 한다.
document
: 붉은 장미꽃은 스토리상 어린 왕자가 별을 떠나게 되는 이유이며, 또한 어린 왕자가 자신의 별로 돌아가게 되는 이유이기도 하다.
question1
: 어린 왕자가 별을 떠나는 이유는 무엇 때문인가?
question2
: 어린 왕자는 붉은 무엇 때문에 별을 떠나는가?
question1의 경우 답변은 ‘붉은 장미꽃’이지만, question2의 경우 ‘붉은’이라는 단어가 질문에 등장하기 때문에 답변은 ‘장미꽃’이 된다.
몇 가지 예시는 2-3개씩 포함하여 총 8개의 Few-Shot 예시를 준비했다.
이제 Few-Shot을 입력하는 방식에는 두 가지가 있다. 첫 번째는 실제 문제를 내가 GPT가 응답하듯이 하나씩 제공하는 것이고, 두 번째는 모든 예시를 이어붙여 한 번에 제공하는 것이다.
1
2
3
4
5
6
7
# 첫 번째 예시
user1 = f"질문: {question1}\n지문: {document1}\n답변: "
assistant1 = f"{answer1}"
user2 = ...
# 두 번째 예시
user = f"예시 1:\n질문: {question1}\n지문: {document1}\n답변: {answer1}\n예시 2: ..."
GPT-4o를 사용했을 때는 첫 번째 방식이 조오금 더 효과가 좋았지만 GPT-4o-mini를 사용했을 때는 두 번째 방식이 보다 나은 출력을 보여줬다. 첫 번째 예시를 사용하면 프롬프트가 길어질 수록 초반에 제공한 예시가 GPT-4o-mini의 메모리에서 잊히는 것 같다.
User Prompt
Few-Shot 프롬프트까지 GPT에게 입력한 후 이제 수행해야 할 작업의 문제를 낸다. 이때 Few-Shot이 예시인 만큼 User 프롬프트와 Few-Shot 프롬프트의 형태는 동일해야 한다.
따라서 나는 답변의 칸을 비워놓고 아래와 같은 형태로 구성 후 format 함수를 사용하여 데이터셋의 질문과 지문을 매핑했다.
1
2
3
user = '''질문: {question}
지문: {document}
답변: '''
결과
프롬프팅 결과 validation dataset을 기준으로 GPT-4o를 사용했을 때 EM 63.75, GPT-4o-mini를 사용했을 때 EM 60.4147을 달성했다. 평가 기준이 Exact Match라서 점수가 낮게 나왔지만, 답변을 살펴보면 문맥 상 적절한 답변을 출력하는 것을 알 수 있다.
아쉬운 점은 프롬프팅을 했음에도 순서 정보를 잘 고려하지 못하는 것과 제공된 지문에서 추론하여 답변을 찾아야 하는 경우 정답률이 낮았다는 것이다.
test dataset으로 수행했을 때는 지문이 한 개가 아니라 retrieval을 수행 후 추출한 열 개의 문서를 입력해야 했기 때문에 정답률이 현저히 낮았다. test dataset과 적합한 환경에서 프롬프팅을 추가로 시도해보고 싶었지만 프로젝트 마감 기한이 다가와 중단했다.
느낀점
GPT 프롬프팅은 말로만 들었던 것보다 세밀한 작업이 필요하다. 기존에는 단순히 ‘Few-Shot 예시를 주면 좋다’, ‘명령형을 사용하면 좋다’, ‘부정어보다는 긍정어를 사용해라’와 같은 팁 정도만 알고 있었는데, 직접 프롬프팅을 수행해보니 보다 명확한 언어 사용과 지시어 등 고려해야 할 것들이 일부 있었다.
이러한 과정 속에서 가장 크게 가진 생각은 1. 사람끼리의 언어는 생각보다 모호하다는 것과 2. 그런 점에서 생성형 모델에게 암묵지를 도입할 수 있을까?이다. 생성형 모델이 지금처럼 세밀한 프롬프트를 제공하는 것 말고도 ‘뭔지 알지?’와 같은 대화를 할 수 있도록 하려면 어떤 작업이 필요할지 궁금하다.