LLM 메모리

대부분의 LLM 기반 응용 프로그램은 WeChat과 유사한 채팅 인터페이스를 가지고 있습니다. AI 대화 과정의 중요한 기능은 이전 대화에서 이야기한 정보를 참조할 수 있는 능력으로, 사람들의 대화 과정과 유사하게 이전 내용을 반복하지 않고도 이전에 대화한 내용을 참조하는 것입니다. 사람들은 역사적인 정보를 자동으로 회상합니다.

LLM 필드에 역사적인 대화 정보를 저장할 수 있는 능력은 보통 "메모리"라고 불리며, 이는 사람들이 기억력을 가지고 있는 것과 유사합니다. LangChain은 다양한 메모리 기능 구성 요소를 캡슐화하여 별도로 사용하거나 체인에 매끄럽게 통합하여 사용할 수 있습니다.

메모리 구성 요소는 읽기와 쓰기 두 가지 기본 작업을 구현해야 합니다.

LangChain의 다양한 체인 작업 구성 요소에 대해 메모리 기능을 활성화하면 다음과 유사한 논리를 실행할 것입니다:

  1. 초기 사용자 입력을 받을 때, 체인 작업은 메모리 구성 요소에서 관련된 역사적인 정보를 쿼리한 후, 역사적인 정보와 사용자 입력을 연결하여 LLM에 전달할 프롬프트로 연결할 것입니다.
  2. LLM에서 반환된 내용을 받을 때, 다음에 쉽게 쿼리할 수 있도록 결과를 자동으로 메모리 구성 요소에 저장할 것입니다.

LangChain에서 메모리 능력을 구현하는 과정은 아래 다이어그램에 나와 있습니다: 메모리 프로세스

시스템에 메모리 구성 요소 통합하기

메모리 구성 요소를 사용하기 전에 다음 두 가지 질문을 고려해야 합니다:

  • 역사적인 메시지 데이터를 어떻게 저장할 것인가
  • 역사적인 메시지 데이터를 어떻게 쿼리할 것인가

저장: 채팅 메시지 목록

채팅 모델을 사용하는 경우 대화 데이터는 채팅 메시지 목록입니다. LangChain은 역사적인 메시지 데이터를 저장하는 데 다양한 저장 엔진을 지원하며, 가장 간단한 방법은 메모리에 저장하는 것입니다. 실제로 가장 많이 사용되는 방법은 데이터베이스에 저장하는 것입니다.

쿼리: 관련된 역사적인 대화 메시지를 어떻게 쿼리할 것인가

LLM의 메모리 능력을 구현하기 위해, 핵심은 역사적인 메시지 내용을 백그라운드 정보로 프롬프트에 연결하는 것입니다. 이렇게 하면 LLM이 질문에 답변할 때 백그라운드 정보를 참조할 수 있습니다.

역사적인 메시지 데이터를 저장하는 것은 비교적 쉬우며, 더 어려운 측면은 현재 대화 내용과 관련된 역사적인 메시지를 어떻게 쿼리할 것인가입니다. 현재 대화 내용과 관련된 역사적인 메시지를 쿼리해야 하는 이유는 LLM의 최대 토큰 제한 때문입니다. 우리는 모든 역사적인 대화 내용을 프롬프트에 먹이기 어렵기 때문에 이렇게 해야 합니다.

일반적인 역사적인 메시지 쿼리 전략에는 다음이 포함됩니다:

  • 프롬프트의 백그라운드 정보로 사용하기 위해 가장 최근의 N개 메시지만 쿼리하기
  • 역사적인 메시지를 요약하여 백그라운드 정보로 사용하기
  • 현재 대화와 유사한 역사적인 메시지를 쿼리하고 백그라운드 정보로 사용하기 위해 벡터 데이터베이스를 활용하기

LangChain 구성 요소 사용 예시

LangChain의 메모리 구성 요소를 살펴보겠습니다. 여기에서는 메모리 구성 요소와 상호 작용하는 기본 지식을 소개할 것입니다.

먼저, 체인 내에서 ConversationBufferMemory를 사용하는 방법을 살펴보겠습니다. ConversationBufferMemory는 메모리에 채팅 메시지 목록을 저장하고 새로운 대화 프롬프트 템플릿에 전달할 수 있는 매우 간단한 메모리 구성 요소입니다.

from langchain.memory import ConversationBufferMemory

memory = ConversationBufferMemory()
memory.chat_memory.add_user_message("안녕!")
memory.chat_memory.add_ai_message("어떻게 지내?")
  • 참고: LangChain은 비슷한 사용 방법으로 다양한 메모리 구성 요소를 제공합니다.

다음으로, 체인 내에서 메모리 구성 요소를 사용하는 방법을 살펴보겠습니다. 아래에서는 LangChain에 캡슐화된 LLM 및 ChatModel 두 모델이 메모리 구성 요소를 사용하는 방법을 소개할 것입니다.

메모리 구성 요소를 사용한 LLM의 예시

from langchain_openai import OpenAI
from langchain_core.prompts import PromptTemplate
from langchain.chains import LLMChain
from langchain.memory import ConversationBufferMemory

llm = OpenAI(temperature=0)

template = """당신은 사람과 대화하는 훌륭한 챗봇입니다.

이전 대화:
{chat_history}

새로운 질문: {question}
AI의 답변:"""
prompt = PromptTemplate.from_template(template)

memory = ConversationBufferMemory(memory_key="chat_history")
conversation = LLMChain(
    llm=llm,
    prompt=prompt,
    verbose=True,
    memory=memory
)
conversation({"question": "안녕"})
from langchain_openai import ChatOpenAI
from langchain.prompts import (
    ChatPromptTemplate,
    MessagesPlaceholder,
    SystemMessagePromptTemplate,
    HumanMessagePromptTemplate,
)
from langchain.chains import LLMChain
from langchain.memory import ConversationBufferMemory

llm = ChatOpenAI()
prompt = ChatPromptTemplate(
    messages=[
        SystemMessagePromptTemplate.from_template(
            "당신은 사람과 대화를 나누는 멋진 챗봇입니다."
        ),
        MessagesPlaceholder(variable_name="chat_history"),
        HumanMessagePromptTemplate.from_template("{question}")
    ]
)
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)

conversation = LLMChain(
    llm=llm,
    prompt=prompt,
    verbose=True,
    memory=memory
)
conversation({"question": "안녕"})