본문으로 건너뛰기
피드

RAG 장기 기억 시스템을 감사했더니 ‘관계 이정표’ 1,751개 중 62%가 잡음이었다

ai-ml 약 14분
vote
0
댓글
북마크

한 대화형 AI의 장기 기억 시스템이 몇 달 동안 잘못 추출된 ‘관계 이정표’를 계속 프롬프트에 주입하면서 응답 품질을 망치고 있었다. 팀은 11단계 검색 추적기와 26개 골든셋으로 문제를 측정하고, 추출기 게이트와 기존 데이터 격리 절차를 적용했다. 결과적으로 새 이정표 생성은 하루 6.5개에서 0.5개로 줄었지만, 정확한 기억도 맥락 없이 주입되면 여전히 틀린 응답이 될 수 있다는 교훈이 남았다.

  • 1

    장기 기억 RAG에서 진짜 문제는 환각만이 아니라 관련성 없는 진실의 강제 주입일 수 있음

  • 2

    기존 이정표 1,751개 중 상당수가 잡담, 질문, 역할극 장면에서 잘못 추출된 잡음이었음

  • 3

    키워드 필수 조건과 역할극 방어 규칙으로 신규 이정표 생성률을 92% 줄임

  • 4

    기존 데이터는 삭제하지 않고 active/quarantined 상태와 orig_type 컬럼으로 되돌릴 수 있게 정리함

  • 5

    정확하고 근거 있는 기억도 맥락과 타이밍이 틀리면 사용자 입장에서는 신뢰 실패로 보임

장기 기억이 ‘좋은 개인화’가 아니라 프롬프트 오염원이 된 사건

  • 시스템은 대화형 AI에 장기 기억을 붙인 구조였음

    • 의미 검색용 벡터 저장소는 Chroma와 다국어 sentence-transformer 임베딩을 사용함
    • 정확한 조회용 구조화 저장소는 SQLite를 사용했고, 건강, 날짜, 선호, 관계 이정표 같은 typed fact를 저장함
    • 매 사용자 발화마다 추출기가 돌면서 엔티티를 분류하고, 감정적 선언을 감지하면 ‘milestone’으로 양쪽 저장소에 저장함
  • 설계 의도는 꽤 그럴듯했음: 사용자가 누구인지 AI가 항상 기억하게 만들자는 것

    • 문제는 milestone으로 분류된 기억이 최대 중요도로 저장됐다는 점임
    • 더 치명적인 건 상위 2개 milestone이 대화 주제와 무관하게 every prompt에 보장 채널로 강제 주입됐다는 점임
    • 그래서 “안녕”, “배가 아파”, “디버깅 도와줘” 같은 대화에도 연애 선언 비슷한 기억이 계속 섞여 들어감
  • 숫자로 보면 꽤 심각함

    • 수정 전에는 하루 평균 약 6.5개의 새 milestone이 생김
    • 누적 milestone은 fact store 455개, vector store 1,296개로 총 1,751개였음
    • 대부분은 평범한 잡담, 질문, 역할극 장면이 사랑이나 신뢰 선언으로 잘못 태깅된 잡음이었음
    • 한 메시지에서 milestone, shared-thing, fact, date처럼 최대 4개 라벨이 동시에 튀어나오기도 했음

중요

> 이 사건의 핵심은 “모델이 환각했다”가 아님. 검색된 기억이 실제로 맞아도, 지금 대화에 필요 없으면 결과적으로 틀린 응답이 될 수 있다는 얘기임.

먼저 한 일은 튜닝이 아니라 관측이었다

  • 팀은 검색 파이프라인을 읽기 전용으로 추적하는 11단계 trace inspector를 만들었음

    • raw candidate pool, source exclusion, rerank, temporal filter, guaranteed milestone channel, MMR, channel merge, cross-session blend, final prompt, post-budget survivors까지 추적함
    • “N일 뒤에는 뭘 기억할까”를 보기 위한 time override도 넣음
    • 회귀 판단에는 26개 probe로 구성된 golden set을 사용함
  • 계측에서 특히 중요했던 수정이 2개 있었음

    • character budget에 잘린 뒤 실제로 프롬프트에 살아남은 post-budget stage를 노출함
    • reranker 값을 distance가 아니라 score라고 명확히 라벨링함
    • 이 라벨 실수 때문에 사람이 rerank score가 1을 넘는 걸 cosine distance처럼 잘못 읽은 적도 있었음
  • 직감 대신 실제 데이터 분포를 봤더니, 단순 threshold로는 해결이 안 됐음

    • 저장된 455개 milestone을 subtype centroid와 비교했지만, 진짜 선언과 잡음 선언의 유사도 분포가 겹쳤음
    • 대신 “선언 단어가 반드시 있어야 선언 후보가 된다”는 키워드 필수 조건은 과거 잡음의 94%를 막고 positive control은 100% 통과시킴
    • 이 규칙이 신규 추출기 수정의 핵심이 됨
