MemKraft는 스스로의 필요성에 의해 만들기 시작한 AI 에이전트를 위한 통합 메모리 시스템이다. 대화를 하면 할수록 알아서 똑똑해진다. 이틀 전 v0.1 개발 후기를 올렸다.

런칭 이후 네 번의 추가적인 업데이트를 했다. 버전마다 구체적인 키워드 몇 개와 방향성을 던져주면, 리서치 에이전트가 해당 주제에 대한 선행 프로젝트들을 정리하고, 기획 에이전트가 설계 방향을 잡고, 개발 에이전트가 구현한다. 이후 버전당 십여 번의 이터레이션을 스스로 돌리며 다양한 시나리오에서 디버깅 후 배포까지 알아서 진행되었다.

일 년 전만 하더라도 이정도 프로젝트를 구현하려면 풀타임으로 최소 몇 달이 걸렸을 것 같은데, 내가 한 일은 업무나 이동 중 남는 시간에 제온이와 몇십 번의 채팅을 주고 받은 게 전부다. 일 년 뒤에는 개발환경이 얼마나 또 달라져 있을지 상상조차 어렵다.

버전 별 키워드를 간략하게 공유한다.

--

v0.2: 같은 질문, 다른 답

"어제 뭐 먹었어?"라고 물으면, 우리는 구글처럼 키워드를 매칭하지 않는다. 어제가 어떤 날이었는지, 누구와 있었는지를 먼저 떠올리고, 그 맥락 안에서 답이 올라온다. v0.2의 출발점은 이 관찰이었다. 같은 질문이라도 지금 내가 뭘 하고 있느냐에 따라 중요한 기억이 달라져야 한다. 그래서 Conway SMS라는 아이디어를 빌렸다. 검색 요청이 들어오면 현재 목표에 가중치를 매겨서, 같은 팩트라도 순위가 달라진다. 시험 기간에는 교과서 내용이 먼저 떠오르고, 여행 중에는 맛집 정보가 먼저 떠오르는 것처럼.

기억에는 타입을 줬다. 내가 누구인지, 무엇을 믿는지, 무엇을 겪었는지. 여덟 가지로 나눈 건 분류 자체가 목적이 아니라, 각각이 다른 속도로 흐려지기 때문이다. 내 이름은 십 년이 지나도 기억하지만, 오늘 아침 루틴은 다음 주면 희미해진다. 감쇠 곡선에 타입마다 다른 반감기를 줬다. 느리게 사라지는 것과 빠르게 사라지는 것을 구분하는 것만으로 기억의 질감이 달라졌다.

그리고 모순이라는 문제가 있었다. "A가 맞다"고 믿다가 "B가 맞다"는 증거를 만나면 사람은 혼란스러워하지만, 어쨌든 둘을 비교하고 판단한다. MemKraft도 그래야 했다. 두 팩트의 유사도를 비교해서, 거의 같은데 결론이 다르면 충돌 목록에 자동으로 올린다. 변증법이라고 이름 붙였지만, 실제로는 "이거 충돌인데 네가 판단해"라는 알림에 가깝다. 테스트 112개에서 158개로.

v0.3: 기억은 쓸수록 단단해진다

기억은 쓸수록 닳는 게 아니라, 쓸수록 단단해진다. 자주 떠올리는 사실은 더 선명해지고 더 많은 맥락과 연결된다. 그런데 검색이 기억을 소비하기만 하는 시스템은 뭔가 빠져 있었다. 그래서 피드백 루프를 넣었다. 검색할 때마다 해당 팩트의 접근 횟수가 올라가고, 관련 맥락이 자동으로 보강된다. 찾는 행위 자체가 미래의 검색을 더 풍부하게 만드는 구조. 은행의 복리처럼, 초기에는 차이가 미미하지만 시간이 쌓이면 자주 쓰이는 팩트와 안 쓰이는 팩트 사이의 격차가 벌어진다.

