SimpleMem: LLM 에이전트의 장기 기억을 압축해 토큰을 최대 30배 줄이는 메모리 프레임워크

SimpleMem 소개

에이전트에게 장기 기억을 붙이는 방법은 크게 두 갈래로 굳어졌습니다. 하나는 지나간 대화를 그대로 들고 다니며 컨텍스트를 늘리는 쪽인데, 같은 이야기가 여러 번 반복되어 들어가고 토큰이 그만큼 낭비됩니다. 다른 하나는 저장된 기록을 매번 다시 읽고 추론해 노이즈를 걸러내는 쪽인데, 이번에는 질문 한 번의 비용과 응답 시간이 올라갑니다. 어느 쪽이든 대화가 길어질수록 정확도와 비용이 함께 나빠지는 구간에 들어갑니다.

SimpleMem은 이 문제를 의미 손실 없는 압축(semantic lossless compression) 으로 접근하는 LLM 에이전트용 메모리 프레임워크입니다. 저장 시점에 대화를 그대로 남기지 않고 자기 완결적인 사실 단위로 다시 쓰고, 관련된 조각들을 곧바로 합쳐 중복을 없앤 뒤, 질문이 들어오면 검색 범위와 깊이를 그 질문의 의도에 맞춰 정합니다. UNC와 UCSC 등의 연구자들이 참여한 AIMING Lab이 공개했으며, arXiv 논문에 방법과 실험이 정리되어 있습니다.

저장소에는 같은 원칙을 서로 다른 지점에 적용한 세 갈래가 함께 들어 있습니다. 텍스트 기억의 효율을 담당하는 SimpleMem, 이미지·오디오·비디오까지 다루는 Omni-SimpleMem, 그리고 검색 설정 자체를 스스로 고쳐 나가는 EvolveMem입니다. pip install simplemem 으로 설치한 뒤 from simplemem import SimpleMem 하나로 세 갈래를 모두 쓸 수 있고, 처음 호출한 메서드에 따라 텍스트 백엔드와 멀티모달 백엔드가 자동으로 선택됩니다.

기존 메모리 시스템과 SimpleMem의 비교

논문의 비교 그래프는 가로축에 평균 토큰 비용(로그 스케일), 세로축에 LoCoMo F1 점수를 놓고 여러 메모리 시스템을 함께 찍은 것입니다. 전체 대화를 그대로 넣는 방식과 MemGPT는 오른쪽 아래, 즉 토큰을 가장 많이 쓰면서 점수는 낮은 자리에 있고, MemoryBank나 ReadAgent는 토큰을 적게 쓰지만 점수도 낮습니다. SimpleMem은 왼쪽 위, 토큰을 가장 적게 쓰면서 점수가 가장 높은 자리에 찍혀 있습니다. 논문은 LoCoMo에서 평균 F1을 26.4% 끌어올리면서 추론 시점 토큰 소비를 최대 30분의 1로 줄였다고 보고합니다(논문 초록).

Omni-SimpleMem 문서에 정리된 LoCoMo 전체 F1 수치는 다음과 같습니다. 같은 벤치마크를 서로 다른 백본 모델로 돌린 결과입니다.

방법 GPT-4o GPT-4o-mini GPT-5.1
Mem0 0.397 0.364 0.390
A-MEM 0.394 0.357 0.385
MemGPT 0.404 0.364 0.385
SimpleMem 0.432 0.404 0.418
Omni-SimpleMem 0.598 0.519 0.613

수치를 읽을 때 주의할 점이 있습니다. 표의 SimpleMem 행은 텍스트 전용 백엔드이고, Omni-SimpleMem 행은 지식 그래프와 하이브리드 검색이 더해진 멀티모달 백엔드입니다. 두 행의 격차는 모달리티 지원 여부가 아니라 검색 구조의 차이에서 나온 부분이 큽니다. 또한 모든 수치는 저자들이 자체 실행한 결과이므로, 다른 평가 조건에서 그대로 재현될지는 직접 돌려 확인하는 편이 안전합니다. 저장소는 test_locomo10.py 로 LoCoMo 재현 절차를 함께 제공합니다.

SimpleMem은 누구에게 유용한가

