요약 메모리와 토큰 인식형 잘라내기
ConversationSummaryMemory를 사용해 오래된 대화 차례를 자동으로 요약하고, 사용자가 앞서 언급한 핵심 사실을 보존하면서 대화를 압축된 상태로 유지합니다.
요약 메모리와 토큰 인식형 잘라내기은(는) CoddyKit의 무료 AI Engineering Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 AI Engineering Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. AI Engineering Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
전체 기록의 토큰 비용
Conversation Buffer Memory는 지금까지 주고받은 모든 메시지를 유지하므로 문맥 창을 빠르게 소모합니다. 100개의 대화 차례로 이루어진 대화에서는 기록에만 20,000개의 토큰이 사용되어 실제 응답을 위한 공간이 거의 남지 않을 수 있습니다. 요약 메모리는 오래된 대화 차례를 압축된 요약으로 바꾸어 이 문제를 해결합니다.
요약 메모리의 작동 방식
총 토큰 수가 임계값을 초과하면 ConversationSummaryMemory가 가장 오래된 대화 차례를 LLM에 전달하고 핵심 내용을 요약하도록 요청합니다. 전체 대화 차례는 삭제되고 이 간결한 요약으로 대체됩니다. 이후의 대화 차례는 요약 위에 계속 쌓입니다.
- 오래된 대화 차례: 요약으로 대체
- 최근 대화 차례: 원문 그대로 유지
- 최종 결과: 정보 손실을 최소화하면서 의미 있게 압축
LangChain의 ConversationSummaryMemory
LangChain은 버퍼가 너무 커질 때마다 자동으로 요약하는 ConversationSummaryMemory를 제공합니다. 메모리 객체에 LLM을 전달하면 필요할 때 모델을 호출하여 요약을 생성할 수 있습니다.
from langchain.memory import ConversationSummaryMemory
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model='gpt-4o-mini')
memory = ConversationSummaryMemory(
llm=llm,
return_messages=True
)
# Add messages manually
memory.save_context(
{'input': 'My name is Alice and I am building a RAG system.'},
{'output': 'Great, I can help you build a RAG system, Alice.'}
)
print(memory.load_memory_variables({}))요약 버퍼 메모리: 두 방식의 장점 결합
ConversationSummaryBufferMemory는 최근 대화 차례를 정확성을 위해 원문 그대로 유지하고, max_token_limit을 초과하는 오래된 대화 차례만 요약하는 혼합 방식입니다. 따라서 최근 문맥은 정확하게 기억하면서 오래된 문맥은 압축된 형태로 기억할 수 있습니다.
from langchain.memory import ConversationSummaryBufferMemory
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model='gpt-4o-mini')
memory = ConversationSummaryBufferMemory(
llm=llm,
max_token_limit=500, # Summarize when older turns exceed 500 tokens
return_messages=True
)
# As the conversation grows, old turns get summarized automatically
print('Moving summary:', memory.moving_summary_buffer)잘라내기 전 토큰 수 세기
현명하게 잘라낼 대상을 결정하려면 메시지가 소비하는 토큰 수를 알아야 합니다. tiktoken 라이브러리를 사용하면 모든 OpenAI 모델의 토큰 수를 셀 수 있습니다. 이를 통해 예산을 엄격하게 넘지 않는 토큰 인식 잘라내기를 구현할 수 있습니다.
import tiktoken
def count_tokens(messages: list, model: str = 'gpt-4o') -> int:
encoding = tiktoken.encoding_for_model(model)
total = 0
for msg in messages:
# Each message has overhead tokens for role framing
total += 4
total += len(encoding.encode(msg.get('content', '')))
total += 2 # Reply primer
return total
messages = [
{'role': 'user', 'content': 'Explain RAG to me.'},
{'role': 'assistant', 'content': 'RAG stands for Retrieval-Augmented Generation...'}
]
print('Token count:', count_tokens(messages))수동으로 토큰을 고려하여 잘라내기
때로는 LangChain의 메모리 클래스 없이 잘라내기를 완전히 직접 제어하고 싶을 수 있습니다. 간단한 방법은 모든 메시지를 유지한 다음 총 토큰 수가 예산 내에 들어올 때까지 가장 오래된 시스템 메시지가 아닌 메시지를 한 번에 하나씩 제거하는 것입니다.
def truncate_to_budget(messages: list, budget: int, model: str = 'gpt-4o') -> list:
'''Remove oldest non-system messages until under budget.'''
import tiktoken
encoding = tiktoken.encoding_for_model(model)
def token_count(msgs):
total = 2
for m in msgs:
total += 4 + len(encoding.encode(m.get('content', '')))
return total
result = list(messages)
while token_count(result) > budget and len(result) > 1:
# Never remove the system prompt at index 0
if result[0]['role'] == 'system':
del result[1]
else:
del result[0]
return result요약 프롬프트 생성하기
직접 요약 메모리를 만들 때는 LLM에 핵심 사실을 추려 내도록 요청하는 프롬프트를 작성합니다. 프롬프트에서 사용자 선호도, 명명된 개체, 해결되지 않은 질문을 포착하도록 모델에 지시해야 합니다. 이러한 사실이 이후 대화 차례에서 중요할 가능성이 가장 높기 때문입니다.
from openai import OpenAI
client = OpenAI()
def summarize_history(old_summary: str, new_turns: list) -> str:
turns_text = '\n'.join(
f'{m["role"].capitalize()}: {m["content"]}' for m in new_turns
)
prompt = f'''Current summary:\n{old_summary}\n\nNew conversation turns:\n{turns_text}\n\nWrite an updated summary that captures key facts, user preferences, and open questions.'''
resp = client.chat.completions.create(
model='gpt-4o-mini',
messages=[{'role': 'user', 'content': prompt}]
)
return resp.choices[0].message.content시스템 프롬프트에 요약 통합하기
요약을 만들었다면 이를 시스템 프롬프트에 주입하여 LLM이 항상 대화 기록에 대한 문맥을 갖도록 하십시오. 주요 페르소나 지침 앞에 요약을 짧은 문맥 블록으로 삽입하십시오.
def build_messages_with_summary(summary: str, recent_turns: list, user_input: str) -> list:
system_content = (
'You are a helpful AI assistant.'
+ ('\n\n[Conversation summary]\n' + summary if summary else '')
)
messages = [{'role': 'system', 'content': system_content}]
messages.extend(recent_turns)
messages.append({'role': 'user', 'content': user_input})
return messages요약 자동 실행하기
일반적인 방식은 대화가 토큰 임계값을 초과할 때 요약을 실행하는 것입니다. 예를 들어 누적 기록이 2,000개의 토큰을 넘을 때 실행할 수 있습니다. 이 시점에서 마지막 두 대화 차례를 제외한 모든 내용을 요약하고, 해당 내용을 요약으로 대체합니다.
class SummaryBufferChat:
def __init__(self, max_tokens=2000):
self.summary = ''
self.recent_turns = []
self.max_tokens = max_tokens
def chat(self, user_message: str) -> str:
from openai import OpenAI
client = OpenAI()
messages = build_messages_with_summary(self.summary, self.recent_turns, user_message)
resp = client.chat.completions.create(model='gpt-4o', messages=messages)
reply = resp.choices[0].message.content
self.recent_turns.append({'role': 'user', 'content': user_message})
self.recent_turns.append({'role': 'assistant', 'content': reply})
if count_tokens(self.recent_turns) > self.max_tokens:
to_summarize = self.recent_turns[:-2]
self.recent_turns = self.recent_turns[-2:]
self.summary = summarize_history(self.summary, to_summarize)
return reply요약에서 명명된 개체 보존하기
요약의 품질은 요약 프롬프트에 크게 좌우됩니다. 사용자가 이름, 위치, 선호도 또는 기한을 언급한다면 프롬프트에서 모델에 이러한 사실을 반드시 포함하도록 명시적으로 지시해야 합니다. 일반적인 요약은 개인화에 가장 중요한 고유 명사를 빠뜨리는 경우가 많습니다.
- 포함: 이름, 날짜, 결정된 기술적 선택, 해결되지 않은 질문
- 제외: 의미 없는 대화, 확인 응답, 반복되는 인사말
절충점: 요약 메모리와 윈도우 메모리
요약 메모리와 윈도우 메모리 중 무엇을 선택할지는 사용 사례에 따라 달라집니다. 윈도우 메모리는 정확한 표현을 보존하므로 정밀한 회상에는 중요하지만, 관련 없는 문맥에도 토큰을 낭비합니다. 요약 메모리는 적극적으로 압축하지만 LLM 호출이 한 번 더 필요하고 특수한 경우의 세부 정보가 사라질 수 있습니다. 대부분의 프로덕션 챗봇은 최근 대화 차례는 정확하게 유지하고 오래된 내용은 계속 갱신되는 요약으로 보존하는 혼합 방식을 사용합니다.
빠른 확인
요약 메모리와 토큰을 고려한 잘라내기 개념을 제대로 이해했는지 확인해 보십시오.
강의 요약
이 강의에서는 다음을 배웠습니다. 요약 메모리는 LLM 호출을 통해 오래된 대화 차례를 압축합니다. ConversationSummaryBufferMemory는 최근 대화 차례를 정확하게 유지하고 오래된 대화 차례는 요약하는 혼합 방식입니다. 또한 tiktoken을 사용하면 토큰을 고려하여 잘라내고 대화를 예산 내에 유지할 수 있습니다. 다음으로 지속적이고 확장 가능한 저장을 위해 대화 기록을 Redis와 PostgreSQL에 저장하는 방법을 살펴보겠습니다.
AI 튜터와 함께 Python을(를) 배우세요 — 무료
브라우저에서 실제 코드를 작성하고 실행하며, 24/7 AI 튜터로부터 즉각적인 도움을 받고, 웹이나 앱에서 중단한 부분부터 계속 학습하세요.
- 코스
- 30
- 레슨
- 120
자주 묻는 질문
“요약 메모리와 토큰 인식형 잘라내기” 강의는 무료인가요?
네 — “요약 메모리와 토큰 인식형 잘라내기” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 AI Engineering Academy 강의 전체를 잠금 해제할 수 있습니다. AI Engineering Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“요약 메모리와 토큰 인식형 잘라내기”에서 뭘 배우나요?
ConversationSummaryMemory를 사용해 오래된 대화 차례를 자동으로 요약하고, 사용자가 앞서 언급한 핵심 사실을 보존하면서 대화를 압축된 상태로 유지합니다. 브라우저에서 직접 실행하는 실습 코드로 AI Engineering Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
AI Engineering Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 AI Engineering Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.
“요약 메모리와 토큰 인식형 잘라내기” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 AI Engineering Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 AI Engineering Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- 상태 비저장 LLMs에 외부 메모리가 필요한 이유
- 버퍼 및 윈도우 메모리
- 요약 메모리와 토큰 인식형 잘라내기
- Redis와 PostgreSQL에 채팅 기록 저장하기