Study/AI

[LangChain] 채팅 히스토리 기억하기 (Memory, MessagesPlaceholder)

Super-Son 2025. 3. 20. 22:03

LangChain의 메모리 관리 기능을 공부했습니다. LangChain의 메모리 관리 기능을 사용하면, AI 챗봇은 이전에 사용자가 나눈 대화 내용을 기억하고 이를 바탕으로 자연스러운 대화를 이어나갈 수 있습니다. 다양한 메모리 저장 방법이 있지만 글에서는 대화 내용을 요약해서 저장하는 코드만 정리하겠습니다.

 

배운 내용 요약

  • 저장된 메모리는 대화 흐름을 자연스럽게 유지하는 데 활용됩니다.
  • 메모리를 사용하면 이전 대화의 맥락을 참고하여 사용자의 질문에 더욱 정확하고 자연스럽게 응답할 수 있습니다.

 

주요 코드 정리

ConversationSummaryBufferMemory

메모리는 언어 모델(llm)을 통해 대화를 요약한 뒤, 지정된 토큰 수 내에서 기억합니다.

from langchain.memory import ConversationSummaryBufferMemory

memory = ConversationSummaryBufferMemory(
    llm=llm,                  # 대화를 요약해 저장할 언어 모델
    max_token_limit=120,      # 메모리에 저장할 최대 토큰 수
    return_messages=True,     # 메모리 호출 시 메시지 형태로 반환
)

 

MessagesPlaceholder

이전의 대화 내용을 동적으로 불러와 프롬프트 내부에 배치하는 역할을 합니다. 이를 통해 챗봇은 이전의 대화 맥락을 참고할 수 있게 됩니다. MessagesPlaceholder를 사용하면 메모리를 템플릿에 쉽게 적용할 수 있습니다.

prompt = ChatPromptTemplate.from_messages(
    [
        ("system", "You are helpful AI assistant."),
        MessagesPlaceholder(variable_name="history"),  # 이전 대화 내용을 동적으로 포함할 수 있는 위치 지정
        ("human", "{question}"),
    ]
)

 

공부한 코드

from langchain.memory import ConversationSummaryBufferMemory
from langchain.chat_models import ChatOpenAI
from langchain.schema.runnable import RunnablePassthrough
from langchain.prompts import PromptTemplate, ChatPromptTemplate, MessagesPlaceholder, FewShotChatMessagePromptTemplate
from langchain.prompts.example_selector import LengthBasedExampleSelector

llm = ChatOpenAI(temperature=0.1)

memory = ConversationSummaryBufferMemory(
    llm=llm,
    max_token_limit=120,
    return_messages=True,
)

# 예시 설정
examples = [
    {"country": "한국", "alphabet": "KR"},
    {"country": "일본", "alphabet": "JP"},
    {"country": "미국", "alphabet": "US"},
    {"country": "프랑스", "alphabet": "FR"},
]

example_selector = LengthBasedExampleSelector(
    examples=examples,
    example_prompt=PromptTemplate(
        input_variables=["country", "alphabet"],
        template="Human: {country}\nAI: {alphabet}"
    ),
    max_length=50,
)

few_shot_prompt = FewShotChatMessagePromptTemplate(
    example_selector=example_selector,
    example_prompt=ChatPromptTemplate.from_messages(
        [("human", "{country}"), ("ai", "{alphabet}")]
    ),
)

prompt = ChatPromptTemplate.from_messages(
    [
        ("system", """You are an AI assistant who responds with alphabetic abbreviations from a particular country.
 If you ask about the country you asked before, please answer with the country name and the abbreviation of the alphabet you expressed."""),
        MessagesPlaceholder(variable_name="history"),
        few_shot_prompt,
        ("human", "{question}"),
    ]
)


def load_memory(_):
    return memory.load_memory_variables({})["history"]


chain = RunnablePassthrough.assign(history=load_memory) | prompt | llm


def invoke_chain(country):
    result = chain.invoke({"question": country})
    memory.save_context(
        {"input": country},
        {"output": result.content},
    )
    print(result.content)

출력 화면 캡처