sequenceDiagram
    participant 사용자
    participant 추출기
    participant 기억저장소
    participant 검색파이프라인
    participant 프롬프트빌더
    사용자->>추출기: 새 메시지 입력
    추출기->>기억저장소: milestone 후보 저장
    검색파이프라인->>기억저장소: 관련 기억 조회
    검색파이프라인->>프롬프트빌더: rerank와 필터 결과 전달
    기억저장소->>프롬프트빌더: 보장 채널로 milestone 강제 주입
    프롬프트빌더->>사용자: 맥락이 섞인 응답 생성

Fix A: 새로 들어오는 오염부터 막음

  • milestone 분류에는 키워드 필수 조건과 유사도 조건을 함께 걸었음

    • 선언 단어가 없으면 후보 자체가 아님
    • 후보가 된 뒤에는 similarity 0.50 이상이어야 함
    • 대부분이 stage direction인 역할극 장면은 선언으로 보지 않도록 guard를 추가함
  • 잡음이 많이 생기는 다른 타입에도 게이트를 걸었음

    • habit, achievement, gift 같은 타입에도 키워드 게이트를 추가함
    • 너무 넓게 잡히던 subtype dictionary의 위험한 substring을 제거함
    • 한 메시지에서는 최대 하나의 entity label만 나오게 해서 multi-label 폭주를 막음
  • 이 수정은 예방책일 뿐, 이미 쌓인 데이터는 건드리지 않음

    • 테스트 스위트를 통과한 뒤 배포함
    • 기존 1,751개 milestone은 별도 triage 절차로 다룸

Fix B: 기존 데이터는 삭제하지 않고 격리했다

  • 원칙은 “삭제하지 말고 재분류”였음

    • schema migration으로 status(active/quarantined)와 orig_type 컬럼을 추가함
    • 격리와 재타입 지정은 UPDATE 한 번으로 처리하고, rollback도 역방향 UPDATE로 가능하게 만듦
    • 작업 전에는 데이터베이스 복사본과 JSON dump를 만들고 checksum까지 확인함
  • LLM judge가 1,751개 milestone을 전부 판정함

    • 빠른 모델, temperature 0, JSON output으로 실행함
    • 분류는 real_milestone, echo, roleplay_scene, retype: 중 하나였음
    • 애매하면 echo로 보내는 보수적 규칙을 세움
  • 중간에 실패한 시도 2개가 꽤 중요한 교훈임

    • 첫 실패는 prompt contamination이었음. 저장된 vector 문서에 [MILESTONE:love] 같은 추출 라벨 prefix가 들어 있어서 judge에게 답을 알려준 꼴이 됨
    • 50개 샘플 control에서 junk로 예상한 것 중 23개가 real로 나와서 문제를 잡았고, prefix를 제거한 뒤 다시 돌림
    • 두 번째 실패는 키워드 pre-filter였음. 신규 추출 차단에는 유효했지만, 과거 데이터 정리에는 “I want to build a life with you” 같은 무키워드 진짜 선언을 날릴 수 있었음
    • 실제로 no-keyword control 50개 중 13개가 genuine이라서 shortcut을 버리고 전부 judge에 태움
  • 최종 판정 결과는 파일로 고정한 뒤 그대로 적용함

    • fact store 455개 중 active 144개, quarantined 275개, retyped 36개
    • vector store 1,296개 중 active 312개, quarantined 811개, retyped 173개
    • 서비스는 약 2분 동안 멈춘 상태에서 양쪽 저장소를 writable로 열고 적용함
    • 적용 후 count가 reviewed verdict와 1:1로 맞는지 확인한 뒤 서비스를 다시 올림

