당신의 AI 에이전트는 효과적이었던 것이 아니라, 관련 있어 보이는 것을 기억합니다
요약
AI 에이전트의 메모리 시스템이 단순히 벡터 유사도에만 의존할 때 발생하는 한계와 실무적인 해결 방안을 다룹니다. 에이전트가 과거의 실패를 반복하지 않도록 실패 로그 관리, 계층적 메모리 구조, 사후 분석 기록 등 다양한 접근 방식을 제안합니다.
핵심 포인트
- 벡터 유사도 기반 검색은 '관련성'은 높지만 '효과성'을 보장하지 않음
- 실패 로그를 일반 메모리와 분리하여 우선적으로 참조하는 방식이 유효함
- 작업 후 사후 분석(Post-mortem)을 통해 경험을 요약하고 저장하는 전략 필요
- 안정적인 사실과 가변적 정보를 구분하는 계층적 메모리 구조 활용
저는 몇 주 동안 사람들에게 꽤 기본적인 질문을 던졌습니다. 만약 당신이 데모 단계를 넘어 실제 운영 환경과 유사한 환경에서 에이전트 (Agent)를 실제로 실행하고 있다면, 메모리 (Memory)를 어떻게 처리하시나요?
저는 몇 가지 팁을 얻을 것으로 기대했습니다. 하지만 대신 제가 얻은 것은 반복되는 똑같은 좌절감이었고, 제가 알기로는 아직 아무도 깔끔하게 해결하지 못한 문제였습니다. 그래서 저는 이 글을 쓰려고 합니다. 왜냐하면 에이전트로 무언가를 구축한다면 당신은 반드시 이 문제에 직면하게 될 것이기 때문입니다.
모두가 시작하는 방식
대부분의 에이전트 메모리 (Agent memory)는 동일한 방식으로 작동합니다. 에이전트가 본 모든 것을 임베딩 (Embed)하고, 벡터 (Vectors)를 저장하며, 새로운 작업이 나타나면 가장 가까운 것을 가져와 컨텍스트 (Context)에 집어넣습니다.
그것은 문제가 생기기 전까지는 괜찮습니다. 함정은 "벡터 공간에서 가장 가깝다"는 것이 실제로는 "관련 있어 보인다"는 것을 의미하며, 관련 있어 보인다는 것이 지난번에 효과가 있었다는 것과 같지는 않다는 점입니다.
따라서 에이전트는 실제로 도움이 되었던 것이 아니라, 눈앞의 작업과 닮은 것을 회상합니다. 그 경로는 막다른 길이라는 것을 아무도 말해주지 않았기 때문에, 에이전트는 이미 세 세션 전에 실패했던 경로를 즐겁게 따라갈 것입니다. 만약 에이전트가 완전한 자신감을 가지고 자신의 실수를 반복하는 것을 본 적이 있다면, 그것이 바로 이 버그의 핵심입니다. 에이전트는 멍청한 것이 아닙니다. 단지 지난 시도가 어떻게 되었는지 알지 못할 뿐입니다.
사람들이 실제로 이에 대해 하고 있는 것
여기가 제가 예상하지 못했던 부분입니다. 제가 대화한 거의 모든 사람이 이미 이 문제에 부딪혔고 조용히 자신만의 해결책을 만들어 두었습니다. 그리고 그 해결책들은 제각각이었는데, 이는 저에게 아직 표준적인 답이 없다는 신호로 다가왔습니다.
자주 언급된 몇 가지 사례가 있습니다.
어떤 사람들은 그냥 파일 (Files)을 사용합니다. 메모리 플랫폼도 없고, 화려한 것도 없습니다. 작업 메모리 (Working memory)는 에이전트가 시작할 때 읽는 일반 파일에 존재하며, 에이전트가 무엇을 쓸지 결정하고, 오래된 데이터는 나중에 벡터 스토어 (Vector store)로 넘어갑니다. 혼자 일하는 한 사람에게는 이것이 분명히 매우 견고한 방식이었으며, 그는 이에 대해 다소 자부심을 느끼고 있었습니다.
다른 사람들은 별도의 실패 로그 (failure log)를 유지합니다. "이것은 실패했으며 그 이유는 다음과 같다"라는 정보를 일반적인 메모리 (general memory)에서 완전히 분리하여 추출한 뒤, 에이전트가 이전에 무언가를 시도했는지 궁금해할 때 일반적인 유사도 검색 (similarity search)보다 먼저 해당 로그를 확인하게 합니다. 누군가 저에게 깊은 인상을 남긴 방식으로 설명해 주었습니다. 임베딩 (Embeddings)은 주제를 회상하는 데는 뛰어나지만, "우리는 이 길로 갔다가 X 때문에 망했다"라는 식의 내용은 거의 기억하지 못합니다.
몇몇 방식은 에이전트가 각 작업 후에 스스로 짧은 사후 분석 (post mortem)을 작성하게 합니다. "이것을 시도했으나 저것 때문에 실패했다, 다음에는 다른 것을 하자"와 같은 식입니다. 그런 다음 새로운 작업을 시작하기 전에 이 기록들을 검색합니다. 그들이 인정한 솔직한 단점은, 이런 기록이 30~40개 정도 쌓이면 파일이 노이즈 (noise)로 변한다는 것이었습니다. 그래서 그들은 오래된 기록들을 요약하는 단계를 추가해야 했습니다.
또한 어떤 이들은 메모리를 계층 (tiers)으로 나눕니다. 에이전트가 신뢰할 수 있도록 허용된 안정적인 사실 (Stable facts)과, 그 외의 모든 것(언급은 할 수 있지만 출처를 제시할 수 없는 한 행동에 옮길 수는 없는 것)으로 구분합니다.
형태는 다르지만, 근본적인 본능은 같습니다. 모든 메모리가 똑같이 신뢰할 수 있는 것처럼 가장하는 것을 멈추는 것입니다.
모든 것이 무너지는 지점
이 방식들을 나란히 놓고 보니 한 가지 사실이 눈에 띄었습니다.
모든 접근 방식은 무엇을 기록할 것인지는 다룹니다. 하지만 무엇을 유지할 것인지는 진정으로 다루지 못합니다.
무언가 실패했다는 것을 알아차리는 것은 쉬운 절반에 불과합니다. 도구 오류 (tool errors), 테스트 실패, 타임아웃 (timeouts), 되돌려진 변경 사항 등을 잡아낼 수 있습니다. 심지어 "작업이 그냥 끝났고 아무도 그것이 성공했는지 확인하지 않았다"라는 상황을 일종의 실패로 취급할 수도 있는데, 이것이 바로 에러를 발생시키지 않는 조용한 실패들을 잡아내는 방법입니다.
그 이후의 모든 것이 어려워집니다. 어떤 실패가 유지할 가치가 있고, 어떤 것이 우연한 일이었는지 판단하는 것. 시스템이 변화함에 따라 어떤 교훈이 더 이상 유효하지 않게 되는 시점. 아무도 그것이 규칙이 되어야 하는지 실제로 확인하지 않았을 때, 어떻게 메모리가 "이런 일이 한 번 있었다"에서 "이것은 규칙이다"로 미끄러지는 것을 막을 것인가 하는 문제입니다.
어떤 분이 제가 계속 되새기게 되는 방식으로 이 문제를 정의했습니다. 메모리는 교훈(moral)이 아니라 증거(proof)를 담고 있어야 합니다. 발생한 가공되지 않은 사건, 즉 무엇이 일어났는지와 그에 대한 증거는 그대로 유지되어야 하며 검증 가능해야 합니다. 그로부터 도출한 교훈은 나중에 무언가에 의해 모순될 때 변경될 수 있어야 합니다. 이 두 가지가 하나의 객체로 합쳐지는 순간, 시스템은 실제로 일어난 일을 기억하는 대신 자신의 해석을 방어하기 시작합니다. 솔직히 말해서, 이는 인간이 저지르는 매우 인간적인 오류 방식입니다.
최신 도구들이 여전히 놓치고 있는 것
현재 저장된 사실이 시간이 흐름에 따라 여전히 유효한지를 추적하는, 비슷하지만 다른 문제를 다루는 새로운 메모리 도구(memory tooling)의 물결이 일고 있습니다. '이전에는 누가 소유했는가, 지금은 누가 소유하는가'와 같은 문제입니다. 이는 진정으로 유용하며, 맹목적인 유사성(similarity)에서 한 단계 진보한 것입니다.
하지만 이것이 다른 질문에 답하고 있다는 점에 주목하십시오. "이 사실이 여전히 최신인가"는 "이 메모리에 따라 행동한 것이 실제로 좋은 결과로 이어졌는가"와 같지 않습니다. 사실이 완벽하게 최신 상태라 할지라도, 에이전트를 세 번 연속으로 벽에 부딪히게 만든 바로 그 원인일 수 있습니다. 어떤 것이 여전히 사실인지와 그것이 효과가 있었는지는 서로 다른 두 축입니다. 이 분야의 대부분은 첫 번째 축에 매달려 있습니다.
오늘날 이를 구축하고 있다면
저보다 이 분야에 더 깊이 관여하고 있는 사람들로부터 간접적으로 배운 실질적인 조언들입니다.
유사성(similarity)에만 의존하지 마십시오. 유사성은 도움이 된 것이 아니라 관련 있어 보이는 것을 가져다줄 뿐입니다. 실패를 실제 메모리로 취급하십시오. 왜냐하면 작동하지 않은 것이 단순히 유사한 것보다 훨씬 더 유용할 때가 많기 때문입니다. 사건과 교훈을 분리하여, 일어난 일을 명확하게 기록하면서도 나중에 결론을 수정할 수 있도록 하십시오. 내구성이 있는 규칙(durable rule)으로 승격되는 것 앞에 실질적인 게이트(gate)를 두십시오. 오류를 인지하는 것이 올바른 것을 배웠다는 것과 같지는 않으며, 잘못된 교훈은 빠르게 고착화되기 때문입니다. 그리고 반드시 되돌아가야 할 상황이 생길 것이라고 가정하십시오. 2주 전에는 사실이었던 교훈이, 그 대상이 되는 코드를 리팩터링(refactor)하고 나면 적극적으로 해가 될 수 있습니다.
이 중 해결된 것은 아무것도 없습니다. 이를 잘 수행하고 있는 사람들은 경험적인 규칙(rules of thumb), 최신성(recency), 두 번 검증하기(prove it twice), 인간의 검토(a human glance), 그리고 가끔씩 수행하는 정리 작업(cleanup pass)과 같은 합리적인 방식들을 사용하고 있습니다. 그리고 이 모든 규칙들은 예측 가능한 지점에서 어딘가 무너지곤 합니다.
저는 더 나은 임베딩 모델(embedding model)이 해결책이라고 생각하지 않습니다. 저에게 이 문제는 다르게 느껴집니다. "이것과 가장 유사한 것이 무엇인가"의 문제도 아니고, 심지어 "무엇이 여전히 사실인가"의 문제도 아닙니다. 그보다는 "무엇이 실제로 효과가 있었는가, 그리고 나머지가 조용히 사라지는 동안 어떻게 그것을 붙잡아 둘 것인가"에 더 가까운 문제입니다.
만약 당신이 프로덕션(production) 환경에서 에이전트(agent)를 운영하며 이 문제로 씨름하고 있다면, 당신이 이를 어떻게 처리하고 있는지 진심으로 듣고 싶습니다. 이 모든 논의를 시작하게 만든 대화는 제가 이 주제에 대해 읽은 그 어떤 것보다 더 많은 것을 가르쳐 주었습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기