[LangChain] Fewshot Prompt Template

pysun·2024년 12월 7일

LangChain

목록 보기
5/13

퓨샷 프롬프트 템플릿

  • 내가 원하는 모든 내용을 프롬프트로 모두 명령하기보다 어떻게 대답해야하는지 성공적인 에제를 제공하는 게 더 효율적 방법

FewShotPromptTemplate

  • 용도: 일반적인 텍스트 기반 프롬프트 생성에 사용
  • 구조: 단순한 텍스트 형식의 프롬프트를 생성
  • 예시 포멧: 주로 키-값 쌍의 딕셔너리 형태로 예시를 제공
  • 주요 파라미터
    👉 example_prompt: 개별 예제를 포멧팅하는 데 사용하는 PromptTemplate
    👉 examples: few-shot 예제 리스트
    👉 suffix: 형식화 된 모든 예제 마지막에 나오는 내용
    👉 input_variables: 유효성 검사를 할 수 있도록 input 변수 설정
from langchain_openai import ChatOpenAI
from langchain.prompts import PromptTemplate
from langchain.prompts.few_shot import FewShotPromptTemplate
from langchain.callbacks import StreamingStdOutCallbackHandler

# llm 모델
chat = ChatOpenAI(
		temperature=0.1,
        streaming=True,
        callbacks=[StreamingStdOutCallbackHandler()]
       )
                  
# few-shot 예시
examples = [
	{
    	'question': 'What do you know about Korea?',
        'answer': '''
         	Here is what I know:
            Capital: Seoul
            Language: Korean
            Food: Kimchi
            Currency: Won        
 	     '''
     },
     {
    	'question': 'What do you know about France?',
        'answer': '''
         	Here is what I know:
            Capital: Paris
            Language: French
            Food: Wine and Cheese
            Currency: Euro        
 	     '''
     },
     {
    	'question': 'What do you know about Italy?',
        'answer': '''
         	Here is what I know:
            Capital: Rome
            Language: Italian
            Food: Pizza
            Currency: Euro        
 	     '''
     }
] 

# few-shot 예시 템플릿 정의
# 예시 데이터 형식을 지정하는 템플릿 정의
example_template = '''
	Human: {question}
    AI: {answer}
'''

# PromptTemplate.from_template 메소드를 사용해 위에서 정의한 템플릿을 PromptTemplate 객체로 반환
example_prompt = PromptTemplate.from_template(example_template)

# FewShotPromptTemplate 생성
# few-shot 예제와 입력 변수를 포함하여 전체 프롬프트를 구성
prompt = FewShotPromptTemplate(
	example_prompt=example_prompt,   # 예시 데이터 형식 탬플릿
    examples=examples,               # 모델에 제공 할 예시 
    suffix='Human: What do you know about {country}?', # 프롬프트 마지막에 추가되는 내용
    input_variables=['country'] # 마지막 프롬프트에 들어갈 변수
)

prompt
FewShotPromptTemplate(
	input_variables=['country'], 
	examples=[
      {
          'question': 'What do you know about Korea?', 
          'answer': '\n        Here is what I know:\n        Capital: Seoul\n        Language: Korean\n        Food: Kimchi\n        Currency: Won\n        '
      }, 
      {
          'question': 'What do you know about France?', 
          'answer': '\n        Here is what I know:\n        Capital: Paris\n        Language: French\n        Food: Wine and Cheese\n        Currency: Euro\n        '
      }, 
      {
          'question': 'What do you know about Italy?', 
          'answer': '\n        Here is what I know:\n        Capital: Rome\n        Language: Italian\n        Food: Pizza\n        Currency: Euro\n        '
      }
    ], 
   example_prompt=PromptTemplate(
   	input_variables=['answer', 'question'], 
    template='  \n    Human: {question}\n    AI: {answer}\n'
   ),
   suffix='Human: What do you know about {country}?'
)

prompt.invoke({'country':'Japan'})
StringPromptValue(
	text='  \n    Human: What do you know about Korea?\n    AI: \n        Here is what I know:\n        Capital: Seoul\n        Language: Korean\n        Food: Kimchi\n        Currency: Won\n        \n\n\n  \n    Human: What do you know about France?\n    AI: \n        Here is what I know:\n        Capital: Paris\n        Language: French\n        Food: Wine and Cheese\n        Currency: Euro\n        \n\n\n  \n    Human: What do you know about Italy?\n    AI: \n        Here is what I know:\n        Capital: Rome\n        Language: Italian\n        Food: Pizza\n        Currency: Euro\n        \n\n\nHuman: What do you know about Japan?'
)

chain = prompt | chat
chain.invoke({'country':'Japan'})
AIMessage(content='\n        Here is what I know:\n        Capital: Tokyo\n        Language: Japanese\n        Food: Sushi\n        Currency: Yen\n        ', response_metadata={'finish_reason': 'stop'}, id='run-16e187f9-badc-48e6-b1b3-9c5d8ad70650-0')

