coredot.today
기술 탐색으로 돌아가기
에이전트 기억실험

SodaMem

모든 기억에 원문 영수증을 붙이고, 바뀐 사실은 지우지 않고 닫는 시간 그래프 기억 — 단, 92.8%를 낸 저장소에서 대체는 꺼져 있었다

직접 해보기 7실측
종류
오픈소스
라이선스
Apache-2.0
언어
Python
사실 확인
2026.11.01

TRY IT

직접 해보기

OVERVIEW

개요

무엇인가

SodaMem은 2026년 8월 8일 arXiv에 올라온 「SodaMem: Evidence-Grounded Temporal Graph Memory for LLM Agents」(arXiv 2608.08055)와 같은 이름의 오픈소스 기억 엔진입니다(Apache-2.0, 저장소는 논문보다 하루 먼저 공개, v0.1.1). 논문 첫 문장이 목표를 요약합니다. 몇 주에 걸쳐 사용자를 돕는 에이전트는 한때 말해진 것이 아니라 지금 참인 것을 기억해야 한다는 것입니다.

기억의 단위는 원문 조각이 반드시 붙은 사실 카드(FactEvent)이고, 카드들은 시간 그래프로 쌓입니다. 사실마다 출처를 달고(출처), 일어난 때·참이었던 때·말한 때를 따로 적고(시간), 사실이 바뀌면 옛 카드를 지우지 않고 유효기간을 닫습니다(대체). 답할 때는 플래너가 증거를 먼저 모으고 리더가 인용을 달아 씁니다. README의 표현으로는 "모든 기억은 영수증을 갖고 다닌다". 논문은 LongMemEval-S 500문항에서 92.8%, 문항당 평균 0.161센트(약 1.8만 토큰)를 보고했습니다. 플래너·리더·채점자가 모두 deepseek-v4-flash입니다. MCP 서버, LangGraph·CrewAI·OpenAI Agents SDK 어댑터, TypeScript SDK도 함께 나와 있습니다.

어떻게 동작하나

넣기
LLM 추출기 → 출처 검사 → 상대 날짜를 세션 날짜 기준 절대 날짜로
→
쌓기
FactEvent 노드 + SUPERSEDES·CONTRADICTS·UPDATES·DERIVED_FROM 엣지, BM25·벡터 이중 색인 (SQLite 한 파일)
→
답하기
세 터널 검색 → 플래너가 도구로 증거 보강 → 리더가 인용 달아 답
  • 사실 카드 일곱 칸. 종류(사실·상태·선호·사건), 술어(user_lives_in_oahu 같은 짧은 영어 식별자), 양상(지난 사건·현재 상태·계획·비서의 조언·바깥 정보), 시간, 역할(누가·어디서), 출처 조각, 상태(유효·대체됨·무효). 시간은 README 기준 네 개의 시계(일어난 때·참이었던 때·말한 때·저장한 때)로 적습니다. "작년에 이사했어"와 "내년에 이사할 거야"를 같은 날 말해도 구분됩니다.
  • 출처 강제. 증거 사슬은 FactEvent → SourceSpan → RawTurn의 외래 키입니다. LLM이 댄 조각 번호가 틀리면 함께 준 인용문(6자 이상)으로 복구하고, 두 조각 이상에 들어 있으면 "모호하면 추측하지 않는다"며 버리고, 글자 일치가 없으면 단어 토큰이 80% 이상 겹치는 조각을 찾습니다. "줄이는 중"을 "싫어한다"로 바꿔 적은 카드는 출처를 못 찾아 들어오지 못합니다.
  • 대체. 같은 주어–술어 슬롯에서 경쟁하는 새 사실이 오면 옛 사실의 상태를 '대체됨'으로, valid_until을 새 사실의 효력 시각으로 닫습니다(추가만 하는 정정). 슬롯 판정은 결정론적 규칙입니다. 비서의 말은 사용자의 말에서 나온 사실을 대체하지 못하고, 선호는 now·currently·instead·moved 같은 갱신 표지가 있을 때만 대체합니다. 순서는 사건·유효 시각, 그다음 말한 때, 동점이면 내용 해시입니다.
  • 세 터널과 연결 밀도. 그래프·엔터티 터널과 BM25 터널(강), 임베딩 터널(약)이 터널마다 검색 머리 최대 10개로 찾고, 여러 길에서 함께 걸린 증거를 위로 올립니다. 검색에는 LLM 호출이 없습니다.
적중 종류강한 터널 (그래프·BM25)약한 터널 (임베딩)
직접 적중0.40.2
파생 적중 (넓혀서 찾음)0.10.05
시간 창과 겹치면+0.3 (β, 증거 하나에 한 번). 창은 거르는 문이 아니라 가산점

