PromptTemplate

프롬프트 엔지니어링

효과적인 프롬프트 템플릿 설계 및 관리 기법을 다룬다.

AI
RAG
LangChain
Prompt Engineering
저자

Kwangmin Kim

공개

2025년 01월 12일

from dotenv import load_dotenv  

load_dotenv()  
# LangSmith 추적을 설정합니다. https://smith.langchain.com  
# !pip install -qU langchain-teddynote  
from langchain_teddynote import logging  

# 프로젝트 이름을 입력합니다.  
logging.langsmith("CH02-Prompt")  

LLM 객체를 정의합니다.

from langchain_openai import ChatOpenAI  

llm = ChatOpenAI()  

0.1 방법 1. from_template() 메소드를 사용하여 PromptTemplate 객체 생성

  • 치환될 변수를 { 변수 } 로 묶어서 템플릿을 정의합니다.
from langchain_core.prompts import PromptTemplate  

# template 정의. {country}는 변수로, 이후에 값이 들어갈 자리를 의미  
template = "{country}의 수도는 어디인가요?"  

# from_template 메소드를 이용하여 PromptTemplate 객체 생성  
prompt = PromptTemplate.from_template(template)  
prompt  

country 변수에 값을 넣어서 문장을 생성할 수 있습니다.

# prompt 생성. format 메소드를 이용하여 변수에 값을 넣어줌  
prompt = prompt.format(country="대한민국")  
prompt  
# template 정의  
template = "{country}의 수도는 어디인가요?"  

# from_template 메소드를 이용하여 PromptTemplate 객체 생성  
prompt = PromptTemplate.from_template(template)  

# chain 생성  
chain = prompt | llm  
# country 변수에 입력된 값이 자동으로 치환되어 수행됨  
chain.invoke("대한민국").content  

0.2 방법 2. PromptTemplate 객체 생성과 동시에 prompt 생성

추가 유효성 검사를 위해 input_variables 를 명시적으로 지정하세요.

이러한 변수는 인스턴스화 중에 템플릿 문자열에 있는 변수와 비교하여 불일치하는 경우 예외를 발생시킵니다.

# template 정의  
template = "{country}의 수도는 어디인가요?"  

# PromptTemplate 객체를 활용하여 prompt_template 생성  
prompt = PromptTemplate(  
    template=template,  
    input_variables=["country"],  
)  

prompt  
# prompt 생성  
prompt.format(country="대한민국")  
# template 정의  
template = "{country1}{country2}의 수도는 각각 어디인가요?"  

# PromptTemplate 객체를 활용하여 prompt_template 생성  
prompt = PromptTemplate(  
    template=template,  
    input_variables=["country1"],  
    partial_variables={  
        "country2": "미국"  # dictionary 형태로 partial_variables를 전달  
    },  
)  

prompt  
prompt.format(country1="대한민국")  
prompt_partial = prompt.partial(country2="캐나다")  
prompt_partial  
prompt_partial.format(country1="대한민국")  
chain = prompt_partial | llm  
chain.invoke("대한민국").content  
chain.invoke({"country1": "대한민국", "country2": "호주"}).content  

0.3 partial_variables: 부분 변수 채움

partial을 사용하는 일반적인 용도는 함수를 부분적으로 사용하는 것입니다. 이 사용 사례는 항상 공통된 방식으로 가져오고 싶은 변수 가 있는 경우입니다.

대표적인 예가 날짜나 시간 입니다.

항상 현재 날짜가 표시되기를 원하는 프롬프트가 있다고 가정해 보겠습니다. 프롬프트에 하드 코딩할 수도 없고, 다른 입력 변수와 함께 전달하는 것도 번거롭습니다. 이 경우 항상 현재 날짜를 반환하는 함수 를 사용하여 프롬프트를 부분적으로 변경할 수 있으면 매우 편리합니다.

다음의 코드는 오늘 날짜를 구하는 파이썬 코드입니다.

from datetime import datetime  

# 오늘 날짜를 출력  
datetime.now().strftime("%B %d")  
# 날짜를 반환하는 함수 정의  
def get_today():  
    return datetime.now().strftime("%B %d")  
prompt = PromptTemplate(  
    template="오늘의 날짜는 {today} 입니다. 오늘이 생일인 유명인 {n}명을 나열해 주세요. 생년월일을 표기해주세요.",  
    input_variables=["n"],  
    partial_variables={  
        "today": get_today  # dictionary 형태로 partial_variables를 전달  
    },  
)  
# prompt 생성  
prompt.format(n=3)  
# chain 을 생성합니다.  
chain = prompt | llm  
# chain 을 실행 후 결과를 확인합니다.  
print(chain.invoke(3).content)  
# chain 을 실행 후 결과를 확인합니다.  
print(chain.invoke({"today": "Jan 02", "n": 3}).content)  