FewShotChatMessagePromptTemplate

  • 용도: 대화형 AI 모델을 위한 채팅 기반 프롬프트 생성에 사용
  • 구조: 대화 형식 프롬프트를 생성하며, 각 메시지에 역할(role)을 지정할 수 있음
  • 예시 포멧: 대화 흐름을 반영한 형태로 예시 제공
  • 주요 파라미터
    👉 example_prompt: 개별 예제를 포멧팅하는 데 사용하는 ChatPromptTemplate
    👉 examples: few-shot 예제 리스트
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate, FewShotChatMessagePromptTemplate
from langchain.callbacks import StreamingStdOutCallbackHandler

chat = ChatOpenAI(
        temperature=0.1,
        streaming=True,
        callbacks=[StreamingStdOutCallbackHandler()]
       )

examples = [
    {
        'country': 'Korea',
        'answer': '''
        Here is what I know:
        Capital: Seoul
        Language: Korean
        Food: Kimchi
        Currency: Won
        '''
    },
    {
        'country': 'France',
        'answer': '''
        Here is what I know:
        Capital: Paris
        Language: French
        Food: Wine and Cheese
        Currency: Euro
        '''
    },
    {
        'country': 'Italy',
        'answer': '''
        Here is what I know:
        Capital: Rome
        Language: Italian
        Food: Pizza
        Currency: Euro
        '''
    }
]

# example_prompt: 예제를 형식화하기 위함
example_prompt = ChatPromptTemplate.from_messages([
    ('human', 'What do you know about {country}?'),
    ('ai', '{answer}')    
])

# ChatMessage용 FewShotPromptTemplate
few_shot_prompt = FewShotChatMessagePromptTemplate(
    example_prompt=example_prompt,
    examples=examples
)

few_shot_prompt
FewShotChatMessagePromptTemplate(
	examples=[
    	{
        	'country': 'Korea', 
            'answer': '\n        Here is what I know:\n        Capital: Seoul\n        Language: Korean\n        Food: Kimchi\n        Currency: Won\n        '
        }, 
        {
        	'country': 'France', 
            'answer': '\n        Here is what I know:\n        Capital: Paris\n        Language: French\n        Food: Wine and Cheese\n        Currency: Euro\n        '
        }, 
        {
        	'country': 'Italy', 
            'answer': '\n        Here is what I know:\n        Capital: Rome\n        Language: Italian\n        Food: Pizza\n        Currency: Euro\n        '
        }
    ], 
    example_prompt=ChatPromptTemplate(
    	input_variables=['answer', 'country'], 
        messages=[HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['country'], template='What do you know about {country}?')),
        		  AIMessagePromptTemplate(prompt=PromptTemplate(input_variables=['answer'], template='{answer}'))]
    )
)

# 최종 프롬프트
final_prompt = ChatPromptTemplate.from_messages(
	[
    	('system', 'You are a geography expert. you give short answers.'),
        few_shot_prompt,
        ('human', 'What do you know about {country}?')
    ]
)

chain = final_prompt | chat
chain.invoke({'country':'China'})
AIMessage(content='\n        Here is what I know:\n        Capital: Beijing\n        Language: Mandarin\n        Food: Dim Sum\n        Currency: Yuan\n        ', response_metadata={'finish_reason': 'stop'}, id='run-88532447-c8e9-47a6-966f-08bc914b735d-0')

랜덤으로 예시 추출하기

from langchain_openai import ChatOpenAI
from langchain_core.prompts import PromptTemplate, FewShotPromptTemplate
from langchain.callbacks import StreamingStdOutCallbackHandler

# LengthBasedExampleSelector: 기본적으로 예제를 형식화 할 수 있고, 예제 양 확인 가능 -> 내가 설정해 놓은 세팅값에 따라 prompt에 알맞는 예제를 골라줌
from langchain.prompts.example_selector import LengthBasedExampleSelector
from langchain.prompts.example_selector.base import BaseExampleSelector
        
    
chat = ChatOpenAI(
		temperature=0.1,
        streaming=True,
        callbacks=[StreamingStdOutCallbackHandler()]
       )

examples = [
    {
        'country': 'Korea',
        'answer': '''
        Here is what I know:
        Capital: Seoul
        Language: Korean
        Food: Kimchi
        Currency: Won
        '''
    },
    {
        'country': 'France',
        'answer': '''
        Here is what I know:
        Capital: Paris
        Language: French
        Food: Wine and Cheese
        Currency: Euro
        '''
    },
    {
        'country': 'Italy',
        'answer': '''
        Here is what I know:
        Capital: Rome
        Language: Italian
        Food: Pizza
        Currency: Euro
        '''
    }
]

# example 중 랜덤 샘플링하는 클래스
class RandomExamplesSelector(BaseExampleSelector):
    def __init__(self, examples):
        self.examples = examples

    def add_example(self, example):
        self.examples.append(example)

    def select_examples(self, input_variables):
        from random import choice
        return [choice(self.examples)]


example_prompt = PromptTemplate.from_template('Human: {country}\nAI: {answer}')

# 예제들 중 랜덤으로 선택하는 selector
example_selector = RandomExamplesSelector(
    examples=examples
)

