
의도적으로 망각하는 AI를 만들었습니다
요약
정보의 중요도와 감정적 무게를 기준으로 기억을 선별하고 통합하는 새로운 메모리 시스템 'Àtúnbí'를 소개합니다. 가공되지 않은 기억은 삭제하고 검증된 지식만을 남기는 5단계 계층 구조의 아키텍처를 통해 AI의 장기 기억 문제를 해결합니다.
핵심 포인트
- 중요도와 감정 점수에 기반한 동적 메모리 관리 시스템 구축
- 작업, 일화, 의미, 엔티티, 절차 메모리의 5단계 계층 구조 활용
- 실시간 응답과 심층 오프라인 통합을 위한 이중 경로 아키텍처
- 헬스케어, 코드베이스, 법률 등 다양한 도메인에 적용 가능한 범용성
AI와의 모든 대화는 제로(zero)에서 시작됩니다. AI는 당신이 어제 말한 것을 기억하지 못합니다. 세션(session) 간에 사실 관계를 연결하지도 못합니다. 그리고 가벼운 "좋은 아침" 인사와 모든 것을 바꾸어 놓을 중요한 실험 결과 사이의 차이점도 확실히 구분하지 못합니다.
그래서 저는 정보가 자신의 자리를 스스로 쟁취해야 하는 메모리 시스템(memory system)을 구축했습니다.
모든 메시지는 도착하는 즉시 중요도와 감정적 무게에 따라 점수가 매겨집니다. 나중에 유용함이 증명되면 그 수명(lifespan)이 연장됩니다. 매일 밤 실행되는 작업(nightly job)은 가장 가치 있는 통찰을 영구적인 요약과 구조화된 사실로 통합합니다. 그 외의 모든 것은 사라집니다.
Àtúnbí라는 이름은 요루바어(Yoruba)로 _"다시 태어남"_을 의미합니다. 가공되지 않은 기억(Raw memory)은 죽고, 지식(Knowledge)은 살아남습니다.
저는 이것을 Qwen Cloud Hackathon을 위해 만들었습니다. 이를 테스트하기 위해 저는 두 명의 당뇨병 환자인 Ada와 Kai를 대상으로 의사 방문, 약물 조정, 변화하는 실험 결과 등 여러 세션에 걸쳐 추적했습니다. 하지만 이것은 단지 헬스케어만을 위한 것이 아닙니다. 환자 대신 코드베이스(codebases), 법률 사건, 연구 논문, 또는 고객 지원 티켓(customer support tickets)을 넣어도 이 인지 메모리 모델(cognitive memory model)은 정확히 동일하게 작동합니다.
아키텍처(Architecture): 두 개의 경로, 하나의 뇌
시스템은 두 개의 상호 보완적인 실행 경로로 나뉩니다. 하나는 빠르고 실시간적인 응답에 최적화되어 있고, 다른 하나는 심층적인 오프라인 통합(offline consolidation)을 위한 것으로, 속도와 장기 학습 사이의 균형을 맞춥니다.
그 중심에는 각각 고유한 목적과 수명을 가진 **다섯 가지의 별도 메모리 계층(memory tiers)**이 자리 잡고 있습니다:
- 작업 메모리 (Working Memory): 동적으로 자동 조정되는 만료 타임스탬프(expiration timestamps)를 가진 가공되지 않은(raw) 수신 메시지.
- 일화 메모리 (Episodic Memory): 야간 통합 단계(nightly consolidation phase) 동안 생성되는 구조화된 대화 요약본.
- 의미 메모리 (Semantic Memory): 독립적으로 검증된 사실들. 새로운 정보가 기존 정보와 모순될 때, 이를 삭제하지 않고 대신 이전 항목을
superseded(대체됨)로 표시하여 전체 감사 추적(audit trail)을 보존합니다. - 엔티티 메모리 (Entity Memory): 사람, 장소, 사물, 개념 간의 관계를 추적하는 NetworkX 그래프.
- 절차 메모리 (Procedural Memory): 반복적인 사용을 통해 결정화되는 학습된 패턴, 선호도 및 워크플로우.
모델 라우터 (The Model Router): 왜 하나의 거대한 LLM만으로는 부족한가
저는 7개의 특화된 Qwen 모델을 사용합니다. 여기서 얻은 가장 큰 교훈은 라우팅(routing)이 전부라는 점입니다. 비전 모델은 숫자를 환각(hallucinate)합니다. 텍스트 모델은 픽셀을 볼 수 없습니다. 작업에 잘못된 도구를 사용하면 대가를 치르게 될 것입니다.
qwen3-asr-flash: 음성 메모 및 녹음된 회의를 위한 오디오 전사(transcription) — 예상보다 의학 용어를 훨씬 더 잘 처리했습니다.qwen3.5-omni-flash: 비전 및 이미지/비디오 설명 — 상위 수준의 문맥(context) 파악에는 훌륭하지만, 정확한 값을 요구해서는 안 됩니다.text-embedding-v4: 의미론적 검색(semantic search)을 위한 1536차원 벡터를 생성하며, 최대 8192 토큰을 지원합니다 — 매우 견고합니다.qwen-flash: 실시간 분류기(classifier) — 모든 수신 메시지에 대해 중요도(0–1)와 감정가(emotional valence, -1 to +1)를 점수화합니다. 빠르고 가볍고 신뢰할 수 있습니다.qwen-plus-latest: 핵심 작업 수행자(workhorse) — 엔티티 추출(entity extraction), PDF로부터의 구조화된 데이터 파싱, 그리고 최종 응답 생성. JSON 및 그래프 구축을 훌륭하게 처리합니다.qwen-turbo: 이진 교차 인코더 리랭커(Binary cross-encoder reranker) — 모든 후보 메모리에 대해 하나의 질문에 답합니다: 이것이 관련이 있는가? 예 또는 아니오. 이것은 순위를 매기는 랭커가 아니라 날카로운 필터입니다.qwen-max: 야간
사흘 동안 씨름한 버그 (그리고 배운 점)
제 디버깅 시간의 대부분은 이곳에서 소요되었습니다. 세 번의 조용한 실패가 있었고, 각각의 실패는 다음 실패를 가리고 있었습니다.
데모: 한 의사가 Ada의 혈액 검사 결과 PDF를 업로드하며 묻습니다: "무엇이 변했나요?" 파일에는 그녀의 HbA1c가 **8.2%**라고 명확히 표시되어 있으며, 이는 상태가 악화되고 있음을 나타냅니다.
응답: 시스템은 자신 있게 대답합니다: "Ada의 HbA1c는 7.1%입니다."
다시 물었을 때, 시스템은 기존 답변을 고수했습니다.
문제 1: 시각적 환각 (Vision Hallucination)
원래 저는 PDF 페이지를 PNG로 렌더링하여 시각 모델 (Vision Model)에 보냈습니다. 모델은 완전히 틀린 숫자임에도 불구하고 그럴듯하게 들리는 숫자를 자신 있게 지어냈습니다. 8.2%는 7.1%가 되었고, eAG 183은 154가 되었습니다.
해결책: 먼저 pymupdf를 사용하여 PDF에서 원시 텍스트 (Raw Text)를 추출한 다음, 해당 텍스트를 텍스트 전용 모델 (Text-only Model)로 보내 구조화된 추출 (Structured Extraction)을 수행하도록 전환했습니다. 텍스트 모델은 픽셀로부터 숫자를 지어내지 않습니다.
# 수정 전: PDF 렌더링 → 시각 모델로 전송
pages = _render_pdf_pages(file_content)
# 모델이 정확한 값을 환각함
# 수정 후: 원시 텍스트 추출 → 텍스트 모델로 전송
pdf_text = _extract_pdf_text(file_content)
# 정확한 값이 신뢰성 있게 추출됨
문제 2: 오염된 캐시 (The Poisoned Cache)
해결되었다고 생각했습니다. 하지만 시스템은 여전히 7.1%라고 말했습니다.
이유는 무엇일까요? 처음에 환각된 답변이 작업 메모리 (Working Memory)에 "사실"로 저장되었기 때문입니다. 모든 새로운 쿼리가 파일을 다시 처리하는 대신 해당 캐시된 실수를 불러왔습니다. 저는 이를 수동으로 삭제해야 했습니다:
DELETE FROM workingmemory WHERE message ILIKE '%HbA1c%7.1%';
문제 3: 조용한 잘림 (Silent Truncation)
다시 해결했습니다. 그런데도 여전히 틀렸습니다.
마침내 데이터베이스를 직접 확인해 보았습니다. 모델은 올바른 값을 출력하고 있었지만, 그 값들이 전혀 저장되지 않고 있었습니다. 저의 데이터 수집 파이프라인 (Ingestion Pipeline)이 모든 청크 (Chunk)를 500자에서 조용히 잘라버리고 있었습니다. 검사 보고서 테이블은 800자 이상이었고, HbA1c 행은 정확히 600번 위치에 있어 디스크에 기록되기 전에 잘려 나갔던 것입니다.
# 범인 — ingest_text() 함수 안에 숨겨져 있음
message=f"[{source_label}]: {para[:500]}", # 조용한 데이터 손실
현재: 전체 문서가 통째로 저장됨; 채팅 메시지는 여전히 청크(chunk)로 나뉨
if source_type in ["pdf", "document"]:
message=f"[{source_label}]: {para}"
...
핵심 요약 (The Takeaway): 채팅 응답만 절대 믿지 마세요. 소스(source)를 확인하고, 모델 출력(model output)을 확인한 다음, 데이터베이스(database)를 확인하세요.
배포: 지루하게 유지하기 (가장 좋은 의미에서)
모든 것은 Alibaba Cloud에서 실행되며, 단순하고 유지보수가 용이하게 유지됩니다:
- 컴퓨팅 (Compute): FastAPI + Nginx가 포함된 단일 Docker 컨테이너, GitHub Actions를 통해 배포
- 데이터베이스 (Database): ApsaraDB RDS 상의 PostgreSQL +
pgvector - 스토리지 (Storage): Alibaba OSS에 원본 파일 저장
- 스케줄링 (Scheduling): EventBridge가 매일 밤 크론(cron)을 트리거 → Function Compute가 Dream Phase를 실행한 후, 다음 실행 전까지 스케일 인(scale to zero) 수행
환경 변수와 함께 하나의 docker run 명령어로 모든 것이 연결되며, 자격 증명(credentials)은 GitHub Secrets에 안전하게 보관됩니다. Kubernetes의 오버헤드나 과도한 엔지니어링(over-engineering) 없이, 그저 작동하는 방식 그대로 구현했습니다.
값진 교훈 (여러분의 시간을 아껴드리기 위해)
- 항상 의존성(dependencies)을 확인하세요.
pymupdf가requirements.txt에 없어서 배포 시 컨테이너가 충돌했고, 원인을 찾는 데 한 시간이 걸렸습니다. - 비전 모델(Vision models)은 묘사하고, 텍스트 모델(text models)은 전사(transcribe)합니다. 정확한 숫자, 날짜 또는 측정값이 필요하다면 먼저 원본 텍스트를 추출하세요.
- 모든 상황에 적용되는 단 하나의 방식은 없습니다. 채팅 메시지와 실험 보고서는 근본적으로 다릅니다. 모든 것에 동일한 청크 크기(chunk size)를 강요하지 마세요.
- 백그라운드 작업(background jobs)을 테스트하세요. 실시간 파이프라인은 완벽하게 다듬었지만, 야간 크론(nightly cron)은 거의 테스트하지 않았습니다. 여러분이 잠든 사이에 실행되는 부분은 항상 검증하세요.
Àtúnbí. Reborn.
_Qwen Cloud Hackathon을 위해 제작되었습니다. GitHub에서 전체 코드 보기.
LLM 애플리케이션에서 장기 기억(long-term memory)에 어떻게 접근하시나요? 여러분이 직면한 가장 큰 과제는 무엇인가요? 댓글로 이야기해 봅시다!
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기