본문 바로가기
Data Analysis/AI

ConversationSummaryBufferMemory: 요약과 버퍼의 절묘한 조합

by Hagrid 2025. 1. 31.
반응형

LangChain에서 메모리(Memory)는 과거 대화를 저장·활용해, LLM(대규모 언어 모델)이 맥락을 유지하고 일관성 있는 답변을 생성하도록 돕는 핵심 요소입니다.

https://www.pinecone.io/learn/series/langchain/langchain-conversational-memory/


이때, 단순히 대화 기록을 통째로 저장하는 방식(예: ConversationBufferMemory)은 대화가 길어지면 토큰 사용량이 폭발할 수 있고,
요약만 하는 방식(예: ConversationSummaryMemory)은 최근 대화의 정교한 정보를 잃을 위험이 있죠.

ConversationSummaryBufferMemory는 이러한 문제점을 절충한 메모리 방식으로,
“최근 대화”는 버퍼(Buffer) 형태로 원문을 유지하고,
그 이전 대화는 요약(Summary) 해서 간결하게 저장함으로써
중요한 최신 대화”와 “과거 맥락”을 모두 놓치지 않게 도와줍니다.


1. ConversationSummaryBufferMemory란?

  • “최근 N개의 대화” 정도는 그대로 저장(버퍼)
  • 오래된 대화는 요약본으로 관리
  • 따라서 LLM에 프롬프트를 보낼 때,
    • 가장 최근 대화 부분(버퍼)은 원문 그대로 전달
    • 오래된 부분은 요약된 텍스트만 전달
  • 이 방식으로 필요한 세부 정보는 놓치지 않고, 토큰 사용량은 일정 수준으로 제어할 수 있습니다.

2. 작동 원리와 흐름

  1. 대화가 시작되면, 초기에는 버퍼에 대화가 그대로 쌓입니다.
  2. 버퍼가 설정한 임계(토큰 한도 또는 메시지 개수)를 초과하면, 가장 오래된 대화를 요약해 요약본(Summary)에 합칩니다.
  3. 이후에는
    • 최신 대화(k개/토큰 제한 이하)는 버퍼에 남기고,
    • 나머지(오래된) 메시지는 이미 업데이트된 요약본에 추가·통합함으로써
    • 요약 + 버퍼를 동시에 관리하게 됩니다.
  4. 결국 LLM에 프롬프트를 보낼 때,
    • 요약본(과거 맥락) + 버퍼(최근 대화) + 새로운 메시지
      이 합쳐져서 맥락으로 제공되므로, 장기 맥락최근 디테일을 모두 챙길 수 있습니다.

3. 기본 코드 예시

 
from langchain.memory import ConversationSummaryBufferMemory
from langchain.chat_models import ChatOpenAI
from langchain.chains import ConversationChain

# 1) LLM 세팅
llm = ChatOpenAI(temperature=0.7)

# 2) ConversationSummaryBufferMemory 설정
memory = ConversationSummaryBufferMemory(
    llm=llm,                # 요약에 사용될 LLM
    return_messages=True,    # 메시지 객체 형태로 반환
    max_token_limit=1000     # 최대 토큰 제한 (대략적으로 조정 가능)
)

# 3) ConversationChain 구성
conversation = ConversationChain(
    llm=llm,
    memory=memory,
    verbose=True
)

# 4) 대화 시뮬레이션
print(conversation.run("안녕하세요? 최근 날씨가 너무 덥네요."))
print(conversation.run("이번 여름휴가 추천지를 알려줄 수 있나요?"))
print(conversation.run("오, 거기 날씨나 볼거리도 궁금해요."))
# ...