여러 세션에 걸쳐 같은 사용자와 오래 대화하는 에이전트, 그리고 그 대화 비용이 이미 문제가 되고 있는 서비스에 가장 잘 맞습니다. OpenAI 호환 엔드포인트만 있으면 되므로 Qwen이나 Azure OpenAI, Ollama 같은 대체 백엔드로 붙일 수 있고, MCP를 지원하는 클라이언트라면 코드를 고치지 않고 Claude Desktop이나 Cursor에서 기억 기능만 얹는 방식도 가능합니다.

반대로 짧은 단발 질의만 처리하는 서비스라면 기억을 만드는 쪽의 비용이 더 클 수 있습니다. 저장 시점에 LLM이 대화를 압축하고 합치는 작업을 하기 때문에, 다시 꺼내 볼 일이 없는 대화에는 그 비용이 회수되지 않습니다. MCP 경로에는 아직 멀티모달과 자기 진화 검색이 들어오지 않았다는 점도 선택에 영향을 줍니다. 두 기능이 필요하면 Python API를 직접 써야 합니다.

SimpleMem의 3단계 압축 파이프라인

첫 단계인 의미 구조적 압축(Semantic Structured Compression) 은 대화 스트림을 기억 단위로 다시 씁니다. 이때 대명사를 실제 대상으로 풀고 상대 시간 표현을 절대 시각으로 바꿔, 문장 하나만 봐도 뜻이 통하는 형태로 만듭니다. 저장소 문서가 든 예시는 다음과 같습니다.

- Input:  "He'll meet Bob tomorrow at 2pm"  [relative, ambiguous]
+ Output: "Alice will meet Bob at Starbucks on 2025-11-16T14:00:00"  [absolute, atomic]

각 기억 단위는 세 가지 색인 계층에 함께 등록됩니다. 하나의 표현에 의존하지 않으므로, 개념이 비슷한 질문과 특정 단어를 정확히 포함한 질문, 기간이나 인물로 좁히는 질문을 모두 같은 저장소에서 처리할 수 있습니다.

계층 유형 목적 구현
의미(Semantic) 밀집 개념적 유사도 1024차원 벡터 임베딩
어휘(Lexical) 희소 정확한 용어 일치 BM25 방식 키워드 색인
기호(Symbolic) 메타데이터 구조적 필터링 타임스탬프, 엔티티, 인물

두 번째 단계인 온라인 의미 종합(Online Semantic Synthesis) 은 압축을 쓰기 시점에 끝냅니다. 많은 메모리 시스템이 백그라운드 작업으로 정리를 미루는 것과 달리, 같은 세션 안에서 관련된 조각을 바로 상위 표현으로 합칩니다.

- Fragment 1: "User wants coffee"
- Fragment 2: "User prefers oat milk"
- Fragment 3: "User likes it hot"
+ Consolidated: "User prefers hot coffee with oat milk"

세 번째 단계인 의도 인식 검색 계획(Intent-Aware Retrieval Planning) 은 고정 깊이 검색을 버리고 질문마다 계획을 세웁니다. 질문 q 와 이력 H 로부터 세 색인에 보낼 질의와 검색 깊이를 함께 뽑아내는 형태입니다.

\{ q_{\text{sem}}, q_{\text{lex}}, q_{\text{sym}}, d \} \sim \mathcal{P}(q, H)

단순한 사실 조회는 기억 단위 하나만 얕게 꺼내고, 여러 사건을 모아야 하는 질문은 깊이를 늘립니다. 세 색인 검색은 병렬로 실행한 뒤 ID 기준으로 중복을 제거해 합칩니다. 이 구성으로 저장소 문서는 전체 컨텍스트 방식 대비 30배 적은 토큰으로 F1 43.24%를 기록했다고 적고 있습니다(docs/text-memory.md §3).

Omni-SimpleMem의 멀티모달 기억

Omni-SimpleMem은 같은 압축 우선 원칙을 텍스트·이미지·오디오·비디오 네 모달리티로 넓힙니다. 입구에는 모달리티별로 다른 필터가 붙습니다. 텍스트는 Jaccard 유사도로 중복을 걸러내고, 이미지는 CLIP 유사도로, 오디오는 음성 구간 검출(VAD)로, 비디오는 프레임 샘플링으로 새로운 정보만 통과시킵니다. 통과한 입력은 LLM이 요약과 임베딩을 붙여 하나의 기억 단위로 만듭니다.

저장 계층은 접근 빈도에 따라 핫 스토리지와 콜드 스토리지로 나뉘고, 추출된 엔티티는 별도의 지식 그래프(Knowledge Graph)로 정리됩니다. 검색은 세 경로를 동시에 돌립니다. FAISS 기반 밀집 검색, BM25 희소 검색, 그리고 그래프를 여러 홉 따라가는 검색 결과를 합집합으로 병합한 뒤, 토큰 예산에 맞춰 요약부터 전체 텍스트, 원본까지 단계적으로 펼치는 방식입니다. 아키텍처 문서가 이를 점진적 검색(Progressive Retrieval)이라고 부릅니다.

이 구조가 나온 과정도 설명되어 있습니다. 사람이 설계한 것이 아니라 자율 연구 파이프라인이 두 벤치마크에서 약 50회의 실험을 돌리며 실패 원인을 진단하고 구조 변경을 제안한 결과이며, 데이터 파이프라인 버그를 스스로 고친 부분도 포함됩니다. 저자들은 버그 수정과 구조 변경 각각이 하이퍼파라미터 튜닝 전체보다 기여가 컸다고 정리합니다.

EvolveMem의 자기 진화형 검색

EvolveMem이 지적하는 빈틈은 저장 내용과 검색 장치의 비대칭입니다. 기억은 계속 쌓이고 바뀌는데, 점수 계산 방식이나 융합 전략, 답변 생성 정책 같은 검색 쪽 설정은 배포 시점에 고정된 채 그대로 남습니다. EvolveMem은 이 설정들을 구조화된 행동 공간으로 노출하고, 다음 네 단계를 반복하며 스스로 조정합니다.

단계 하는 일
평가(Evaluate) 검증용 QA를 돌려 질문별 실패 로그를 남깁니다
진단(Diagnose) LLM이 실패 로그를 읽고 원인을 짚습니다
제안(Propose) 원인에 맞춘 설정 변경을 제시합니다
보호(Guard) 성능이 떨어지면 자동으로 되돌립니다

7라운드를 완전 자동으로 돌린 결과 LoCoMo에서 가장 강한 베이스라인보다 상대적으로 25.7%, MemBench에서 18.9% 높은 성능을 기록했다고 보고합니다. 질의 분해와 엔티티 교체, 답변 검증처럼 원래 설계에 없던 검색 차원 세 가지를 새로 찾아냈다는 점, 그리고 한 벤치마크에서 진화한 설정이 다른 벤치마크에도 긍정적으로 옮겨 갔다는 점을 함께 적어 두었습니다.

이 루프는 simplemem.optimize() 로 얇게 감싸져 있어, 자기 개발 데이터셋에서 검색 설정을 미리 조정한 뒤 그 설정을 배포하는 식으로 쓸 수 있습니다.

import simplemem
from simplemem import SimpleMem, load_config

dev_questions = [
    ("When is the meeting?", "2pm tomorrow at Starbucks"),
    ("What should Bob prepare?", "market analysis report"),
]
config = simplemem.optimize(mem, dev_questions, max_rounds=3)
config.save("my_config.json")

config = load_config("my_config.json")
mem = SimpleMem(config=config)

SimpleMem 설치 및 사용법

Python 3.10 이상과 OpenAI 호환 API가 필요합니다. 저장소를 클론한 뒤 편집 가능 설치로 붙이는 방식이 기본입니다.

git clone https://github.com/aiming-lab/SimpleMem.git
cd SimpleMem

pip install -e .                  # 텍스트 + 멀티모달 + 진화 루프
pip install -e ".[server]"        # MCP / HTTP 서버 추가
pip install -e ".[all]"           # 개발 도구까지 전부

cp config.py.example config.py

설정 파일에는 API 키와 사용할 모델을 적습니다. OPENAI_BASE_URL 을 바꾸면 OpenAI 외의 호환 엔드포인트로 그대로 돌릴 수 있습니다.

# config.py
OPENAI_API_KEY = "your-api-key"
OPENAI_BASE_URL = None  # Qwen/Azure 등 커스텀 엔드포인트

LLM_MODEL = "gpt-4.1-mini"
EMBEDDING_MODEL = "Qwen/Qwen3-Embedding-0.6B"

사용 코드에서 백엔드를 직접 고를 필요는 없습니다. 기본값인 mode="auto" 는 처음 호출한 메서드로 백엔드를 정합니다. add_dialogue() 를 먼저 부르면 텍스트 백엔드, add_text()·add_image()·add_audio()·add_video() 중 하나를 먼저 부르면 멀티모달 백엔드가 선택됩니다.

from simplemem import SimpleMem

mem = SimpleMem()  # auto mode

mem.add_dialogue(
    "Alice",
    "Bob, let's meet at Starbucks tomorrow at 2pm",
    "2025-11-15T14:30:00",
)
mem.add_dialogue(
    "Bob",
    "Sure, I'll bring the market analysis report",
    "2025-11-15T14:31:00",
)
mem.finalize()

answer = mem.ask("When and where will Alice and Bob meet?")
# → "16 November 2025 at 2:00 PM at Starbucks"

대량의 대화를 한 번에 넣는 경우에는 병렬 처리를 켤 수 있습니다. 기억 구축과 질의 실행에 각각 별도의 워커 수를 지정하는 형태입니다.

from simplemem import create

mem = create(
    mode="text",
    clear_db=True,
    enable_parallel_processing=True,
    max_parallel_workers=8,
    enable_parallel_retrieval=True,
    max_retrieval_workers=4
)

한국어 안내가 필요하면 저장소의 한국어 README도 함께 제공됩니다.

SimpleMem의 MCP 서버와 채널별 지원 범위

텍스트 기억은 MCP 서버로도 쓸 수 있습니다. 클라우드 호스팅 주소가 제공되며, Docker로 직접 띄우는 것도 가능합니다. MCP 클라이언트 설정은 URL과 토큰만 넣으면 끝납니다.

{
  "mcpServers": {
    "simplemem": {
      "url": "https://mcp.simplemem.cloud/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_TOKEN"
      }
    }
  }
}

다만 채널에 따라 쓸 수 있는 기능이 다릅니다. 저장소가 직접 밝힌 현재 상태는 다음과 같습니다.

기능 Python 패키지 MCP 서버
텍스트 기억 지원 지원
멀티모달(이미지·오디오·비디오) 지원 예정
optimize() 자기 진화형 검색 지원 예정

MCP 쪽 격차를 문서 문제로 넘기지 않고 남은 작업까지 적어 둔 점이 눈에 띕니다. 멀티모달을 MCP로 열려면 MCP가 로컬 파일 경로를 넘길 수 없으므로 base64나 URL 기반 업로드 경로를 새로 만들어야 하고, 저장 백엔드를 멀티 테넌트 구조로 바꿔야 합니다. optimize() 쪽은 현재 MCP 검색기가 EvolveMem이 조정하는 약 10개 차원 중 두 개만 반영하고 있어, 남은 설정을 지원하도록 검색기를 확장하고 LLM 호출이 많은 진화 루프를 비동기로 돌릴 장치가 필요합니다.

SimpleMem의 라이선스

SimpleMem 저장소는 MIT 라이선스로 공개되어 있어 개인 및 상업적 목적으로 자유롭게 사용할 수 있습니다. 한 가지 예외가 있는데, 멀티모달 구현이 들어 있는 OmniSimpleMem/ 하위 디렉토리에는 Apache License 2.0 이 별도로 들어 있습니다. 두 라이선스 모두 상업적 사용을 허용하지만, Apache 2.0은 변경 사항 고지와 특허 조항을 포함하므로 멀티모달 부분을 재배포할 계획이라면 해당 파일을 확인하는 편이 좋습니다.

:framed_picture: SimpleMem 인터랙티브 데모 페이지

:scroll: SimpleMem 논문

:github: SimpleMem 프로젝트 GitHub 저장소

더 읽어보기




이 글은 GPT 모델로 정리한 초안을 바탕으로 한 것으로, 원문의 내용 또는 의도와 다르게 정리된 내용이 있을 수 있습니다. 관심있는 내용이시라면 원문도 함께 참고해주세요! 읽으시면서 어색하거나 잘못된 내용을 발견하시면 댓글로 알려주시기를 부탁드립니다. :hugs:

이 도구를 직접 설치해 사용해보셨다면, :pytorch:파이토치 한국 사용자 모임:south_korea: 회원들을 위해 경험이나 팁을 댓글로 남겨주세요! :folded_hands: