ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 컨텍스트 윈도우 확장이 해결하지 못하는 인지 인프라: 에이전트 4계층 기억 모델과 망각 정책 설계

    AI 2026. 10. 14. 09:00
    반응형

    컨텍스트 윈도우 확장이 해결하지 못하는 인지 인프라: 에이전트 4계층 기억 모델과 망각 정책 설계

    핵심 요약: 1M, 2M 토큰으로 팽창한 컨텍스트 윈도우는 에이전트의 영구 기억 문제를 해결하지 못합니다. 모든 대화 기록을 프롬프트에 밀어 넣는 방식은 주의력 분산(Attention Dilution), 지연 시간 증가, 과거 폐기 지식의 간섭을 부릅니다. 에이전트에게 필요한 인프라는 무한한 RAM이 아닌 기억을 분류하고 정제하는 기억 운영체제(Memory OS)입니다. 인지과학의 기억 모델을 공학으로 전환한 4계층 기억 분류(Working·Episodic·Semantic·Procedural), 시행착오를 누적하는 자가 반추(Self-Reflexion), 에빙하우스 반감기 수식 기반 감쇄, 로그 스케일 사용성 강화, 설명 가능한 Soft/Hard 망각 정책을 코드 레벨로 분석합니다.


    1. 프롬프트 누적이 만드는 인지 부채(Cognitive Debt)

    컴퓨터 아키텍처에서 L1 캐시 크기를 무한정 키우지 못하듯, LLM의 컨텍스트 윈도우 확장도 만능 해결책이 아닙니다. 컨텍스트 윈도우는 고속 연산을 위한 작업 메모리(SRAM/DRAM)일 뿐, 영속 지식을 구조화해 보관하는 스토리지 엔진이 아닙니다.

    대화 기록을 무차별 압축해 시스템 프롬프트에 누적하면 세 가지 병목이 발생합니다.

    [무차별 프롬프트 누적의 한계]
    1. 주의력 희석 (Attention Dilution) ──► 수만 줄의 히스토리 속에서 핵심 제약조건 망각
    2. 고정관념 오염 (Stale Beliefs)   ──► 3주 전 실패한 디버깅 가설을 현재 세션에 재적용
    3. 추론 비용 폭증 (Token Bleed)     ──► 단순 질의마다 수만 토큰 왕복으로 지연과 비용 발생
    
    [컴퓨터 아키텍처 vs 에이전트 인지 계층 비교]
    컴퓨터 계층:  [CPU 레지스터 / L1-L3 캐시] ──► [메인 메모리 DRAM] ──► [NVMe SSD] ──► [콜드 아카이브]
    에이전트 계층: [Attention Context Window] ──► [Working Memory]  ──► [Episodic]  ──► [Semantic/Procedural]
    

    인간의 뇌가 모든 감각 입력을 장기 기억으로 남기지 않듯, 자율 에이전트 역시 휘발할 상태와 보존할 지식을 구분하고 쓸모를 다한 기록을 적극 지워내야 합니다.


    2. 4계층 기억 분류 체계

    Memento는 에이전트가 축적하는 기억을 인지적 특성과 수명에 따라 4가지 계층으로 분리합니다.

    ┌───────────────────────────────────────────────────────────────────────────┐
    │                           4계층 기억 모델 상세                            │
    ├─────────────┬──────────────────────────┬───────────┬──────────────────────┤
    │   기억 유형  │         역할 및 내용      │ 기본 반감기│       대표 예시      │
    ├─────────────┼──────────────────────────┼───────────┼──────────────────────┤
    │   Working   │ 현재 세션 태스크 중간 상태 │    2일    │ 임시 포트, 빌드 단계 │
    ├─────────────┼──────────────────────────┼───────────┼──────────────────────┤
    │  Episodic   │ 과거 실행 사건, 실패 로그 │   30일    │ 10/10 DB 롤백 발생   │
    ├─────────────┼──────────────────────────┼───────────┼──────────────────────┤
    │  Semantic   │ 불변 사실, 개념 정의, 규격│  180일    │ Node 24 런타임 제약  │
    ├─────────────┼──────────────────────────┼───────────┼──────────────────────┤
    │ Procedural  │ 워크플로, 복구 절차, 스킬 │   90일    │ 배포 롤백 5단계 규칙 │
    └─────────────┴──────────────────────────┴───────────┴──────────────────────┘
    

    1) 작업 기억 (Working Memory)

    현재 실행 중인 세션 안에서만 유효한 단기 스크래치패드입니다.
    - 특징: 태스크가 완료되면 즉시 가치가 떨어집니다.
    - 반감기: 2일. 며칠만 지나도 망각 점수가 급등해 정리 대상에 오릅니다.

    2) 일화 기억 (Episodic Memory)

    시점과 구체적 맥락이 결합된 사건 기록입니다.
    - 특징: "어제 오후 어떤 API 호출에서 504 게이트웨이 타임아웃이 발생했다"처럼 특정 사건의 발생 이력을 추적합니다.
    - 반감기: 30일. 반복 참조되지 않으면 자연 소멸합니다.

    3) 의미 기억 (Semantic Memory)

    시간 맥락이 탈락한 순수 사실과 도메인 규칙입니다.
    - 특징: "우리 서비스는 인증에 Ed25519 서명을 검증한다"처럼 프로젝트 전반에 지속 적용되는 불변 규칙입니다.
    - 반감기: 180일. 지식 베이스의 뼈대를 형성합니다.

    4) 절차 기억 (Procedural Memory)

    특정 목표를 달성하기 위한 단계별 행동 지침(Action Plan)입니다.
    - 특징: 조건문과 실행 순서를 내장하여 도구 호출 시 우선 반영됩니다.
    - 반감기: 90일. 반복 실행과 검증을 통해 최적화됩니다.


    3. 절차 기억과 자가 반추(Self-Reflexion) 루프

    절차 기억은 단순 텍스트 블록으로 방치하면 에이전트가 실행 단계에서 환각을 일으킵니다. Memento는 엄격한 스키마와 동시성 제어, 반추 노트를 결합합니다.

    1) 엄격한 절차 스키마와 Compare-and-Swap (CAS)

    절차 기억은 목표(task_goal), 세부 단계(steps), 발동 조건(trigger_conditions), 반추 노트(reflection_notes)를 독립 필드로 강제합니다.

    export const RememberSchema = z.object({
      content: CommonSchemas.Content,
      type: CommonSchemas.MemoryType.optional(),
      memory_id: z.string().max(200).optional(),
    
      // Procedural Memory 전용 필드
      task_goal: CommonSchemas.TaskGoal,
      steps: CommonSchemas.Steps,
      reflection_notes: CommonSchemas.ReflectionNotes,
      workflow_name: CommonSchemas.WorkflowName,
      skill_name: CommonSchemas.SkillName,
      trigger_conditions: CommonSchemas.TriggerConditions,
    
      // 다중 에이전트 동시성 방어 (CAS)
      expected_version: z.number().int().min(1).optional()
        .describe('현재 memory_item.version과 일치할 때만 갱신 허용'),
      importance: CommonSchemas.Importance.default(0.5),
    });
    

    여러 에이전트 워커가 동시에 같은 절차를 수정할 때 발생하는 덮어쓰기 손실은 expected_version 검증으로 차단합니다. 버전이 불일치하면 즉시 예외를 던져 재조회를 유도합니다.

    2) 실패 교훈 누적: 반추 노트(Reflection Notes) 병합

    에이전트가 워크플로를 수행하다 실패하면 절차 전체를 새로 쓰는 대신 기존 절차의 reflection_notes를 증분 갱신합니다.

    async function getExistingReflectionNotes(
      db: Database.Database,
      taskGoal: string | null | undefined,
      host: RememberToolHost
    ): Promise<ExistingReflectionNotesResult> {
      const existingRecord = DatabaseUtils.get(
        db,
        `SELECT reflection_notes FROM memory_item
         WHERE type = 'procedural' AND task_goal = ?
         ORDER BY created_at DESC LIMIT 1`,
        [taskGoal]
      );
      return parseReflectionNotes(existingRecord?.reflection_notes, host);
    }
    
    [절차 기억 자가 반추 루프]
    태스크 실행 ──► 도구 실패 감지 ──► 원인 분석 ──► reflection_notes 추가 ──► 다음 세션 실패 회피
    

    "Docker 볼륨 마운트 시 권한 에러 발생: UID 1000 명시 필요" 같은 교훈이 누적되어 동일한 실수를 원천 차단합니다.


    4. 에빙하우스 기반 지수 감쇄와 사용성 강화

    기억의 생애주기는 '자연 감쇄'와 '참조 강화'의 상호작용으로 결정됩니다.

    신선도 (Recency)
     1.0 ┬───────
         │ \
         │  \     지수 감쇄 곡선: R = exp(-ln(2) * t / halfLife)
     0.5 │   \---- 반감기 도달 시점
         │        \
     0.0 └─────────┴────────────────► 경과 시간 (t)
    

    1) 타입별 반감기 감쇄 (Recency)

    시간 경과에 따른 신선도 점수는 타입별 반감기($h$) 기반 지수 함수를 따릅니다.

    $$\text{Recency} = \exp\left(-\ln(2) \times \frac{\text{AgeDays}}{\text{HalfLife}}\right)$$

    private calculateRecency(createdAt: Date, type: string): number {
      const ageDays = daysBetween(new Date(), createdAt);
      const halfLife = this.getHalfLife(type);
      return Math.exp(-Math.log(2) * ageDays / halfLife);
    }
    
    private getHalfLife(type: string): number {
      switch (type) {
        case 'working': return 2;      // 2일
        case 'episodic': return 30;    // 30일
        case 'procedural': return 90;  // 90일
        case 'semantic': return 180;   // 180일
        default: return 30;
      }
    }
    

    2) 로그 스케일 사용성 강화 (Usage)

    기억을 조회(view), 인용(cite), 편집(edit)할 때마다 신선도 감쇄를 상쇄하는 강화 점수가 누적됩니다. 선형 가산 시 특정 기억이 점수를 무한정 독점하는 왜곡을 막기 위해 로그 스케일을 적용합니다.

    $$\text{UsageScore} = \ln(1 + \text{viewCount}) + 2\ln(1 + \text{citeCount}) + 0.5\ln(1 + \text{editCount})$$

    private calculateUsage(
      lastAccessed?: Date,
      viewCount: number = 0,
      citeCount: number = 0,
      editCount: number = 0
    ): number {
      const accessScore = lastAccessed 
        ? Math.exp(-daysBetween(new Date(), lastAccessed) / 30) 
        : 0;
    
      const usageScore = Math.log(1 + viewCount) + 
                        2 * Math.log(1 + citeCount) + 
                        0.5 * Math.log(1 + editCount);
    
      const normalizedUsage = Math.min(1, usageScore / 10);
      return Math.max(accessScore, normalizedUsage);
    }
    

    인용 횟수(citeCount)에 가중치 2를 부여하여 단순 조회보다 실제 에이전트 추론에 채택된 기억을 강하게 보존합니다.


    5. 정량적 망각 판정과 5대 신호 가중치

    배치 스케줄러는 주기적으로 모든 메모리의 5대 인지 특징을 추출해 망각 점수($\text{ForgetScore}$)를 산출합니다.

    export interface ForgettingFeatures {
      recency: number;           // 신선도 (0~1)
      usage: number;             // 사용 빈도 (0~1)
      duplication_ratio: number; // 타 메모리와의 중복 비율 (0~1)
      importance: number;        // 사용자 지정 중요도 (0~1)
      pinned: boolean;           // 강제 고정 여부
    }
    
    export class ForgettingAlgorithm {
      private readonly weights = {
        recency: 0.35,      // 오래될수록 망각 유도
        usage: 0.25,        // 방치될수록 망각 유도
        duplication: 0.20,  // 중복될수록 망각 유도
        importance: 0.15,   // 중요할수록 망각 억제
        pinned: 0.30        // 고정 시 망각 억제
      };
    
      calculateForgetScore(features: ForgettingFeatures): number {
        const { recency, usage, duplication_ratio, importance, pinned } = features;
    
        const recencyScore = this.weights.recency * (1 - recency);
        const usageScore = this.weights.usage * (1 - usage);
        const duplicationScore = this.weights.duplication * duplication_ratio;
        const importanceScore = this.weights.importance * importance;
        const pinnedScore = this.weights.pinned * (pinned ? 1 : 0);
    
        return recencyScore + usageScore + duplicationScore - importanceScore - pinnedScore;
      }
    
      shouldForget(forgetScore: number, threshold: number = 0.6): boolean {
        return forgetScore >= threshold;
      }
    }
    

    $$\text{ForgetScore} = 0.35(1 - R) + 0.25(1 - U) + 0.20 D_{\text{ratio}} - 0.15 I - 0.30 P$$

    • 신선도($R$)와 사용도($U$)가 바닥나면 기본 망각 점수는 $0.60$에 도달합니다.
    • 사용자가 pinned: true로 지정한 기억은 점수가 $0.30$ 깎여 임계값($0.60$)을 넘지 못합니다.
    • 중복 내용($D_{\text{ratio}}$)이 감지되면 점수가 가산되어 정리 우선순위가 올라갑니다.

    6. 설명 가능한 망각: Soft Delete와 감사 추적

    기억의 삭제는 에이전트 시스템에서 가장 위험한 파괴적 연산입니다. 무결성을 보장하기 위해 2단계 격리 파이프라인을 둡니다.

    [망각 판정 및 감사 파이프라인]
    배치 분석 ──► 망각 점수 >= 0.60 ──► 사유 생성 (Reason Generator)
                                               │
                     ┌─────────────────────────┴─────────────────────────┐
                     ▼                                                   ▼
             [Soft Delete]                                       [Hard Delete]
       - 검색 인덱스 즉시 제외                              - 물리 레코드 완전 파기
       - memory_forgetting_event 기록                       - 명시적 확인(confirm: true)
       - 30일 격리 유예 후 자동 소멸                        - DB VACUUM 대상
    

    1) 사유 생성기 (Explainable Reason Generator)

    삭제 결정 시 투명한 사유 문자열을 남깁니다.

    generateForgetReason(features: ForgettingFeatures, forgetScore: number): string {
      const reasons: string[] = [];
      if (features.recency < 0.3) reasons.push('오래된 기억');
      if (features.usage < 0.2) reasons.push('사용되지 않음');
      if (features.duplication_ratio > 0.7) reasons.push('중복도 높음');
      if (features.importance < 0.3) reasons.push('중요도 낮음');
      if (!features.pinned) reasons.push('고정되지 않음');
      return reasons.join(', ');
    }
    

    2) 감사 이벤트 테이블 (memory_forgetting_event)

    망각 조치가 실행될 때마다 감사 레코드를 영구 보존합니다.

    CREATE TABLE memory_forgetting_event (
      id TEXT PRIMARY KEY,
      memory_id TEXT NOT NULL,
      action TEXT NOT NULL CHECK (action IN ('soft', 'hard', 'review')),
      reason TEXT NOT NULL,
      policy TEXT NOT NULL,
      forget_score REAL,
      ttl_days INTEGER,
      created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
      metadata_json TEXT
    );
    

    소프트 삭제된 기억은 검색 인덱스에서 즉시 배제되며 30일 동안 데이터베이스에 격리 보관됩니다. 에이전트 오판으로 인한 지식 유실 시 언제든 복구합니다.


    7. 아키텍처 비교 요약

    비교 축 무제한 컨텍스트 누적 방식 Memento 기억 생애주기 운영체제
    저장 철학 모든 토큰을 단일 컨텍스트에 유지 인지 특성에 따라 4계층으로 분리 격리
    시간 처리 슬라이딩 윈도우로 과거 기억 잘림 반감기 곡선 기반 점진적 지수 감쇄
    참조 반영 빈도에 따른 가중치 변화 없음 인용·수정 시 로그 스케일 영구 강화
    절차 개선 프롬프트에 정적 지침 나열 CAS 동시성 제어 및 반추 노트 자가 갱신
    정리 방식 수동 컨텍스트 초기화 (/clear) 5대 인지 신호 기반 자율 망각 (Soft/Hard)
    감사 추적 삭제 내역 증발 memory_forgetting_event 영구 기록 및 30일 복구 유예
    반응형
Designed by Tistory.