논문: https://arxiv.org/abs/2504.19413
github: https://github.com/mem0ai/mem0
Abstract 한눈에 보기
문제 — LLM의 고정된 컨텍스트 윈도우는 여러 세션에 걸친 장기 대화에서 일관성을 유지하는 데 근본적 한계가 있다.
방법 — 진행 중인 대화에서 핵심 정보를 동적으로 추출·통합·검색하는 확장 가능한 메모리 아키텍처 Mem0, 그리고 개체·관계를 명시적으로 표현하는 그래프 확장판 Mem0^g를 제안한다.
결과 — LOCOMO에서 메모리 시스템·RAG·전체 컨텍스트·상용 솔루션 등 6개 베이스라인 범주를 일관되게 능가(OpenAI 대비 LLM-as-a-Judge +26%, Mem0^g는 Mem0보다 +2%)하면서, 전체 컨텍스트 방식 대비 p95 지연 91%↓, 토큰 비용 90%↓를 달성했다.
초록 전체
대규모 언어 모델(LLM)은 문맥적으로 일관된 응답을 생성하는 데 탁월한 능력을 보여 왔지만, 고정된 컨텍스트 윈도우는 장기간에 걸친 다중 세션 대화에서 일관성을 유지하는 데 근본적인 어려움을 초래한다. 본 연구에서는 진행 중인 대화에서 중요한 정보를 동적으로 추출하고, 통합하며, 검색함으로써 이러한 문제를 해결하는 확장 가능한 메모리 중심 아키텍처인 Mem0를 제안한다. 이러한 기반 위에서, 대화 요소들 사이의 복잡한 관계 구조를 포착하기 위해 그래프 기반 메모리 표현을 활용하는 확장형 변형도 추가로 제안한다. LOCOMO 벤치마크에 대한 포괄적인 평가를 통해, 본 연구의 접근법을 다음의 여섯 가지 베이스라인 범주와 체계적으로 비교한다. (i) 기존의 메모리 증강 시스템, (ii) 서로 다른 청크 크기와 값을 사용하는 검색 증강 생성(RAG), (iii) 전체 대화 기록을 처리하는 전체 컨텍스트 접근법, (iv) 오픈소스 메모리 솔루션, (v) 독점 모델 시스템, (vi) 전용 메모리 관리 플랫폼이다. 실험 결과, 본 연구의 방법은 단일 홉, 시간적, 다중 홉, 오픈 도메인의 네 가지 질문 범주 전반에서 기존의 모든 메모리 시스템을 일관되게 능가하였다. 특히 Mem0는 OpenAI 대비 LLM-as-a-Judge 지표에서 상대적으로 26% 향상되었으며, 그래프 메모리를 사용하는 Mem0는 기본 Mem0 구성보다 전체 점수가 약 2% 더 높았다. 정확도의 향상뿐 아니라, 전체 컨텍스트 접근법과 비교하여 계산 오버헤드도 현저하게 감소시켰다. 구체적으로 Mem0는 p95 지연시간을 91% 낮추고 토큰 비용을 90% 이상 절감하여, 고도화된 추론 능력과 실제 배포상의 제약 사이에서 매력적인 균형을 제공한다. 본 연구의 결과는 장기적인 대화 일관성을 위해 구조화되고 영속적인 메모리 메커니즘이 핵심적인 역할을 한다는 점을 강조하며, 더욱 신뢰할 수 있고 효율적인 LLM 기반 AI 에이전트로 나아가는 길을 제시한다.
§1 핵심 3줄
컨텍스트 윈도우는 ‘기억’이 아니다.

메모리는 ‘대화 품질’을 넘어 ‘에이전트 능력’의 문제다
“컨텍스트를 더 늘리면 되지않나?”에 대한 반박
본 논문의 기여
§2 핵심 3줄
invalid로 표시한다.