시간을 문이 아니라 가산점으로 쓰는 이유는 사람이 날짜를 틀리게 기억하기 때문입니다(석 달 전을 "두 달 전"이라고 말한다). 딱딱하게 거르는 것은 무효·대체된 사실과, 유효 기간이 알려져 있는데 창과 어긋나는 사실뿐입니다. 플래너는 검색·세션 펼치기·시간선·세기·계산 도구를 단계 예산 안에서 부르고, 리더는 고른 증거 ID만 보고 인용을 달아 답합니다.

빠른 시작

설치 명령은 원 글에서 다루지 않았습니다. 대신 저장소가 공개한 벤치마크 답안으로 숫자를 직접 확인하는 길이 열려 있습니다. README가 "아무 채점자로나 다시 채점하고, 검색 결과를 당신의 리더에게 줘 보라"고 권하는 그 절차입니다.

1저장소 benchmarking/artifacts/에서 답안 500개(sodamem_lme_judged.json)와 검색 결과 8,427행(sodamem_lme_retrieved_context.json)을 받습니다.
2LongMemEval 공식 evaluate_qa.py의 문항 유형별 채점 템플릿을 고치지 않고, 답한 모델과 다른 채점 모델로 다시 채점합니다.
3채점자끼리 엇갈린 문항은 다수결 대신 사람이 읽어 판정합니다.
4검색 결과를 자기 리더 모델에 질문 날짜와 함께 읽혀, 저장소와 리더의 몫을 나눠 봅니다.

코어닷투데이 실측

2026년 11월 1일, 유료 API 없이 로컬 머신과 사내 A100에서 Qwen 모델로 쟀습니다.

공개 답안 500개 다시 채점. 답안은 그대로 두고 LongMemEval 공식 템플릿으로 채점자만 바꿨습니다.

채점자정답 수정확도
DeepSeek v4 Flash (자기 채점, 논문)46492.8%
Qwen 3.8 27B44388.6%
Qwen 3.5 9B44488.8%
엇갈린 21문항을 사람이 판정448~45089.6~90.0%
  • DeepSeek와 Qwen 27B가 엇갈린 21문항은 전부 DeepSeek만 정답으로 본 문항이었습니다. 직접 읽으니 14개는 실제로 틀린 답(그중 9개가 시간 추론), 5개는 실제로 맞음, 2개는 애매했습니다. 둘 다 오답으로 본 36문항에는 숨은 정답이 없었습니다.
  • 잘못 통과한 답안은 길었습니다(중앙값 1,067자 대 672자). 사람 판정을 반영하면 시간 추론이 94.7%에서 88.0%로 가장 크게 내려갑니다.

같은 검색 결과를 Qwen 3.5 9B가 읽으면 356/500(71.2%), Qwen 27B 채점 기준으로 SodaMem 답안(88.6%)보다 17점 낮았습니다. 한 세션·비서 문항은 98.2%로 같았지만 시간 추론과 다중 세션은 59.4%였습니다. 공개 검색 결과에는 플래너의 세기·기간 계산 결과가 없고 증거 행 절반(4,278행)에 날짜가 없어, "9B가 17점 못하다"가 아니라 정답률이 저장소 혼자 내는 숫자가 아니라는 뜻으로 읽어야 합니다.

리더 지침 한 문장 지우기. "가장 최근의 직접적인 사용자 발화를 우선하라"가 지식 갱신을 지킨다고 짐작하고, 9B 리더로 지식 갱신 78문항에서 그 문장만 지웠습니다. 결과는 62 대 62, 맞고 틀린 문항까지 같았습니다(답안 문구는 58개가 바뀜). 짐작은 틀렸습니다.

공개 장부 세기. 검색 결과 8,427행의 상태는 전부 active였고 valid_until이 채워진 행은 6개뿐이었습니다. 토큰 기록으로 다시 계산한 비용은 논문과 소수점 다섯째 자리까지 같았습니다(입력의 53%가 캐시 적중).

한국어·영어 12턴 직접 실행. 공개 코드 v0.1.1 기본 설정, 추출·플래너·리더 모두 Qwen 3.5 9B, 6세션(망원동 거주·매운 음식·판교 출근 → 위염·이사·고양이·퇴사), 언어별 한 번씩입니다.

확인한 것한국어영어
BM25 토큰0개 (6개 세션 모두)정상
옛 주소 '망원동'·옛 선호 '매운 음식'이 닫혔나둘 다 아니오둘 다 아니오
'신분당선 출근'이사 사실에 닫힘 (둘 다 사건 유형 travel)
끝단 답 5문항5개 모두 맞음4개, 위염 사용자에게 매운 김치찌개 권함
문항당 답변 시간 (A100)약 100~134초약 83~112초