코드 주요 포인트

  1. ConversationSummaryBufferMemory
    • 버퍼와 요약을 함께 관리하는 고급 메모리 클래스입니다.
    • llm 인자로 요약을 수행할 LLM을 지정해 주어야 해요. (보통 대화용 LLM과 같은 모델 쓰는 경우가 많습니다.)
  2. max_token_limit
    • 버퍼가 무한정 커지지 않도록,
    • 프롬프트에 포함될 토큰이 일정 한도를 넘으면, 오래된 대화를 요약본으로 이전합니다.
    • 이 값은 실제 토큰 사용량과 일정 오차가 있을 수 있으므로, 적절히 조금 여유롭게 잡는 것이 좋습니다.
  3. verbose=True
    • 대화 시 어떤 프롬프트가 실제로 모델에게 전달되는지 콘솔 로그로 확인할 수 있습니다.
    • 디버깅이나 테스트 시 매우 유용합니다.

4. 언제 쓰면 좋을까?

  1. 장기간 이어지는 대화
    • 유저가 여러 번 질문하고, 답변이 길어지는 상황에서 모든 대화를 통째로 기억하려면 토큰이 폭증할 수 있습니다.
    • 요약+버퍼 전략을 쓰면 부담이 훨씬 줄어듭니다.
  2. 가장 최신 내용이 특히 중요한 시나리오
    • 최근에 나온 명령이나 정보는 정확히 유지해야 하지만,
    • 오래된 기록은 전체 흐름만 알면 충분한 경우.
    • 예: 채팅봇이 “직전 몇 번의 메시지”를 디테일하게 파악해야 하면서, “그 이전 맥락”은 놓치면 안 되지만 자세히 필요하지는 않을 때.
  3. 트랜잭션성 대화
    • 예: 어느 정도 시간이 지난 정보는 요약 수준으로만 갖고 있어도 되는 온라인 주문 상담,
    • “최근 2~3번의 변경 사항”이 중요하고, 나머지는 흐름 파악만 필요한 경우.

5. 장단점

장점

  • 효율성: 모든 대화를 전부 유지하는 방법보다, 토큰 사용량을 크게 줄일 수 있음.
  • 정확도: 가장 최신 대화는 원문 형태로 전달되므로, 중요한 디테일이 손실되지 않음.
  • 맥락 보존: 오래된 내용은 요약으로 전환하되, 대화의 핵심 흐름을 유지할 수 있음.

단점

  • 요약 품질 의존: 요약 자체가 잘못되면, 오류가 누적될 가능성이 있음.
  • 설정 난이도: 적절한 버퍼 크기나 토큰 제한을 잡는 것이 중요하고, 상황에 따라 미세 튜닝이 필요.
  • 추가 비용: 요약을 할 때마다 LLM 호출이 추가로 일어날 수 있으므로,
    전체적인 API 호출 수가 늘어날 수도 있습니다(다만, 긴 프롬프트 비용을 줄이는 것과 어느 쪽이 더 비싼지는 케이스 바이 케이스).

6. 다른 Memory와 비교

  1. ConversationBufferMemory
    • 모든 대화를 쌓아두고 계속 전달
    • 대화가 길어지면 토큰 폭발 위험이 큼
  2. ConversationSummaryMemory
    • 전부 요약해서 기억
    • 가장 최신 디테일도 요약되므로, 세부 정보가 사라질 수 있음
  3. ConversationBufferWindowMemory
    • 최근 N개 대화만 저장(버퍼)
    • 오래된 대화는 아예 사라져서, 중요한 과거 정보가 유실될 수 있음
  4. ConversationSummaryBufferMemory
    • Buffer(최근 N개) + Summary(오래된 대화)
    • 최신 상세 정보 & 오래된 맥락을 둘 다 챙길 수 있음
    • 구현이 조금 복잡하지만, 다양한 시나리오에서 실용적

7. 마무리

ConversationSummaryBufferMemory는 긴 대화를 다루면서도,
가장 최근 대화의 정밀한 맥락과 과거 대화의 요약된 흐름동시에 유지해야 할 때 최고의 선택지입니다.

  • 최적의 토큰 절감
  • 최대한의 맥락 보존 사이에서 고민 중이라면,
    꼭 한번 시도해 보시길 추천드립니다.

이 글이 도움이 되셨다면, 댓글공유 부탁드립니다!
궁금한 점이나 추가로 다루었으면 하는 주제가 있다면, 댓글로 자유롭게 남겨주세요. 감사합니다.

반응형

댓글