여기에 신뢰도라는 축을 하나 더 추가했다. 확인된 사실인지, 실험적 관찰인지, 그냥 가설인지. 적용 조건도 붙였다. "이 기억은 Python 프로젝트에서만 유효하다" 같은 것. 기억에 맥락이 생기니, 엉뚱한 상황에서 엉뚱한 기억이 튀어나오는 일이 줄었다. 건강 검진이라는 개념도 도입했다. 출처 없는 팩트, 아무 관계도 없는 고아 팩트, 일주일 넘게 정리 안 된 팩트를 주기적으로 점검한다. 서랍 속에 쌓이기만 하는 영수증을 정리하는 일과 비슷하다.

구현은 의외로 단순했다. 검색 함수에 피드백 플래그 하나를 추가한 것에서 시작한다. 결과를 반환하면서 동시에 메타데이터를 갱신한다. 접근 시각, 어떤 맥락에서 불렸는지, 몇 번째 접근인지. 건강 검진 5개 항목은 각각 독립적인 체크 함수로, 전부 통과하면 깨끗하고 하나라도 걸리면 리포트가 나온다. 테스트 198개.

v0.4: 왜 같은 버그를 두 번 디버깅하는가

디버깅의 과정을 떠올려 보자. 대부분 머릿속에서 일어나고, 해결되면 커밋 메시지 한 줄로 압축된다. 시도했다 실패한 가설, 기각한 이유, 중간에 발견한 부수적 관찰은 전부 휘발된다. 다음에 비슷한 증상을 만나면 다시 처음부터. "디버깅이 곧 기억이다"라는 컨셉은 이 낭비에 대한 답이었다. 디버그 세션을 시작하고, 가설을 세우고, 증거를 모으고, 기각하거나 확인하는 전체 흐름을 기억 시스템에 기록한다.

특히 기각된 가설이 중요했다. "이건 아니었다"라는 기록은, 다음에 누군가 같은 길로 빠지려 할 때 "거기 이미 가봤는데 막다른 골목이야"라고 말해줄 수 있다. 의학에서 감별 진단 목록을 관리하는 것과 같다. "이 증상이면 이건 아니다"를 축적하는 것. 기각된 가설은 별도로 검색 가능하게 인덱싱해서, 안티패턴 라이브러리로 기능한다. 가설이 두 번 연속 실패하면 "혹시 방향 자체가 틀린 거 아닌가?"라는 알림도 켜진다. 테스트가 198개에서 277개로, 네 버전 중 가장 큰 폭으로 늘었다.

v0.5: 기억의 스냅샷마다 git이 필요하다

"지금 내가 아는 것"도 중요하지만, "일주일 전에 내가 알던 것"과 "그 사이에 뭐가 바뀌었는지"가 때로는 더 중요하다. 코드에 git이 있는 것처럼, 기억에도 버전 관리가 필요했다. v0.5에 이르러서야 빠져 있던 마지막 조각을 찾았다.

스냅샷은 특정 시점의 메모리 전체를 얼린다. diff는 두 시점 사이에 뭐가 추가되고 삭제되고 바뀌었는지를 보여준다. time travel은 과거 시점의 기억 상태로 검색을 돌릴 수 있게 한다. "3일 전 기준으로 이 프로젝트에 대해 뭘 알고 있었지?"라는 질문에 답할 수 있는 시스템. 오래된 일기장을 꺼내서 "그때 나는 이걸 이렇게 생각했구나" 하고 되돌아보는 것과 같다.

328개의 테스트, 외부 의존성은 여전히 제로. 기억이라는 주제를 파고 들어가 보니, 결국 시간의 문제였다. 맥락을 알아야 했고, 쓸수록 강해져야 했고, 실패를 기록해야 했고, 과거를 되돌아볼 수 있어야 했다. v0.5에 와서야 MemKraft는 시간을 다룰 수 있게 되었다.

--

현존하는 에이전트 메모리 시스템은 각각 다른 강점을 가지고 있다. 감쇠 기반, 그래프 기반, 벡터 검색 기반, 세션 요약 기반. MemKraft는 그 컨셉들을 최대한 충돌 없이 하나의 시스템 안에 흡수하려는 시도다. 아직 갈 길이 남았지만, 방향은 분명하다.

영원한 MIT 라이선스, 맘대로 쓰면 된다. 스타, 포크, PR 전부 환영!

https://github.com/seojoonkim/memkraft