망원동이 닫히지 않은 이유는 언어와 무관했습니다. 추출 모델이 live_in_mangwon_dong처럼 술어에 값을 섞어 지어 '같은 슬롯'으로 보이지 않았습니다. 대체 규칙은 결정론적이지만 그 입력인 술어와 사건 유형은 LLM이 짓습니다.

언제 쓰고, 언제 피하나

상황판단
"왜 나를 그렇게 생각해?"에 원문으로 답해야 함 (열람·정정 요구, 상담·돌봄 기록)출처 사슬과 이벤트 로그(/v1/events) 설계가 잘 맞는다
영어 대화, 싼 모델로 장기 기억쓸 만하다. 독립 채점 기준 약 90%
설계를 빌려 쓰기출처 강제, 비서 발화로 사용자 사실을 덮지 않기, 시간은 가산점으로. 엔진을 안 써도 가져갈 수 있다
한국어 서비스그대로는 피한다. BM25·출처 복구·갱신 표지·상대 날짜 네 곳을 고쳐야 한다
"3월에는 어디 살았지?" 같은 시점 질의search(as_of=…)는 아직 미구현이라 오류를 낸다
대화형 응답 속도가 중요공개 답안 기준 문항당 평균 18.5초, 최대 62초

한계와 주의

  • 92.8%를 낸 저장소는 대체를 '관찰만' 했습니다. 저장소 이름 longmemeval_s_500_Hobs_entitysubj의 obs는 observe-only입니다. 테스트 주석에 따르면 supersede_observed 기록 16,926건에 SUPERSEDES 엣지는 0건이고, CHANGELOG는 "어떤 배포도 아무것도 대체한 적이 없다"고 적었습니다. 플래그는 논문 이틀 전인 8월 6일에 지워졌습니다. 지식 갱신 97.4%(공개 답안, 자기 채점)는 대체가 아니라 리더가 낸 점수이고, 이 벤치마크로는 대체의 효과를 잴 수 없습니다.
  • 92.8%는 세 번 중 최고입니다. 논문이 밝힌 중앙값은 90.6%이고, 저장소 사양 문서(issue-24)의 중앙값·범위·표준편차 6.35에서 역산하면 세 점수는 453·453·464입니다. 리더·채점자가 같은 모델인 자기 채점이라 GPT-4o로 채점한 다른 시스템과 2~3점 차이는 비교가 어렵습니다.
  • 비용에 적재가 빠져 있습니다. 기록 약 11.5만 토큰을 같은 Flash 단가로 한 번 읽기만 해도 문항당 약 1.6센트로, 답변 비용(0.161센트)의 열 배입니다. 또 deepseek-v4-flash는 2026년 10월 말 퇴역해 V4.1-Flash로 연결되고 단가가 2~4배 올랐습니다. 결과를 낸 빌드는 공개 이력(v0.1.0) 이전 것이고, LoCoMo 86.88%는 답안이 공개되지 않아 검증할 수 없습니다.
  • 논문과 코드가 다른 곳. 연결 밀도는 단순 합(식 5)이 아니라 noisy-OR(1 − ∏(1 − w))이고, 거의 같은 증거 병합은 임베딩 유사도 θ가 아니라 결정론적 사건 지문입니다(코드의 0.8은 출처 복구의 겹침 기준). 융합 단계의 시간 창은 날짜 문자열(ISO 날짜, 'May 2026', 네 자리 연도)만 읽고 정렬 방향 δ는 쓰이지 않습니다. 흐릿한 시간 표현을 푸는 파서는 호출되지 않는 코드였다가 8월에 지워졌습니다.
  • 영어 밖에서는 부품이 조용히 꺼집니다. BM25와 출처 복구의 토크나이저는 한글을 토큰으로 만들지 못하고(CJK 지원은 한자 범위만, 출처 복구는 [a-z0-9]만), 오류나 경고 없이 넘어갑니다. 한국어 인용문은 출처 복구에서 곧장 버려집니다. 갱신 표지에도 '요즘·이제·사실은'이 없습니다.
  • 논문 그림 2는 표 1을 대신하지 못합니다. 1448×1086 래스터 이미지이고, 표에 없는 이름(TMem 등)이 있으며, SodaMem 별이 92.8%가 아니라 약 94% 높이에 찍혀 있고, 범례가 칠한 영역의 의미를 본문과 반대로 적었습니다. 소거 실험도 없어 출처 강제·세 터널·플래너 중 무엇이 몇 점을 냈는지 알 수 없습니다.
  • 그래도 위 사실 대부분은 저자들이 공개한 답안·검색 결과와 스스로의 실수를 적은 코드 주석으로 확인한 것입니다.

DEEP DIVE

더 깊이 읽기