본문 바로가기
Data Analysis/AI

ConversationBufferWindowMemory: 핵심만 기억하는 효율적인 대화 메모리

by Hagrid 2025. 1. 29.
반응형

LangChain에는 여러 가지 메모리(Memory) 방식이 있습니다.
그중에서 ConversationBufferMemory가 전체 대화 내용을 전부 저장해 둔다면,
ConversationBufferWindowMemory최근 일정 개수의 대화만 유지하는 방식이에요.

장시간 대화가 이어지는 경우, 모든 대화를 무작정 기억하면 토큰 비용이나 맥락 처리가 부담될 수 있습니다.
그래서 최근 대화만 추적하면 충분한 상황이라면, ConversationBufferWindowMemory가 훨씬 효율적이죠.


1. ConversationBufferWindowMemory란?

  • “최근 N개의 대화만 기억” 하는 메모리 방식
  • 예: k=3이라면, 마지막 3개의 (질문-답변) 쌍만 저장
  • 전체 기록 대신, 윈도우(Window) 크기에 맞춰서 가장 최신 대화들만 프롬프트에 포함
  • 이전의 모든 대화를 전부 넘겨주지 않으니, 토큰 사용이 줄고, 응답 속도도 빨라집니다.

2. 왜 Window Memory가 필요할까?

  1. 토큰 절감
    • 대화가 길어질수록 모든 대화를 계속 불러오면 금방 토큰 한도를 초과하거나, API 비용이 커집니다.
    • “꼭 필요한 최근 대화”만으로도 충분하다면, 여기에 맞춰서 메모리 부담을 줄일 수 있죠.
  2. 맥락 유지
    • 여러 가지 프로젝트에서, “방금 전 몇 차례의 대화”만 중요할 때가 있어요.
    • 예: 테크니컬한 내용이 아닌, 가벼운 잡담 / 짧은 정보 갱신 등
    • 너무 이전 이야기는 굳이 보지 않아도 답변 품질이 크게 떨어지지 않는 경우가 많습니다.
  3. 단순 구현
    • 메모리를 아주 복잡하게 요약하거나, 검색할 필요 없이,
    • “최근 k개만” 가져오면 되기 때문에 코드가 간결합니다.

3. 코드 예시와 설명

아래 코드를 보면, ConversationBufferWindowMemory를 어떻게 설정하는지 감이 올 거예요.

from langchain.memory import ConversationBufferWindowMemory

memory = ConversationBufferWindowMemory(
    return_messages=True,
    k=4,
)​
  1. return_messages=True
    • 이 옵션을 True로 설정하면, “이전 대화”가 문자열이 아니라 메시지 객체(Message 객체 리스트) 형태로 반환됩니다.
    • 이렇게 하면, 메시지의 역할(시스템 / 사용자 / 어시스턴트 등)과 내용이 구분되어 있어서 후속 처리에 유리하죠.
    • 예: 대화형 인터페이스, 특정 사용자 메시지를 별도로 수정하거나 로그를 남길 때 좋습니다.
  2. k=4
    • k는 “윈도우 크기”를 뜻합니다.
    • 즉, 가장 최근 대화(메시지) 4개추출해서 프롬프트로 넘겨주겠다는 의미예요.
    • 예를 들어, 대화가 이미 10번 이상 오갔다고 해도, LLM에는 마지막 4번의 대화만 맥락으로 전달됩니다.
    • “4개”라고 하면 보통 사용자 메시지 & 어시스턴트 메시지 각각 4개가 아니라,
      사용자 메시지 + 어시스턴트 메시지를 포함한 4개 “메시지 단위”를 뜻합니다.
      (대화 하나를 보낼 때마다 메시지가 1개씩 증가하므로, 실제로는 “2번의 Q&A 쌍” 정도로 이해하시면 됩니다.)

동작 예시

  • 처음 1~4번째 대화까지는 모두 최신이니 그대로 사용됩니다.
  • 5번째 대화가 들어오면, 1번째 대화가 “가장 오래된” 대화가 되어 프롬프트에서 제외됩니다.
  • 이후 대화가 추가될 때마다, 가장 오래된 메시지부터 차례로 버려지고, 가장 최근 4개만 유지됩니다.

4. 실제 사용 시나리오

  1. 짧은 FAQ 챗봇
    • 사용자가 몇 개의 질문을 연달아 하는데, “바로 직전 질문” 정도만 참조해도 충분하다면,
      Window Memory로 부담 없이 구현할 수 있습니다.
  2. 일회성 혹은 가벼운 대화
    • 사용자 문의가 순간순간 달라지고, 이전 맥락을 길게 끌고 갈 이유가 없는 상황.
    • 대화가 복잡하게 이어지지 않는다면, “최근 몇 번의 문의”만 추적하면 충분하죠.
  3. 토큰 관리가 중요한 서비스
    • 예: OpenAI API 가격이 부담이 될 때, “딱 필요한 만큼”만 대화 맥락을 전달해 비용 절감 효과를 노릴 수 있습니다.

5. 다른 Memory 방식과의 비교

  • ConversationBufferMemory
    • 모든 대화가 누적 → 장기 대화 시 토큰 폭증 가능
    • 하지만 이전 모든 맥락을 잃지 않고 계속 이어갈 수 있음
  • ConversationBufferWindowMemory
    • k개만 기억 → 토큰 사용이 일정하게 제한됨
    • 오래된 대화 맥락은 사라지므로, “과거”가 너무 중요한 시나리오엔 부적합
  • ConversationSummaryMemory
    • 대화를 요약해서 저장 → 오래된 대화를 짧게 압축
    • “어느 정도 맥락”은 유지하되, 전체 길이를 줄이고 싶을 때 적합
  • VectorStore-Backed Memory
    • 대화 내용을 벡터로 저장하고, 필요할 때 유사도 검색으로 특정 부분만 불러옴
    • 더욱 세밀하게 과거 문맥을 찾아볼 수 있음

6. 마무리

요점 정리

  • ConversationBufferWindowMemory“최근 N개 대화만” 저장함으로써,
    • 토큰 사용량을 일정 수준으로 유지하고,
    • 상대적으로 심플한 대화형 앱을 구축할 때 유용합니다.
  • 코드 예시에서 return_messages=True와 k=4를 사용하면,
    • 메시지 객체 형태로 반환해 추가 가공이 쉬워지고,
    • 가장 최근 4개의 메시지만을 대화 맥락으로 제공하게 됩니다.

언제 쓰면 좋을까?

  • 연속된 몇 번의 대화 이상은 필요 없거나,
  • 비용(토큰) 절감이 중요할 때,
  • 복잡한 요약 로직이 필요 없는 단순한 시나리오에서.

LangChain에서는 대화가 길어지면 길어질수록,
어떻게 그 대화를 효율적으로 관리할지가 큰 고민입니다.
ConversationBufferWindowMemory는 초보자나 중급 사용자가 빠르게 대화형 시스템을 만들 때,
부담을 줄여주는 실용적인 방법이에요.

반응형

댓글