2.1.5. MessagesPlaceholder

MessagesPlaceholder는 LangChain에서 대화 기반 애플리케이션을 개발할 때 중요한 구성 요소 중 하나로, 특히 대화 기록(Conversation History)이나 동적으로 생성되는 메시지를 처리할 때 유용합니다.

동적 대화 관리의 핵심

LangChain은 대화형 AI 애플리케이션 개발을 위한 강력한 프레임워크로, 대화 흐름을 자연스럽게 관리할 수 있는 도구들을 제공합니다. 그중 MessagesPlaceholder는 대화 기록이나 동적으로 추가되는 메시지를 처리하는 데 핵심적인 역할을 합니다.

MessagesPlaceholder는 LangChain의 langchain_core.prompts 모듈에 포함된 클래스입니다. 이 클래스는 프롬프트 템플릿(Prompt Template) 내에서 동적으로 삽입되는 메시지 리스트를 예약된 공간으로 정의합니다. 주로 대화형 애플리케이션에서 대화 기록(예: 사용자 입력과 AI 응답의 히스토리)을 처리하거나, 특정 변수에 따라 메시지를 유연하게 추가할 때 사용됩니다.

MessagesPlaceholder의 핵심 기능은 다음과 같습니다:

  • 동적 메시지 관리: 대화 기록이나 특정 메시지를 런타임에 삽입할 수 있도록 플레이스홀더를 제공합니다.
  • 유연한 프롬프트 설계: 정적인 텍스트뿐만 아니라 동적으로 변하는 대화 흐름을 프롬프트에 통합할 수 있습니다.
  • 대화 기록 통합: HumanMessage, AIMessage, SystemMessage 등 다양한 메시지 타입을 체계적으로 관리합니다.

언제 사용해야 할까?

MessagesPlaceholder는 다음과 같은 상황에서 특히 유용합니다:

  • 챗봇에서 사용자와의 대화 기록을 기반으로 응답을 생성할 때.
  • 대화 흐름에 따라 시스템 메시지나 추가적인 맥락을 동적으로 삽입해야 할 때.
  • 여러 사용자 입력을 하나의 프롬프트에 통합해 처리할 때.

MessagesPlaceholder의 기본 구조

MessagesPlaceholder는 PromptTemplate 내에서 특정 변수 이름으로 정의되며, 해당 변수에 메시지 리스트가 런타임에 바인딩됩니다. 기본적인 구조는 다음과 같습니다:

from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder

prompt = ChatPromptTemplate.from_messages([
    ("system", "당신은 도움이 되는 AI 어시스턴트입니다. 사용자의 질문에 친절하고 정확하게 답변하세요."),
    MessagesPlaceholder(variable_name="chat_history"),
    ("human", "{user_input}")
])

위 코드에서:

  • MessagesPlaceholder(variable_name=”chat_history”)는 chat_history라는 이름의 변수에 대화 기록(메시지 리스트)이 삽입될 공간을 예약합니다.
  • ChatPromptTemplate.from_messages는 시스템 메시지, 대화 기록, 사용자 입력을 순서대로 조합합니다.

주요 파라미터

  • variable_name: 플레이스홀더에 바인딩될 변수의 이름. 이 이름은 나중에 메시지 리스트를 전달할 때 사용됩니다.
  • optional (선택 사항): True로 설정하면 해당 플레이스홀더가 비어 있어도 프롬프트가 정상적으로 동작합니다. 기본값은 False입니다.

MessagesPlaceholder 사용 예제

이제 MessagesPlaceholder를 실제로 사용하는 몇 가지 예제를 살펴보겠습니다.

예제 1: 대화 기록을 포함한 챗봇

사용자와의 대화 기록을 기반으로 응답하는 챗봇을 구현한다고 가정해 보겠습니다. 아래는 MessagesPlaceholder를 활용한 간단한 구현입니다.

from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.messages import HumanMessage, AIMessage
from langchain_ollama import ChatOllama

# 프롬프트 템플릿 정의
prompt = ChatPromptTemplate.from_messages([
    ("system", "당신은 친절한 여행 가이드입니다. 사용자의 질문에 맞춰 여행 정보를 제공하세요."),
    MessagesPlaceholder(variable_name="chat_history"),
    ("human", "{user_input}")
])

# LLM 모델 초기화
llm = ChatOllama(model="exaone3.5", temperature=0.7)

# 대화 기록 초기화
chat_history = [
    HumanMessage(content="서울에서 가볼 만한 곳을 추천해 주세요."),
    AIMessage(content="서울에는 경복궁, 북촌 한옥마을, 남산타워 등이 인기 있습니다. 어떤 분위기를 원하시나요?"),
]

# 사용자 입력
user_input = "역사적인 장소가 좋습니다."

# 프롬프트에 변수 바인딩
chain = prompt | llm
response = chain.invoke({
    "chat_history": chat_history,
    "user_input": user_input
})

print(response.content)
역사 애호가님을 위한 서울 여행 추천지 몇 군데를 소개해 드릴게요!

경복궁: 조선시대 왕궁으로, 웅장한 건축물과 아름다운 정원을 자랑합니다. 궁궐 안을 둘러보며 역사 속으로 시간 여행을 떠나보세요! 특히 경복궁 야간 개장 기간에는 특별한 야경을 감상할 수 있어요.
창덕궁: 경복궁과 함께 조선시대 왕궁 중 하나로, 자연과 조화를 이룬 아름다운 정원이 특징입니다. 후원은 꼭 방문해야 할 곳으로, 조선시대 왕들의 휴식처였던 곳입니다.
남산 한옥마을: 전통 한옥들이 모여 있는 곳으로, 고즈넉한 분위기 속에서 역사를 느낄 수 있습니다. 한복 대여도 가능하니, 전통 의상을 입고 사진도 남겨보세요!
세종대왕릉: 조선시대 넷째 왕 세종대왕의 무덤으로, 역사적 의미가 매우 깊습니다. 웅장한 무덤 양식과 주변 자연환경을 함께 감상할 수 있습니다.
국립중앙박물관: 한국 역사와 문화를 한눈에 담을 수 있는 곳입니다. 다양한 유물 전시와 특별전시를 통해 깊이 있는 역사 여행을 경험해보세요!

