2024. 3. 10. 18:02ㆍDevelopment
안녕하세요, 이번 시간에는 저번 시간에 이어 프롬프트 공학을 다뤄볼 거예요.
이번 게시물은 아래 게시물과 이어지는 내용이니 안 보신 분은 보는 걸 추천드려요.
Prompt Engineering: ChatGPT와 대화하기 1편
안녕하세요, 오늘은 ChatGPT 같은 LLM을 사용할 때 알면 좋은 내용인 프롬프트 공학(Prompt Enginnering)에 대해 다뤄보려고 해요. ChatGPT를 사용할 때, "Message ChatGPT..."에 물어보고 싶은 말들을 열심히 쓰
dalmeng-commeng.tistory.com
이 글은 GPT 모델을 만든 OpenAI 사의 프롬프트 공학 가이드를 참고했어요.
https://platform.openai.com/docs/guides/prompt-engineering
1. 지시문을 명확하게 작성하라 - Write clear instructions
2. 참고할 수 있는 자료를 제공하라 - Provide Reference Text
3. 간단한 작업으로 나누어 진행하라 - Split complex tasks into simpler subtasks
4. 모델에게 생각할 시간을 주어라 - Give model time to think
5. 외부 도구를 활용하라 - Use External Tools
이 글에서 제가 사용한 모델은 모두 GPT-3.5와 GPT-4를 섞어서 사용했어요.
2. 참고할 수 있는 자료를 제공하라 - Provide Reference Text
저희는 살다 보면 긴 글을 읽어야 할 때가 많습니다.
요약은 LLM에게는 매우 쉬운 일이기 때문에 아무리 전문적인 내용을 다루고 있어도 쉽게 요약해낼 수 있습니다.
2 - 1. 참고 자료를 이용하여 문제에 답하도록 하고, 그 근거를 제시하도록 하자 - Instruct the model to answer with citations from a reference text
LLM은 추론에 특화된 친구이기 때문에 요약에서 멈추지 않고 문제에 답하게 하는 등 생각을 해야 하는 일을 주는 것이 더 잘 써먹는 거라고 할 수 있어요.
특히, 답변에 왜 그렇게 생각했는지, 어디서 그런 답을 찾았는지와 같은 출처를 밝히라고 하면 저희도 그 글과 답변을 이해하는 데 더 도움이 되겠죠?
저는 GPT에게 논문과 문제를 주고, 답변과 그 출처를 같이 밝혀달라고 요청해보았어요. 아래는 프롬프트의 일부예요.
You will be provided with a paper delimited by triple quotes and a questions.
Your task is to answer the questions only using information based on paper provided, and also provide citation where you find the idea of answer and what made you think about it. If you can't find clue of the answer from the paper, say like "I can't find it only using this paper."
Answer following format like this: Answer 1. ... Citation 1. ..., Answer 2. ... Citation 2. ..., ...
"""
Research in Human-Computer Interaction (HCI) has been spectacularly successful, and has fundamentally ...
...
"""
Question 1. What is the main topic of this paper?
Question 2. Why is HCI important?
Question 3. Which interaction methods don't cover in this paper?
(1. Moving Recognition, 2. Eye Tracking 3. Multimedia)
영어가 불편한 분들을 위해 간단하게 번역해보았어요.
내가 따옴표 세 개로 둘러싸인 논문과 여러 질문을 주어주면, 너는 그 논문만을 토대로 문제에 답해야 해. 그리고 그렇게 답한 이유도 같이 제공해줘. 만약 논문에서 답을 찾을 수 없으면 "이 논문에서는 답을 찾을 수 없습니다."라고 답 해.
답변은 아래와 같은 형식으로 부탁해:
답 1: ..., 출처 1: ..., 답 2: ... 출처 2: ..., ...
"""
논문 내용... (생략)
"""
질문 1: 이 논문의 주요 내용은?
질문 2: 왜 HCI가 중요하지?
질문 3: 이 논문에서 다루지 않는 상호작용은 뭐지? (1. 움직임 감지, 2. 아이트래킹, 3. 멀티미디어)
아래는 GPT의 결과예요. 문제의 답변과 함께 출처도 같이 밝힌 것을 알 수 있죠?