print('# RandomExamplesSelector로 뽑은 랜덤 예시')
print(example_selector.select_examples('country'))
print('\n')

prompt = FewShotPromptTemplate(
    example_prompt=example_prompt,
    example_selector=example_selector,  # examples=examples 경우에는 모든 예제를 형식화한거였음
    suffix='Human: What do you know about {country}?',
    input_variables=['country']
)

print('# FewShotPromptTemplate 템플릿 형식화')
print(prompt.format(country='Russia'))
print('\n')

print('# invoke 수행')
chain = prompt | chat
chain.invoke({'country':'Russia'})
# RandomExamplesSelector로 뽑은 랜덤 예시
[{'country': 'France', 'answer': '\n        Here is what I know:\n        Capital: Paris\n        Language: French\n        Food: Wine and Cheese\n        Currency: Euro\n        '}]


# FewShotPromptTemplate 템플릿 형식화
Human: France
AI: 
        Here is what I know:
        Capital: Paris
        Language: French
        Food: Wine and Cheese
        Currency: Euro
        

Human: What do you know about Russia?


# invoke 수행
AI: 
        Here is what I know:
        Capital: Moscow
        Language: Russian
        Food: Borscht, Blini, Pelmeni
        Currency: Russian Ruble
        Famous landmarks: Red Square, Kremlin, Saint Basil's Cathedral

입력과 유사한 예시 추출하기

from langchain.vectorstores import Chroma
from langchain_core.example_selectors import SemanticSimilarityExampleSelector
from langchain_openai import OpenAIEmbeddings


examples = [
    {
        "input": "2 🦜 2", 
        "output": "4"
    },
    {
        "input": "2 🦜 3", 
        "output": "5"
    },
    {
        "input": "2 🦜 4", 
        "output": "6"
    },
    {
        "input": "What did the cow say to the moon?", 
        "output": "nothing at all"
    },
    {
        "input": "Write me a poem about the moon",
        "output": "One for the moon, and one for me, who are we to talk about the moon?",
    },
]

# 예제 데이터의 input, output 값을 텍스트로 결합하여 벡터화하기 위한 코드
to_vectorize = [' '.join(example.values()) for example in examples]

# 벡터화된 데이터 저장 및 검색할 수 있는 vectorstore 생성
embeddings = OpenAIEmbeddings()
vectorstore = Chroma.from_texts(to_vectorize, embeddings, metadatas=examples) # 디스크에 저장하고 싶다면 persist_directory 파라미터 설정 및 vectorstore.persist() 메소드를 실행해야 함

'''  
SemanticSimilarityExampleSelector:
- 주어진 입력과 벡터 스토어에 저장된 예제들의 유사성을 계산.
- 유사성이 가장 높은 예제 k개를 반환.
'''
example_selector = SemanticSimilarityExampleSelector(
    vectorstore=vectorstore,
    k=2
)

'''
select_examples:
- 주어진 입력('tell me about earth')을 벡터로 변환.
- 해당 벡터와 벡터 스토어에 저장된 예제 벡터들의 유사성을 계산.
- 유사성이 높은 순서로 k=2개의 예제를 반환.

'''
example_selector.select_examples({'input':'tell me about earth'})
[{'input': 'What did the cow say to the moon?', 'output': 'nothing at all'},
 {'input': 'Write me a poem about the moon',
  'output': 'One for the moon, and one for me, who are we to talk about the moon?'}]
from langchain_core.prompts import ChatPromptTemplate, FewShotChatMessagePromptTemplate

# Define the few-shot prompt.
few_shot_prompt = FewShotChatMessagePromptTemplate(
    # Define how each example will be formatted.
    # In this case, each example will become 2 messages:
    # 1 human, and 1 AI
    example_prompt=ChatPromptTemplate.from_messages(
        [('human', '{input}'), ('ai', '{output}')]
    ),
    example_selector=example_selector,
    # The input variables select the values to pass to the example_selector
    input_variables=['input']
)

final_prompt = ChatPromptTemplate.from_messages(
    [
        ('system', 'You are a wondrous wizard of math.'),
        few_shot_prompt,
        ('human', '{input}')
    ]
)

chain = final_prompt | ChatOpenAI(model='gpt-4o-mini', temperature=0.1)
chain.invoke({'input':"What's 3 🦜 3?"})
AIMessage(content='3 🦜 3 equals 6.', response_metadata={'token_usage': {'completion_tokens': 10, 'prompt_tokens': 59, 'total_tokens': 69, 'prompt_tokens_details': {'cached_tokens': 0, 'audio_tokens': 0}, 'completion_tokens_details': {'reasoning_tokens': 0, 'audio_tokens': 0, 'accepted_prediction_tokens': 0, 'rejected_prediction_tokens': 0}}, 'model_name': 'gpt-4o-mini', 'system_fingerprint': 'fp_bba3c8e70b', 'finish_reason': 'stop', 'logprobs': None}, id='run-88fe8449-4d7b-4a78-afb0-197dadfd497f-0')```
profile
배움의 흔적이 성장으로 이어지는 공간

0개의 댓글