| 문맥 정보원 | 역할 | 성격 |
|---|---|---|
| 대화 요약 (DB에서 조회) | 전체 대화 기록의 의미적 내용을 압축해 전반적 주제를 제공 | 넓지만 거친 문맥 |
| 최근 메시지 | 요약에 아직 통합되지 않은 세밀한 시간적 문맥 제공 | 좁지만 정밀한 문맥 |
| 연산 | 발동 조건 | 지식베이스 변화 | 예시(이해를 위한 구성) |
|---|---|---|---|
| ADD | 의미적으로 동등한 기존 메모리가 없음 | 새 메모리 생성 | "채식주의자다"를 최초로 언급 |
| UPDATE | 새 정보가 기존 메모리에 보완적 정보를 추가 | 기존 메모리를 확장 또는 대체 | 기존 "채식주의자" + 신규 "유제품도 피함" |
| DELETE | 새 정보가 기존 메모리와 모순 | 기존 메모리 제거 | 기존 "닭고기를 좋아함" ↔ 신규 "채식을 시작함" |
| NOOP | 지식베이스를 수정할 필요 없음 | 변화 없음 | 이미 저장된 사실의 단순 재언급 |
| 항목 | 값 |
|---|---|
| 최근 메시지 수 | 10 |
| 비교할 유사 메모리 수 | 10 |
| 언어 모델 (전 연산) | GPT-4o-mini |
| 저장소 | 벡터 DB (dense embedding 기반 유사도 검색) |
| 구성요소 | 의미 | 예시 |
|---|---|---|
| (노드) | 엔터티 | Alice, San Francisco |
| (엣지) | 엔터티 사이의 관계 | lives_in |
| (라벨) | 노드의 의미적 유형 | Alice → Person, San Francisco → City |
!image.png
flowchart LR
Alice(["Alice · Person"]) -->|lives_in| SF(["San Francisco · City"])
Alice -->|prefers| Veg(["Vegetarian food · Preference"])
Alice -->|attended| Ev(["Team offsite · Event"])
Ev -->|happened_on| D(["2025-03-14 · Date"])
lives_in, prefers, owns, happened_on 같은 라벨로 분류한다. 프롬프트 엔지니어링을 통해 명시적 진술뿐 아니라 암묵적 정보까지 추론하도록 유도한다.| 전략 | 동작 | 강점 |
|---|---|---|
| 엔터티 중심 검색 (entity-centric) | 질문에서 핵심 엔터티를 식별 → 의미적 유사도로 그래프의 대응 노드를 찾음 → 기준 노드의 들어오는·나가는 관계를 모두 체계적으로 탐색해 하위 그래프 구성 | 특정 엔터티에 초점을 둔 질문 |
| 의미적 삼중항 검색
(semantic triplet) | 질문 전체를 하나의 dense embedding으로 인코딩 → 그래프의 각 관계 삼중항의 텍스트 인코딩과 비교 → 관련성 임계값을 넘는 삼중항만 유사도 순으로 반환 | 넓은 개념적 질문 |
| 항목 | 값 |
|---|---|
| 그래프 DB | Neo4j |
| 추출기·업데이트 모듈 | GPT-4o-mini (function calling) |
| Mem0 | Mem0^g | |
|---|---|---|
| 저장 형태 | 자연어 dense memory | 방향성 라벨 그래프 |
| 저장소 | 벡터 DB | Neo4j |
| 갱신 방식 | ADD / UPDATE / DELETE / NOOP | 노드 재사용(sim > ) + 관계 invalid 표시 |
| 검색 | 임베딩 유사도 top- | 엔터티 중심 + 의미적 삼중항 |
§3 핵심 3줄
| 항목 | 값 |
|---|---|
| 대화 수 | 10개 장기 대화 |
| 대화당 턴 수 | 평균 약 600 |
| 대화당 토큰 수 | 평균 약 26,000 |
| 대화당 질문 수 | 평균 약 200 (정답 동반) |
| 구조 | 다중 세션(multi-session) |
| 내용 | 두 사람이 일상 경험·과거 사건에 대해 나누는 대화 |
유형별 측정 능력
| 질문 유형 | 요구되는 능력 |
|---|---|
| 단일 홉 (single-hop) | 하나의 대화 턴 안에 있는 단일 사실 구간을 찾아내기 |
| 다중 홉 (multi-hop) | 여러 세션에 흩어진 정보를 종합하기 |
| 시간적 (temporal) | 사건의 순서·상대적 선후관계·지속기간을 정확히 모델링하기 |
| 오픈 도메인 (open-domain) | 대화 메모리와 외부 지식을 통합하기 |
유형별 예시
| 유형 | 대화 맥락 | 질문 | 정답 |
|---|---|---|---|
| 단일 홉 Single-Hop | 어젯밤 .. 우리는 딸의 생일을 축하했어(Last night .. we celebrated my daughter's birthday.) | X는 누구의 생일을 축하했는가?(Whose birthday did X celebrate?) | 딸(daughter) |
| 다중 홉 Multi-Hop | 나는 2년 전에 뉴욕에 갔었어(I visited New York two years ago.) — 별도 세션 — 예전 여행 중 하나에서 찍은 사진이야(A picture from one of my older travels) | X가 방문한 곳은 어디인가?(Which places has X visited?) | 뉴욕, 호스슈 캐니언(New York, Horseshoe Canyon) |
| 시간적 Temporal | 2022년 7월 10일: .. 새 영화가 잘돼서 최근에 책을 쓰기 시작했어!(July 10, 2022: … I actually started on a book recently since my new movie did well!) 2022년 10월 6일: .. 지난주에 책 집필을 끝냈어(Oct 6, 2022: … I finished up my writing for my book last week..) | X가 책 집필을 끝내는 데 얼마나 걸렸는가?(How long did it take for X to finish writing the book?) | 3개월(three months) |
| 오픈 도메인 Commonsense & World Know. | 나는 바흐나 모차르트 같은 클래식도, 에드 시런의 'Perfect' 같은 현대 음악도 좋아해(I'm a fan of both classical like Bach and Mozart, as well as modern music like Ed Sheeran's "Perfect".) | X는 비발디의 '사계'를 좋아할 가능성이 있는가?(Would X likely enjoy "The Four Seasons" by Vivaldi?) | 그렇다; 그는 클래식 음악을 좋아한다(Yes; she likes classical music.) |
| 적대적 Adversarial | 2020년 9월 5일: 나는 피아노를 배우는 중이야(Sep 5 2020: I'm learning the piano.) | X는 언제 바이올린을 배우기 시작했는가?(When did X start learning violin?) (A) 2020년 9월 5일 (B) 답할 수 없음 | (B) 답할 수 없음((B) Not answerable) |
유형별 통계
| 유형 | 문항 수 | 전체 비중 | 적대적 제외 후 재계산 |
|---|---|---|---|
| 단일 홉 (single-hop retrieval) | 2,705 | 36.0% | 48.0% |
| 다중 홉 (multi-hop retrieval) | 1,104 | 14.6% | 19.6% |
| 시간적 (temporal reasoning) | 1,547 | 20.6% | 27.4% |
| 오픈 도메인 (open domain knowledge) | 285 | 3.9% | 5.1% |
| 적대적 (adversarial) | 1,871 | 24.9% | (제외) |
| 합계 | 7,512 | 100% | 5,641 |
⚠️ 적대적(adversarial) 범주는 평가에서 제외했다
원 데이터셋에는 "시스템이 답할 수 없는 질문임을 인식하는 능력"을 평가하는 적대적 범주가 포함되어 있다. 그러나 ① 정답이 제공되지 않았고, ② 기대되는 행동 자체가 "답할 수 없음"의 인식이었기 때문에 본 평가에서는 제외되었다.
🔴 어휘 유사도 지표가 실패하는 방식
내용 정답 (gold) "Alice was born in March" 생성 답변 "Alice is born in July" 사실 판정 ❌ 출생 월이라는 핵심 사실이 틀림 / Alice,born등 토큰이 겹치므로 비교적 높은 점수→ 의미적 정확성을 포착하지 못하는, 잘못된 평가로 이어진다.
- 이를 보완하기 위해 LLM-as-a-Judge() 를 상호보완적 지표로 사용한다.
- 더 강력한 별도의 LLM이 질문·정답·생성 답변을 함께 분석해, 사실적 정확성, 관련성, 완전성, 문맥적 적절성을 포함한 여러 차원에서 응답 품질을 평가하며, 인간 판단과 더 잘 부합하는 세밀한 평가를 제공한다.
- 각 방법마다 전체 데이터셋에서 10회의 독립 실행을 수행하고, 결과는 평균과 ±1 표준편차로 보고한다.
| 지표 | 정의 | 측정 세부 |
|---|---|---|
| Token Consumption | 검색 단계에서 추출되어 질문 응답의 문맥으로 사용되는 토큰 수 | tiktoken cl100k_base 인코딩. 메모리 기반 = 지식베이스에서 검색된 메모리의 토큰 수 / RAG 기반 = 검색된 원문 텍스트 청크 전체의 토큰 수 |
| Search latency | 메모리(또는 청크)를 검색하는 데 걸린 전체 시간 | — |
| Total latency | 검색 시간 + LLM 답변 생성 시간 | 전체 응답 생성 시간 |
| # | 범주 | 대표 시스템 |
|---|---|---|
| 1 | 기존 LOCOMO 벤치마크 | LoCoMo, ReadAgent, MemoryBank, MemGPT, A-Mem |
| 2 | 오픈소스 메모리 솔루션 | LangMem (Hot Path) |
| 3 | RAG | 청크 128~8192 토큰 × =1,2 |
| 4 | 전체 컨텍스트 처리 | 전체 대화를 컨텍스트에 직접 투입 |
| 5 | 상용 모델 | OpenAI memory (GPT-4o-mini) |
| 6 | Memory providers | Zep |
| 방법 | 메모리 메커니즘 |
|---|---|
| LoCoMo | 대화를 세션 요약 + 관찰 사실로 저장하고, 시간적 사건 그래프로 관련 기억을 검색 |
| ReadAgent | 긴 대화를 자연스러운 구간으로 나눠 요약한 뒤, 질문에 필요한 원문 구간만 선택적으로 조회 |
| MemoryBank | 대화 기록·사건 요약·사용자 프로필을 저장. 관련 기억은 강화하고 미사용 기억은 점차 약화(망각 곡선) |
| MemGPT | 운영체제처럼 기억을 주 컨텍스트와 외부 저장소로 나누고, 함수 호출로 필요한 정보를 불러옴 |
| A-Mem | 기억을 구조화된 노트로 저장하고, 새 기억과 관련된 기존 노트를 연결·갱신해 동적 기억 네트워크 구축 |
text-embedding-3-small| 설정 항목 | 값 |
|---|---|
| 청크 크기 | 128, 256, 512, 1024, 2048, 4096, 8192 토큰 (8192는 사용 임베딩 모델의 최대치) |
| 임베딩 모델 | text-embedding-3-small |
| 검색 개수 | — =1은 최상위 청크 1개, =2는 상위 2개 연결(최대 16,384토큰) |
§4 핵심 3줄

<표 1 - LOCOMO 질문 유형별 F1, B1, J 점수 비교>
전반적으로 두 제안 모델은 대부분의 질문 유형에서 세 지표 모두 새로운 최고 수준을 기록했다. 유형별로 보면 승자와 그 이유가 뚜렷하게 갈린다.
| 질문 유형 | 1위 | 핵심 수치 | 해석의 핵심 |
|---|---|---|---|
| 단일 홉 | Mem0 | 38.72 · 27.13 · 67.13 | 답이 한 턴 안에 있으면 관계 구조의 효용이 제한적 |
| 다중 홉 | Mem0 | 28.64 · 51.15 | 자연어 dense memory만으로도 세션 간 통합이 가능 |
| 오픈 도메인 | Zep | 49.56 · 76.60 | 대화 메모리 + 외부 지식 통합에서 작지만 일관된 우위 |
| 시간적 | Mem0^g | 51.55 · 58.13 | 구조화된 관계 표현이 시간적 근거 판단에 크게 기여 |

<표 2 - 메모리 관리 방법 baseline과의 latency, J 비교>
| 방법 | Overall | 최고 RAG 대비 |
|---|---|---|
| 최고 RAG 설정 | 약 61% | — |
| Mem0 | 약 67% | 약 +10% (상대) |
| Mem0^g | 68% 초과 | 약 +12% (상대) |
⚠️ 짚어야 할 부분 — 정확도 1위는 전체 컨텍스트 방식이다
약 26,000토큰의 전체 대화를 그대로 넣는 방식이 약 73%로 최고 점수를 기록했다. 즉 Mem0는 "가장 정확한 방법"이 아니다.
대신 그 방식은 질문마다 전체 대화를 다시 읽어야 하므로 총 p95 지연 약 17초를 소비한다. Mem0는 약 1.44초, Mem0^g는 약 2.6초로 각각 약 92% / 85% 감소다.

💡 지연시간 요약
- Mem0는 모든 방법 중 검색 지연이 가장 낮다: 검색 p50 0.148s / p95 0.200s, 전체 p50 0.708s / p95 1.440s. 고정 크기 청크가 아니라 가장 중요한 정보만 동적으로 식별·검색하는 선택적 메모리 검색과 인프라 개선에서 나온 결과다.
- Mem0^g는 관계 모델링 대가로 중간 정도의 지연 시간을 추가한다: 검색 p50 0.476s / p95 0.657s, 전체 p50 1.091s / p95 2.590s. 그럼에도 메모리 솔루션 중에서 기존 모든 메모리 솔루션·베이스라인보다 검색이 빠르며, 계산 비용이 막대한 전체 컨텍스트 다음으로 높은 Overall 68.44를 유지한다.
베이스라인별로 보면, A-Mem은 더 큰 메모리 저장소를 사용하며 검색 p50 0.668s · 전체 p50 1.410s를, Zep은 전체 p50 1.292s로 중간 수준을 기록했다. 전체 컨텍스트 베이스라인은 검색 단계 자체가 없지만 26,000토큰을 LLM에 직접 전달하므로 전체 p50 9.870s · p95 17.117s의 막대한 지연이 발생한다.
| 시스템 | 대화당 메모리 구성 토큰 | 비고 |
|---|---|---|
| Mem0 | 약 7,000 | 완전한 대화 턴을 자연어 표현으로 인코딩 |
| Mem0^g | 약 14,000 | 노드 + 관계 그래프가 추가되어 저장 규모 2배 |
| 원문 대화 전체 (메모리 추상화 없음) | 약 26,000 | 참조 기준선 |
| Zep | 600,000 초과 | 원문 대화 전체보다 약 23배, Mem0보다 약 85배 |
🔴 Zep의 또 다른 문제 — 메모리가 즉시 사용 가능하지 않다
저자들은 Zep에 메모리를 추가한 직후 동일한 정보를 검색하면 질문에 정확히 답하지 못하는 경우를 자주 관찰했다. 그런데 몇 시간 뒤 같은 검색을 반복하면 결과가 상당히 좋아졌다. 이는 Zep의 그래프 구성이 여러 비동기 LLM 호출과 광범위한 백그라운드 처리를 포함함을 시사한다.
반면 Mem0의 그래프 구성은 최악의 경우에도 1분 이내에 완료되어, 새로 추가한 메모리를 즉시 질의 응답에 사용할 수 있다.
→ 결론: Zep은 동일한 지식을 여러 노드에 복제하면서 운영 지연까지 유발하는 반면, Mem0와 Mem0^g는 훨씬 적은 토큰 비용과 더 빠른 메모리 가용성으로 같은 정보를 보존한다.
결론
두 아키텍처의 역할 분담은 다음과 같이 정리된다.
| 강점 | 적합한 상황 | |
|---|---|---|
| Mem0의 dense memory 파이프라인 | 단순한 질문에서 빠른 검색, 토큰 사용량과 계산 오버헤드 최소화 | 지연·비용이 제약인 일반 대화 제품 |
| Mem0^g의 구조화된 그래프 표현 | 세밀한 관계 명확성, 복잡한 사건 순서와 풍부한 문맥 통합 지원 | 시간·관계 추론 비중이 높은 도메인 |
당신의 과제는 질문에 대한 답변을 “CORRECT” 또는 “WRONG”으로 판정하는 것입니다. 다음과 같은 데이터가 주어집니다.
질문: 한 사용자가 다른 사용자에게 한 질문
‘골드’ 답변: 정답으로 간주되는 기준 답변
생성된 답변: 당신이 CORRECT 또는 WRONG으로 평가할 답변
이 질문의 목적은 이전 대화를 바탕으로 한 사용자가 다른 사용자에 대해 알고 있어야 하는 내용을 묻는 것입니다. 골드 답변은 일반적으로 언급된 주제를 포함하는 짧고 간결한 답변입니다. 예시는 다음과 같습니다.
Question: 내가 지난번 하와이에 갔을 때 무엇을 샀는지 기억해?
Gold answer: 조개 목걸이
생성된 답변은 훨씬 길 수 있지만, 평가할 때는 관대하게 판단해야 합니다. 생성된 답변이 골드 답변과 동일한 주제를 언급하기만 한다면 CORRECT로 판정해야 합니다.
시간과 관련된 질문의 경우, 골드 답변은 특정 날짜, 월, 연도 등이 될 수 있습니다. 생성된 답변은 더 길거나 ‘지난주 화요일’, ‘다음 달’과 같은 상대적 시간 표현을 사용할 수도 있습니다. 이 경우에도 관대하게 평가해야 하며, 골드 답변과 동일한 날짜 또는 시간대를 가리킨다면 CORRECT로 판정해야 합니다. 형식이 다르더라도, 예를 들어 ‘May 7th’와 ‘7 May’처럼 동일한 날짜를 의미한다면 CORRECT로 간주하십시오.
이제 실제 질문을 평가할 차례입니다.
Question: {question}
Gold answer: {gold_answer}
Generated answer: {generated_answer}
먼저 판단 근거를 한 문장으로 짧게 설명한 뒤, 마지막에 CORRECT 또는 WRONG으로 끝내십시오. 응답에 CORRECT와 WRONG을 모두 포함하면 평가 스크립트가 정상적으로 작동하지 않으므로, 둘 중 하나만 포함해야 합니다.
최종적으로는 label을 키로 사용하여 CORRECT 또는 WRONG 중 하나만 JSON 형식으로 반환하십시오.
{"label": "CORRECT"}
당신은 대화 기억에서 정확한 정보를 검색하는 지능형 메모리 어시스턴트입니다.
맥락:
당신은 대화에 참여한 두 화자의 기억에 접근할 수 있습니다. 이 기억에는 질문에 답하는 데 관련될 수 있는 타임스탬프가 포함된 정보가 담겨 있습니다.
지침:
두 화자의 모든 기억을 주의 깊게 분석하십시오.
답을 판단하기 위해 타임스탬프에 특별히 주의를 기울이십시오.
질문이 특정 사건이나 사실을 묻는 경우, 기억에서 직접적인 근거를 찾으십시오.
기억에 서로 모순되는 정보가 있다면 가장 최근의 기억을 우선하십시오.
질문에 “작년”, “두 달 전”과 같은 시간 표현이 포함되어 있다면, 기억의 타임스탬프를 기준으로 실제 날짜를 계산하십시오. 예를 들어 2022년 5월 4일의 기억에 “작년에 인도에 갔다”라고 적혀 있다면, 해당 여행은 2021년에 이루어진 것입니다.
상대적인 시간 표현은 항상 구체적인 날짜, 월 또는 연도로 변환하십시오. 예를 들어 기억의 타임스탬프를 기준으로 “작년”은 “2022년”으로, “두 달 전”은 “2023년 3월”로 변환하십시오. 답변할 때는 원래의 상대적 표현을 사용하지 마십시오.
두 화자의 기억에 포함된 내용에만 집중하십시오. 기억에서 언급된 등장인물의 이름을 해당 기억을 생성한 실제 사용자와 혼동하지 마십시오.
답변은 5~6단어 이내로 작성하십시오.
접근 방법(단계별로 생각하기):
먼저 질문과 관련된 정보가 포함된 모든 기억을 검토하십시오.
해당 기억의 타임스탬프와 내용을 주의 깊게 살펴보십시오.
질문에 답할 수 있는 날짜, 시간, 장소 또는 사건에 대한 명시적인 언급을 찾으십시오.
상대적 시간 표현의 변환처럼 계산이 필요한 경우, 계산 과정을 제시하십시오.
기억에 있는 근거만을 바탕으로 정확하고 간결한 답변을 작성하십시오.
최종 답변이 질문에 직접 답하고 있는지 다시 확인하십시오.
최종 답변이 구체적이며 모호한 시간 표현을 사용하지 않는지 확인하십시오.
사용자 {speaker_1_user_id}의 기억:
{speaker_1_memories}
사용자 {speaker_2_user_id}의 기억:
{speaker_2_memories}
질문: {question}
답변:
(이전과 동일)
# 접근 방법 (단계별로 생각하세요):
1. 먼저, 질문과 관련된 정보를 담고 있는 모든 메모리를 살펴봅니다
2. 해당 메모리들의 타임스탬프와 내용을 주의 깊게 검토합니다
3. 질문에 답이 되는 날짜, 시간, 장소, 사건에 대한 명시적 언급을 찾습니다
4. 답변에 계산이 필요한 경우(예: 상대적 시간 표현의 변환), 그 과정을 보여줍니다
5. 지식 그래프의 관계(relations)를 분석하여 사용자의 지식 맥락을 파악합니다
6. 오직 메모리에 담긴 근거만을 바탕으로 정확하고 간결한 답변을 작성합니다
7. 작성한 답변이 질문에 직접적으로 대응하는지 다시 확인합니다
8. 최종 답변이 구체적이며 모호한 시간 표현을 사용하지 않도록 합니다
사용자 {speaker_1_user_id}의 메모리: {speaker_1_memories}
사용자 {speaker_1_user_id}의 관계: {speaker_1_graph_memories}
사용자 {speaker_2_user_id}의 메모리: {speaker_2_memories}
사용자 {speaker_2_user_id}의 관계: {speaker_2_graph_memories}
질문: {question}
답변:
현재 구현 버전에서는 mem^g가 사라졌으며, mem0에서도 ADD 기능만 남음.
# 역할 (ROLE)
당신은 **Memory Extractor(메모리 추출기)** 입니다 — 대화로부터 풍부하고 맥락이 살아있는 메모리를 추출하는, 정확하고 근거에 엄격히 구속된 처리기입니다. 당신이 수행하는 유일한 연산은 **ADD**입니다: 기억할 가치가 있는 모든 정보를 식별하여, 그 자체로 완결되고 맥락이 풍부한 사실 진술문으로 만들어 내십시오.
당신은 **사용자(user) 메시지와 어시스턴트(assistant) 메시지 양쪽 모두**에서 추출합니다. 사용자 메시지는 개인적 사실, 선호, 계획, 경험을 드러냅니다. 어시스턴트 메시지에는 사용자가 나중에 참조할 수 있는 추천, 계획, 제안, 실행 가능한 정보가 담겨 있습니다.
정확성과 완전성이 무엇보다 중요합니다. 기억할 만한 모든 정보는 반드시 포착되어야 합니다 — 추출 누락은 곧 맥락의 손실이며, 이는 향후 개인화 품질을 떨어뜨립니다. 대화가 여러 주제를 다룰 경우, 각 주제를 별도로 추출하십시오. 지배적인 주제 하나 때문에 부차적인 정보를 놓치는 일이 없도록 하십시오.
---
# 입력 (INPUTS)
## New Messages (신규 메시지)
"role"(user/assistant)과 "content"로 구성된 현재 대화 턴(들)입니다.
두 역할 모두 추출 대상 정보를 포함합니다:
- **사용자 메시지**: 개인적 사실, 선호, 계획, 경험, 해본 일 / 한 번도 해보지 않은 일, 의견, 요청, 질문을 통해 암묵적으로 드러나는 선호
- **어시스턴트 메시지**: 제공된 구체적 추천, 사용자를 위해 작성된 계획이나 일정, 조사·제공된 정보, 제시된 해결책, 대화 중 이루어진 합의
귀속을 정확히 하십시오: 사용자가 진술한 사실에는 "User"를 사용합니다. 어시스턴트가 생성한 내용은 사용자의 맥락에 맞춰 표현하십시오(예: "User was recommended X" 또는 "User's plan includes X as discussed in conversation").
**추출하지 말아야 할 것:**
- 어시스턴트의 모호한 성격 규정("당신은 열정적인 것 같네요", "많이 힘드시겠어요") — 단, 사용자가 명시적으로 이를 인정한 경우는 제외
- 어시스턴트의 일반적인 맞장구("물론이죠!", "좋은 질문이에요!")
- 어시스턴트가 자기 능력에 대해 언급하는 메타 코멘트
## Summary (요약)
이전 대화들로부터 축적된 사용자 프로필의 서술형 요약입니다. 신규 사용자의 경우 비어 있을 수 있습니다. 이름, 거주지, 인간관계 등 확립된 맥락이 담겨 있으므로 추출을 풍부하게 하는 데 활용하십시오.
## Recently Extracted Memories (최근 추출된 메모리)
현재 세션의 최근 메시지들에서 이미 포착된 메모리입니다(최대 20개). 이것이 **중복 제거의 1차 기준**입니다 — 여기에 이미 포착된 정보를 다시 추출하지 마십시오.
## Existing Memories (기존 메모리)
현재 시스템에 저장되어 있으며 이 대화와 관련된 메모리입니다. 형식은 다음과 같습니다:
[{"id": "uuid-string", "text": "..."}, ...]
이것은 **오직 중복 제거와 연결(linking)을 위해서만** 사용하십시오 — Existing Memories로부터 새 메모리를 추출해서는 **안 됩니다**. 당신의 추출물은 오로지 New Messages에서만 나와야 합니다. New Messages의 새 정보가 어떤 Existing Memory와 의미상 동일하고 의미 있는 새 맥락이 없다면, 건너뛰십시오.
새 메모리가 어떤 Existing Memory와 관련될 때 — 동일 주제, 겹치는 개체(entity), 갱신·변화된 선호, 후속 사건, 이야기의 연속 — 해당 Existing Memory의 ID를 새 메모리의 `linked_memory_ids` 배열에 포함시키십시오. ADD 출력의 `id`는 순차적("0", "1", ...)으로 유지되지만, `linked_memory_ids`에는 이 목록의 UUID를 사용합니다.
**중요:** 어떤 개체에 관한 기존 메모리(예: "User has a dog named Max")가 존재한다고 해서 그 개체에 관한 모든 정보가 이미 포착되었다는 뜻은 아닙니다. 알려진 개체에 관한 새로운 사건, 활동, 경험, 세부사항은 **반드시** 별도의 메모리로 추출하고 기존 메모리에 연결해야 합니다. 추출을 건너뛰는 것은 그 특정 사실·사건 자체가 이미 포착된 경우에 한정되며, 단지 그 개체가 기존 메모리에 등장한다는 이유만으로 건너뛰어서는 안 됩니다. "User has a dog named Max"와 "User went on a camping trip with Max where they hiked and swam"는 중복이 아니라 서로 다른 두 개의 메모리입니다.
## Last k Messages (직전 k개 메시지)
New Messages 직전의 최근 메시지들입니다(최대 20개). New Messages 내의 지시어와 대명사를 해석하는 데 사용하십시오.
## Observation Date (관찰 일자)
해당 대화가 **실제로 이루어진 시점**입니다(예: "2023-05-24"). 이것이 시간 표현을 해석하는 **유일한** 기준점입니다.
모든 상대적 시간 표현을 Observation Date 기준으로 해석하십시오:
- "yesterday(어제)" → Observation Date의 전날
- "last week(지난주)" → Observation Date 직전 주
- "next month(다음 달)" → Observation Date 다음 달
- "recently(최근)" → Observation Date 직전 무렵
- "just finished(방금 끝냈다)", "today(오늘)" → Observation Date 당일 또는 그 무렵
**핵심:** "User went to Paris last week"는 6개월 뒤에는 아무 쓸모가 없습니다. "User went to Paris the week of May 15, 2023"는 영구적으로 의미가 있습니다. 상대적 시간 표현은 **항상** 구체적 날짜로 고정하십시오.
## Current Date (현재 일자)
오늘의 시스템 날짜입니다. Observation Date보다 몇 년 뒤일 수도 있습니다. 메시지 내 시간 표현을 해석할 때 이 값을 사용하지 **마십시오** — 사용자 및 어시스턴트의 진술을 고정하는 기준은 오직 Observation Date입니다.
## 선택 입력 (Optional Inputs)
- **includes**: 집중해야 할 주제
- **excludes**: 건너뛸 주제
- **custom_instructions**: 사용자 정의 규칙 (최우선순위)
- **feedback_str**: 이 피드백에 따라 추출 방식을 조정
---
# 가이드라인 (GUIDELINES)
## 무엇을 추출할 것인가
사용자와 어시스턴트 메시지 양쪽에서 기억할 만한 **모든** 정보를 추출하십시오. 폭넓게 사고하십시오:
**사용자 메시지에서:**
- 신상 정보, 선호, 계획, 인간관계, 직업적 맥락
- 건강/웰빙, 의견, 취미, 감정 상태
- 개체의 속성(품종, 모델, 색상, 제조사, 크기)
- 요청을 통해 암묵적으로 드러나는 선호
- **공유된 콘텐츠 및 참고 자료** — 사용자가 문서, 판례 요약, 기사, 데이터, 사양, 스탯 블록, 코드 등 구조화된 정보를 공유할 때, 그 콘텐츠 **안에 담긴** 핵심 사실 데이터를 추출하십시오. 사용자가 그것을 공유한 이유는 기억되기를 원하기 때문입니다.
- 최초 경험과 이정표 — '첫 출동', '이제 막 시작함', '최근 합류함' 등
- 구체적인 음식, 식사, 그리고 그 자리에 함께 있던 사람(예: '엄마와의 저녁 식사 — 샐러드, 샌드위치, 집에서 만든 디저트')
- 영감과 동기 — 무엇이 계기가 되어 그 일을 시작했는지, 누가 격려했는지
**어시스턴트 메시지에서 (진정으로 새로운 정보일 때에만):**
- 제공된 구체적 추천(책, 식당, 제품, 서비스)
- 사용자를 위해 작성된 계획이나 일정
- 조사·제공된 정보(사실, 지침, 해결책)
- 대화 중 이루어진 합의
- **이름이 명시된 화자가 공유한 개인적 사실, 경험, 세부사항** — 다중 화자 대화에서 "assistant" 역할은 자신의 삶을 이야기하는 실제 인물일 수 있습니다(예: "Maria: I just got a new cat named Bailey"). 이 경우 그 사람의 개인 정보를 사용자 진술과 동일한 엄밀함으로, 이름에 귀속시켜 추출하십시오.
사용자가 이미 말한 내용을 어시스턴트가 단순히 되풀이·요약·확인하는 메시지에서는 추출하지 **마십시오**. 사용자 본인의 말이 1차 출처입니다 — 사용자가 말한 것을 어시스턴트가 반복했다면, 사용자 버전에서 **한 번만** 추출하십시오. 단, 하나의 어시스턴트 메시지가 되풀이와 새로운 개인적 사실을 **동시에** 담을 수 있습니다 — 되풀이 부분은 건너뛰되 새로운 사실은 반드시 추출하십시오.
인사말, 군더더기, 모호한 맞장구, 지나치게 일반적이어서 쓸모없는 내용은 추출하지 **마십시오**.
**애매하면 추출하십시오.** 약간 중복된 메모리는 누락된 메모리보다 훨씬 비용이 적습니다. 진짜 중복은 하류의 중복 제거 시스템이 처리합니다 — 당신의 임무는 의미 있는 정보가 하나도 유실되지 않게 하는 것입니다.
### 사소해 보이는 주제도 추출 대상입니다
반려동물, 취미, 어린 시절 추억, 웃긴 일화, 개인적 선호에 관한 대화는 건너뛰어도 되는 "잡담"이 **아닙니다**. 개인 메모리 시스템에서 이런 일상적 노출은 종종 **가장 가치 있는** 정보입니다 — 반려동물의 이름, 부모와 함께한 어린 시절의 활동, 재미있는 사건, 새로 시작한 취미. 정보량이 전혀 없는 순수한 사교적 표현("안녕!", "좋아요!", "고마워요!")만 건너뛰십시오.
### 요청뿐 아니라 부수적 사실도 추출하십시오
사용자가 질문이나 요청을 할 때, 그 메시지에는 맥락으로 언급된 **부수적 개인 사실**이 담겨 있는 경우가 많습니다. 이 사실들은 요청 자체만큼이나 추출 가치가 있습니다:
- "정원에서 방울토마토를 수확했는데 — 함께 심을 작물 추천해 주세요" → "User grows cherry tomatoes in their garden"도 함께 추출
- "Kristin Hannah의 'The Nightingale'을 막 읽기 시작했어요 — 비슷한 책 추천해 주세요" → "User started reading 'The Nightingale' by Kristin Hannah on [date]"도 함께 추출
- "스탠드업 코미디언 지망생인데, 넷플릭스 코미디 스페셜 추천해 주세요" → 직업적 지망 사실도 함께 추출
- "제 딸 Sara가 그림 그리기를 좋아하는데 — 아동 미술 수업은 어디서 찾나요?" → "User has a daughter named Sara who loves painting" 추출
요청이 사실을 가리게 하지 마십시오. 함께 심을 작물에 대한 질문은 일시적이지만, 사용자가 방울토마토를 기른다는 사실은 지속적으로 기억할 가치가 있는 개인적 세부사항입니다.
**중요 — 대화의 모든 차원을 추출하십시오.** 하나의 세션에 커리어 관련 사실, 엔터테인먼트 취향, 예정된 계획, 개인적 의견이 모두 담겨 있을 수 있습니다. 각 차원을 별도의 메모리로 추출하십시오. 하나의 지배적 주제 때문에 부차적 정보를 놓치지 마십시오.
### 공유된 사진과 이미지
메시지에 사진 설명(예: "[Shared photo: ...]")이 포함되어 있거나 이미지 공유 상황이 서술되어 있는 경우, **주변 대화 텍스트와 사진 설명 양쪽 모두**에서 사실 정보를 추출하십시오. 사진 설명은 중요한 시각적 맥락을 담고 있을 수 있습니다:
- 공원에 모인 사람들의 사진 → 활동을 추출(예: "공원에서 피크닉을 했다")
- 특정 사물, 장소, 인물이 담긴 사진 → 무엇이 찍혀 있는지 추출
- 텍스트가 보이는 사진(간판, 포스터, 책 표지) → 그 텍스트 내용을 추출
## 메모리 품질 기준
### 원자적(atomic)이 아니라 맥락이 풍부하게
사실과 그 주변 맥락을 **하나의 통합된 메모리**로 담아내되, 파편으로 흩뿌리지 마십시오.
- 나쁨: "User has a dog"
- 좋음: "User has a dog named Poppy and their morning walks together are the highlight of their day"
이는 특히 **전환과 변화**에 적용됩니다. 사용자가 무언가를 바꾸거나, 전환하거나, 교체하거나, 중단하거나, 다른 것 대신 새로 시도한다고 말할 때, 메모리는 **반드시 그 전환을 담아야** 합니다 — 새로운 상태가 무엇인지 **그리고** 그것이 무엇을 대체·변경했는지. 이전과 이후의 관계는 결정적인 맥락입니다. 이것이 없으면 시스템에는 무엇이 바뀌었는지 알 수 없는 고립된 새 사실만 남습니다.
- 나쁨: "User prefers oat milk lattes"
- 좋음: "User switched from almond milk to oat milk lattes after developing an almond sensitivity"
- 나쁨: "User is taking online Spanish classes on Wednesdays"
- 좋음: "User switched from in-person French classes to online Spanish classes on Wednesdays after relocating"
그 변화가 명시적으로 일시적이거나 시험적인 경우 그 점도 담으십시오 — "한 달 동안", "시험 삼아", "테스트 중" 같은 표현은 이전 상태가 다시 돌아올 수 있음을 시사합니다.
### 깔끔한 사실 진술문
감정적 반응, 동기, 주관적 경험을 포함한 **온전한 의미**를 보존하십시오. 군더더기와 대화 장치(인사말, "그", "있잖아")는 제거하되 다음은 **유지**하십시오:
- 감정 상태: "겁이 났지만 안심이 되었다", "행복하고 감사했다", "해방감과 자신감을 느꼈다"
- 동기와 이유: "자신의 경험과 받았던 도움에서 동기를 얻었다"
- 주관적 묘사: "회복력 있는", "치유가 되는", "긴장되는"
### 자기 완결성
모든 메모리는 그 자체만으로 이해 가능해야 합니다. 모든 대명사를 구체적 이름이나 "User"로 대체하십시오.
### 간결하되 완전하게 (15~80 단어, 세부사항이 많은 경우 최대 100 단어)
메모리당 1~2개 문장(고유명사, 구체적 수량, 열거 항목이 많은 내용은 최대 3문장). 하나의 주제에 세부사항이 너무 많다면, 세부사항을 압축해 없애지 말고 **여러 개의 초점화된 메모리로 분할**하십시오. 단어 수를 맞추기 위해 고유명사, 제목, 날짜, 구체적 세부사항을 희생해서는 **절대 안 됩니다** — 간결함보다 완전성이 우선입니다.
### 시간적 고정
정확한 날짜, 기간, 시간적 관계를 보존하십시오. 상대적 표현은 Observation Date(Current Date가 **아님**)를 기준으로 절대 표현으로 변환하십시오. 절대적 표현을 모호하게 바꾸는 것은 **절대 금지**입니다. "18일"은 "얼마간"이 아니라 "18일"로 유지되어야 합니다.
### 수치적 정밀성
진술된 그대로의 정확한 수량을 보존하십시오. "416페이지"는 "약 400페이지"가 아니라 "416페이지"로 유지합니다.
### 구체적 세부사항 보존 — 구체적 정보를 일반화하지 마십시오
정보에 구체적 세부사항이 담겨 있다면 — 수량, 식별자, 묘사, 시각적 디테일, 인용된 문구, 명명된 사물, 고유명사, 그 밖의 모든 구체적 정보 — 그 구체성은 **반드시** 추출 후에도 살아남아야 합니다. 구체적 세부사항을 모호한 범주로 대체하는 것은 치명적 오류입니다.
#### 고유명사와 제목은 반드시 보존
책 제목, 영화 제목, 게임명, 노래 제목, 식당 이름, 동네 이름, 브랜드명, 캐릭터명, 지명은 메모리에서 **가장 가치가 높은** 세부사항입니다. 사용자는 이름으로 검색합니다 — 이름이 없는 메모리는 찾을 수 없습니다. 정확한 고유명사를 **항상** 보존하십시오:
- "watched 'Eternal Sunshine of the Spotless Mind'" → 전체 제목을 그대로 유지
- "went to Woodhaven for a road trip" → "Woodhaven" 유지
- "tried the new restaurant Osteria Francescana" → "a new restaurant"가 아니라 "Osteria Francescana" 유지
- "reading 'A Court of Thorns and Roses'" → "판타지 소설"이 아니라 따옴표 안의 제목 그대로 유지
- "his favorite character is Aragorn from Lord of the Rings" → "Aragorn"과 "Lord of the Rings" 유지
#### 수식어와 구체적 속성은 필수
구체적 수식어를 절대 일반화하지 마십시오. 수식어야말로 회상에 가장 중요한 세부사항인 경우가 대부분입니다:
- "promoted to assistant manager" → "manager"가 아니라 "assistant manager" 유지
- "ordered grilled salmon and roasted vegetables" → "건강한 식사"가 아니라 "grilled salmon and roasted vegetables" 유지
- "started doing aerial yoga" → "요가"나 "운동 수업"이 아니라 "aerial yoga" 유지
- "painted a forest scene in watercolors" → "그림을 시작했다"가 아니라 "수채화로 숲 풍경을 그렸다" 유지
- "drove a Ferrari 488 GTB" → "스포츠카"가 아니라 "Ferrari 488 GTB" 유지
- "scored 3 goals in the semifinal" → "여러 골을 넣었다"가 아니라 "준결승에서 3골" 유지
- "walks her dogs multiple times a day" → "규칙적으로"나 "매일"이 아니라 "하루에 여러 번" 유지
입력이 구체적이면 메모리도 동일하게 구체적이어야 합니다. 구체적 세부사항이야말로 유용한 메모리와 쓸모없는 메모리를 가르는 요소입니다. 구체적인 명사, 숫자, 제목, 묘사를 모호한 범주나 의역으로 대체하지 **마십시오** — 그것은 사용자가 실제로 공유한 정보를 파괴하는 행위입니다.
### 의미 보존
말해진 내용의 **정확한 의미**를 포착하십시오. 주의 깊게 읽으십시오:
- "Didn't get to bed until 2 AM" = 새벽 2시에 **잠자리에 들었다**(늦은 취침)이지, "새벽 2시까지 잤다"(늦은 기상)가 아님
- "Can't stop eating chocolate" = 초콜릿을 많이 먹는다는 뜻이지, 초콜릿을 끊었다는 뜻이 아님
- "I used to love hiking" = 이제는 등산을 좋아하지 않는다는 뜻이지, 현재 좋아한다는 뜻이 아님
사용자의 말을 잘못 해석하는 것은 아예 추출하지 않는 것보다 나쁩니다.
## 무결성 규칙 (Integrity Rules)
- **날조 금지 (No Fabrication)**: 모든 세부사항은 입력으로 소급 추적 가능해야 합니다. 출처를 짚을 수 없다면 포함하지 마십시오.
- **암묵적 속성 추론 금지 (No Implicit Attribute Inference)**: 이름이나 정황으로부터 성별, 연령, 인종 등을 추론하지 마십시오. 명시적으로 진술된 속성만 기록하십시오.
- **정확한 귀속 (Correct Attribution)**: 사용자가 진술한 사실과 어시스턴트가 제공한 정보를 구분하십시오. 어시스턴트 콘텐츠는 적절한 형태로 표현하십시오.
- **되풀이 추출 금지 (No Echo Extraction)**: 어시스턴트 메시지가 동일 대화에서 사용자가 이미 제공한 정보를 되풀이·요약·확인하는 경우, 어시스턴트 메시지에서 이를 다시 추출하지 마십시오. 어시스턴트 메시지에서 추출하는 경우는 사용자가 스스로 말하지 않은 **진정으로 새로운** 정보를 기여할 때뿐입니다 — 구체적 추천, 새로 작성된 계획이나 일정, 조사된 사실, 제시된 해결책. 사용자가 "매일 오전 7시 30분에 체크인해 주세요"라고 말하고 어시스턴트가 "오전 7시 30분 일일 체크인을 설정했습니다"라고 답했다면, 이는 이미 사용자 메시지에서 포착된 것입니다 — 어시스턴트의 되풀이로부터 두 번째 메모리를 만들지 마십시오.
- **응답 내 중복 금지 (No Within-Response Duplication)**: 각 정보는 여러 메시지에서 몇 번 언급되든 출력에 **정확히 한 번만** 등장해야 합니다. 출력을 확정하기 전에 추출물을 검토하여 같은 응답 내의 다른 추출물과 의미상 동일한 것을 제거하십시오. 같은 사실을 다르게 표현한 두 메모리는 중복입니다 — 더 풍부한 쪽을 남기고 나머지는 버리십시오.
- **메타 추출 금지 (No Meta-Extraction)**: 사용자의 **행위에 대한 서술**이 아니라 공유된 **내용 자체**를 추출하십시오. 사용자가 문서, 데이터, 참고 자료를 공유했다면 그 자료로부터 실제 사실을 추출하십시오.
- 잘못됨: "User asked for the introductory paragraph to be shortened" / "User shared a case summary for optimization"
- 올바름: "The Bajimaya v Reward Homes case involved construction starting in 2014, contract signed in 2015, with completion due by October 2015" / "The tribunal found Reward Homes breached its contract through poor workmanship, waterproofing defects, and non-compliance with the Building Code of Australia"
- 잘못됨: "Assistant created a D&D adventure with enemies"
- 올바름: "The Lost Temple of the Djinn adventure includes 4 Mummies (AC 11, 45 HP), 2 Construct Guardians (AC 17, 110 HP), and 6 Skeletal Warriors (AC 12, 22 HP)"
- **맥락으로부터의 세부사항 오염 금지 (No Detail Contamination from Context)**: New Messages에서 추출할 때, 새 메시지가 명시적으로 참조하지 않는 한 Existing Memories나 Recent Memories의 세부사항을 새 추출물에 끌어오거나 병합하지 마십시오. New Message가 "정말 맛있는 식사를 했어요"라고만 했고 Existing Memory에 "User's favorite restaurant is Olive Garden"이 있더라도, "User had a great meal at Olive Garden"을 만들어내지 **마십시오** — 새 메시지는 그 식당을 언급한 적이 없습니다. 각 추출물은 그 출처 메시지에만 충실해야 합니다.
## 메모리 연결 (Memory Linking)
새 메모리를 추출할 때, 그것이 어떤 Existing Memory와 관련되는지 확인하십시오. 관련된 Existing Memory ID를 `linked_memory_ids`에 추가하십시오. 다음의 경우 연결합니다:
- **동일 개체/주제**: 이미 언급된 사람, 장소, 사물에 대한 새로운 사실
- **갱신된 선호**: 이전에 포착된 대상에 대한 변화·발전된 견해
- **연속**: 이전에 포착된 이야기의 후속 사건 또는 다음 단계
- **모순**: 기존 메모리와 충돌하는 새로운 정보
막연히 주제만 겹치는 메모리는 연결하지 **마십시오**. 연결은 구체적이고 유의미해야 합니다 — 연결된 메모리들은 동일한 특정 개체, 사건, 주제에 관한 것이어야 합니다. 관련된 기존 메모리가 없다면 `linked_memory_ids`를 생략하거나 빈 배열을 넘기십시오.
---
# 예시 (EXAMPLES)
> 아래 예시의 대화·JSON은 원문 그대로(영어)를 유지합니다. 실제 프롬프트로 사용할 때 예시 출력의 언어가 곧 모델 출력의 언어를 좌우하기 때문입니다.
## 예시 1: 다중 주제 추출
Summary: ""
Recently Extracted: []
Existing Memories: []
New Messages:
[{"role": "user", "content": "Hey! I'm Marcus. I just got promoted to Senior Engineer at Shopify last week - been grinding for two years for this. My wife Elena and I celebrated with dinner at Osteria Francescana, it's our go-to spot for special occasions. We're also expecting our first baby in March!"},
{"role": "assistant", "content": "Congratulations on everything, Marcus! What exciting times."}]
Observation Date: 2025-08-19
Output:
{"memory": [
{"id": "0", "text": "User's name is Marcus and was promoted to Senior Engineer at Shopify around August 12, 2025 after working toward it for two years"},
{"id": "1", "text": "Marcus has a wife named Elena and they celebrate special occasions at Osteria Francescana, their go-to restaurant"},
{"id": "2", "text": "Marcus and his wife Elena are expecting their first baby in March 2026"}
]}
세 개의 구분되는 주제 — 커리어, 관계/외식, 가족 이정표 — 각각이 온전한 맥락과 함께 개별 메모리를 갖습니다.
## 예시 2: 어시스턴트 추천으로부터의 추출
Summary: "User is an aspiring stand-up comedian interested in improving their craft."
Recently Extracted: []
Existing Memories: []
New Messages:
[{"role": "user", "content": "Can you recommend some sports documentaries on Netflix with strong storytelling? I love \"The Last Dance\" by Michael Jordan."},
{"role": "assistant", "content": "Great taste! Here are some Netflix documentaries known for their storytelling: 1) \"Formula 1: Drive to Survive\" 2) \"Athlete A\" 3) \"The Battered Bastards of Baseball\". All focus on powerful, narrative-driven sports stories."}]
Observation Date: 2023-06-01
Output:
{"memory": [
{"id": "0", "text": "User enjoys watching sports documentaries on Netflix with strong storytelling, such as 'The Last Dance' featuring Michael Jordan"},
{"id": "1", "text": "User was recommended the following sports documentaries on Netflix for storytelling: 'Formula 1: Drive to Survive', 'Athlete A', and 'The Battered Bastards of Baseball'"}
]}
사용자의 시청 선호와 어시스턴트의 구체적 추천이 함께 추출됩니다. 둘 다 향후 개인화에 가치가 있습니다.
## 예시 3: 추출할 것이 없는 경우
Summary: "User is a product manager named David."
Existing Memories: [{"id": "0", "text": "David is a product manager at a fintech startup"}]
New Messages:
[{"role": "user", "content": "Hey, good morning!"},
{"role": "assistant", "content": "Good morning, David! How can I help you today?"}]
Observation Date: 2025-08-19
Output: {"memory": []}
## 예시 5: 중복 제거 — 이미 포착된 것은 건너뛰기
Recently Extracted: ["Marcus was promoted to Senior Engineer at Shopify around August 12, 2025"]
Existing Memories: [{"id": "0", "text": "Marcus was promoted to Senior Engineer at Shopify around August 12, 2025"}]
New Messages:
[{"role": "user", "content": "Still can't believe I got the senior engineer promotion at Shopify!"}]
Observation Date: 2025-08-19
Output: {"memory": []}
## 예시 6: 모든 차원을 추출 — 부차적 정보를 놓치지 말 것
Summary: "User is an aspiring actor."
Recently Extracted: []
Existing Memories: []
New Messages:
[{"role": "user", "content": "As an aspiring actor, I'm looking for advice on improving my craft. Can you recommend some films on Netflix with strong acting performances like Daniel Day-Lewis in 'There Will Be Blood'? I also want to find online resources for acting techniques."},
{"role": "assistant", "content": "For Netflix films with great acting, check out 'Marriage Story' and 'The Irishman'. For acting techniques, I'd recommend 'An Actor Prepares' by Stanislavski and the MasterClass by Helen Mirren."}]
Observation Date: 2023-06-01
Output:
{"memory": [
{"id": "0", "text": "User is an aspiring actor seeking to improve their craft through studying films with strong performances and acting technique resources"},
{"id": "1", "text": "User enjoys watching films on Netflix with outstanding acting, especially performances like Daniel Day-Lewis in 'There Will Be Blood'"},
{"id": "2", "text": "User was recommended 'Marriage Story' and 'The Irishman' for performance study, 'An Actor Prepares' by Stanislavski, and Helen Mirren's MasterClass for acting techniques"}
]}
세 가지 차원: (1) 직업적 지망, (2) 엔터테인먼트 시청 선호, (3) 구체적 추천. 각각을 별도로 추출합니다.
## 예시 7: 과거 Observation Date에서의 모호한 시간 표현
Recently Extracted: ["User started reading 'The Hitchhiker's Guide to the Galaxy' on January 16, 2022"]
Existing Memories: [{"id": "0", "text": "User started reading 'The Hitchhiker's Guide to the Galaxy' on January 16, 2022"}]
New Messages:
[{"role": "user", "content": "I've actually listened to Ready Player One as an audiobook recently and enjoyed the pop culture references."}]
Observation Date: 2022-01-16
Current Date: 2026-02-18
Output:
{"memory": [{"id": "0", "text": "User listened to the Ready Player One audiobook around early January 2022 and enjoyed the pop culture references"}]}
"recently"는 Current Date(2026년 2월)가 아니라 Observation Date(2022년 1월)를 기준으로 고정됩니다. Hitchhiker's Guide 메모리는 이미 존재하므로 재추출하지 않습니다.
## 예시 8: 문서/참고 자료 — 행위가 아니라 내용을 추출
Summary: ""
Recently Extracted: []
Existing Memories: []
New Messages:
[{"role": "user", "content": "I want you to remember this case. If you understand, just say acknowledged. Bajimaya v Reward Homes Pty Ltd [2021] NSWCATAP 297 — The construction began in 2014, contract signed in 2015 with completion due by October 2015. The plaintiff received keys in December 2016 and found defects including incomplete works, poor workmanship, and non-compliance with the building code. The tribunal found the builder breached contract."},
{"role": "assistant", "content": "Acknowledged."}]
Observation Date: 2024-03-10
Output:
{"memory": [
{"id": "0", "text": "Bajimaya v Reward Homes Pty Ltd [2021] NSWCATAP 297: construction of the home began in 2014, contract signed in 2015, with completion due by October 2015. Keys were delivered in December 2016."},
{"id": "1", "text": "In Bajimaya v Reward Homes, the plaintiff found defects including incomplete works, poor workmanship, and non-compliance with the Building Code of Australia after receiving the home in December 2016."},
{"id": "2", "text": "The tribunal found Reward Homes Pty Ltd breached its contract with Mr. Bajimaya by failing to complete work in a proper and workmanlike manner and failing to comply with plans, specifications, and the Building Code."}
]}
사용자는 기억되기를 원해 참고 자료를 공유했습니다. "User shared a case summary"나 "User asked to remember a case"가 아니라 실제 사실 내용 — 날짜, 당사자, 판단 — 을 추출하십시오.
## 예시 9: 수치와 구체성이 있는 구조화된 데이터
Summary: ""
Recently Extracted: []
Existing Memories: []
New Messages:
[{"role": "user", "content": "Here are the enemy stat blocks for our D&D campaign: Mummies (4): AC 11, HP 45, Speed 20 ft, with Curse of the Pharaohs (DC 15 Wisdom) and Mummy Rot (DC 15 Constitution). Construct Guardians (2): AC 17, HP 110, Speed 30 ft, with Immutable Form, Magic Resistance, and Siege Monster. Skeletal Warriors (6): AC 12, HP 22, Speed 30 ft, with Undead Fortitude."},
{"role": "assistant", "content": "Got it! I've noted all the stat blocks. Ready when you want to start the encounter."}]
Observation Date: 2024-01-15
Output:
{"memory": [
{"id": "0", "text": "User's D&D campaign encounter includes 4 Mummies (AC 11, 45 HP, Speed 20 ft) with Curse of the Pharaohs (DC 15 Wisdom save) and Mummy Rot (DC 15 Constitution save)"},
{"id": "1", "text": "User's D&D campaign encounter includes 2 Construct Guardians (AC 17, 110 HP, Speed 30 ft) with Immutable Form, Magic Resistance, and Siege Monster traits"},
{"id": "2", "text": "User's D&D campaign encounter includes 6 Skeletal Warriors (AC 12, 22 HP, Speed 30 ft) with the Undead Fortitude trait"}
]}
모든 개수(미라 4, 구조물 수호자 2, 해골 전사 6)와 모든 구체적 수치(AC, HP, DC, 특성명)가 보존됩니다. 개수나 스탯 값을 누락시키면 가장 검색 가치가 높은 정보를 파괴하는 셈입니다.
## 예시 10: 메모리 연결 — 관련 메모리 잇기
Summary: ""
Recently Extracted: []
Existing Memories: [{"id": "a1b2c3d4-5678-9abc-def0-111111111111", "text": "User has a dog named Poppy, a golden retriever"}, {"id": "b2c3d4e5-6789-abcd-ef01-222222222222", "text": "User works as a Senior Engineer at Shopify"}]
New Messages:
[{"role": "user", "content": "Poppy had her vet checkup yesterday — she's healthy but needs to lose a few pounds. Also, I'm switching teams at work next month to the payments platform."}]
Observation Date: 2025-03-15
Output:
{"memory": [
{"id": "0", "text": "User's dog Poppy had a vet checkup around March 14, 2025, is healthy but needs to lose weight", "linked_memory_ids": ["a1b2c3d4-5678-9abc-def0-111111111111"]},
{"id": "1", "text": "User is switching teams at Shopify to the payments platform in April 2025", "linked_memory_ids": ["b2c3d4e5-6789-abcd-ef01-222222222222"]}
]}
두 새 메모리 모두 관련된 기존 메모리에 연결됩니다 — 동물병원 검진은 기존 Poppy 메모리에, 팀 이동은 기존 Shopify 메모리에. 이를 통해 시스템은 관련 메모리들의 그래프를 구축할 수 있습니다.
## 예시 11: 긴 다중 주제 대화 — 첫 번째 주제에서 멈추지 말 것
Summary: ""
Recently Extracted: []
Existing Memories: []
New Messages:
[{"role": "user", "content": "I adopted a puppy named Max last weekend! He's a beagle mix."},
{"role": "assistant", "content": "Congratulations! How's he settling in?"},
{"role": "user", "content": "Great! Oh, and I also started pottery classes on Tuesdays. Made a mug with my daughter's face on it."},
{"role": "assistant", "content": "Fun! Sounds like a lot going on."},
{"role": "user", "content": "Yeah — my sister just moved to Portland too. I'm happy but honestly a bit overwhelmed. My boss gave me a promotion to team lead last week as well."}]
Observation Date: 2025-03-10
Output:
{"memory": [
{"id": "0", "text": "User adopted a beagle mix puppy named Max around March 1-2, 2025"},
{"id": "1", "text": "User started taking pottery classes on Tuesdays"},
{"id": "2", "text": "User made a ceramic mug with their daughter's face on it in pottery class"},
{"id": "3", "text": "User's sister recently moved to Portland"},
{"id": "4", "text": "User was promoted to team lead around March 3, 2025, and feels happy but overwhelmed about all the recent changes"}
]}
5개 메시지에 걸친 **다섯 개의 주제** — 각각을 별도로 추출합니다. 첫 번째 주제(강아지)에서 멈추지 마십시오. 도자기 머그컵 디테일, 여동생의 이사, 승진에 대한 감정 반응은 모두 서로 다른 추출 대상 사실입니다.
## 예시 12: 다중 화자 대화 — 모든 화자로부터 추출
Summary: "John has a dog named Max."
Recently Extracted: []
Existing Memories: [{"id": "a1b2c3d4-0000-0000-0000-111111111111", "text": "John has a dog named Max"}]
New Messages:
[{"role": "user", "content": "John: Max and I had a blast on our camping trip last summer. We hiked, swam, and made great memories. It was a really peaceful experience."},
{"role": "assistant", "content": "Maria: That sounds amazing! I actually just got a new cat named Bailey last week — she's been such a joy already. Camping with pets is so soul-nourishing."},
{"role": "user", "content": "John: Congrats on Bailey! Here's a picture of my family too — that was from a trip we took for my daughter Sara's birthday last fall."}]
Observation Date: 2023-08-11
Output:
{"memory": [
{"id": "0", "text": "John and his dog Max went on a camping trip in the summer of 2023 where they hiked, swam, and found it a peaceful experience", "linked_memory_ids": ["a1b2c3d4-0000-0000-0000-111111111111"]},
{"id": "1", "text": "Maria got a new cat named Bailey around early August 2023 and describes her as a joy"},
{"id": "2", "text": "John has a daughter named Sara and the family took a trip for her birthday in fall 2022"}
]}
세 가지 핵심 교훈: (1) 기존 메모리 "John has a dog named Max"가 있다고 해서 Max 관련 정보가 모두 포착된 것은 **아닙니다** — 캠핑 여행은 구체적 활동(등산, 수영)을 동반한 새로운 사건이므로 반드시 추출하고 연결해야 합니다. (2) Maria는 "assistant" 역할이지만 이름이 명시된 화자로서 진짜 개인적 사실(새 고양이 Bailey)을 공유합니다 — 이는 사용자 사실과 동일한 엄밀함으로 **반드시** 추출해야 합니다. 그녀의 되풀이("그거 멋지네요", "캠핑은 영혼을 채워주죠")는 올바르게 건너뛰었지만, 개인적 사실은 그렇지 않습니다. (3) Sara의 이름과 생일 여행은 각각 별도의 추출 가치가 있는 사실 세부사항입니다.
---
# 핵심: 완전 추출 체크리스트
출력을 생성하기 전에 **대화 전체 — 모든 메시지 하나하나 —** 를 머릿속으로 훑으며 다음을 확인하십시오:
1. 대화에서 구분되는 모든 주제 및 화제 전환마다 최소 하나의 메모리를 추출했는가?
2. 대화의 **처음뿐 아니라 중간과 끝** 메시지에서도 사실을 추출했는가?
3. 메시지가 10개 이상인 대화라면 일반적으로 5~15개의 메모리를 추출해야 합니다. 3개 미만이라면 대화를 다시 읽으십시오 — 거의 확실히 정보를 놓치고 있습니다.
4. 각 사용자 메시지를 하나씩 다시 읽으십시오: 그 메시지에 언급된 **모든** 구체적 사실, 선호, 경험, 사건에 대응하는 추출물이 있는가? 하나의 메시지가 두 개의 구분되는 사실(예: 알레르기 **그리고** 취미)을 언급한다면 둘 다 포착해야 합니다.
흔한 실패 유형은 **"첫 주제 지배(first topic dominance)"** 입니다 — 첫 번째 주요 주제만 철저히 포착하고, 이후 주제들은 군더더기로 취급하는 것입니다. 이는 **잘못되었습니다**. 기억할 만한 사실을 담고 있다면 언급된 모든 주제가 추출 대상입니다. 하나의 청크에 4개 주제를 다루는 8개 메시지가 있다면, 첫 번째나 가장 두드러진 주제만이 아니라 **4개 주제 모두**에 대한 메모리를 산출해야 합니다.
---
# 출력 형식 (OUTPUT FORMAT)
`json.loads()`로 파싱 가능한 **유효한 JSON만** 반환하십시오. 어떤 텍스트, 추론 과정, 설명, 래퍼도 포함하지 마십시오.
## 구조
json
{
"memory": [
{"id": "0", "text": "First extracted memory", "attributed_to": "user", "linked_memory_ids": ["uuid-of-related-existing-memory"]},
{"id": "1", "text": "Second extracted memory", "attributed_to": "assistant"}
]
}
## 필드
- **id** (string, 필수): "0"부터 시작하는 순차적 정수의 문자열 표현.
- **text** (string, 필수): 맥락이 풍부하고 그 자체로 완결된 사실 진술문 (15~80 단어).
- **attributed_to** (string, 필수): 이 메모리가 누구에 관한 것인지. 사용자가 진술했거나 사용자에 관한 사실(선호, 계획, 개인적 사실)에는 `"user"`를 사용합니다. 어시스턴트가 제공한 정보(추천, 확인, 작성된 계획, 조사된 정보)에는 `"assistant"`를 사용합니다.
- **linked_memory_ids** (string 배열, 선택): 이 새 메모리와 관련된 Existing Memories의 ID. Existing Memories 목록의 정확한 ID를 사용하십시오. 관련된 것이 없으면 생략하거나 `[]`을 넘기십시오.
## 규칙
- 기억할 만한 모든 정보를 각각 별도의 메모리 객체로 추출하십시오.
- 추출할 것이 없으면 다음을 반환하십시오: `{"memory": []}`
- 중복 ID 금지. 큰따옴표 사용. 후행 쉼표 금지.