3. 간단한 작업으로 나누어 진행하라 - Split complex tasks into simpler subtasks
GPT에게 복잡한 과정을 거쳐야 하는 작업을 요청을 해야할 때가 있어요.
그럴 때는 간단한 작업으로 나누어 최종 답을 도출할 수 있도록 하는 것이 좋아요.
작업의 크기가 너무 커서 중간 과정을 생략하게 되면 잘못된 추론을 할 확률이 높아지기 때문에 각 과정을 거치도록 해서 올바른 추론을 하고 있는지 확인하는 것이 좋아요.
3 - 1. 각 과정이 뚜렷하고 독립적이도록 프롬프트를 분류시켜보자 - Use intent classification to identify the most relevant instructions for a user query
복잡한 조건에 따라 작업을 처리해야 한다면 조건을 확실히 구분되게 처리해야 합니다.
여기서 좋은 방법은 조건을 들여쓰기의 개수나 특수 기호의 종류와 개수를 달리하여 정의하는 방법이 있습니다.
예시로 여러 보험 가입자의 유형을 분류하는 프롬프트를 구성해보았습니다.
보험 가입 기간과 종류로 구분하는데, 만족시키는 조건에 따라 비교해야 하는 조건이 달라지는 복잡한 구조를 갖고 있습니다.
따라서 하이픈("-")의 개수로 조건의 레벨을 달리하여 비교 조건을 독립적으로 구성할 수 있도록 했습니다.
너는 주어진 조건에 따라 보험 가입자를 분류하는 역할을 해야 해. 아래 조건을 보고, 여덟 명의 보험 가입자에 따라 유형을 나눠줘.
조건에 대해서, 하이픈("-")의 개수에 따라 조건의 레벨을 나눴어. 아래 조건으로 유형을 나눌 수 없으면 "유형 결정 불가"라고 말하면 돼.
유형을 결정하고 나서는, 그렇게 분류한 이유도 같이 말해야 해. 형식은 "첫 번째로 ... 조건이 있으므로 현재 가능한 유형은 (A, B, ...)이다. 여기서 다음 조건을 고려하면 현재 가능한 유형은 (C, ...)이다. ... 최종적으로 ...을 고려해면 이 가입자의 유형은 D이다." 와 같은 형식으로 답해야 해.
[조건]
만약 보험을 가입한지 10년 이상 되었으면,
- 만약 들은 보험의 종류가 1개이고 암 보험이면,
- - A 유형
- 만약 들은 보험의 종류가 1개이고 생명 보험이면,
- - B 유형
- 만약 들은 보험의 종류가 여러 개이면,
- - 암 보험과 생명 보험을 모두 들었으면
- - - C 유형
- - 암 보험과 생명 보험 중 하나만 들었으면,
- - - D 유형
- - 둘 다 들지 않았으면,
- - - E 유형
그렇지 않으면,
- F 유형
[보험 가입자 정보]
보험 가입자 1. 2010년에 암 보험을 가입하였다.
보험 가입자 2. 2009년에 암 보험과 생명 보험을 가입하였다.
보험 가입자 3. 2013년에 손해 보험을 가입하였다.
보험 가입자 4. 2011년에 생명 보험을 가입하였다.
보험 가입자 5. 2012년에 손해 보험과 암 보험을 가입하였다.
보험 가입자 6. 2010년에 손해 보험과 건강 보험을 가입하였다.
보험 가입자 7. 2016년에 암 보험과 생명 보험을 가입하였다.
보험 가입자 8. 2017년에 손해 보험을 가입하였다.
아래는 GPT의 답변입니다.
이제 각 보험 가입자의 정보를 기반으로 유형을 결정하고 그 이유를 설명해보겠습니다.
[보험 가입자 1]
- 첫 번째로 보험 가입 기간이 10년 이상 되었으므로 현재 가능한 유형은 (A, B, C, D, E)입니다.
- 들은 보험의 종류가 1개이고 암 보험이므로 현재 가능한 유형은 A입니다.
- 최종적으로 이 가입자의 유형은 A입니다.
[보험 가입자 2]
- 첫 번째로 보험 가입 기간이 10년 이상 되었으므로 현재 가능한 유형은 (A, B, C, D, E)입니다.
- 들은 보험의 종류가 여러 개이고 암 보험과 생명 보험을 모두 들었으므로 현재 가능한 유형은 C입니다.
- 최종적으로 이 가입자의 유형은 C입니다.
[보험 가입자 3]
- 첫 번째로 보험 가입 기간이 10년 이상 되었으므로 현재 가능한 유형은 (A, B, C, D, E)입니다.
- 그러나 들은 보험의 종류가 1개이며, 그것이 암 보험이나 생명 보험이 아니기 때문에 조건에 해당하지 않습니다.
- 이 경우 가입자 3의 조건을 만족시키는 추가적인 유형이 명시되어 있지 않으므로 "유형 결정 불가"로 평가하는 것이 적절합니다.
[보험 가입자 4]
- 첫 번째로 보험 가입 기간이 10년 이상 되었으므로 현재 가능한 유형은 (A, B, C, D, E)입니다.
- 들은 보험의 종류가 1개이고 생명 보험이므로 현재 가능한 유형은 B입니다.
- 최종적으로 이 가입자의 유형은 B입니다.
[보험 가입자 5]
- 첫 번째로 보험 가입 기간이 10년 이상 되었으므로 현재 가능한 유형은 (A, B, C, D, E)입니다.
- 들은 보험의 종류가 여러 개이지만, 암 보험을 포함하므로 현재 가능한 유형은 D입니다.
- 최종적으로 이 가입자의 유형은 D입니다.
[보험 가입자 6]
- 첫 번째로 보험 가입 기간이 10년 이상 되었으므로 현재 가능한 유형은 (A, B, C, D, E)입니다.
- 들은 보험의 종류가 여러 개이지만, 암 보험과 생명 보험을 모두 들지 않았으므로 현재 가능한 유형은 E입니다.
- 최종적으로 이 가입자의 유형은 E입니다.
[보험 가입자 7]
- 보험 가입 기간이 10년 미만이므로 현재 가능한 유형은 F입니다.
- 최종적으로 이 가입자의 유형은 F입니다.
[보험 가입자 8]
- 보험 가입 기간이 10년 미만이므로 현재 가능한 유형은 F입니다.
- 최종적으로 이 가입자의 유형은 F입니다.
이러한 분류는 가입 기간, 보험 종류의 수, 그리고 특정 보험 종류의 유무를 기반으로 합니다.
의도한 대로, [보험 가입자 3]은 하이픈 두 개의 조건을 전부 고려했지만 해당하는 조건을 찾지 못 했기 때문에 다음 조건을 고려할 수 없다는 것을 인지하고 "유형 결정 불가"로 알맞게 분류한 것을 알 수 있습니다.
이와 같이 복잡한 조건을 따라 추론해야 할 때는 들여쓰기의 개수나 특수 기호의 종류와 개수와 같은 구분자를 사용하여 복잡한 조건을 고려하도록 할 수 있습니다.
아래와 같이 파이썬의 조건문과 비슷한 형태로 제공하면 LLM이 이해하기 좋다는 의미입니다.
if "보험 기간" >= 10:
if "보험 종류 개수" == 1 and "보험 종류" == "암":
print("A")
elif "보험 종류 개수" == 1 and "보험 종류" == "생명":
print("B")
elif "보험 종류 개수" > 1:
if "암" in "보험 종류" and "생명" in "보험 종류":
print("C")
elif "암" in "보험 종류" or "생명" in "보험 종류":
print("D")
else:
print("E")
else:
print("유형 결정 불가")
else:
print("F")
3 - 2. 긴 대화 활용 시, 이전 대화는 어느 정도 요약해서 제공하자 - For dialogue applications that require very long conversations, summarize or filter previous dialogue
LLM의 정확도는 토큰의 개수가 많아지면 점점 감소합니다.
따라서 지시문을 주절주절 작성하기 보다는 간결하지만 깔끔하게 작성하는 것이 중요합니다. 이는 곧 프롬프트 공학의 중요성과도 관련이 있죠.
지시문이 긴 것을 떠나 제공하는 데이터가 길다면 역시 토큰 개수에 따른 정확도 감소의 효과를 받게 됩니다.
따라서 나누어서 요약을 하거나, 이전 데이터는 요약해서 제공하는 것이 좋은 방법이 될 수 있습니다.
아까 2 - 1에서 사용했던 논문 전문을 요약해달라고 하겠습니다.
하지만 논문을 그대로 제공하기엔 토큰 개수가 4,700개로 말도 안 되게 많습니다. 글자로 환산하면 20,000글자가 넘어가네요.