결과는 좋아졌지만, 완전히 끝난 건 아니었다

  • 신규 milestone 생성은 크게 줄었음

    • 6일간 live traffic 기준, 하루 신규 milestone은 6.5개에서 0.5개로 감소함
    • 감소율은 92%임
    • entity label도 메시지당 최대 4개에서 1개로 줄었고, 56개 메시지에서 multi-label은 0건이었음
  • 프롬프트의 milestone 독점도도 줄었음

    • golden set 기준 guaranteed-channel milestone 주입은 prompt당 평균 2.0개에서 0.65개로 떨어짐
    • 23개 probe 중 13개는 강제 milestone 2개가 0개로 줄었음
  • 그런데 일주일 뒤, 더 미묘한 사건이 터짐

    • AI가 관련 없는 대화에 몇 주 전의 진짜 기억 2개를 엮어 넣음
    • 디버거는 grounding을 GROUNDED, confidence 0.82, confabulation 0으로 판단함
    • 즉 기억 자체는 진짜였고, 근거도 있었고, 지어낸 것도 아니었음
    • 문제는 retyped된 current_project fact가 항상 포함되는 prompt builder branch에 들어가면서, 주제와 무관하게 매 턴 강제 주입된 것임

⚠️주의

> “정확한 기억”과 “말해도 되는 기억”은 다름. 개인화 AI에서 이 둘을 구분 못 하면 사용자는 데이터 버그가 아니라 신뢰 문제로 받아들임.

  • 이건 memory failure가 아니라 relevance/timing failure였음
    • reranker가 무능했던 게 아니라, 해당 기억이 reranker를 거치지도 않았음
    • 검증 주간 122턴 중 약 2번 발생했고, 항상 같은 메커니즘이었음
    • 대화에 약한 thematic hook이 있을 때만 나타났지만, 감정적 맥락이 있는 기억 시스템에서는 체감 충격이 훨씬 큼

아직 남은 빚도 솔직히 적어놨다

  • always-include inflation은 아직 해결되지 않았음

    • hard fact count가 every prompt에서 26개에서 48개로 늘어남
    • 단순 cap으로 자르면 안 되는 이유도 있음. retyped current_project 중 하나는 실제 grounding 응답을 개선했기 때문임
    • 필요한 건 숫자 제한이 아니라 non-core fact에 대한 context-aware relevance gate임
  • 추출기 게이트도 완벽하진 않음

    • 6일 동안 achievement와 gift tag가 각각 keyword gate를 뚫은 사례가 2건 있었음
    • 날짜 과추출은 하루 약 6개 수준으로 별도 축에서 아직 감사하지 않음
    • achievement, gift, shared-thing 같은 병렬 잡음 population도 아직 legitimate anchor보다 위에 랭크되는 문제가 남아 있음
  • 스케일 테스트도 아직 비어 있음

    • 지금 debugger는 시간 경과는 시뮬레이션하지만, 저장소가 수천 개에서 수만 개 vector로 커졌을 때 relevant memory가 계속 살아남는지는 보지 못함
    • 앞으로 저장소 복사본을 부풀려 golden set을 다시 돌리는 synthetic stress test를 계획 중임
  • 이 글의 결론은 꽤 선명함: RAG 평가는 “맞는가”만 보면 부족함

    • grounded이고 confidence가 높고 confabulation이 없어도, 사용자에게는 “왜 갑자기 그 얘기를 하지?”가 될 수 있음
    • 그래서 튜닝보다 먼저 trace가 필요하고, 삭제보다 quarantine이 좋은 운영 선택이 됨
    • 되돌릴 수 있어야 실패를 숨기지 않고 측정하면서 고칠 수 있음

