[LangChain] LLM Model로 Few-shot Prompting 하기
Deep Learning (TF, Keras, PyTorch)/Natural Language Processing 2024. 1. 2. 23:44LLM(Large Language Model, 대규모 언어 모델)에서의 Few-shot prompting는 GPT-3나 GPT-4 같은 모델에 소수의 예시(보통 하나에서 다섯 사이)를 제공하여 그 반응을 안내하거나 특정 작업을 가르치는 기술을 말합니다. 이는 '프롬프트 엔지니어링 (Prompt Engineering)'이라고 하는 더 넓은 범위의 기술 중 하나로, 이는 이러한 AI 모델과 효과적으로 소통하기 위해 입력(프롬프트)을 설계하는 예술입니다.
Few-shot prompting에서는 모델에게 주어진 예시들이 패턴을 보여주거나 특정한 반응 방식을 가르치기 위해 신중하게 선택됩니다. 그런 다음 모델은 이 예시들을 참조로 사용하여 자신의 반응에서 기대되는 것을 이해합니다. 이는 단순한 지시만으로는 모델이 의도된 작업을 충분히 이해하기 어려운 복잡하거나 미묘한 작업에 특히 유용합니다.
Few-shot prompting에 대한 주요 포인트는 다음과 같습니다.
- 예시를 통한 시연 (Demonstration through Examples): 특정 예시를 제공함으로써 모델에게 어떤 종류의 출력이 기대되는지를 보여줍니다. 이는 분류, 번역 또는 심지어 창의적 글쓰기와 같은 작업에 특히 도움이 될 수 있습니다.
- 모호성 감소 (Reduction in Ambiguity): Few-shot prompting는 작업 지시에서 모호성을 줄여 모델에게 무엇을 해야 하는지 더 명확하게 합니다.
- 유연성과 적응성 (Flexibility and Adaptability): 이 방법은 모델이 재교육이나 핵심 알고리즘에 대한 업데이트 없이도 새로운 작업에 적응할 수 있게 해줍니다.
- 효율성 (Efficiency): 퓨샷 학습은 새로운 작업에 모델을 적응시키기 위해 대량의 데이터나 광범위한 파인튜닝이 필요하지 않다는 점에서 효율적입니다.
- 예시 품질에 대한 의존성 (Dependency on Example Quality): Few-shot prompting의 효과는 제공된 예시의 품질과 관련성에 크게 의존합니다. 잘못 선택된 예시는 모델로 하여금 부적절하거나 잘못된 반응을 할 수 있게 만듭니다.
전반적으로, Few-shot prompting은 특히 모델 Finetuning 이나 대규모 데이터셋이 실행 가능하지 않은 상황에서 LLM의 능력을 유연하고 효율적으로 활용하기 위한 강력한 도구입니다.
이번 포스팅에서는 LangChain과 ChatGPT LLM 모델을 사용하여 Few-shot Prompting 하는 방법을 소개하겠습니다.
1. 몇 개의 예시를 제공하여 LLM 모델에게 특정 출력을 지시하는 Few-shot Prompting
2. 사용자 인풋과의 유사도에 따라 예시를 선택해서 LLM 모델에 Few-show Prompting 하기
ChatModel 에 Few-shot Prompting 하는 방법은 다음 포스팅에서 소개하겠습니다.
1. 몇 개의 예시를 제공하여 LLM 모델에게 특정 출력을 지시하는 Few-shot Prompting
먼저 터미널에서 pip install 을 이용하여 langchain, openai, faiss-cpu 모듈을 설치합니다.
! pip install -q langchain openai faiss-cpu
필요한 모듈을 importing 합니다.
from langchain.embeddings import OpenAIEmbeddings
from langchain.prompts import FewShotPromptTemplate, PromptTemplate
from langchain.prompts.example_selector import SemanticSimilarityExampleSelector
from langchain.vectorstores import FAISS
from langchain.llms import OpenAI
from langchain_core.output_parsers import StrOutputParser
OpenAI의 LLM 모델을 사용할것이므로 OpenAI API Key를 등록합니다.
import os
os.environ["OPENAI_API_KEY"]="sk-xxxx..." # set with yours
Few-shot Prompting을 하기 위해 다음의 순서대로 Prompt 를 작성합니다.
(1) 몇 개의 예시를 작성 (아래 예에서는 Input 의 반대말을 Output으로 출력하는 7개 예시)
(2) PromptTemplate()로 예시의 인풋 변수와 예시 템플릿 포맷을 생성
(3) FewShotPromptTemplate()에 (1) 예시, (2) 예시 PromptTemplate을 입력하여 Prompt 생성
# (1) Examples of creating antonyms
examples = [
{"input": "happy", "output": "sad"},
{"input": "tall", "output": "short"},
{"input": "sunny", "output": "rainy"},
{"input": "surprised", "output": "calm"},
{"input": "dry", "output": "humid"},
{"input": "hot", "output": "cold"},
{"input": "satisfied", "output": "dissatisfied"},
]
# (2) Example Prompt Template
example_prompt = PromptTemplate(
input_variables=["input", "output"],
template="Input: {input}\nOutput: {output}"
)
print(example_prompt.format(**examples[0]))
# Input: happy
# Output: sad
# (3) Feed examples and formatter to FewShotPromptTemplate
prompt = FewShotPromptTemplate(
examples=examples,
example_prompt=example_prompt,
suffix="Input : {input}",
input_variables=["input"],
)
위에서 작성한 Prompt와 LLMs 모델, 그리고 Output Parser를 '|'를 이용하여 chaining 해줍니다.
# LLMs model
llm = OpenAI()
# Output Parser
parser = StrOutputParser()
# Chaining
chain = prompt | llm | parser
위에서 작성한 Few-shot Prompting을 위한 Prompt를 출력해보면 아래와 같습니다. 위에서 작성했던 예시들이 모두 들어가 있고, 마지막에 사용자 인풋이 들어가 있습니다.
print(prompt.format(input="excited"))
# Input: happy
# Output: sad
# Input: tall
# Output: short
# Input: sunny
# Output: rainy
# Input: surprised
# Output: calm
# Input: dry
# Output: humid
# Input: hot
# Output: cold
# Input: satisfied
# Output: disappointed
# Input : excited
그럼, 드디어 위에서 정의한 chain = prompt | model | parser 를 사용해서 chain.invoke()로 사용자 인풋을 넣었을 때 각 형용사별로 반대말을 잘 출력하는지 실행시켜 보겠습니다.
ChatGPT LLM 모델이 똑똑해서 몇 개의 예시로 부터 잘 학습을 해서 원하는 지시대로 Output을 잘 출력하네요.
chain.invoke({"input": "excited"})
# '\nOutput: bored'
chain.invoke({"input": "foggy"})
# ' \nOutput : clear'
2. 사용자 인풋과의 유사도에 따라 예제를 선택해서 LLM모델에 Few-show Prompting 하기
여러개의 예시 중에서 사용자 인풋과 유사하고 관련성이 높은 예시를 선별해 Prompt를 만들어서 LLM 모델에 전달하면 Token의 개수가 줄어들어서 비용이 줄어들고 Latency가 향상되는 효과, 그리고 LLM 모델이 좀더 향상된 답변을 제시할 수 있는 효과가 있습니다.
LangChain이 제공하는 Example Selector Types은 아래와 같이 4가지가 있습니다.
[ LangChain - Example Selector Types ]
이번 포스팅에서는 예시와 사용자 인풋을 Text Embeddings 변환하여, Cosine Similarity가 가장 높은 k개의 예시를 선별해서 Few-shot Prompt에 넣어서 LLM 모델에 전달하는 방법을 소개하겠습니다.
예시와 사용자 인풋을 Text Embeddings 변환하는 것은 OpenAIEmbeddigns() 를 사용하였으며, 임베딩 변환된 벡터를 저장하고 코사인 유사도 계산을 하는 것은 FAISS 벡터 DB를 사용하였습니다.
# Select examples based on similarity to the inputs
# by finding the examples with the embeddings that have the greatest cosine similarity with the inputs.
example_selector = SemanticSimilarityExampleSelector.from_examples(
# the list of examples available to select from.
examples,
# The embedding class used to produce embeddings which are used to measure semantic similarity.
OpenAIEmbeddings(),
# The VectorStore class used to store the embeddings and do a similarity search over.
FAISS,
# the number of examples to produce.
k=2,
)
similar_prompt = FewShotPromptTemplate(
# we provide an ExampleSelector instead of examples.
example_selector=example_selector,
example_prompt=example_prompt,
prefix="Give the antonym of every input",
suffix="Input: {input}\nOutput:",
input_variables=["input"]
)
k=2 로 설정하여 사용자 인풋과 Semantic Similarity 가 가장 높은 2개의 예시를 선택하도록 하였습니다.
아래의 예를 보면, 먼저 "excited"의 경우 감정에 해당하므로 "surprised", "satisfied" 의 두 개 예시가 선택되었습니다.
# Input is a feeling
print(similar_prompt.format(input="excited"))
# Give the antonym of every input
# Input: surprised
# Output: calm
# Input: satisfied
# Output: disappointed
# Input: excited
# Output:
위에서 Semantic Similarity 기준의 Example Selector 로 정의한 similar_prompt 를 LLM 모델과 Output Parser 와 함께 '|'로 chaining 하였습니다. fewshot_similar_chain.invoke() 로 실행을 해보겠습니다.
감정에 해당하는 "excited"를 사용자 인풋으로 넣어주면 "surprised", "satisfied"에 대한 예시를 Prompt에 함께 넣어서 ChatGPT LLM 모델에 보내게 되고, ChatGPT LLM 모델은 "excited"에 대한 반대말로 "bored"를 Output으로 반환하였습니다.
# Chaining
fewshot_similar_chain = similar_prompt | llm | parser
# Feeling
fewshot_similar_chain.invoke({"input": "excited"})
# ' bored'
날씨에 해당하는 "snowy"를 사용자 인풋으로 넣었더니 k=2 개의 Semantic Similarity가 높은 예시로 "sunny", "hot"의 2개 예시가 적절하게 잘 선택되었습니다.
# Input is a weather
print(similar_prompt.format(input="snowy"))
# Give the antonym of every input
# Input: sunny
# Output: rainy
# Input: hot
# Output: cold
# Input: snowy
# Output:
fewshot_similar_chain.invoke({"input": "snowy"}) 로 Few-shot Prompting ("sunny", "hot"의 2개 예시)하여 ChatGPT LLM 모델을 실행시켰더니 "dry"라는 Output을 생성하였습니다.
fewshot_similar_chain.invoke({"input": "snowy"})
# ' dry'
[ Reference ]
- LangChain Modules - Prompts - Select by similarity:
https://python.langchain.com/docs/modules/model_io/prompts/example_selector_types/similarity
- LangChain Example Selector Types:
https://python.langchain.com/docs/modules/model_io/prompts/example_selector_types/
이번 포스팅이 많은 도움이 되었기를 바랍니다.
행복한 데이터 과학자 되세요! :-)