따라서 저는 목차 단위로 나누어 요약을 해달라고 지시했습니다.
또한 현재 목차가 이전 목차의 내용을 참고할 수도 있으므로 이전 목차에 요약한 내용을 같이 제공하여 정확도를 높이려고 했습니다.
우선 첫 번째 목차인 "1. Introduction"만 넣은 후 요약해달라고 했습니다. 또한, 너무 길어지지 않도록 다섯 줄 아래로 요약해달라고 했습니다. 결과물의 분량을 조절하는 기술도 제가 저번 게시물에서 다뤘죠?
아래 논문을 다섯 줄 아래로 요약해줘.
[1. Introduction]
Research in Human-Computer Interaction (HCI) has been spectacularly successful, and has fundamentally ch...
아래는 결과입니다.
이 논문은 인간-컴퓨터 상호작용(HCI) 기술의 중요한 연구 발전을 간략히 요약하고자 한다. 주로 대학과 정부, 기업 연구소(예: 제록스 PARC)에서의 탐색적인 연구를 다룬다. 이 논문은 주로 컴퓨터 측면의 HCI 기술을 다루며, 실제 제품과는 직접적인 관련이 없는 연구를 의미한다. 이 논문의 동반 기사로 심리학, 디자인, 인간 요소 및 인간공학 등에서의 기여를 논하는 것도 적절하다. HCI 분야의 주요 성과 중 많은 것이 기업에서 개발되었다는 잘못된 인식을 극복하고자 하며, 실제로 대부분의 성공적인 HCI 발전은 대학 연구에서 비롯된 것임을 보여주려고 한다. 주요 HCI 기술들의 자금 지원원을 나열하여 대부분의 발전은 대학 및 연구소에서의 연구에 근간을 두고 있음을 보여준다. 이 논문은 직접 조작, 마우스 포인팅 장치, 창 등과 같은 기본 상호작용 스타일부터 제스처 인식, 멀티미디어, 3D와 같은 미래 인터페이스에 큰 영향을 미칠 것으로 예상되는 기술까지, 여러 중요한 영역을 다룬다.
다음으로 두 번째 목차인 "2. Basic Interactions"을 요약해보겠습니다.
이전 요약본을 같이 제공하여 토큰 수를 줄이면서 이전 내용을 참고할 수 있도록 하였습니다.
너의 역할은 논문 본문을 요약하는 거야.
아래 내용은 아래 논문 이전의 내용을 요약한건데, 논문 본문을 요약할 때 참고해도 좋아.
[이전 내용 요약]
이 논문은 인간-컴퓨터 상호작용(HCI) 기술의 중요한 연구 발전을 간략히 요약...
[논문 본문]
2. Basic Interactions
* Direct Manipulation of graphical objects: The now ubiquitous direct manipulation interface, where visible objects on the screen are directly manipulated with a pointing device, was first demonstrated by Ivan Su...
이와 같은 방법으로 차근차근 논문의 전문을 요약해나가면 됩니다.
요약을 프롬프트에 제공하고, 나온 결과를 또 프롬프트에 제공하고, 요약을 계속 다음 프롬프트의 입력으로 사용하면서 문맥을 잃지 않으며 요약 태스크를 할 수 있습니다.
3 - 3. 재귀적으로 요약하자 -Summarize long documents piecewise and construct a full summary recursively
위와 같은 논문보다 더 긴 문서, 그리고 나누기 애매한 문서의 경우에는 그냥 일정 길이 이상이 넘어가면 자르고 프롬프트에 줄 수 있습니다.
예를 들어, 1,000,000글자 문서를 1,000개의 문서로 나누어서 프롬프트에 전달해주는 방법을 쓸 수 있습니다.
그러면 문서에 대해 1,000개의 요약본이 생기게 되겠죠?
그러면 그 요약본을 다시 100개로 나누어 프롬프트에 전달해줍니다. 그러면 1,000개의 요약본에서 100개의 요약본으로 줄어들겠죠?
마지막으로 100개의 요약본을 프롬프트에 전달해서 최종적으로 하나의 요약본을 얻을 수 있습니다.
이와 같이 재귀적으로 요약본을 생성하면 아무리 긴 문서라도 성공적으로 요약할 수 있습니다.
말로 설명하니 조금 어려운데, 아래 그림을 보면 이해가 될 거예요. 재귀적이라는 의미를 아시겠죠?