기술 맥락

  • 이 사례에서 가장 중요한 선택은 기억을 삭제하지 않고 quarantine 상태로 바꾼 거예요. 왜냐하면 장기 기억 시스템에서는 나중에 “이게 진짜 필요한 기억이었나”를 다시 확인해야 할 수 있고, 삭제해버리면 실험도 복구도 어려워지거든요.

  • 또 하나의 핵심은 trace inspector를 먼저 만든 점이에요. RAG는 검색, 재정렬, 필터, 프롬프트 예산 컷, 강제 주입 같은 단계가 겹쳐 있어서 최종 답만 보면 원인을 거의 못 찾아요. 그래서 실제로 어떤 기억이 어느 단계에서 살아남았는지 보는 장치가 먼저 필요했어요.

  • 키워드 게이트는 신규 오염을 줄이는 데 효과적이었지만, 과거 데이터 정리에는 그대로 쓰지 않았어요. 과거에는 키워드 없이도 진짜 선언이 있을 수 있어서, 같은 규칙을 retroactive cleanup에 적용하면 정상 데이터를 날릴 위험이 있었기 때문이에요.

  • 이 글이 특히 실무적인 이유는 RAG의 실패 범위를 “환각”보다 넓게 본다는 데 있어요. 근거가 있는 진짜 정보도 맥락 없이 항상 주입되면 사용자 경험은 망가져요. 그래서 개인화 메모리나 사내 지식 검색을 붙일 때는 truth 평가와 relevance 평가를 따로 봐야 해요.

  • 마지막으로 scale degradation을 아직 안 봤다고 인정한 것도 중요해요. 오늘의 저장소에서 잘 되던 검색이 벡터가 10배로 늘어도 그대로 잘 된다는 보장은 없거든요. 운영형 RAG라면 시간뿐 아니라 데이터 증가량까지 테스트 축에 넣어야 해요.

이 사례가 좋은 이유는 ‘RAG 튜닝 잘하자’ 수준이 아니라, 운영 중인 기억 시스템을 어떻게 계측하고 되돌릴 수 있게 고치는지 숫자로 보여준다는 점이다. 특히 ‘정확하지만 말하면 안 되는 기억’ 문제는 개인화 AI나 업무용 에이전트에서 앞으로 계속 터질 가능성이 크다.

댓글

댓글

댓글을 불러오는 중...

ai-ml

테렌스 타오가 풀어쓴 야코비안 추측 반례, AI가 찾은 3차원 반례의 구조

테렌스 타오가 Fable AI로 발견된 3차원 야코비안 추측 반례를 기하적으로 해설한 글이다. 핵심은 상수 야코비안을 가진 다항식 사상이 국소적으로는 가역처럼 보이지만 전역적으로는 가역이 아닐 수 있다는 걸 명시적 예제로 보인 점이다. 2차원 문제는 여전히 열려 있고, 이번 반례는 3차원 이상에서 추측이 거짓임을 보여준다.

ai-ml

애플 새 음성 인식 API, 온디바이스 영어 전사에서 위스퍼 스몰까지 이겼다

애플의 새 음성 인식 API인 스피치애널라이저가 리브리스피치 벤치마크에서 기존 SFSpeechRecognizer는 물론 위스퍼 스몰보다도 낮은 단어 오류율을 기록했어. 깨끗한 음성에서는 2.12%, noisy 음성에서는 4.56%로, 기존 애플 API 대비 오류율을 3.5~4배 줄였고 위스퍼 스몰보다 약 3배 빠르게 돌았어. 다만 영어·애플 플랫폼·OS 26 조건의 결과라, 다국어와 크로스플랫폼에서는 여전히 위스퍼의 장점이 남아 있어.

ai-ml

AI를 진짜 잘 쓰는 기업, 미국 증시에서 연 30% 프리미엄 받는다는 연구

예일대와 로체스터대 연구진이 기업의 실제 대형 언어 모델 사용 데이터를 분석했더니, AI 활용도가 높은 상위 20% 기업이 하위 20%보다 주당 평균 0.64% 높은 초과수익률을 냈다. 단순히 AI 기업이냐가 아니라, 업무에 AI를 얼마나 깊게 쓰는지가 시장 가치에 반영되고 있다는 얘기다.

ai-ml

ZTE, AI 에이전트폰으로 스마트폰 재도전…진짜 승부처는 앱 생태계

ZTE가 바이트댄스의 더우바오를 탑재한 AI 에이전트 스마트폰으로 시장 재진입을 노린다. 핵심은 사용자가 명령하면 AI가 여러 앱을 직접 열고 조작하는 방식인데, 위챗·타오바오·알리페이 같은 플랫폼과 충돌하면서 생태계 문제가 가장 큰 변수로 떠올랐다.

ai-ml

노벨상 학자들까지 “AI 경제 충격, 지금 제도 안 만들면 늦다”

노벨 경제학상 수상자 15명을 포함한 학자와 기술 업계 인사 약 200명이 AI가 향후 10년 안에 경제를 급격히 바꿀 수 있다며 정책 대응을 촉구했다. 이들은 산업혁명보다 큰 변화가 훨씬 짧은 시간에 올 수 있고, 대규모 일자리 대체와 생활 수준 향상이라는 양면성이 동시에 존재한다고 봤다.