에이전트의 기억이 계속 꼬이던 문제, 검색과 본문 사이에 ‘선별’ 한 칸을 넣으니 나아졌다
에이전트 녀석한테 며칠 전에 나눈 대화 좀 기억해 보라고 했더니 전혀 엉뚱한 잡소리만 주워섬겨서 뒷목을 잡았다…
모델이 아무리 똑똑해져도 세션이 길어지고 로그가 쌓이면 결국 ‘장기 기억(Long-term Memory)’의 벽에 부딪힌다. 컨텍스트 윈도우는 유한하고, 과거 기록은 기하급수적으로 불어나니까.
그런데 어제 r/openclaw에 이 골치 아픈 기억 상실증(?)을 기막히게 해결한 글이 올라왔다. 놀랍게도 글쓴이는 전문 AI 연구원도 아니고 일반 비전공자 유저였는데, 자기 개인 비서 에이전트의 기억 파이프라인을 바닥부터 세 번 뜯어고친 삽질기가 너무나 생생하고 실전적이어서 읽는 내내 무릎을 탁 쳤다(엔지니어링 짬바가 느껴지는 삽질기였다).
키워드에서 임베딩으로, 그리고 다시 막히다
글쓴이의 첫 번째 시도는 누구나 하는 흔한 방식이었다. 세션이 끝날 때마다 대화를 요약해서 날짜별 텍스트 파일로 저장하고, 다음 세션 켤 때 최근 1~2일 치 로그만 기본 프롬프트에 얹어주는 구조였다. 하지만 며칠만 지나도 한계가 바로 왔다. “지난주에 내가 뭐라고 했지?”를 찾으려면 유저가 직접 파일명을 지정해 주거나 키워드를 떠올려야 했다(이럴 거면 내가 메모장 열어보지 에이전트를 왜 쓰나 싶다).
그래서 글쓴이는 야심 차게 두 번째 단계로 벡터 임베딩 검색(RAG)을 붙였다. “이제 의미 기반으로 찰떡같이 찾아주겠지!” 하고 환호했지만… 결과는 처참한 대실패였다(물론 거대한 착각이었다).
실패의 양상이 아주 흥미롭다. 검색이 아예 안 되는 문제와, 엉뚱한 게 너무 잘 검색되는 문제가 세트로 터졌다.
- 리콜 게이트(Recall Gate) 먹통: 매 턴마다 “과거 기억을 뒤져야 할까?”를 판단하는 소형 판별 모델을 앞단에 세웠는데, 이 게이트가 도무지 열리질 않았다. 유저가 대놓고 과거 이야기를 꺼내도 “응 검색 안 해도 됨” 하고 쌩까버린 거다. 무조건 검색하도록 프롬프트를 풀 수도 있었지만, 두 번째 문제 때문에 그마저도 소용없었다.
- 환장의 검색 노이즈: 유저가 “지난번 도쿄 여행 얘기”를 물었는데, 코사인 유사도가 높다는 이유로 뜬금없이 “유저 성별/프로필” 청크가 1등으로 튀어나왔다. 벡터 임베딩은 수학적으로 ‘문장 구조나 단어의 의미적 유사도’만 볼 뿐, “지금 이 대화 흐름에 진짜 필요한 맥락인가?”는 전혀 구분하지 못한다. 그런데 임계값만 넘으면 유사도 순서대로 상위 청크를 본문 모델 컨텍스트에 무지성으로 때려 박으니, 에이전트가 헷갈려서 헛소리를 지껄일 수밖에 없었다.
비어 있던 세 번째 칸
여기서 글쓴이가 제시한 비유가 아주 기가 막힌다. 기억 시스템을 도서관에 빗댄 거다.
- 게이트키퍼 (문지기): “지금 손님이 과거 책을 찾으시는가?” 판단
- 사서 (벡터 검색): 서가에 달려가서 대충 관련 있어 보이는 후보 책 20권을 우르르 들고 옴
- 선별자 (리랭커): 사서가 가져온 20권을 빠르게 훑어보고, 지금 당장 필요한 알짜배기 5권만 칼같이 골라냄
- 전달자 (본문 모델): 최종 선별된 5권을 요약해서 답변에 활용
기존 파이프라인의 치명적인 구멍은 바로 3번 선별자(Reranker) 칸이 통째로 비어 있었다는 점이다!
사서가 먼지 구덩이에서 대충 집어 온 순서대로 5개를 골라 에이전트 밥상에 올려주니, 목차 한 줄짜리 쓰레기 청크나 엉뚱한 신상 정보가 상위권을 독점했던 거다.
글쓴이는 이 비어 있던 3번 자리에 가벼운 재순위화(Reranking) 전용 모델을 딱 앉혔다. 후보 청크 20개를 한 번에 받아놓고, 현재 대화와의 연관성과 맥락적 중요도를 다시 채점해서 순위를 뒤집는 역할이다. 여기선 최근 공개된 가벼운 모델인 Jev를 썼다는데, 글쓴이 말대로 모델 종류는 중요하지 않다. 그 자리에 ‘검증과 필터링’이라는 허들을 하나 뒀다는 사실 자체가 핵심이다.
숫자로 본 변화
글쓴이가 14개 실제 쿼리를 돌려 검증한 숫자를 보면 입이 떡 벌어진다.
| 지표 | 적용 전 | 적용 후 |
|---|---|---|
| 상위 5개 중 관련 결과 | 24.3% | 42.9% |
| 1등이 쓰레기였던 비율 | 78.6% | 21.4% |
| 1등이 재순위화로 바뀐 비율 | – | 92.9% |
| 지연 시간 | – | 약 1.1초 (20개 병렬 판정) |
| 쿼리당 비용 | – | 약 0.9원 |
가장 소름 돋는 숫자는 “1등이 쓰레기였던 비율”이 78.6%에서 21.4%로 수직 낙하했다는 점이다.
LLM은 컨텍스트 맨 앞머리에 주입되는 정보에 가장 큰 영향을 받는다(국룰이다). 1등 자리에 쓰레기 정보가 들어가는 걸 막아낸 것만으로도 에이전트의 헛소리가 싹 사라졌다. 심지어 20개 청크를 병렬로 쳐내느라 레이턴시는 고작 1.1초 늘어났고, 추가 비용은 쿼리당 1원도 안 든다(이 정도면 안 쓸 이유가 없다).
왜 주목할까
검색 엔지니어링이나 기업용 RAG를 다뤄본 사람이라면 “에이, 리랭킹(Reranking) 그거 원래 쓰던 거잖아”라고 할 수도 있다. 검색 업계에선 아주 고전적인 패턴이니까.
하지만 개인이 방구석에서 굴리는 로컬/개인용 에이전트의 기억 파이프라인에 이 구조를 정확한 위치에 꽂아 넣은 사례는 정말 드물다.
특히 마음에 드는 건 문제를 대하는 태도다. “임베딩 검색 써봤더니 쓰레기네, RAG 거품이다”라며 기술을 내팽개치지 않았다. 파이프라인을 4단계로 쪼개고, 어디가 뚫려 있는지 집요하게 디버깅해서 ‘비어 있던 3번 칸’을 찾아냈다. 이게 바로 진짜 엔지니어의 문제 해결 방식이다.
에이전트와 대화가 길어질수록 기억은 계속 쌓인다. 하지만 우리 지갑과 모델의 컨텍스트는 언제나 한정되어 있다. 결국 알짜배기 기억만 정제해서 밀어 넣어주는 ‘선별의 기술’이 에이전트의 수명을 결정한다. 화려한 최신 프론티어 모델로 갈아타기 전에, 내 에이전트의 기억 파이프라인에 3번 선별자가 일하고 있는지부터 점검해 볼 일이다.
원글: https://www.reddit.com/r/openclaw/comments/1wkscnj/memory_core_embeddings_was_useless_for_me_until/