프롬프트 엔지니어링
프롬프트 엔지니어링 (Prompt engineering)
프롬프트 엔지니어링(또는 프롬프팅)은 자연어를 사용해 다양한 작업에서 대규모 언어 모델(LLM)의 성능을 향상시키는 기법입니다. 프롬프트는 모델이 원하는 출력을 생성하도록 이끌 수 있습니다. 많은 경우 작업에 파인튜닝된 모델조차 필요하지 않습니다. 좋은 프롬프트만 있으면 됩니다.
출처: 문서
본문
LLM에 일부 텍스트를 분류하도록 프롬프팅해 보세요. 프롬프트를 만들 때는 작업과 결과가 어떻게 보여야 하는지에 대해 매우 구체적인 지시를 제공하는 것이 중요합니다.
from transformers import pipeline
import torch
pipeline = pipeline(task="text-generation", model="mistralai/Mistral-7B-Instruct-v0.1", dtype=torch.bfloat16, device_map="auto")
prompt = """Classify the text into neutral, negative or positive.
Text: This movie is definitely one of my favorite movies of its kind. The interaction between respectable and morally strong characters is an ode to chivalry and the honor code amongst thieves and policemen.
Sentiment:
"""
outputs = pipeline(prompt, max_new_tokens=10)
for output in outputs:
print(f"Result: {output['generated_text']}")
Result: Classify the text into neutral, negative or positive.
Text: This movie is definitely one of my favorite movies of its kind. The interaction between respectable and morally strong characters is an ode to chivalry and the honor code amongst thieves and policemen.
Sentiment:
Positive
언어는 믿을 수 없을 정도로 미묘하고 표현력이 풍부하기 때문에, 기대하는 결과를 만들어내는 프롬프트를 설계하는 것이 도전 과제입니다.
이 가이드는 언어 및 추론 작업을 해결하기 위한 프롬프트 엔지니어링 모범 사례, 기법, 예시를 다룹니다.
모범 사례 (Best practices)
-
최상의 성능을 위해 최신 모델을 선택해 보세요. LLM에는 base와 instruction-tuned(또는 chat) 두 가지 변형이 있다는 점을 기억하세요.
Base 모델은 초기 프롬프트가 주어지면 텍스트를 완성하는 데 뛰어나지만 지시를 따르는 데는 그렇게 좋지 않습니다. Instruction-tuned 모델은 지시적 또는 대화형 데이터로 훈련된 base 모델의 특수 버전입니다. 따라서 instruction-tuned 모델이 프롬프팅에 더 잘 맞습니다.
[!WARNING] 현대 LLM은 보통 디코더 전용(decoder-only) 모델이지만, Flan-T5나 BART 같은 일부 인코더-디코더 LLM도 프롬프팅에 사용할 수 있습니다. 이러한 모델은 Pipeline을 사용하는 대신 AutoModelForSeq2SeqLM 클래스로 직접 로드하고 모델 자체에서 출력을 생성하세요.
-
짧고 간단한 프롬프트로 시작하고, 더 나은 결과를 얻기 위해 반복해 보세요.
-
지시를 프롬프트의 시작이나 끝에 두세요. 더 긴 프롬프트의 경우 모델은 어텐션이 2차적으로 확장되지 않도록 최적화를 적용할 수 있는데, 이는 프롬프트의 시작과 끝에 더 강조를 둡니다.
-
지시를 관심 텍스트와 명확하게 분리하세요.
-
작업과 원하는 출력에 대해 구체적이고 설명적으로 표현하세요. 예를 들어 형식, 길이, 스타일, 언어를 포함합니다. 모호한 설명과 지시는 피하세요.
-
지시는 "하지 말 것"보다 "무엇을 할 것"에 초점을 맞춰야 합니다.
-
첫 단어나 첫 문장을 써서 모델이 올바른 출력을 생성하도록 이끄세요.
-
결과를 개선하기 위해 few-shot이나 chain-of-thought 같은 다른 기법도 시도해 보세요.
-
다양한 모델로 프롬프트를 테스트해 견고성을 평가하세요.
-
프롬프트 성능을 버전 관리하고 추적하세요.
기법 (Techniques)
좋은 프롬프트만 만드는 것(제로샷 프롬프팅이라고도 함)으로는 원하는 결과를 얻기에 충분하지 않을 수 있습니다. 최상의 성능을 얻으려면 몇 가지 프롬프팅 기법을 시도해야 할 수 있습니다.
이 섹션에서는 몇 가지 프롬프팅 기법을 다룹니다.
Few-shot 프롬프팅
Few-shot 프롬프팅은 입력이 주어졌을 때 모델이 생성해야 하는 것의 구체적인 예시를 포함해 정확도와 성능을 향상시킵니다. 명시적인 예시는 모델이 작업과 찾고 있는 출력 형식을 더 잘 이해하게 해 줍니다. 성능에 어떤 영향을 미치는지 확인하려면 서로 다른 수의 예시(2, 4, 8 등)를 실험해 보세요. 아래 예시는 반환해야 할 출력 형식(MM/DD/YYYY 형식의 날짜)의 예시 1개(1-shot)를 모델에 제공합니다.
from transformers import pipeline
import torch
pipeline = pipeline(model="mistralai/Mistral-7B-Instruct-v0.1", dtype=torch.bfloat16, device_map="auto")
prompt = """Text: The first human went into space and orbited the Earth on April 12, 1961.
Date: 04/12/1961
Text: The first-ever televised presidential debate in the United States took place on September 28, 1960, between presidential candidates John F. Kennedy and Richard Nixon.
Date:"""
outputs = pipeline(prompt, max_new_tokens=12, do_sample=True, top_k=10)
for output in outputs:
print(f"Result: {output['generated_text']}")
# Result: Text: The first human went into space and orbited the Earth on April 12, 1961.
# Date: 04/12/1961
# Text: The first-ever televised presidential debate in the United States took place on September 28, 1960, between presidential candidates John F. Kennedy and Richard Nixon.
# Date: 09/28/1960
few-shot 프롬프팅의 단점은 더 긴 프롬프트를 만들어야 해서 계산과 지연 시간이 증가한다는 점입니다. 또한 프롬프트 길이에도 한계가 있습니다. 마지막으로, 모델이 예시에서 의도하지 않은 패턴을 학습할 수 있으며, 복잡한 추론 작업에서는 잘 작동하지 않을 수 있습니다.
현대의 instruction-tuned LLM에 대한 few-shot 프롬프팅을 개선하려면 모델 특유의 chat template을 사용하세요. 이러한 모델은 "user"와 "assistant" 사이의 턴 기반 대화가 있는 데이터셋으로 훈련됩니다. 프롬프트를 이에 맞춰 구성하면 성능이 향상될 수 있습니다.
프롬프트를 턴 기반 대화로 구성하고 apply_chat_template 메서드를 사용해 토크나이즈하고 형식화하세요.
from transformers import pipeline
import torch
pipeline = pipeline(model="mistralai/Mistral-7B-Instruct-v0.1", dtype=torch.bfloat16, device_map="auto")
messages = [
{"role": "user", "content": "Text: The first human went into space and orbited the Earth on April 12, 1961."},
{"role": "assistant", "content": "Date: 04/12/1961"},
{"role": "user", "content": "Text: The first-ever televised presidential debate in the United States took place on September 28, 1960, between presidential candidates John F. Kennedy and Richard Nixon."}
]
prompt = pipeline.tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
outputs = pipeline(prompt, max_new_tokens=12, do_sample=True, top_k=10)
for output in outputs:
print(f"Result: {output['generated_text']}")
기본 few-shot 프롬프팅 접근 방식이 단일 텍스트 문자열에 예시를 포함한 반면, 채팅 템플릿 형식은 다음과 같은 이점을 제공합니다.
- 모델이 사용자 입력과 어시스턴트 출력의 기대 역할뿐 아니라 패턴을 더 잘 인식할 수 있으므로 잠재적으로 이해도가 향상됩니다.
- 훈련 중 입력과 같은 구조이므로 모델이 원하는 출력 형식을 더 일관되게 생성할 수 있습니다.
항상 특정 instruction-tuned 모델의 문서를 확인해 채팅 템플릿의 형식에 대해 더 알아보고, 그에 맞게 few-shot 프롬프트를 구성하세요.
Chain-of-thought
Chain-of-thought(CoT)는 모델이 주제에 대해 더 철저하게 "생각"하도록 돕는 일련의 프롬프트를 제공함으로써 더 일관되고 논리적인 출력을 생성하는 데 효과적입니다.
아래 예시는 중간 추론 단계를 거치도록 모델에 여러 프롬프트를 제공합니다.
from transformers import pipeline
import torch
pipeline = pipeline(model="mistralai/Mistral-7B-Instruct-v0.1", dtype=torch.bfloat16, device_map="auto")
prompt = """Let's go through this step-by-step:
1. You start with 15 muffins.
2. You eat 2 muffins, leaving you with 13 muffins.
3. You give 5 muffins to your neighbor, leaving you with 8 muffins.
4. Your partner buys 6 more muffins, bringing the total number of muffins to 14.
5. Your partner eats 2 muffins, leaving you with 12 muffins.
If you eat 6 muffins, how many are left?"""
outputs = pipeline(prompt, max_new_tokens=20, do_sample=True, top_k=10)
for output in outputs:
print(f"Result: {output['generated_text']}")
Result: Let's go through this step-by-step:
1. You start with 15 muffins.
2. You eat 2 muffins, leaving you with 13 muffins.
3. You give 5 muffins to your neighbor, leaving you with 8 muffins.
4. Your partner buys 6 more muffins, bringing the total number of muffins to 14.
5. Your partner eats 2 muffins, leaving you with 12 muffins.
If you eat 6 muffins, how many are left?
Answer: 6
few-shot 프롬프팅과 마찬가지로 CoT의 단점은 모델이 복잡한 작업을 추론하도록 돕는 일련의 프롬프트 설계에 더 많은 노력이 필요하고, 프롬프트 길이가 지연 시간을 증가시킨다는 점입니다.
파인튜닝 (Fine-tuning)
프롬프팅은 LLM을 사용하는 강력한 방법이지만, 파인튜닝된 모델이나 심지어 모델을 파인튜닝하는 것이 더 잘 작동하는 시나리오도 있습니다.
파인튜닝된 모델이 합리적인 선택인 몇 가지 예시 시나리오는 다음과 같습니다.
- 도메인이 LLM이 사전훈련된 것과 극도로 다르고, 광범위한 프롬프팅으로도 원하는 결과를 얻지 못한 경우.
- 모델이 저자원 언어(low-resource language)에서 잘 작동해야 하는 경우.
- 엄격한 규제 요구사항이 있는 민감한 데이터로 모델을 훈련해야 하는 경우.
- 비용, 프라이버시, 인프라 또는 기타 제약으로 인해 작은 모델을 사용하는 경우.
이러한 모든 시나리오에서 모델을 훈련할 충분히 큰 도메인 특화 데이터셋이 있고, 충분한 시간과 리소스가 있으며, 파인튜닝 비용이 그만한 가치가 있는지 확인하세요. 그렇지 않다면 프롬프트 최적화를 시도하는 편이 더 나을 수 있습니다.
예시 (Examples)
아래 예시는 서로 다른 작업에 LLM을 프롬프팅하는 것을 보여줍니다.
from transformers import pipeline
import torch
pipeline = pipeline(model="mistralai/Mistral-7B-Instruct-v0.1", dtype=torch.bfloat16, device_map="auto")
prompt = """Return a list of named entities in the text.
Text: The company was founded in 2016 by French entrepreneurs Clément Delangue, Julien Chaumond, and Thomas Wolf in New York City, originally as a company that developed a chatbot app targeted at teenagers.
Named entities:
"""
outputs = pipeline(prompt, max_new_tokens=50, return_full_text=False)
for output in outputs:
print(f"Result: {output['generated_text']}")
Result: [Clément Delangue, Julien Chaumond, Thomas Wolf, company, New York City, chatbot app, teenagers]
from transformers import pipeline
import torch
pipeline = pipeline(model="mistralai/Mistral-7B-Instruct-v0.1", dtype=torch.bfloat16, device_map="auto")
prompt = """Translate the English text to French.
Text: Sometimes, I've believed as many as six impossible things before breakfast.
Translation:
"""
outputs = pipeline(prompt, max_new_tokens=20, do_sample=True, top_k=10, return_full_text=False)
for output in outputs:
print(f"Result: {output['generated_text']}")
Result: À l'occasion, j'ai croyu plus de six choses impossibles
from transformers import pipeline
import torch
pipeline = pipeline(model="mistralai/Mistral-7B-Instruct-v0.1", dtype=torch.bfloat16, device_map="auto")
prompt = """Permaculture is a design process mimicking the diversity, functionality and resilience of natural ecosystems. The principles and practices are drawn from traditional ecological knowledge of indigenous cultures combined with modern scientific understanding and technological innovations. Permaculture design provides a framework helping individuals and communities develop innovative, creative and effective strategies for meeting basic needs while preparing for and mitigating the projected impacts of climate change.
Write a summary of the above text.
Summary:
"""
outputs = pipeline(prompt, max_new_tokens=30, do_sample=True, top_k=10, return_full_text=False)
for output in outputs:
print(f"Result: {output['generated_text']}")
Result: Permaculture is the design process that involves mimicking natural ecosystems to provide sustainable solutions to basic needs. It is a holistic approach that comb
from transformers import pipeline
import torch
pipeline = pipeline(model="mistralai/Mistral-7B-Instruct-v0.1", dtype=torch.bfloat16, device_map="auto")
prompt = """Answer the question using the context below.
Context: Gazpacho is a cold soup and drink made of raw, blended vegetables. Most gazpacho includes stale bread, tomato, cucumbers, onion, bell peppers, garlic, olive oil, wine vinegar, water, and salt. Northern recipes often include cumin and/or pimentón (smoked sweet paprika). Traditionally, gazpacho was made by pounding the vegetables in a mortar with a pestle; this more laborious method is still sometimes used as it helps keep the gazpacho cool and avoids the foam and silky consistency of smoothie versions made in blenders or food processors.
Question: What modern tool is used to make gazpacho?
Answer:
"""
outputs = pipeline(prompt, max_new_tokens=10, do_sample=True, top_k=10, return_full_text=False)
for output in outputs:
print(f"Result: {output['generated_text']}")
Result: A blender or food processor is the modern tool