하지만 여기서 주의할 점이 있어요.
문서를 나눌 때 어느 정도 Offset을 두고 분리하는 것이 좋아요.
문서를 그저 글자 수, 문장 수 같은 기준으로 자르기 때문에 문맥이 소실될 수 있어요.
예를 들어, 아래와 같은 대화가 있다고 해봅시다.
A : 어제 시험 잘봤어?
B : 아니, 망쳐버렸어.
A : 시험지 좀 보자.
B : 찢어버렸어.
A : 속 시원했겠네.
어쩌다가 아래와 같이 두 대화로 나뉘어졌어요.
A : 어제 시험 잘봤어?
B : 아니, 망쳐버렸어.
A : 시험지 좀 보자.
B : 찢어버렸어.
A : 속 시원했겠네.
두 번째 대화를 보면, "시험을 잘봐서 찢었다!"라고 잘못 이해 할 가능성이 있죠?
그래서 Offset을 두어서 아래와 같이 분리하면 문맥을 어느 정도 유지할 수 있어요.
A : 어제 시험 잘봤어?
B : 아니, 망쳐버렸어.
A : 시험지 좀 보자.
A : 시험지 좀 보자.
B : 찢어버렸어.
A : 속 시원했겠네.
Offset의 크기는 문서의 종류, 크기 등을 고려해서 좋은 성능을 낼 수 있도록 조절해야 해요.
너무 크면 토큰의 크기가 커지게 되어 분리하는 의미가 점점 없어질거고, 너무 작아지면 문맥 소실을 못 막을 가능성이 높아져요.
아래 그림으로 보면 Offset의 의미가 한 번에 이해 되죠?

오늘 내용은 여기까지입니다.
특히 아래 세 가지 기법은 유용하게 쓰이니 알아두는 것이 좋아요.
1. 문제에 답하도록 하고 근거를 제시하도록 하기
2, 들여쓰기로 조건 분리하기
3. 긴 문서는 나누어 요약하기
다음 글도 중요하고 좋은 내용을 담고 있으니 꼭 봐주세요!
제 글이 많은 도움이 되었길 바라며,
긴 글 봐주셔서 감사합니다!
멋진 개발자가 되기 위해 더 열심히 달리겠습니다!
- 달맹 -
'Development' 카테고리의 다른 글
| Prompt Engineering: ChatGPT와 대화하기 4편 [끝] (0) | 2024.03.10 |
|---|---|
| Prompt Engineering: ChatGPT와 대화하기 3편 (0) | 2024.03.10 |
| TOPCIT 체험기 [문제 예시, 유형, 후기] (0) | 2024.03.10 |
| Prompt Engineering: ChatGPT와 대화하기 1편 (0) | 2024.03.09 |
| 비동기 프로그래밍 4편 [끝] (0) | 2024.03.05 |