I Built a Python Agent That Uses a Vector DB as Memory, Not Retrieval
개요
Actian VectorAI DB를 에이전트의 메모리 계층으로 활용하여, 사전 로드된 문서가 아닌 에이전트 자체의 과거 대화 기록을 동적으로 구축하고 관리하는 Python 에이전트가 개발되었습니다.
주요 내용
* 기존 RAG 패턴과의 차별점: 일반적인 RAG(Retrieval Augmented Generation)는 미리 문서들을 벡터 DB에 저장하고 필요 시 검색하는 방식이지만, 본 에이전트는 에이전트가 실행되면서 모든 상호작용을 벡터로 저장하고, 이를 기반으로 자신의 과거 대화를 의미론적으로 검색하여 컨텍스트로 활용합니다. 즉, 벡터 DB가 문서 저장소가 아닌 에이전트의 능동적인 메모리 계층 역할을 수행합니다.
* 구축 스택: Actian VectorAI DB(벡터 스토어 및 의미론적 검색), Ollama + llama3.2(로컬 LLM), BAAI/bge-small-en-v1.5(임베딩 모델), Python(접착제)을 사용하여 모두 로컬 환경에서 구동됩니다.
* 동작 방식: 사용자의 메시지를 받으면, 해당 메시지를 벡터로 임베딩하고, VectorAI DB에서 의미론적으로 유사한 과거 상호작용을 검색합니다. 검색된 관련 메모리를 시스템 프롬프트에 주입한 후 LLM이 응답을 생성합니다. 생성된 응답과 사용자의 메시지를 포함한 전체 대화 기록을 VectorAI DB에 에피소드 메모리로 저장합니다.
* 메모리 계층의 특징:
* 크로스 세션 검색: 기본적으로 세션을 넘어선 메모리 검색이 가능하여 이전 대화 내용이 현재 대화에 영향을 줄 수 있습니다.
* 영속성: Docker 볼륨을 통해 컬렉션이 디스크에 저장되어 재시작 시에도 유지됩니다.
* 명시적 사실 저장: remember: <fact> 명령어를 통해 중요도가 높은 명시적 사실을 저장할 수 있습니다.
* 문제점 해결 및 개선:
* 로컬 파일 로딩: 초기 설정 시 임베딩 모델 다운로드 실패 문제를 local_files_only=True 설정을 통해 해결하여 초기 수동 다운로드 후에는 완전히 오프라인으로 작동하도록 했습니다.
* 메모리 감쇠 (Memory Decay): 모든 상호작용에 동일한 중요도를 부여하던 기존 방식에서 벗어나, 메모리의 오래됨(age), 최근 접근 빈도(recency), 접근 횟수(access\_frequency) 등을 종합적으로 고려한 중요도 가중치 감쇠 메커니즘을 추가하여 오래되거나 덜 사용된 메모리가 덜 중요하게 취급되도록 했습니다. 최종 점수는 코사인 유사도, 중요도, 최근성, 접근 빈도를 가중 평균하여 산출됩니다.
* 환각 (Hallucination) 문제 해결: 에이전트가 환각을 생성하고 이를 학습된 기억으로 저장하는 문제를 해결하기 위해, LLM에게 개인적 주장은 명시된 메모리 내에서만 사용하도록, 질문에 대한 답변을 알 수 없을 때는 "모르겠다"고 답하도록, 개인적인 세부 정보를 추론하거나 추측하지 않도록 세 가지 명시적인 규칙을 추가했습니다. 또한, 환각으로 생성된 응답의 중요도를 낮추어(0.3) 명시적 사실(0.9)보다 낮은 우선순위를 갖도록 했습니다. 약하게 일치하는 메모리가 컨텍스트로 주입되는 문제를 해결하기 위해 검색 임계값을 높이고 min_importance 필터를 추가하여 명시적 사실만 LLM에 전달되도록 했습니다.
* 핵심 발견: VectorAI DB는 사전에 로드된 문서 인덱스가 아닌, 에이전트 자체의 과거 대화에서 동적으로 구축되는 지식 기반 역할을 수행하며, 이는 벡터 DB의 용도에 대한 인식 전환을 의미합니다.
시사점
이 접근 방식은 벡터 DB를 단순한 정보 검색 도구가 아닌, 에이전트의 경험과 상호작용을 통해 시간이 지남에 따라 성장하고 망각하는 동적인 메모리 계층으로 활용할 수 있음을 보여줍니다. 이는 로컬 우선 AI 스택 및 에이전트 메모리 분야에서 새로운 활용 가능성을 제시합니다.
댓글
GitHub Discussions