어떤 장소에 가장 관심이 있으신가요? 좀 더 자세히 알려주시면 맞춤 추천을 해드릴 수 있습니다! 😊

이 예제에서 MessagesPlaceholder는 chat_history 변수에 저장된 대화 기록을 프롬프트에 동적으로 삽입하여, LLM이 이전 대화 맥락을 고려한 응답을 생성하도록 합니다.

예제 2: 동적으로 시스템 메시지 추가

MessagesPlaceholder는 대화 기록뿐만 아니라 특정 조건에 따라 시스템 메시지를 추가하는 데도 사용할 수 있습니다. 예를 들어, 사용자의 언어 설정에 따라 시스템 메시지를 동적으로 변경하는 경우를 살펴보겠습니다.

from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.messages import SystemMessage
from langchain_ollama import ChatOllama

# 언어별 시스템 메시지
def get_system_message(language):
    if language == "ko":
        return SystemMessage(content="당신은 한국어로 대화하는 AI입니다. 자연스럽고 친절하게 답변하세요.")
    elif language == "en":
        return SystemMessage(content="You are an AI that communicates in English. Respond naturally and kindly.")
    return SystemMessage(content="You are a helpful AI assistant.")

# 프롬프트 템플릿 정의
prompt = ChatPromptTemplate.from_messages([
    MessagesPlaceholder(variable_name="system_message"),
    MessagesPlaceholder(variable_name="chat_history"),
    ("human", "{user_input}")
])

# LLM 모델 초기화
llm = ChatOllama(model="exaone3.5")

# 대화 기록 및 입력
chat_history = []
user_input = "안녕하세요! 오늘 기분이 어때요?"
system_message = [get_system_message("ko")]

# 프롬프트 실행
chain = prompt | llm
response = chain.invoke({
    "system_message": system_message,
    "chat_history": chat_history,
    "user_input": user_input
})

print(response.content)
안녕하세요! 저는 인공지능이기 때문에 감정을 직접 느끼지는 않지만, 오늘 당신과 대화할 수 있어서 정말 기쁩니다. 어떻게 도와드릴까요? 기분이 좋으시다면 더욱 재미있는 이야기나 도움이 필요한 정보를 함께 나누는 것도 좋을 것 같아요! 어떤 활동을 원하시나요?

이 예제에서는 MessagesPlaceholder를 사용해 시스템 메시지를 동적으로 삽입했습니다. 이를 통해 언어 설정이나 사용자 선호도에 따라 프롬프트를 유연하게 조정할 수 있습니다.

MessagesPlaceholder 활용 시 고려 사항

MessagesPlaceholder는 강력하지만, 올바르게 사용하기 위해 몇 가지 주의할 점이 있습니다.

대화 기록의 크기 관리

대화 기록이 길어질수록 LLM의 토큰 제한에 영향을 미칩니다. 따라서 다음과 같은 전략을 고려하세요:

  • 최근 대화만 유지: 예를 들어, 최근 5개의 메시지만 chat_history에 포함.
  • 요약 사용: LangChain의 ConversationSummaryMemory를 활용해 긴 대화 기록을 요약.
  • 토큰 모니터링: LLM 호출 시 사용된 토큰 수를 모니터링해 제한을 초과하지 않도록 관리.

메시지 타입 일관성

MessagesPlaceholder에 삽입되는 메시지는 HumanMessage, AIMessage, SystemMessage 등 LangChain의 메시지 클래스 인스턴스여야 합니다. 일반 문자열 리스트를 직접 삽입하면 오류가 발생할 수 있으니 주의하세요.

프롬프트 최적화

MessagesPlaceholder를 사용할 때는 프롬프트의 구조가 복잡해질 수 있습니다. 따라서:

  • 프롬프트 디버깅 도구(예: LangChain의 PromptTemplate.format 메서드)를 활용해 예상 출력 확인.
  • 시스템 메시지와 사용자 입력의 역할이 명확히 구분되도록 설계.

실제 애플리케이션 사례

MessagesPlaceholder는 다양한 실세계 애플리케이션에서 활용됩니다. 몇 가지 대표적인 사례를 소개합니다:

  • 고객 지원 챗봇: 고객과의 대화 기록을 기반으로 문맥을 유지하며 응답. 예: “이전에 말씀하신 주문 번호에 대해 추가 정보를 드리겠습니다.”
  • 교육용 AI 튜터: 학생의 질문과 이전 답변을 참조해 맞춤형 학습 가이드를 제공.
  • 다국어 지원 챗봇: 사용자의 언어 설정에 따라 시스템 메시지를 동적으로 변경해 자연스러운 대화 제공.

MessagesPlaceholder는 LangChain에서 대화형 애플리케이션의 유연성과 확장성을 높여주는 강력한 도구입니다. 이를 통해 대화 기록을 체계적으로 관리하고, 동적으로 변하는 메시지를 프롬프트에 통합할 수 있습니다. 이 챕터에서 다룬 개념과 예제를 바탕으로, 여러분만의 대화형 AI 애플리케이션에서 MessagesPlaceholder를 효과적으로 활용해 보세요.

이 글은 카테고리: 랭체인 (LangChain)에 포함되어 있습니다. 고유주소를 북마크하세요.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다