왜 당신의 챗봇은 세션 사이에 모든 것을 잊어버리는가
요약
챗봇이 대화 맥락을 유지하지 못하는 근본적인 원인인 '상태 비저장(Stateless)' 특성을 분석합니다. 대화 기록 재생 방식의 한계인 오버플로, 세션 간 단절, 비용 문제를 해결하기 위한 메모리 레이어의 필요성을 설명합니다.
핵심 포인트
- LLM API는 기본적으로 상태를 유지하지 않는 Stateless 구조임
- 대화 기록을 모두 다시 보내는 방식은 토큰 오버플로와 비용 문제를 야기함
- 효율적인 메모리 레이어는 추출, 저장, 회상 과정을 통해 컨텍스트를 최적화함
- 메모리 레이어를 통해 컨텍스트 윈도우의 한계를 극복하고 비용을 절감할 수 있음
대부분의 챗봇 품질 불만은 모델의 탓으로 돌려지곤 합니다. 하지만 실제 운영 환경(production)에서의 원인은 보통 더 단순하며 스택(stack)의 더 아래쪽에 있습니다. 시스템 내에 상태(state)를 유지하는 것이 아무것도 없기 때문에, 모든 턴(turn)이 처음부터 다시 재구성되는 것입니다.
상태 비저장(Stateless) 기본값
모든 주류 LLM API는 완료(completion)를 반환하는 순간 잊어버립니다. 당신이 전체 대화 내용이 포함된 요청을 보내면, 모델은 응답을 생성하고 그 후에는 아무것도 유지하지 않습니다. 모든 내용을 다시 보내지 않는 한, 다음 요청은 제로(zero) 상태에서 시작됩니다.
이는 대부분의 챗봇에서 말하는 "메모리(memory)"가 실제 메모리가 아니라는 것을 의미합니다. 그것은 각 새로운 요청에 추가되는 이전 메시지들의 늘어나는 목록일 뿐입니다. 대화가 짧고 내일 다시 방문하는 사람이 없는 데모 환경에서는 잘 작동합니다.
대화 기록 재생(Transcript Replay)이 깨지는 세 가지 방식
첫 번째 깨짐은 오버플로(overflow)입니다. 50턴의 대화는 쉽게 30,000 토큰(tokens)을 초과할 수 있으며, 시스템 프롬프트(system prompt), 도구 정의(tool definitions), 검색된 문서(retrieved documents)가 동일한 공간을 두고 경쟁하게 됩니다. 입력이 모델의 한계를 넘어서면 무언가가 잘려 나가는데, 보통 가장 오래된 메시지들이 잘립니다. 사용자가 처음 세 개의 메시지에서 자신의 이름, 회사, 사용 사례를 말했더라도, 40번째 메시지에 이르면 그 모든 것이 사라집니다. 챗봇은 이미 물어봤던 질문을 다시 하기 시작합니다.
두 번째 깨짐은 세션 간 연속성(cross-session continuity)이 기본적으로 존재하지 않는다는 점입니다. 사용자가 브라우저를 닫고 내일 다시 돌아오면, 보낼 히스토리(history)가 없습니다. 이 사람이 누구인지, 무엇이 논의되었는지, 무엇이 결정되었는지, 무엇을 선호하는지에 대한 정보가 전혀 없습니다.
세 번째 깨짐은 비용입니다. 메시지마다 20,000 토큰의 히스토리를 다시 보내는 것은, 해당 콘텐츠의 95%가 이전 턴과 동일함에도 불구하고 매 턴마다 그 20,000개의 입력 토큰에 대해 비용을 지불해야 함을 의미합니다. 긴 대화를 나누는 수천 명의 동시 접속 사용자가 있을 경우, 이러한 중복성은 지출 항목의 주된 부분이 되며, 청구서 외에도 지연 시간(latency)을 초래합니다.
메모리 레이어(Memory Layer)가 실제로 하는 일
메모리 레이어(memory layer)는 전체 시스템에 걸쳐 위치하며 추출(extraction), 저장(storage), 회상(recall)이라는 세 가지 작업을 수행합니다.
추출(Extraction)은 대화를 읽고 무엇을 보관할 가치가 있는지 식별합니다. 저장(Storage)은 이를 쿼리(query)할 수 있는 형태로 영구적으로 보관합니다. 회상(Recall)은 컨텍스트 조립(context assembly) 단계에서 적절한 기억을 찾아내는데, 이 단계는 모델이 실제로 무엇을 보게 될지 결정하는 과정입니다.
그 결과로 얻는 이점은 형태의 변화입니다. 20,000개의 토큰(tokens)으로 이루어진 가공되지 않은 대화 기록을 그대로 보내는 대신, 시스템은 이 사용자 및 이 주제와 관련된 5~10개의 사실을 메모리에서 쿼리하여 약 500개의 토큰으로 검색해 옵니다. 결과적으로 모델은 훨씬 적은 공간을 사용하면서도 더 나은 컨텍스트(context)를 갖게 됩니다. 메모리는 컨텍스트 윈도우(context window)와 독립적으로 확장되며, 이는 대화가 길어질수록 매우 중요한 요소가 됩니다.
추출(Extraction)에서 품질이 결정된다
다음과 같은 메시지 하나를 예로 들어보겠습니다: "저는 Acme Corp의 엔지니어링 부사장(VP of Engineering)이며, 개발자는 약 200명 정도 있고, 이번 분기에 AWS에서 GCP로 마이그레이션(migration)을 진행 중입니다."
단순한 추출(Naive extraction)은 이를 하나의 덩어리(blob)로 저장합니다. 이제 "클라우드 마이그레이션(cloud migration)"을 검색하면 마이그레이션 세부 사항과 함께 직함과 인원수까지 반환되며, 아무도 요청하지 않은 정보에 컨텍스트 공간을 낭비하게 됩니다.
구조화된 추출(Structured extraction)은 역할, 회사 규모, 그리고 타임라인을 포함한 진행 중인 마이그레이션이라는 세 가지 별도의 기억을 생성합니다. 각 기억은 개별적으로 검색 가능하며 독립적으로 유용합니다. 검색 품질은 벡터 데이터베이스(vector database)가 아니라 주로 여기서 결정됩니다. 이것이 저장소를 교체하는 것만으로는 회상(recall) 문제를 해결하기 어려운 이유입니다.
시작하는 방법
무언가를 추가하기 전에, 긴 대화에서 컨텍스트 조립(context assembly) 단계가 실제로 무엇을 전송하는지 로그(log)를 남겨보세요. 대부분의 팀은 새로운 정보 대비 반복되는 히스토리의 비율을 보고 놀라게 되며, 그 수치는 현재 문제가 모델의 문제인지 아니면 상태(state)의 문제인지를 알려줍니다.
만약 상태(state)의 문제라면, 해결책은 더 큰 컨텍스트 윈도우를 사용하는 것이 아니라 아키텍처(architectural)적인 접근입니다. 레이어, 대화 관리 패턴(dialogue management patterns), 그리고 요약의 트레이드오프(summarization tradeoffs)에 대한 자세한 분석은 여기에서 확인할 수 있습니다: https://www.adaptiverecall.com/conversational-ai/
결론은 충분히 간단합니다. 지식이 풍부한 동료처럼 느껴지는 챗봇과 갓 만난 낯선 사람처럼 느껴지는 챗봇은 대개 동일한 모델을 실행하고 있습니다. 그 차이는 지난 세션이 끝난 후 무엇인가가 살아남았는지 여부에 달려 있습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기