1 파일로부터 template 읽어오기

from langchain_core.prompts import load_prompt  

prompt = load_prompt("prompts/fruit_color.yaml", encoding="utf-8")  
prompt  

Window 사용자 중 이전의 코드가 오류가 나는 경우 아래의 코드로 실행하세요(인코딩 설정)

from langchain_teddynote.prompts import load_prompt  

# Windows 사용자 only: 인코딩을 cp949로 설정  
load_prompt("prompts/fruit_color.yaml", encoding="utf-8")  
prompt.format(fruit="사과")  
prompt2 = load_prompt("prompts/capital.yaml")  
print(prompt2.format(country="대한민국"))  

2 ChatPromptTemplate

ChatPromptTemplate 은 대화목록을 프롬프트로 주입하고자 할 때 활용할 수 있습니다.

메시지는 튜플(tuple) 형식으로 구성하며, (role, message) 로 구성하여 리스트로 생성할 수 있습니다.

role
- "system": 시스템 설정 메시지 입니다. 주로 전역설정과 관련된 프롬프트입니다.
- "human" : 사용자 입력 메시지 입니다.
- "ai": AI 의 답변 메시지입니다.

from langchain_core.prompts import ChatPromptTemplate  

chat_prompt = ChatPromptTemplate.from_template("{country}의 수도는 어디인가요?")  
chat_prompt  
chat_prompt.format(country="대한민국")  
from langchain_core.prompts import ChatPromptTemplate  

chat_template = ChatPromptTemplate.from_messages(  
    [  
        # role, message  
        ("system", "당신은 친절한 AI 어시스턴트입니다. 당신의 이름은 {name} 입니다."),  
        ("human", "반가워요!"),  
        ("ai", "안녕하세요! 무엇을 도와드릴까요?"),  
        ("human", "{user_input}"),  
    ]  
)  

# 챗 message 를 생성합니다.  
messages = chat_template.format_messages(  
    name="테디", user_input="당신의 이름은 무엇입니까?"  
)  
messages  

생성한 메시지를 바로 주입하여 결과를 받을 수 있습니다.

llm.invoke(messages).content  

이번에는 체인을 생성해 보겠습니다.

chain = chat_template | llm  
chain.invoke({"name": "Teddy", "user_input": "당신의 이름은 무엇입니까?"}).content  

3 MessagePlaceholder

또한 LangChain은 포맷하는 동안 렌더링할 메시지를 완전히 제어할 수 있는 MessagePlaceholder 를 제공합니다.

메시지 프롬프트 템플릿에 어떤 역할을 사용해야 할지 확실하지 않거나 서식 지정 중에 메시지 목록을 삽입하려는 경우 유용할 수 있습니다.

from langchain_core.output_parsers import StrOutputParser  
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder  

chat_prompt = ChatPromptTemplate.from_messages(  
    [  
        (  
            "system",  
            "당신은 요약 전문 AI 어시스턴트입니다. 당신의 임무는 주요 키워드로 대화를 요약하는 것입니다.",  
        ),  
        MessagesPlaceholder(variable_name="conversation"),  
        ("human", "지금까지의 대화를 {word_count} 단어로 요약합니다."),  
    ]  
)  
chat_prompt  

conversation 대화목록을 나중에 추가하고자 할 때 MessagesPlaceholder 를 사용할 수 있습니다.

formatted_chat_prompt = chat_prompt.format(  
    word_count=5,  
    conversation=[  
        ("human", "안녕하세요! 저는 오늘 새로 입사한 테디 입니다. 만나서 반갑습니다."),  
        ("ai", "반가워요! 앞으로 잘 부탁 드립니다."),  
    ],  
)  

print(formatted_chat_prompt)  
# chain 생성  
chain = chat_prompt | llm | StrOutputParser()  
# chain 실행 및 결과확인  
chain.invoke(  
    {  
        "word_count": 5,  
        "conversation": [  
            (  
                "human",  
                "안녕하세요! 저는 오늘 새로 입사한 테디 입니다. 만나서 반갑습니다.",  
            ),  
            ("ai", "반가워요! 앞으로 잘 부탁 드립니다."),  
        ],  
    }  
)  

Subscribe

Enjoy this blog? Get notified of new posts by email: