관심 있는 NLP 논문을 읽어보고 간단히 정리했습니다.
혹시 부족하거나 잘못된 내용이 있다면 댓글 부탁드립니다 🙇♂️
[Mem0]
- single-hop, temporal, multi-hop, open-domain 카테고리로 memory system 평가 (LOCOMO benchmark)
- 생성까지 걸리는 시간과 생성 퀄리티 둘 다 잡은 방식, Mem0 & Mem0(g) 제안
- memory 업데이트, 추가 등 관리 전반에 LLM을 활용한다는 특징
출처 : https://arxiv.org/abs/2504.19413v1
1. Introduction
LLM은 학습이 끝난 시점 이후 발생한 사건이나 정보들에 대해 접근할 수 없기 때문에,
최신 정보나 도메인 특화된 정보를 제공하기 위해 RAG (Retrieval Augmented Generation) 와 같은 방법론이 크게 인기를 끌게 되었습니다.
뿐만 아니라 유저와의 기존 대화 내용 등을 기반으로 유저의 선호나 특성을 파악하여 추론해주는 memory system이 활발히 적용되고 있습니다.
(OpenAI에서도 memory 기능을 지원하면서 대화를 시작할 때마다 내가 원하는 것들을 반복적으로 설명하지 않아도 되게 바뀌었죠)
하지만 현재 LLM 아키텍쳐 특성상, 모델이 받아들일 수 있는 입력의 길이가 제한(fixed context windows)되어 있기 때문에,
LLM이 persistent memory를 갖는다는 것은 사실상 굉장히 어려운 문제로 남아 있습니다.
(Figure 1에서는 한 유저의 여러 세션이 독립적으로 관리될 때와 그렇지 않을 때를 비교하고 있습니다)
사람은 (모든 것을 기억할 수 없지만) 필요한 & 중요한 정보들을 선별적으로 우리 뇌에 잘 저장하고, 그렇지 않은 것들은 희미하게 저장되는 등의 메커니즘이 알아서 적용되는데, 모델은 이를 스스로 수행할 수 없다는 문제점을 갖고 있습니다.
어찌 보면 사람도 수용 가능한 최대 메모리가 있을 텐데 이를 효율적으로 관리 & 업데이트하고 있는 셈이겠죠?
그래서 본 논문에서는 LLM의 memory를 장기적으로 보존하고 관리할 수 있는 방법론을 제시하는데,
이를 Mem0, Mem$0^g$ 라고 합니다.
(후자의 $g$는 graph를 의미합니다)
각 방법론들을 LOCOMO라는 벤치마크에 대해 성능 평가한 내용들을 논문에 포함하고 있고요.
실제로 이 방법론들은 기존 방법론들 대비 속도(latency) & 성능(performance) 모두 뛰어나 두 마리 토끼를 다 잡았다는 평가를 받고 있습니다.
깃허브에 가보시면 현재 25.06.22 기준으로 35K stars를 기록할 정도로 크게 주목받고 있고요.
2. Methods
2.1. Mem$0$
대화 내의 중요한 정보를 추출, 평가, 관리하는 방식입니다.
- 추출 단계 (Extraction Phase)
새로 입력된 message pair $(m_{t-1},m_t)$에서 memory를 추출합니다.
이 pair는 주로 single turn (user message & assistant response) 을 의미합니다.
memory를 적절하게 추출할 수 있도록 두 개의 보충 정보를 활용합니다.
(1) a conversation Summary $S$
전체 대화 히스토리의 semantic content를 담고 있는 데이터베이스로부터 가져옵니다.
(2) a sequence of recent messages ${m_{t-m}, m_{t-m+1}, ..., m_{t-2}}$
recency window $m$을 하이퍼파라미터로 사용하여 최근 대화 내용을 추가 정보로 활용합니다.
(default $m$은 10으로 설정됩니다)
new message pair + (1) + (2) 를 결합한 prompt는 다음과 같이 표현됩니다.
$P=(S, {m_{t-m}, ..., m_{t-2}}, m_{t-1}, m_t)$
이를 입력으로 받는 extraction function $\phi(P)$는 salient memories $\Omega = {\omega_1, \omega_2, ..., \omega_n}$를 추출합니다.
즉, 여기서 추출된 salient memories는 전부 저장되는 것이 아니라 knowledge base에 저장될 가능성이 있는 candiate facts 입니다.
- 업데이트 단계 (Update Phase)
각 candidate fact에 대해서 기존 memories의 consistency를 유지하고 redundancy를 피하기 위한 평가를 수행합니다.
(memory management operation for each extracted fact $\omega_i \in \Omega$)
우선 각 fact $\omega_i$에 대해서 데이터베이스로부터 semantically similar memories를 top $s$개 검색합니다.
(default $s$는 10으로 설정됩니다)
(이때 활용되는 dense embeddings는 OpenAI의 'text-embedding-small-3'입니다)
검색된 $s$개의 memories는 candidate fact와 함께 'tool call'이라고 부르는 function-calling으로 넘겨집니다.
이에 따라 LLM은 네 개의 operation 중 한 개를 실행하게 됩니다.
- ADD
- semantically 유사한 memory가 없을 때, 새로운 memory로 추가합니다.
- UPDATE
- 기존 memories에 대해 보충할 정보가 있을 때, 기존 메모리를 업데이트합니다.
- DELETE
- 새로운 정보와 상충하는 것이 있을 때, 기존 memories를 삭제합니다.
- NOOP
- 기존 knowledge base에 어떤 변경 사항도 적용하지 않습니다.
저자는 이를 위해 별도의 classifier를 두지 않고 LLM(GPT-4o-mini)을 사용함으로써 knowledge base의 coherence & temporal consistency를 유지한다고 설명합니다.
2.2. Mem$0^g$
Mem$0^g$는 graph-based memory approach로, 자연어로부터 contextual information을 효과적으로 capture, store, retireve 하는 memory 방법론입니다.
(graph database로 Neo4j 사용)
여기서의 memories는 directed labeld graph $G=(V, E, L)$로 표현되는데 각 기호의 의미는 아래와 같습니다.
- Nodes $v \in V$
- entities (e.g. Alice, San_Francisco)
- (1) entity type classification (e.g. Person, Location, Event)
- (2) embedding vector $e_v$
- (3) metadata including creation timestamp $t_v$
- Edges $E$
- relationships between entities (e.g. Lives_In)
- Labels $L$
- assign semantic types to nodes (e.g. Alice - Person, San_Francisco - City)
위 요소들을 종합한 relationship는 $(v_s, r, v_d)$와 같은 triplet으로 구조화됩니다.
($s$: source, $r$: labeled edge, $d$: destination)
- 추출 (Extraction Phase)
unstuctured text를 sturctured graph representations로 변환하기 위해 LLM 기반의 two-stage pipeline을 이용합니다.
(1) Entity Extractor
이 모듈은 input text 내의 entities & corresponding types를 찾아냅니다.
여기에서 entities는 대화 내의 key information elements를 뜻하는데, peopl, locations, objects 등의 속성들입니다.
entity extractor가 다양한 information units를 잘 식별할 수 있도록 semantic importance, uniqueness, persistence of elements 등을 분석하도록 했다고 설명합니다.
(프롬프트에 잘 반영한 것을 설명한 내용으로 해석됩니다. 아마도..?)
(2) 관계 생성 (Relationship Generator)
entities가 다른 entity와 어떤 식으로 관계를 맺고 있는지 파악하기 위해 linguistic patterns, contextual cues, domain knowledge 등을 활용했다고 합니다.
(마찬가지로 프롬프트에 반영한 내용으로 보입니다)
generator는 먼저 각 potential entity pair에 대해서 둘 사이에 meaningful relationship이 존재할지 평가하고,
만약 존재한다면 적절한 label로 이 관계를 분류합니다.
(e.g. 'lives_in', 'prefers', 'owns', 'happened_on')
이렇게 하면 각 entity에 대한 정보, 각 entities 간의 관계 정보를 포함하여 triplet을 만들 수 있게 됩니다.
- 업데이트 (Update Phase)
Mem$0^g$는 새로운 정보를 정교하게 관리하기 위한 storage & update strategy가 있다고 합니다.
(1) Conflict Detector
consistent knowledge graph를 유지하기 위해서 conflict detection mechanism을 실행하는데,
이는 새로운 정보가 주어졌을 때 기존 관계와 conflict 하는지 아닌지를 판별하는 것입니다.
우선 각 relationship triplet에 대해 source ($s$) & destination ($d$) entities의 embeddings를 계산합니다.
그리고 존재하는 노드들에 대해 이것들과의 유사도가 threshold $t$ 이상인 것들을 검색합니다.
검색 결과에 따라 두 노드를 추가로 생성하거나, 한 개만 생성하거나, 기존 노드의 정보를 사용하게 됩니다.
(2) Update Resolver
LLM 기반(GPT-4o-mini)의 update resolver는 특정 관계가 필요 없어졌는지(obsolete) 확인하여 이들을 invalid 한 것으로 표시합니다.
이때 특징은 구식(obsolete)의 정보를 완전히 제거하지 않고 invalid로 표시함으로써 temporal reasoning이 가능하도록 한 점입니다.
Mem$0^g$는 최적의 information access를 위한 dual-approach를 실행합니다.
1) 우선 query 내의 key entities를 식별하고, semnatic similarity를 이용하여 knowledge graph 내에 상응하는 노드를 찾아냅니다.
이때 anchor 노드로 들어오는 & 나가는 관계를 모두 explore 함으로써 contextual information을 충분히 저장합니다.
2) 그리고 query는 embedding vector로 변환되어 각 triplet의 embedding과의 유사도를 계산하게 됩니다. (내림차순 정렬)
이를 통해 relevance threshold를 넘는 triplet만을 반환하게 됩니다.
결과적으로, Mem$0^g$는 semantic embeddings를 포함하는 graph-based representations와 LLM 기반의 information을 통합한 구조라고 간단 요약할 수 있겠습니다.
3. Experimental Setup
3.1. Dataset
[LoCoMo dataset]
(Evaluating Very Long-Term Conversational Memory of LLM Agents: https://snap-research.github.io/locomo/)
대화 시스템 내에서 long-term conversationl memory를 평가하기 위해 설계된 데이터셋으로,
각각 평균 26000 토큰, 600개의 dialogues로 구성된 10개의 extended conversations입니다.
각 conversation은 daily experiences 또는 과거 사건들에 대해 이야기를 나누는 두 인물의 대사로 구성되어 있습니다.
이에 대해서 ground truth answers를 뽑을 수 있는 200개씩의 질문이 수반됩니다.
각 질문들은 'single-hop, multi-hop, temporal, open-domain' 유형으로 구분됩니다.
원데이터셋에는 모델의 unanswerable questions에 대한 능력을 보는 데이터도 포함되어 있으나 본 실험의 평가 대상이 아니어서 제외되었습니다.
<LoCoMo Figure2>를 보면 (1) Question Answering Task에 대한 것만 본 연구에서 활용했음을 알 수 있습니다.
3.2. Evaluation Metrics
(1) Performance Metrics
- F1 Score ($F_1$) & BLEU-1 ($B_1$)
- LLM-as-a-Judge ($J$)
- $J$ 평가의 stochastic 특성을 감안하여 10번을 독립적으로 실행했다고 합니다.
(2) Deployment Metrics
- Token Consumption
- tiktoken의 cl100k_base 사용 (OpenAI tokenizer - 깃허브 링크
- retrieval에서 context로 사용되는 토큰의 개수 측정 (여기서는 knoledge base에서 retrieved memories)
- Latency
- (1) search latency: memory에서 필요한 정보를 찾아오는 데 걸린 총 시간
- (2) total latency: 최종 응답을 생성하는 데 걸린 총 시간
- 두 metric 간의 trade-off 존재가 일반적입니다.
- system design이 복잡할수록 정교한 검색 및 생성이 가능할 테지만, 그만큼 latency가 올라갈 것임을 쉽게 예상할 수 있습니다.
3.3. Baselines
가능하면 재현 가능한 실험 위해 temperature는 0으로 설정하고 실행을 진행합니다.
사용된 베이스라인들은 다음과 같습니다.
- Established LoCoMo benchmarks
- LoCoMo 데이터셋을 평가하기 위해 사용되었던 다섯 개의 approaches: LoCoMo, ReadAgent, MemoryBank, MemGPT, A-Mem
- gpt-4o-mini를 평가자로 사용
- Open-Source Memory Solutions
- LangMem (Hot Path)
- LLM은 gpt-4o-mini, embedding은 text-embedding-small-3 사용
- Retrieval-Augmented Generation (RAG)
- 128, 256, 512, 1024, 2048, 4096, 8192로 고정된 길이의 대화를 사용 (8192가 embedding 모델이 받을 수 있는 최대 길이)
- text-embedding-small-3 모델로 embedded
- top $k$개 chunks를 가져오는데, $k \in {1,2}$. 이는 평균 대화 길이가 26000 토큰으로 $k=2$만 되어도 16384 토큰을 차지하여 이를 초과하는 경우 memory 시스템 존재 의미가 없어지기 때문
- Full-Context Processing
- 전체 conversation history를 LLM에 전달
- Proprietary Models
- OpenAI's memory (gpt-4o-mini)
- Memory Providers
- Zep
4. Evaluation Results, Analysis and Discussion
4.1. Performance Comparison Across Memory-Enabled Systems
- Single-Hop, Multi-Hop
- Mem$0$가 가장 우수, 의외로 Mem$0^g$ 성능이 좋지 않음
- 단순한 형태의 retrieval tasks에서는 graph design이 불필요하다는 것을 반증
- Open-Domain, Temporal Reasoning
- Mem$0^g$가 강세를 보임
- 구조화된 memory가 장점을 발휘하는 영역
- 특히 temporal reasoning을 잘할 수밖에 없다는 점이 두드러지는 듯
4.2. Performance Comparison of Mem$0$ and Mem$0^g$ Against RAG Approaches and Full-Context Model & Latency Analysis
Overall $J$ 열을 보면,
- Mem$0$와 Mem$0^g$를 사용함으로써 확실한 성능 gain이 있음
- 그럼에도 불구하고 Full-context를 사용하는 것보다 뛰어나지는 않음
을 알 수 있습니다.
하지만 RAG 시나리오에서 chunk size가 8192일 때와, Full-context를 사용할 때의 latency를 보면,
각각 4.416 / 9.942 / 17.117 초인 것을 알 수 있습니다. (Total, p95 기준)
서비스 관점에서 보면 성능 향상 대비 latency 상승 폭이 지나치게 크다고 볼 수 있겠습니다.
당연한 이야기지만 Full-context를 사용할 때는 별도의 retireval 과정이 없으므로 total latency만 존재하게 됩니다.
이와 달리 빨간색으로 표시된 Mem$0$의 latency를 보면 1.440초 정도밖에 걸리지 않습니다. (Total, p95 기준)
이를 잘 보여주는 것이 아래 두 그래프입니다.
(추가로, 논문에서는 Token 사용량을 대상으로 Memory System의 Overhead를 설명하고 있는데, minor 한 것 같아서 본 포스팅에서는 다루지 않습니다.)
5. Conclusion and Future Work
지금까지 LLM agents의 memory를 효율적으로 관리 및 업데이트하여 빠르게 검색하면서도 멀티턴에서 뛰어난 성능을 보일 수 있도록 만드는 Mem$0$ & Mem$0^g$ 방법론에 대해 알아봤습니다.
LoCoMo 벤치마크 데이터셋을 대상으로 LLM agents의 memory system을 latency & performance 두 관점에서 실험한 결과는,
다른 기존의 방법론들 대비 훨씬 적은 latency로도 높은 성능을 낼 수 있음을 보여주었습니다.
한 파이프라인 내에 여러 LLM들을 활용하여 분기 처리하는 agentic flow가 대세인 지금, 가장 활발히 이용되는 방법론이었는데요.
내용적으로는 엄청 특별하거나 참신한 것은 딱히 느껴지지 않는 것 같습니다.
예를 들면 GPT-4o-mini의 function call을 이용하여 데이터 업데이트, 추가 등의 분기 처리 역시 기존에 존재하던 방법론들이니까요.
다만, 전체 대화 히스토리를 비동기적으로 업데이트하고, 빠르고 정확한 메모리 검색을 가능하도록 하는 방법들을 사용하여 속도와 성능 (사실 속도도 성능이지만요) 둘 다 훌륭하게 챙긴 덕분에 많은 사람들의 사랑을 받는 것 같습니다.
빠르지 않으면 실서비스에 활용하기는 불가능하니까요.
게다가 사용하는 토큰의 양도 적다는 점은 토큰 사용량 자체가 비용이 되는 서비스들에 대해서도 큰 메리트를 갖는 것으로 보입니다.