인공지능 개발자 수다(유튜브 바로가기) 자세히보기

자연어처리/Langchain

[langchain] Prompt templetes(프롬프트 탬플릿) 만들기

Suda_777 2024. 9. 14. 17:27

목차

    반응형

    1. LLM의 입력값 형식

    입력 데이터를 기준으로 두가지 종류의 LLM으로 나눌 수 있습니다.

    프롬프트를 만들기 전에, 모델에 어떤 형식으로 데이터가 들어가는지 확인해 봅시다.

    1.1. 완성형 LLM (Completion-based LLM)

    • 동작 방식: 주어진 프롬프트에 이어질 텍스트를 예측하여 생성
    • 사용 사례: 코드 자동 완성, 문장 또는 단락 생성, 문서 작성 보조
    • 입력 데이터: 문자열
    • 입력 데이터 예시
    "안녕하세요."

     

    1.2. 대화형 LLM (Chat-based LLM)

    • 동작 방식: 사용자와의 대화를 통해 상호 작용하며, 이전 대화 내용을 기반으로 응답
    • 사용 사례: 챗봇, 대화 기반 학습 도구
    • 입력 데이터: Json
    • 입력 데이터 예시
    [
        {"role": "user", "content": "안녕하세요."},
        {"role": "assistant", "content": "안녕하세요! 무엇을 도와드릴까요?"},
        {"role": "user", "content": "인공지능은 미래에 어떤 영향을 미칠까요?"}
    ]

    2. 완성형 LLM을 위한 Prompt Templetes

    2.1. PromptTemplate

    • 설명
      • PromptTemplate는 동적이고 유연한 프롬프트를 생성하기 위해 사용
      • 프롬프트에 변수를 삽입 -> 다양한 입력에 따라 맞춤형 프롬프트
    • 변수 삽입 방법
      • 프롬프트 내에 {variable_name} 형식으로 변수를 포함
      • input_variables: 프롬프트에서 사용되는 변수들의 리스트
    • 예시 코드
    template = "안녕하세요, {name}님! 오늘 기분은 어떠신가요?"
    
    prompt = PromptTemplate(
        input_variables=["name"],
        template=template,
    )
    filled_prompt = prompt.format(name="홍길동")
    print(filled_prompt)

     

    출력

    안녕하세요, 홍길동님! 오늘 기분은 어떠신가요?

    2.2. FewShotPromptTemplate

    Few-shot 프롬프트 템플릿은 대형 언어 모델(LLM)에게 원하는 작업의 예시(Examples)를 프롬프트에 포함시켜 모델이 그 패턴을 학습하고 유사한 방식으로 응답하도록 하는 방법입니다. 이는 모델이 특정 작업의 형식이나 스타일을 이해하도록 도와주어, 적은 수의 예시만으로도 높은 품질의 결과를 얻을 수 있게 합니다.

     

    예시를 통해 모델은 작업의 구체적인 예를 보게 되어, 무엇을 해야 하는지 명확히 이해합니다.

     

    아래는 예시, 탬플릿 정의 입니다.

    # 예시 정의
    examples = [
        {"english": "Good morning", "korean": "좋은 아침입니다"},
        {"english": "Thank you", "korean": "감사합니다"},
    ]
    
    # 예시 포맷 템플릿 정의
    example_formatter_template = """
    English: {english}
    Korean: {korean}
    """
    
    example_prompt = PromptTemplate(
        input_variables=["english", "korean"],
        template=example_formatter_template,
    )

     

    아래는 FewShotPromptTemplate 사용 예시 입니다.

    • example: 모델에게 제공할 예시들의 리스트. 모델이 수행해야 할 작업의 패턴과 형식을 이해하도록 도와줌
    • example_prompt: 각 예시를 어떻게 포맷팅할지 정의한 프롬프트 템플릿. (예시를 포멧팅한다.)
    • prefix: 프롬프트의 시작 부분으로, 모델에게 작업에 대한 지침이나 배경 정보를 제공
    • surfix: 프롬프트의 끝 부분으로, 일반적으로 사용자 입력 변수를 포함하며, 모델이 응답해야 하는 부분을 명확히 표시 (앞으로 질문한 부분을 포맷팅 한다.)
    • input_variables
    • example_seperator
    prefix = "Translate the following English sentences to Korean.\n"
    suffix = "\nEnglish: {input}\nKorean:"
    
    few_shot_prompt = FewShotPromptTemplate(
        examples=examples,
        example_prompt=example_prompt,
        prefix=prefix,
        suffix=suffix,
        input_variables=["input"],
        example_separator="\n",
    )

     

    실행

    user_input = "How are you?"
    
    formatted_prompt = few_shot_prompt.format(input=user_input)
    print(formatted_prompt)

     

    출력

    다음 영어 문장을 한국어로 번역하세요.
    
    English: Good morning
    Korean: 좋은 아침입니다
    
    English: Thank you
    Korean: 감사합니다
    
    English: How are you?
    Korean:

     

    2.3. FewShotPromptTemplate + example selector

    Example Selector(예시 선택자)LangChain에서 입력에 따라 적절한 예시를 동적으로 선택할 수 있도록 합니다.

    입력에 가장 관련성이 높은 예시들을 선택 

     

    Example Selector 사용 이유

    • LLM의 최대 토큰 길이를 초과하지 않도록 프롬프트에 포함되는 예시의 수를 조절 (필요없는 예시 제외함)
    • 입력과 가장 관련성이 높은 예시를 선택

    다양한 examples, example_prompt 설정

    examples = [
        {"word": "빠르다", "antonym": "느리다"},
        {"word": "크다", "antonym": "작다"},
        {"word": "밝다", "antonym": "어둡다"},
        {"word": "무겁다", "antonym": "가볍다"},
        {"word": "높다", "antonym": "낮다"},
        {"word": "뜨겁다", "antonym": "차갑다"},
        {"word": "길다", "antonym": "짧다"},
        {"word": "행복하다", "antonym": "슬프다"},
        # 더 많은 예시 추가 가능
    ]
    
    example_prompt = PromptTemplate(
        input_variables=["word", "antonym"],
        template="단어: {word}\n반의어: {antonym}\n",
    )

     

    example selector 설정

    • 다양한 종류의 example selector가 있지만, 여기서는 단어의 길이가 max_length를 넘지 않도록 예시를 선택.
    example_selector = LengthBasedExampleSelector(
        examples=examples,
        example_prompt=example_prompt,
        max_length=200,  # 최대 토큰 길이 설정
    )

     

    FewShotPromptTemplate 생성

    • example은 example_selector로 대체된다.
    few_shot_prompt = FewShotPromptTemplate(
        example_selector=example_selector,
        example_prompt=example_prompt,
        prefix="다음 단어의 반의어를 제공하세요.\n",
        suffix="\n단어: {input}\n반의어:",
        input_variables=["input"],
        example_separator="\n",
    )

     

    프롬프트 생성 및 확인

    user_input = "차다"
    
    formatted_prompt = few_shot_prompt.format(input=user_input)
    print(formatted_prompt)

     

    출력

    다음 단어의 반의어를 제공하세요.
    
    단어: 뜨겁다
    반의어: 차갑다
    
    단어: 차다
    반의어:

    3. 대화형 LLM을 위한 Prompt Templetes

    LangChain에서 대화형 LLM 모델을 위한 프롬프트를 생성하는 데 사용되는 클래스

    대화형 LLM 모델은 메시지의 리스트를 입력으로 받습니다. 각 메시지는 역할(role)내용(content)을 포함합니다.

     

    프롬프트 탬플릿을 만드는 방법은

    • 각 역할의 MessagePromptTemplate를 만든다. 역할 종류는 시스템, 사람, AI, 커스텀이 있다.
    • 다음에, ChatPromptTemplate 를 이용해, 하나의 대화형 프롬프트 입력로 합쳐준다.

    3.1. MessagePromptTemplate의 종류와 사용 방법 정리

    다양한 역할(role)에 따라 여러 종류의 MessagePromptTemplate이 제공되며, 이를 통해 대화의 흐름과 맥락을 효과적으로 관리할 수 있습니다.

    3.1.1. SystemMessagePromptTemplate

    • 역할(Role): system
    • 설명
      • 모델에게 전반적인 지침이나 역할을 설정해주는 메시지입니다.
      • 대화의 시작 부분에 위치하며, 모델의 행동 방식을 결정하는 데 사용됩니다.
    from langchain.prompts import SystemMessagePromptTemplate
    
    system_template = "당신은 전문적인 번역가입니다."
    system_message_prompt = SystemMessagePromptTemplate.from_template(system_template)

     

    3.1.2. HumanMessagePromptTemplate

    • 역할(Role): user
    • 설명:
      • 사용자가 모델에게 전달하는 메시지를 나타냅니다.
      • 대화에서 사용자의 질문이나 요청을 표현합니다.
    from langchain.prompts import HumanMessagePromptTemplate
    
    human_template = "{user_input}"
    human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)

    3.1.3. AIMessagePromptTemplate

    • 역할(Role): assistant
    • 설명:
      • 모델(인공지능)의 응답을 나타냅니다.
      • 이전에 모델이 사용자에게 어떤 응답을 했는지 대화 이력을 포함시킬 때 사용됩니다.

    3.1.4. ChatMessagePromptTemplate

    • 역할(Role): 사용자 정의 가능 (예: user, assistant, system 외에 사용자 정의 역할)
    • 설명:
      • 사용자 정의 역할을 가진 메시지를 생성할 때 사용합니다.
      • 특정한 역할이나 성격을 가진 가상의 화자를 추가할 수 있습니다.
    from langchain.prompts import ChatMessagePromptTemplate
    
    custom_template = "{content}"
    role = "의사"
    chat_message_prompt = ChatMessagePromptTemplate.from_template(role=role, template=custom_template)

     

    3.2. ChatPromptTemplate

    위에서 만든 다양한 MessagePromptTemplate를 합쳐 봅시다.

     

    다양한 MessagePromptTemplate 생성

    from langchain.chat_models import ChatOpenAI
    from langchain.prompts import (
        ChatPromptTemplate,
        SystemMessagePromptTemplate,
        HumanMessagePromptTemplate,
        AIMessagePromptTemplate,
        ChatMessagePromptTemplate,
    )
    
    system_message = SystemMessagePromptTemplate.from_template("당신은 유능한 여행 가이드입니다.")
    human_message = HumanMessagePromptTemplate.from_template("{user_input}")
    ai_message = AIMessagePromptTemplate.from_template("{assistant_response}")
    tourist_message = ChatMessagePromptTemplate.from_template(role="관광객", template="{tourist_question}")

     

    다양한 MessagePromptTemplate을 조합하여 복잡한 대화 프롬프트를 구성

    # ChatPromptTemplate 생성
    chat_prompt = ChatPromptTemplate.from_messages([
        system_message,
        human_message,
        ai_message,
        tourist_message,
    ])

     

    출력하기

    # 변수 정의
    variables = {
        "user_input": "파리에 대해 알려주세요.",
        "assistant_response": "파리는 프랑스의 수도로, 에펠탑과 루브르 박물관이 유명합니다.",
        "tourist_question": "에펠탑은 언제 방문하는 것이 가장 좋나요?",
    }
    
    # 메시지 생성
    messages = chat_prompt.format_messages(**variables)
    print(messages)

     

    출력

    • 실제 API에 전달되는 메세지는 json 형식으로 변경된다.
    [
        SystemMessage(content='당신은 유능한 여행 가이드입니다.'),
        HumanMessage(content='파리에 대해 알려주세요.'),
        AIMessage(content='파리는 프랑스의 수도로, 에펠탑과 루브르 박물관이 유명합니다.'),
        ChatMessage(role='관광객', content='에펠탑은 언제 방문하는 것이 가장 좋나요?')
    ]

     

    3.3. FewShotChatMessagePromptTemplate

    FewShotChatMessagePromptTemplate은 LangChain에서 대화형 LLM 모델에 Few-shot 학습을 적용하기 위해 사용되는 클래스입니다. 이를 통해 대화형 프롬프트에 예시를 포함시켜 모델이 원하는 패턴이나 형식을 학습하도록 도와줍니다.

     

    예시를 대화 형태로 정의하고, 예시 포맷 템플릿을 사용하여 예시를 포맷팅합니다.

    Example Selector를 사용하여 입력에 따라 적절한 예시를 선택할 수 있습니다.

     

    예시 정의

    # 예시 정의
    examples = [
        [
            HumanMessagePromptTemplate.from_template("안녕하세요! 자기소개 부탁드립니다."),
            AIMessagePromptTemplate.from_template("안녕하세요! 저는 인공지능 챗봇입니다."),
        ],
        [
            HumanMessagePromptTemplate.from_template("오늘 날씨가 어떤가요?"),
            AIMessagePromptTemplate.from_template("오늘은 맑고 화창한 날씨입니다."),
        ],
        [
            HumanMessagePromptTemplate.from_template("시간이 몇 시인가요?"),
            AIMessagePromptTemplate.from_template("현재 시간은 오후 3시입니다."),
        ],
        [
            HumanMessagePromptTemplate.from_template("인공지능은 무엇인가요?"),
            AIMessagePromptTemplate.from_template("인공지능은 인간의 지능을 모방하는 기술입니다."),
        ],
    ]
    
    # 예시 포맷 템플릿 정의
    example_prompt = ChatPromptTemplate.from_messages([
        HumanMessagePromptTemplate.from_template("{user_input}"),
        AIMessagePromptTemplate.from_template("{ai_response}"),
    ])

     

    example selector 만들기

    • 여기서는 openai 임베딩을 이용해 유사한 예시를 추출함
    # 임베딩 모델 초기화
    embedding_model = OpenAIEmbeddings()
    
    # Example Selector 생성
    example_selector = SemanticSimilarityExampleSelector.from_examples(
        examples,
        embedding_model,
        k=2
    )

     

    FewShotChatMessagePromptTemplate 생성

    few_shot_prompt = FewShotChatMessagePromptTemplate(
        example_selector=example_selector,
        example_prompt=example_prompt,
        prefix_messages=[
            SystemMessagePromptTemplate.from_template("당신은 친절한 도우미입니다."),
        ],
        suffix_messages=[
            HumanMessagePromptTemplate.from_template("{user_question}"),
        ],
        example_separator="\n\n",
    )

     

    출력하기

    # 사용자 질문 정의
    user_question = "지금 몇 시인가요?"
    
    # 프롬프트 생성
    messages = few_shot_prompt.format_messages(user_question=user_question)

     

    출력 결과

    system: 당신은 친절한 도우미입니다.
    
    user: 시간이 몇 시인가요?
    assistant: 현재 시간은 오후 3시입니다.
    
    user: 오늘 날씨가 어떤가요?
    assistant: 오늘은 맑고 화창한 날씨입니다.
    
    user: 지금 몇 시인가요?

    4. Example Selector

    Example Selector는 LangChain에서 Few-shot 프롬프트를 구성할 때 입력에 따라 적절한 예시를 동적으로 선택해주는 기능입니다. 많은 예시 중에서 가장 관련성이 높은 예시들을 선택하여 모델의 응답 품질을 향상시키고, 프롬프트의 길이를 효율적으로 관리할 수 있습니다.

     

    Example Selector의 종류

    • Fixed Example Selector: 사전에 정의된 고정된 예시들을 항상 사용
    from langchain.prompts.example_selector import FixedExampleSelector
    
    examples = [ ... ]  # 예시 리스트
    example_selector = FixedExampleSelector(examples=examples)
    • Length-Based Example Selector: 프롬프트의 전체 길이가 지정된 최대 길이를 넘지 않도록 예시의 수를 조절
    from langchain.prompts.example_selector import LengthBasedExampleSelector
    
    example_selector = LengthBasedExampleSelector(
        examples=examples,
        example_prompt=example_prompt,
        max_length=2048  # 최대 토큰 길이 설정
    )
    • Semantic Similarity Example Selector: 입력과 예시들 간의 의미적 유사도를 계산
    from langchain.prompts.example_selector import SemanticSimilarityExampleSelector
    from langchain.embeddings import OpenAIEmbeddings
    
    embedding_model = OpenAIEmbeddings()
    example_selector = SemanticSimilarityExampleSelector.from_examples(
        examples,
        embedding_model,
        k=3  # 선택할 예시 수
    )
    • Maximum Marginal Relevance (MMR) Example Selector: 입력과의 유사성과 예시들 간의 다양성을 모두 고려하여 예시를 선택
    from langchain.prompts.example_selector import MaxMarginalRelevanceExampleSelector
    
    embedding_model = OpenAIEmbeddings()
    example_selector = MaxMarginalRelevanceExampleSelector.from_examples(
        examples,
        embedding_model,
        k=3
    )
    • Random Example Selector: 무작위로 일정 수의 예시를 선택
    from langchain.prompts.example_selector import RandomExampleSelector
    
    example_selector = RandomExampleSelector(examples=examples, k=3)

     

    반응형