프롬프트 템플릿은 크게 2가지가 존재합니다.
- Prompt Template
- Chat Prompt Template
1번 Prompt Template은 일반적인 프롬프트 템플릿을 생성할때 활용합니다.
2번 Chat Prompt Template은 채팅 LLM에 프롬프트를 전달하는 데에 활용할 수 있는 특화 프롬프트 템플릿입니다.
Prompt 예시
from langchain.prompts import PromptTemplate, ChatPromptTemplate
#프롬프트 템플릿을 통해 매개변수 삽입 가능한 문자열로 변환
string_prompt = PromptTemplate.from_template("tell me a joke about {subject}")
#매개변수 삽입한 결과를 string_prompt_value에 할당
string_prompt_value = string_prompt.format_prompt(subject="soccer")
#채팅LLM이 아닌 LLM과 대화할 때 필요한 프롬프트 = string prompt
string_prompt_value
#-> StringPromptValue(text='tell me a joke about soccer')
#to_string() 함수를 통해 prompt template으로 생성한 문장 raw_text 반환 가능
print(string_prompt_value.to_string())
#-> tell me a joke about soccer
chat_prompt = ChatPromptTemplate.from_template("tell me a joke about {subject}")
chat_prompt_value = chat_prompt.format_prompt(subject="soccer")
chat_prompt_value
#-> ChatPromptValue(messages=[HumanMessage(content='tell me a joke about soccer', additional_kwargs={}, response_metadata={})])
chat_prompt_value.to_string()
#-> Human: tell me a joke about soccer
GPT-3와 (1) Prompt Template을 활용하여 대화해보기
from langchain.prompts.prompt import PromptTemplate
llm = ChatOpenAI(
model_name="gpt-3.5-turbo",
max_tokens = 1000
)
template = """
너는 요리사야. 내가 가진 재료들을 갖고 만들 수 있는 요리를 추천하고, 그 요리의 레시피를 제시해줘.
내가 가진 재료는 아래와 같아.
<재료>
{재료}
"""
prompt_template = PromptTemplate(
input_variables = ['재료'],
template = template
)
print(prompt_template.format(재료 = '양파, 계란, 사과, 빵'))
'''
너는 요리사야. 내가 가진 재료들을 갖고 만들 수 있는 요리를 추천하고, 그 요리의 레시피를 제시해줘.
내가 가진 재료는 아래와 같아.
<재료>
양파, 계란, 사과, 빵
'''
print(llm.invoke(
prompt_template.format(
재료 = '양파, 계란, 사과, 빵'
)
).content)
'''
요리 추천: 계란 토스트
<레시피>
1. 양파를 송송 썰고 계란을 풀어 잘 섞는다.
2. 팬에 식용유를 두르고 양파를 볶다가 계란을 부어 스크램블을 만든다.
3. 빵을 굽거나 토스터기에 구워서 바삭하게 만든다.
4. 사과를 슬라이스하여 곁들인다.
5. 계란 스크램블을 빵 위에 올리고 사과 슬라이스를 곁들여 계란 토스트를 완성한다. 맛있게 즐기세요!
'''
ChatGPT와 (2) Chat Prompt Template을 활용하여 대화해보기
from langchain.prompts import (
ChatPromptTemplate,
PromptTemplate,
SystemMessagePromptTemplate,
AIMessagePromptTemplate,
HumanMessagePromptTemplate,
)
from langchain.schema import (
AIMessage,
HumanMessage,
SystemMessage
)
# ChatGPT 모델을 로드합니다.
chatgpt = ChatOpenAI(temperature=0)
#ChatGPT에게 역할을 부여합니다.(위에서 정의한 Template 사용)
system_message_prompt = SystemMessagePromptTemplate.from_template(template)
#사용자가 입력할 매개변수 template을 선언합니다.
human_template = "{재료}"
human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)
#ChatPromptTemplate에 system message와 human message 템플릿을 삽입합니다.
chat_prompt = ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt])
#ChatGPT API에 ChatPromptTemplate을 입력할 때, human message의 매개변수인 '재료'를 할당하여 전달합니다.
#이와 같은 방식을 통해 ChatGPT는 ChatPromptTemplate의 구성요소인 system message와 human message를 전달받아, 대답 생성에 활용합니다.
answer = chatgpt(chat_prompt.format_prompt(재료="양파, 계란, 사과, 빵").to_messages())
print(answer.content)
'''
제가 추천하는 요리는 "양파 계란 토스트"입니다. 이 요리는 간단하면서도 맛있는 아침 식사나 간식으로 딱 좋아요. 준비물과 레시피는 아래와 같습니다.
<양파 계란 토스트>
<재료>
- 빵 4조각
- 양파 1개
- 계란 2개
- 소금
- 후추
- 식용유
<레시피>
1. 양파를 얇게 슬라이스해줍니다.
2. 팬에 식용유를 두르고 양파를 볶아 투명해질 때까지 볶아줍니다.
3. 볶은 양파를 접시에 옮겨놓고 계란 2개를 풀어 잘 섞어줍니다. 소금과 후추로 간을 해줍니다.
4. 빵 4조각에 계란물을 골고루 발라줍니다.
5. 또 다른 팬에 식용유를 두르고 빵을 구워줍니다.
6. 빵이 바삭해질 때쯤 양파를 골고루 얹어줍니다.
7. 계란물이 익을 때까지 뚜겅에 뚜겅 뒤집어가며 익혀줍니다.
8. 완성된 양파 계란 토스트를 그릇에 담아 맛있게 즐기세요!
간단하면서도 고소한 맛이 일품인 이 요리, 한 번 만들어보시면 좋을 것 같아요. 맛있게 드세요! 🍳🍞🧅
'''
(3) Few-shot 예제를 통한 프롬프트 템플릿
Few-shot이란, 딥러닝 모델이 결과물을 출력할 때 예시 결과물을 제시함으로써 원하는 결과물로 유도하는 방법론입니다.
LLM 역시, Few-shot 예제를 제공하면 예제와 유사한 형태의 결과물을 출력합니다.
내가 원하는 결과물의 형태가 특수하거나, 구조화된 답변을 원할 경우, 결과물의 예시를 수 개 제시함으로써 결과물의 품질을 향상시킬 수 있습니다.
from langchain.prompts.few_shot import FewShotPromptTemplate
from langchain.prompts.prompt import PromptTemplate
examples = [
{
"question": "아이유로 삼행시 만들어줘",
"answer":
"""
아: 아이유는
이: 이런 강의를 들을 이
유: 유가 없다.
"""
},
{
"question": "김민수로 삼행시 만들어줘",
"answer":
"""
김: 김치는 맛있다
민: 민달팽이도 좋아하는 김치!
수: 수억을 줘도 김치는 내꺼!
"""
}
]
example_prompt = PromptTemplate(input_variables=["question", "answer"], template="Question: {question}\\n{answer}")
print(example_prompt.format(**examples[0]))
'''
Question: 아이유로 삼행시 만들어줘
아: 아이유는
이: 이런 강의를 들을 이
유: 유가 없다.
'''
prompt = FewShotPromptTemplate(
examples=examples,
example_prompt=example_prompt,
suffix="Question: {input}",
input_variables=["input"]
)
print(prompt.format(input="호날두로 삼행시 만들어줘"))
'''
Question: 아이유로 삼행시 만들어줘
아: 아이유는
이: 이런 강의를 들을 이
유: 유가 없다.
Question: 김민수로 삼행시 만들어줘
김: 김치는 맛있다
민: 민달팽이도 좋아하는 김치!
수: 수억을 줘도 김치는 내꺼!
Question: 호날두로 삼행시 만들어줘
'''
print(llm.invoke(
prompt.format(input="호날두로 삼행시 만들어줘")
).content)
'''
호: 호날두는
날: 날마다 열정을 보여주는
두: 두 발로 골을 넣는다.
'''
(4) Example Selector를 이용한 동적 Few-shot 러닝
Few-shot 예제를 동적으로 입력하고 싶은 경우, Example Selector를 활용할 수 있습니다.
LLM이 여러 작업을 수행하도록 만들되 내가 원하는 범위의 대답을 출력하도록 하려면 사용자의 입력에 동적으로 반응해야 합니다.이와 동시에, 예제를 모두 학습시키는 것이 아니라 적절한 예시만 포함하도록 함으로써 입력 prompt의 길이를 제한하고, 이를 통해 오류가 발생하지 않도록 조절할 수 있습니다.
from langchain.prompts.example_selector import SemanticSimilarityExampleSelector
from langchain.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings
from langchain.prompts import FewShotPromptTemplate, PromptTemplate
example_prompt = PromptTemplate(
input_variables=["input", "output"],
template="Input: {input}\\nOutput: {output}",
)
# These are a lot of examples of a pretend task of creating antonyms.
examples = [
{"input": "행복", "output": "슬픔"},
{"input": "흥미", "output": "지루"},
{"input": "불안", "output": "안정"},
{"input": "긴 기차", "output": "짧은 기차"},
{"input": "큰 공", "output": "작은 공"},
]
embedding = OpenAIEmbeddings()
example_selector = SemanticSimilarityExampleSelector.from_examples(
# This is the list of examples available to select from.
examples,
# This is the embedding class used to produce embeddings which are used to measure semantic similarity.
embedding,
# This is the VectorStore class that is used to store the embeddings and do a similarity search over.
Chroma,
# This is the number of examples to produce.
k=1
)
similar_prompt = FewShotPromptTemplate(
# We provide an ExampleSelector instead of examples.
example_selector=example_selector,
example_prompt=example_prompt,
prefix="주어진 입력에 대해 반대의 의미를 가진 단어를 출력해줘",
suffix="Input: {단어}\\nOutput:",
input_variables=["단어"],
)
# Input is a feeling, so should select the happy/sad example
print(similar_prompt.format(단어="무서운"))
# Input is a feeling, so should select the happy/sad example
print(similar_prompt.format(단어="큰 비행기"))
query = "큰 비행기"
print(llm.invoke(
similar_prompt.format(단어=query)
).content)
5) Output Parser를 활용한 출력값 조정
LLM의 답변을 내가 원하는 형태로 고정하고 싶다면 OutputParser 함수를 활용할 수 있습니다. 리스트, JSON 형태 등 다양한 형식의 답변을 고정하여 출력할 수 있습니다.
from langchain.output_parsers import CommaSeparatedListOutputParser
from langchain.prompts import PromptTemplate, ChatPromptTemplate, HumanMessagePromptTemplate
from langchain.llms import OpenAI
from langchain.chat_models import ChatOpenAI
output_parser = CommaSeparatedListOutputParser()
format_instructions = output_parser.get_format_instructions()
format_instructions
prompt = PromptTemplate(
template="{주제} 5개를 추천해줘.\\n{format_instructions}",
input_variables=["주제"],
partial_variables={"format_instructions": format_instructions}
)
model = OpenAI(temperature=0)
_input = prompt.format(주제="영화")
output = model.invoke(_input)
print(ouput)
'''
\\n\\n1. Parasite\\n2. The Shawshank Redemption\\n3. Inception\\n4. The Godfather\\n5. Pulp Fiction
'''
output_parser.parse(output)
'''
['1. Parasite',
'2. The Shawshank Redemption',
'3. Inception',
'4. The Godfather',
'5. Pulp Fiction']
'''
파서 | 설명 |
CommaSeparatedListOutputParser | 쉼표(,)로 구분된 리스트 변환 |
StructuredOutputParser | JSON 스키마를 기반으로 구조화된 데이터 반환 |
PydanticOutputParser | pydantic 모델을 사용하여 데이터 변환 |
BooleanOutputParser | "yes"/"no"를 True/False로 변환 |
RetryWithErrorOutputParser | 잘못된 출력 발생 시 재시도 유도 |
ListOutputParser | 줄바꿈(\\n)을 기준으로 리스트 변환 |
JsonOutputKeyToolsParser | JSON 데이터를 키를 기준으로 변환 |
'LLM > LLM 공부' 카테고리의 다른 글
Retrieval-Text Embeddings (0) | 2025.03.07 |
---|---|
Retrieval - Text Splitters (0) | 2025.03.07 |
Retrieval - Document Loaders (0) | 2025.03.07 |
ChatGPT API 실습 (0) | 2025.03.07 |
LangChain의 개념 (0) | 2025.03.07 |