내가 채팅 기록(Chat History) 사용을 중단하고 사후 기억(Hindsight Memory)을 사용하게 된 이유
요약
LLM 에이전트 구축 시 발생하는 토큰 비용 증가와 컨텍스트 윈도우 피로 문제를 해결하기 위해, 단순 채팅 기록 전달 방식 대신 Hindsight를 활용한 이중 뱅크 인지 메모리 아키텍처로 전환한 사례를 다룹니다.
핵심 포인트
- 전체 채팅 기록 주입 시 발생하는 지연 시간 및 품질 저하 문제 지적
- 개인용 및 글로벌 해결책을 분리한 이중 뱅크 인지 메모리 구조 도입
- 단순 RAG 방식의 한계와 개인정보 보호(PII) 이슈 해결 방안 제시
- PostgreSQL과 Hindsight Cloud를 결합한 계층적 아키텍처 설계
고객 지원을 위한 프로덕션급 LLM 에이전트(LLM agent)를 구축해 본 적이 있다면, 토큰 비용이 급증하고 에이전트의 응답 품질이 낭떠러지 아래로 떨어지는 정확한 순간을 알고 있을 것입니다. 그것은 바로 에이전트에게 "장기 기억(long-term memory)"을 부여하려는 순진한 시도로서, 전체 원시 채팅 기록(raw chat history)을 시스템 프롬프트(system prompt)에 전달하기로 결정하는 순간입니다.
우리가 처음 고객 지원 에이전트를 구축했을 때—Groq를 통해 Llama 3.3에서 실행되는 전체 PERN 스택 애플리케이션(PostgreSQL, Express, React, Node.js)으로 설계되었습니다—우리는 정확히 이 경로를 따랐습니다. 우리는 모든 과거 사용자 메시지와 에이전트 응답을 순환 컨텍스트 윈도우(rolling context window)에 추가했습니다. 작고 단발적인 상호작용이 발생하는 데모 환경에서는 아름답게 작동했습니다. 하지만 실제 환경에서는 빠르게 문제가 발생했습니다. 에이전트는 컨텍스트 윈도우 피로(context window fatigue)를 겪었고, 과거의 문제 해결 세션들을 혼동했으며, 시스템 프롬프트의 길이가 확장됨에 따라 엄청난 지연 시간(latency) 급증을 겪었습니다.
다음은 우리가 원시 채팅 기록 주입 방식에서 벗어나 Hindsight를 사용하는 구조화된 이중 뱅크 인지 메모리(dual-bank cognitive memory) 아키텍처로 전환한 방법과, 왜 우리가 벡터 데이터베이스(vector databases)나 일반적인 RAG 편법(RAG hacks)에 의존하지 않기로 선택했는지에 대한 내용입니다.
시스템 아키텍처: 어떻게 결합되어 있는가
우리의 고객 지원 시스템은 PERN 스택 아키텍처를 기반으로 구축되었으며, 세 가지 별도의 계층을 조정합니다:
-
운영 데이터베이스 (PostgreSQL): Neon DB 내부에 저장되며, Postgres는 티켓, 사용자, 메시지 세션의 원시 기록과 같은 트랜잭션 엔티티(transactional entities)를 관리합니다. 이는 현재 상태에 대한 신뢰할 수 있는 원천(source of truth) 역할을 합니다.
-
AI 오케스트레이션 백엔드 (Express + Node.js): Groq API(
llama-3.3-70b-versatile모델 사용)와 인터페이스하고 컨텍스트 컴파일(context compilation)을 조정하는 컨트롤러를 실행합니다. -
인지 메모리 계층 (Hindsight Cloud): 장기적인 의미론적 메모리(semantic memory)를 처리하며, 이는 개인별 고객 전용 기록과 고객 간 글로벌 해결책(cross-customer global resolutions)으로 나뉩니다.
고객이 우리의 React 클라이언트에서 새로운 메시지를 제출하면, Express 백엔드는 단순히 Postgres에서 채팅 로그를 쿼리하는 것에 그치지 않습니다. 대신, 대화의 의미론적 본질(semantic essence)을 추출하여 Hindsight에 호스팅된 두 개의 별도 메모리 뱅크(memory banks)에 쿼리합니다. 하나는 고객의 사용자 ID(user ID)를 키로 하는 개인용 뱅크이고, 다른 하나는 익명화된 글로벌 해결책(global resolutions)을 나타내는 공유 뱅크입니다. 관련 사실들이 가져와져 깔끔한 지시문 블록(instruction block)으로 포맷팅된 후
만약 고객 A가 희귀한 API 버그를 경험하고 지원팀이 이를 수동으로 해결했다면, 고객 B도 즉시 해당 해결책의 혜택을 받아야 합니다. 데이터베이스 중심의 채팅 기록 (Chat History)은 사용자 ID (User ID)에 의해 완전히 격리되어 있습니다. 원본 티켓 (raw tickets)에 대한 단순한 RAG (Retrieval-Augmented Generation) 방식 또한 실패하는데, 티켓에는 고객 간에 유출되어서는 안 되는 방대한 양의 개인정보 (PII: 이름, 특정 계좌 잔액, IP 등)가 포함되어 있기 때문입니다.
핵심 기술 이야기: 사후 기억 뱅크 (Hindsight Memory Banks)로의 전환
이러한 문제들을 해결하기 위해, 우리는 기존의 기록 파이프라인을 구조화된 인지 메모리 루프 (structured cognitive memory loop)로 교체했습니다. 우리는 Vectorize 에이전트 메모리 (agent memory) -> (https://vectorize.io/what-is-agent-memory)를 활용하여 두 개의 격리된 메모리 계층을 설계했습니다.
-
개별 고객 뱅크 (
User {userId}): 비익명화된 개인 고객 정보(예: 기술 스택, 운영 환경, 팀 규모)를 보유합니다. -
글로벌 해결책 뱅크 (
global_resolutions): 플랫폼 전체의 해결된 티켓들로부터 컴파일된, 엄격하게 익명화된 고도의 기술적 문제-해결 쌍 (problem-resolution pairs)을 보유합니다. 이러한 이중 뱅크 쓰기 (dual-bank write) 방식을 통해, Shankar의 사용자 메모리에는 "고객은 Node 18에서 Neon Postgres를 실행 중임"과 같은 사실이 업데이트되는 동시에, 글로벌 뱅크에는 "문제: Express 페이로드 파싱 제한으로 인해 Webhook 검증 실패. 해결책: 앱 진입점에 express.json({ limit: '10mb' })를 설정할 것."과 같은 내용이 업데이트되도록 보장합니다.
결과 및 동작
이 아키텍처로 전환함으로써, 우리는 시스템 프롬프트 (system prompt)의 토큰 크기를 줄이는 동시에 에이전트 상호작용의 품질을 획기적으로 개선했습니다.
배운 점
이러한 메모리 기반 에이전트를 구축하고 확장하면서, 우리는 인지 아키텍처 (cognitive architectures)에 관한 세 가지 중요한 교훈을 얻었습니다.
1. 상태 (State)와 컨텍스트 (Context)를 혼동하지 마세요:
당신의 데이터베이스(messages 테이블)는 애플리케이션의 연대기적 상태 (State)를 나타냅니다. 이는 AI의 인지적 컨텍스트 (Context)로 설계된 것이 아닙니다. 가공되지 않은 상태 (Raw state)를 LLM 시스템 프롬프트에 그대로 주입하는 것은 높은 지연 시간 (Latency), 치솟는 토큰 비용, 그리고 환각 (Hallucination) 현상을 일으키는 지연된 지름길입니다. Hindsight와 같은 시맨틱 메모리 엔진 (Semantic memory engine)을 사용하여 상태 (State)를 내구성 있는 컨텍스트 (Context)로 정제하여 사용하세요.
2. 엔터프라이즈 신뢰를 위해서는 격리 (Isolation)가 필수적입니다:
모든 고객 지원 티켓을 단일 공유 벡터 인덱스 (Vector index)에 단순히 집어넣어서는 안 됩니다. 그렇게 하면 LLM이 필연적으로 고객 프로필을 교차 오염시키고, 민감한 설정이나 개인 정보를 유출하게 됩니다. 반드시 개인 고객의 메모리를 글로벌 지식으로부터 엄격히 격리해야 하며, 공유 저장소에 기록하기 전에 엄격한 자동 익명화 (Anonymization) 검사를 강제해야 합니다.
3. 항상 오프라인 폴백 (Offline Fallback)을 구현하세요:
클라우드 기반 AI 인프라는 속도 제한 (Rate limits), 네트워크 타임아웃 (Network timeouts), 그리고 다운타임 (Downtime)의 영향을 받습니다. 만약 Hindsight Cloud나 Groq가 실패하더라도, 당신의 고객 지원 에이전트가 단순히 충돌(Crash)해서는 안 됩니다. 우리는 키워드 벡터 파싱 (Keyword vector parsing)을 보조 유지 엔진으로 사용하는 로컬 PostgreSQL 데이터베이스 폴백(recallMemoryMockFallback)을 구현했습니다. 첫날부터 회복 탄력성 (Resilience)을 구축하면 API 장애 발생 중에도 고객 지원 대기열을 계속 운영할 수 있습니다.
상세한 API 참조 및 통합 전략에 대해서는 다음을 확인하실 수 있습니다:
Hindsight 문서 -> https://hindsight.vectorize.io/
해당 리포지토리 확인 -> https://github.com/vectorize-io/hindsight
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기