[ChatGPT] 프롬프트 작성 가이드라인
ChatGPT Prompt Engineering for Developers 중 Guidelines for Prompting 정리
들어가기 전에
개-하!
재밌어보여서 + 빠르다 빨라 현대사회를 따라가기 위해 듣는 중이고여? 저슽 저의 기록용으로 작성합니다.
아래 내용은 ChatGPT 한테 시킨 직역이 많고, 간간히 의역 포함되어있습니다. 그럼 ㄱㄱ
프롬프트 작성 가이드라인
이 강의에서는 원하는 결과를 얻기 위해 도움이 되는 효과적인 프롬프트 작성을 위한 두 가지 주요 원칙을 설명합니다.
원칙 1. 명확하고 구체적인 명령어를 사용합니다.
전략 1. 구분자를 사용합니다.
구분자는 """
, ```
, <>
,---
, <tag> </tag>
와 같이 무엇이든 될 수 있습니다.
어떤 단락을 요약하는것이 목표라면 프롬프트에는 “ ```
으로 구분된 텍스트를 한 문장으로 요약해라” 라고 지시할 수 있습니다.
이때 요약하고자 하는 하는 문장은 ```
라는 구분자로 감싸져있기 때문에, 해당 문장을 분리해서 모델에게 명확한 정보를 전달하는 데 사용됩니다.
예시
text = f"""
모델이 수행해야 하는 작업을 명확하고 구체적인 지시로 표현해야 합니다.
이렇게 하면 모델이 원하는 출력을 만들도록 안내할 수 있으며, 관련 없거나 잘못된 응답을 받을 가능성을 줄일 수 있습니다.
명확한 프롬프트를 작성하는 것을 간단한 프롬프트를 작성하는 것과 혼동하지 마세요.
많은 경우, 긴 프롬프트가 모델에 대한 더 많은 명확성과 문맥을 제공하여 보다 자세하고 관련성 높은 출력을 제공할 수 있습니다.
"""
prompt = f"""
세 개의 역따옴표로 구분된 텍스트를 한 문장으로 요약하십시오.
```{text}```
"""
response = get_completion(prompt)
print(response)
결과
모델 작업을 명확하게 안내하는 프롬프트를 작성해야 하며, 긴 프롬프트가 더 자세하고 관련성 높은 출력을 제공할 수 있다.
전략 2: 구조화된 출력을 요청합니다.
모델 출력을 파싱하기 쉽게 만들기 위해 HTML 또는 JSON과 같은 구조화된 출력을 요청하는 것이 도움이 될 수 있습니다.
아래 예시의 결과로 나온 JSON 구조화된 출력을 사용하면 코드에서 딕셔너리 또는 리스트로 읽을 수 있습니다.
예시
prompt = f"""
JSON 형식으로 book_id, title, author, genre 키를 가진 3권의 가짜 책 제목, 저자, 장르 목록을 생성해라.
"""
response = get_completion(prompt)
print(response)
결과
{
"books": [
{
"book_id": 1,
"title": "The Great Gatsby",
"author": "F. Scott Fitzgerald",
"genre": "Fiction"
},
{
"book_id": 2,
"title": "To Kill a Mockingbird",
"author": "Harper Lee",
"genre": "Fiction"
},
{
"book_id": 3,
"title": "The Hitchhiker's Guide to the Galaxy",
"author": "Douglas Adams",
"genre": "Science Fiction"
}
]
}
전략 3: 조건이 충족되는지 확인합니다.
다음 전략은 모델이 조건을 충족시켰는지 확인하는 것입니다.
task 를 달성할 수 있는지 먼저 확인하고, 만약 조건이 충족되지 않으면 작업을 중단하도록 합니다. 예상치 못한 오류 또는 결과를 방지하기 위해 모델이 어떻게 처리해야 할지에 대한 잠재적인 엣지 케이스를 고려할 수도 있습니다.
예시 — 조건 충족
text_1 = f"""
차를 만드는 것은 쉽습니다! 먼저 물을 끓이세요. 그 사이에 컵을 가져와서 차백을 넣으세요. 물이 충분히 뜰 때 차백 위에 끓인 물을 부어주세요. 차가 우려난 후에 차백을 빼주세요. 원한다면 설탕이나 우유를 넣을 수 있습니다. 그리고 이제 맛있는 차가 완성됐습니다!
"""
prompt = f"""
세 개의 따옴표로 구분된 텍스트가 제공됩니다.
만약 그 안에 일련의 지시문이 있다면 다음 형식으로 재작성하세요:
1단계 - ...
2단계 - ...
...
N단계 - ...
만약 그 안에 지시문이 없다면, "지시문 없음"을 작성하세요. # 모델이 조건을 충족시켰는지 확인하는 부분
\"\"\"{text_1}\"\"\"
"""
response = get_completion(prompt)
print("Completion for Text 1:")
print(response)
결과
Completion for Text 1:
1단계 - 물을 끓이세요.
2단계 - 컵을 가져와서 차백을 넣으세요.
3단계 - 물이 충분히 뜰 때 차백 위에 끓인 물을 부어주세요.
4단계 - 차가 우려난 후에 차백을 빼주세요.
5단계 - 원한다면 설탕이나 우유를 넣을 수 있습니다.
6단계 - 맛있는 차가 완성됐습니다!
예시 — 조건 미충족
text_2 = f"""
오늘 해가 밝게 비추고 있고, 새들이 지저귀고 있습니다. 공원에서 산책하기에 아름다운 날입니다. 꽃들이 피어있고 나무들이 바람에 부드럽게 흔들리고 있습니다. 사람들은 아름다운 날씨를 즐기기 위해 밖에 나와 있습니다. 피크닉을 하거나, 게임을 하거나, 풀 위에서 쉬거나 하는 사람들이 있습니다. 자연의 아름다움을 즐기며 시간을 보내기에 완벽한 날입니다.
"""
prompt = f"""
세 개의 따옴표로 구분된 텍스트가 제공됩니다.
만약 그 안에 일련의 지시문이 있다면 다음 형식으로 재작성하세요:
1단계 - ...
2단계 - ...
...
N단계 - ...
만약 그 안에 지시문이 없다면, "지시문 없음"을 작성하세요.
\"\"\"{text_2}\"\"\"
"""
response = get_completion(prompt)
print("Completion for Text 2:")
print(response)
결과
Completion for Text 2:
지시문 없음
전략 4: Few-shot prompting
작업을 성공적으로 완료하는 예시를 제공하고, 그런 다음 모델에게 작업을 수행하도록 요청합니다.
아래 예시처럼 아이와 조부모 사이의 대화를 먼저 제공하여, 이 예시를 기반으로 일관된 스타일로 대답하도록 모델에 지시할 수 있습니다. 이전 대화에서 은유유적인 표현으로 대답을 했기 때문에, 다음 대답에서도 은유를 사용합니다.
예시
prompt = f"""
당신의 임무는 일관된 스타일로 대답하는 것입니다.
<아이>: 인내심에 대해 가르쳐주세요.
<조부모>: 가장 깊은 계곡을 파내는 강은 작은 샘터에서 시작되고, 가장 웅장한 교향곡은 하나의 음표에서 시작되며, 가장 복잡한 벽걸이 융단은 하나의 실로부터 시작된단다.
<아이>: 탄력성에 대해 가르쳐주세요.
"""
response = get_completion(prompt)
print(response)
결과
탄력성은 바람과 함께 휘어지되 결코 꺾이지 않는 나무와 같습니다. 그것은 역경에서 다시 일어설 수 있는 능력이고, 상황이 어려워질 때에도 계속해서 앞으로 나아갈 수 있는 능력입니다. 폭풍이 몰아칠 때마다 더 강해지는 나무처럼, 회복력은 시간이 지남에 따라 발전하고 강화될 수 있는 자질입니다.
(🤔 근데 영어로 하면 은유적인 표현으로 잘 대답해주는데, 한국어로 하면 어미만 맞춰서 탄력성의 정의에 대해 말해줬음;;)
원칙 2. 모델이 생각할 시간을 제공합니다.
만약 모델이 잘못된 결론에 서둘러 도달해서 추론 오류를 범하는 경우에는, 최종 답변을 제공하기 전에 일련의 관련된 추론을 실행하도록 쿼리를 다시 구성해 보는 것이 좋습니다. 짧은 시간 또는 적은 단어로 수행하기에 너무 복잡한 작업을 모델에게 지시하면 잘못된 추측을 하게 될 가능성이 높으므로, 이러한 상황에서 모델에게 문제를 더 오랫동안 고민하도록 지시하여 더 많은 계산 노력을 기울일 수 있습니다.
전략 1: 작업을 완료하기 위해 필요한 단계를 구체적으로 명시합니다.
아래 예시에서는
- 하나의 문장으로 구성된 삼중 역따옴표로 구분된 다음 텍스트의 요약을 수행하고,
- 이를 프랑스어로 번역하며,
- 프랑스어 요약에서 각 이름을 나열하고,
french_summary
와num_names
이라는 키를 포함하는 JSON 객체를 출력하도록 지시합니다.
모든 답변은 줄 바꿈으로 구분하도록 합니다.
예시
text = f"""
마을에서 자란 형제 Jack과 Jill은 산 꼭대기 우물에서 물을 길어오기 위해 여행을 떠납니다. 노래를 부르며 오르던 중, Jack이 바위에 걸려서 산 아래로 떨어지고, Jill도 뒤따랐습니다. 살짝 상처를 입었지만, 둘은 용감하게 집으로 돌아와 안아주는 가족들의 위로를 받았습니다. 사건에도 불구하고, 둘의 모험가 정신은 사라지지 않았으며, 둘은 기쁜 마음으로 계속해서 탐험을 이어갔습니다.
"""
# example 1
prompt_1 = f"""
다음 동작을 수행하세요:
1- 세 개의 역따옴표로 구분된 다음 텍스트를 1문장으로 요약합니다.
2- 요약문을 프랑스어로 번역합니다.
3- 프랑스어 요약문에 있는 모든 이름을 나열합니다.
4- 다음 키를 포함하는 JSON 객체를 출력합니다 : french_summary, num_names.
각 답변을 줄바꿈 문자로 구분하세요.
Text:
```{text}```
"""
response = get_completion(prompt_1)
print("Completion for prompt 1:")
print(response)
결과
Completion for prompt 1:
1- Jack과 Jill은 우물에서 물을 길어오다가 사고를 당하고 상처를 입었지만, 가족들의 위로를 받고 계속해서 모험을 이어갑니다.
2- Jack et Jill, qui ont grandi dans le village, partent en voyage pour puiser de l'eau dans un puits au sommet de la montagne. En chantant en montant, Jack est tombé sur un rocher et Jill l'a suivi. Bien qu'ils aient été légèrement blessés, ils ont été réconfortés par leur famille qui les a accueillis à bras ouverts à leur retour à la maison. Malgré l'incident, leur esprit d'aventure n'a pas disparu et ils ont continué à explorer avec joie.
3- Jack, Jill
4- {
"french_summary": "Jack et Jill, qui ont grandi dans le village, partent en voyage pour puiser de l'eau dans un puits au sommet de la montagne. En chantant en montant, Jack est tombé sur un rocher et Jill l'a suivi. Bien qu'ils aient été légèrement blessés, ils ont été réconfortés par leur famille qui les a accueillis à bras ouverts à leur retour à la maison. Malgré l'incident, leur esprit d'aventure n'a pas disparu et ils ont continué à explorer avec joie.",
"num_names": 2
}
(🤔 영어에서는 line break 가 잘 먹어서 한칸씩 띄워지는데,,, 한국어로 주니까 공백이 안생겨있다 )
위와 동일한 작업을 모델의 출력 구조를 명시해서 실행해보겠습니다. 왜냐하면 1-
이나 2-
와 같은 형식을 원하지 않을 수도 있고, 입력마다 출력 형식이 달라질 수도 있기 때문입니다. 따라서 표준화된 형식으로 결과를 전달하면 코드에서도 예상된 값으로 사용할 수 있습니다.
예시
prompt_2 = f"""
Your task is to perform the following actions:
다음 동작을 수행하세요:
1- <> 로 구분된 다음 텍스트를 1문장으로 요약합니다.
2- 요약문을 프랑스어로 번역합니다.
3- 프랑스어 요약문에 있는 모든 이름을 나열합니다.
4- 다음 키를 포함하는 JSON 객체를 출력합니다 : french_summary, num_names.
다음 형식을 사용하십시오:
텍스트 : <요약할 텍스트>
요약 : <요약>
번역 : <요약 번역>
이름 : <요약에서의 이름 목록>
출력 JSON : <summary 및 num_names이 포함된 JSON>
Text: <{text}>
"""
response = get_completion(prompt_2)
print("\nCompletion for prompt 2:")
print(response)
결과
Completion for prompt 2:
요약 : Jack과 Jill은 우물에서 물을 길어오기 위해 여행을 떠납니다. 그러나 Jack이 바위에 걸려서 산 아래로 떨어지고, Jill도 뒤따랐습니다. 상처를 입었지만, 둘은 용감하게 집으로 돌아와 안아주는 가족들의 위로를 받았습니다. 그들은 여전히 모험가 정신을 가지고 있으며, 계속해서 탐험을 이어갑니다.
번역 : Jack et Jill, qui ont grandi dans un village, partent en voyage pour chercher de l'eau dans un puits au sommet d'une montagne. En chantant, Jack tombe d'un rocher et Jill le suit. Bien qu'ils soient légèrement blessés, ils rentrent chez eux courageusement et reçoivent le réconfort de leur famille. Malgré l'incident, leur esprit d'aventure ne disparaît pas et ils continuent à explorer avec joie.
이름 : Jack, Jill
출력 JSON : {"french_summary": "Jack et Jill, qui ont grandi dans un village, partent en voyage pour chercher de l'eau dans un puits au sommet d'une montagne. En chantant, Jack tombe d'un rocher et Jill le suit. Bien qu'ils soient légèrement blessés, ils rentrent chez eux courageusement et reçoivent le réconfort de leur famille. Malgré l'incident, leur esprit d'aventure ne disparaît pas et ils continuent à explorer avec joie.", "num_names": 2}
전략 2: 서둘러 결론으로 도달하기 전에 모델에게 자체적으로 해결책을 찾도록 지시합니다.
때로는 모델에게 명시적으로 자체적으로 해결책을 추론하도록 지시하면 더 나은 결과를 얻을 수 있습니다. 이는 우리가 모델이 사람처럼 정답 여부를 판단하기 전에 실제로 문제를 해결하는 데 시간을 주는 것과 같은 개념입니다.
아래 예시에서는 모델에게 학생의 답안이 정답인지 아닌지를 판단하도록 지시합니다. 실제로 이 답안은 틀렸지만 (유지 보수 비용을 유지 보수 비용을 100,000 + 10x
가 아닌, 100,000 + 100x
로 계산했기 때문에), 학생의 풀이 과정만 보면 정답인것처럼 보입니다.
예시
prompt = f"""
학생의 해결책이 옳은지 아닌지 결정하세요.
문제:
저는 태양광 발전소를 건설하고 있는데, 금융 측면에서 도움이 필요합니다.
땅 비용은 1평방 피트 당 $100입니다.
태양광 패널은 1평방 피트 당 $250에 구매할 수 있습니다.
유지보수를 위한 계약에서는 고정 비용으로 연간 $100,000을, 그리고 1평방 피트 당 추가로 $10의 비용이 듭니다.
제일 첫 해의 운영 총 비용을 평방 피트 수의 함수로 구하세요.
학생의 해결책:
x를 평방 피트의 설치 크기로 정의합니다.
비용:
땅 비용: 100x
태양광 패널 비용: 250x
유지보수 비용: 100,000 + 100x
총 비용: 100x + 250x + 100,000 + 100x = 450x + 100,000
"""
response = get_completion(prompt)
print(response)
결과
해결책이 옳습니다.
따라서 이 문제를 해결하기 위해 모델에게 자체적으로 해결책을 찾도록 지시하고, 그 후에 모델의 해결책과 학생의 답안을 비교하여 학생의 답안이 올바른지 판단하도록 지시합니다.
결과적으로 모델이 직접 계산을 수행하고 정답을 구한 후 학생의 답안과 비교하여 일치하지 않음을 발견는데, 이를 통해 모델이 문제를 스스로 해결하고 답안을 제시하도록 하면 더 정확한 결과를 얻을 수 있다는 예시를 보여주고 있습니다.
예시
prompt = f"""
당신의 작업은 학생의 해답이 올바른지 여부를 결정하는 것입니다.
문제를 해결하려면 다음을 수행하십시오.
먼저 문제에 대한 자체 해결책을 찾으십시오.
그런 다음 학생의 해답과 비교하여 학생의 해답이 올바른지 여부를 평가하십시오.
학생의 해답이 올바른지 여부를 결정하기 전에 반드시 스스로 문제를 해결해야 합니다.
다음 형식을 사용합니다:
질문:
```
질문 내용
```
학생의 답:
```
학생의 답변 내용
```
실제 솔루션:
```
정답 도출 과정 및 답변
```
학생의 답변과 방금 계산된 정답은 무엇입니까?:
```
학생의 답변 및 계산된 정답
```
학생의 답변과 방금 계산된 정답이 일치합니까?:
```
예 또는 아니오
```
학생 성적:
```
정답 또는 오답
```
질문:
```
태양광 발전 시설을 건설하고 금융 문제를 해결해야합니다.
- 토지는 평방 피트당 $100 입니다.
- 태양광 패널은 평방 피트당 $250 에 구매할 수 있습니다.
- 유지보수를 위한 계약을 $100000 로 체결했으며, 추가로 평방 피트당 $10 의 비용이 듭니다.
평방 피트 수에 대한 첫 해 운영 총 비용은 얼마입니까?
```
학생의 답:
```
x를 평방 피트의 설치 크기로 정의합니다.
비용:
땅 비용: 100x
태양광 패널 비용: 250x
유지보수 비용: 100,000 + 100x
총 비용: 100x + 250x + 100,000 + 100x = 450x + 100,000
```
실제 솔루션:
"""
response = get_completion(prompt)
print(response)
결과
정답 도출 과정 및 답변:
- 토지 비용: 100달러/평방피트
- 태양광 패널 비용: 250달러/평방피트
- 유지보수 비용: 10달러/평방피트
- 첫 해 운영 총 비용: (100 + 250 + 10) * x + 100000 = 360x + 100000
학생의 답변 및 계산된 정답:
학생의 답변: 450x + 100,000
계산된 정답: 360x + 100,000
학생의 답변과 방금 계산된 정답이 일치합니까?:
아니오
학생 성적:
오답
(🤔 사실 원문 영어 예시에서는 아래 질문이 추가적으로 없음.
학생의 답변과 방금 계산된 정답은 무엇입니까?:
학생의 답변 및 계산된 정답
그런데 한국어에서는 이거 안넣어주면 잘 계산해놓고서도 학생과 자신의 답이 일치하다고 해서 중간에 한번 더 질문 넣어준거임; ㅜ)
한계점 : 환각 현상 (Hallucinations)
환각 현상은 모델이 덜 알려진 주제에 대한 질문에 답하려고 시도하고, 그럴싸한 소리를 내지만 실제로는 사실이 아닌 것을 만들어내는 경우를 말합니다. 이것은 모델의 약점 중 하나이며, 현재 적극적으로 대처하려고 노력하고 있는 것입니다.
이러한 문제를 피하기 위해서, 앞서 배운 기술들 중 일부를 사용하세요.
또한, 텍스트를 기반으로 모델이 답변을 생성하도록 원하는 경우, 모델이 먼저 텍스트에서 관련된 인용문을 찾도록 요청한 다음 이러한 인용문을 사용하여 질문에 대답하도록 요청하는 것이 환각을 줄이는 추가적인 전략입니다.
출처
https://learn.deeplearning.ai/chatgpt-prompt-eng/lesson/2/guidelines