04-rules-conflict-resolution

Dec 7, 2025

Conflict Resolution

동일한 정보에 대해 충돌하는 값이 있을 때 어떤 것을 사용할지 결정하는 규칙입니다.

왜 충돌이 발생하는가?

시나리오 1: 정보 업데이트

이메일 1 (1/15): "미팅 2시에 합시다"
이메일 2 (1/18): "미팅 3시로 변경됐습니다"

같은 미팅에 대해 2vs 3

시나리오 2: 정보 불일치

이메일 A: "김철수, ABC회사"
이메일 B: "김철수, XYZ회사"

같은 사람의 소속이 다름

시나리오 3: 다중 소스

Gmail에서 추출: "프로젝트 마감일 1/25"
사용자 직접 입력: "프로젝트 마감일 1/28"

어떤 정보를 믿을까

우선순위 체계

SourceType 우선순위

USER_INPUT > BOOTSTRAPPED > TOOL_OUTPUT > REALTIME

순위

SourceType

설명

신뢰도

1

USER_INPUT

사용자가 직접 입력

최고

2

BOOTSTRAPPED

초기 데이터 수집 (검증됨)

높음

3

TOOL_OUTPUT

MCP 도구가 생성

중간

4

REALTIME

실시간 수집 (검증 시간 없음)

낮음

왜 이 순서인가?

USER_INPUT이 최우선:

  • 사용자가 명시적으로 입력 = 의도적

  • "시스템이 틀렸어, 이게 맞아"

BOOTSTRAPPED가 두 번째:

  • 초기 설정 시 검증 과정 거침

  • 일괄 처리로 품질 관리 가능

REALTIME이 최하위:

  • 즉각적으로 처리되어 검증 시간 부족

  • 잠재적 오류 가능성 높음

충돌 해결 알고리즘

function resolveConflict(
  existing: Memory | Person | Entity,
  incoming: Memory | Person | Entity
): 'KEEP_EXISTING' | 'USE_INCOMING' | 'MERGE' {

  // 1. SourceType 우선순위 비교
  const priority = {
    [SourceType.USER_INPUT]: 4,
    [SourceType.BOOTSTRAPPED]: 3,
    [SourceType.TOOL_OUTPUT]: 2,
    [SourceType.REALTIME]: 1,
  };

  const existingPriority = priority[existing.sourceType];
  const incomingPriority = priority[incoming.sourceType];

  if (incomingPriority > existingPriority) {
    return 'USE_INCOMING';
  }

  if (incomingPriority < existingPriority) {
    return 'KEEP_EXISTING';
  }

  // 2. 같은 우선순위면 → 추가 기준 적용
  return resolveSamePriority(existing, incoming);
}

동일 우선순위 해결

SourceType이 같을 때 추가 기준:

2-1. 시간 기반 (Time-based)

// 더 최근 정보 우선
if (incoming.updatedAt > existing.updatedAt) {
  return 'USE_INCOMING';
}

적용 상황: 정보 업데이트 (미팅 시간 변경 등)

2-2. 신뢰도 기반 (Confidence-based)

// 더 높은 confidence 우선
if (incoming.confidence > existing.confidence + 0.1) {
  return 'USE_INCOMING';
}

적용 상황: LLM 추출 결과 비교

2-3. 중요도 기반 (Importance-based)

// 더 높은 importance 우선
if (incoming.importance > existing.importance) {
  return 'USE_INCOMING';
}

적용 상황: 중요한 정보가 덜 중요한 정보를 덮어씀

2-4. 병합 (Merge)

// 둘 다 유효하면 병합
return 'MERGE';

적용 상황: 상호 보완적인 정보

필드별 해결 전략

Person.organization

Email A: 김철수, ABC회사
Email B: 김철수, XYZ회사

전략: 최신 정보 사용 + 이전 정보 기록

person.organization = "XYZ회사";  // 최신
person.previousOrganizations = ["ABC회사"];  // 이력

Memory.content

Memory v1: "미팅 2시"
Memory v2: "미팅 3시로 변경"

전략: 버전 관리 (UPDATE 관계)

memoryV2.previousVersionId = memoryV1.id;
// UPDATES 관계 생성

Entity.aliases

Entity A: name="삼성", aliases=[]
Entity B: name="Samsung", aliases=[]

전략: 병합

merged.name = "삼성";  // primary 유지
merged.aliases = ["Samsung"];  // 병합

CONTRADICTS 관계 활용

해결 불가능한 충돌은 명시적으로 표시:

// 충돌 감지
if (isContradictory(existing, incoming)) {
  // 관계로 기록
  createExplicitRelationship({
    type: ExplicitRelationType.CONTRADICTS,
    sourceId: incoming.id,
    targetId: existing.id,
    confidence: 0.9,
    evidence: `${existing.content} vs ${incoming.content}`,
  });

  // 사용자에게 알림
  notifyConflict(existing, incoming);
}

충돌 판단 기준

function isContradictory(a: Memory, b: Memory): boolean {
  // 1. 같은 주제인가?
  const sameSubject = a.subject === b.subject ||
                      hasSameEntities(a, b);

  // 2. 내용이 다른가?
  const differentContent = a.content !== b.content;

  // 3. 상충하는가? (LLM 판단)
  const contradicts = llmJudgeContradiction(a.content, b.content);

  return sameSubject && differentContent && contradicts;
}

실제 예시

예시 1: 미팅 시간 변경

기존: { content: "미팅 2시", sourceType: BOOTSTRAPPED, updatedAt: 1/15 }
수신: { content: "미팅 3시", sourceType: BOOTSTRAPPED, updatedAt: 1/18 }

1. SourceType 동일 추가 기준
2. 수신이 최근 USE_INCOMING
3. 기존에 UPDATES 관계 추가

결과: 메모리 저장, 기존 메모리와 연결

예시 2: 사용자 수정

기존: { content: "예산 500만원", sourceType: BOOTSTRAPPED }
수신: { content: "예산 800만원", sourceType: USER_INPUT }

1. USER_INPUT > BOOTSTRAPPED
2. USE_INCOMING

결과: 사용자 입력으로 덮어쓰기

예시 3: 실시간 vs 초기

기존: { organization: "ABC회사", sourceType: BOOTSTRAPPED }
수신: { organization: "XYZ회사", sourceType: REALTIME }

1. BOOTSTRAPPED > REALTIME
2. KEEP_EXISTING

결과: 기존 유지 (실시간 정보 무시)

우선순위 요약 다이어그램

┌─────────────────────────────────────────────────────────┐
충돌 해결 흐름                          
└─────────────────────────────────────────────────────────┘
                         
                         
              ┌─────────────────────┐
              SourceType 비교      
              └──────────┬──────────┘
                         
         ┌───────────────┼───────────────┐
         
    incoming >      동일 우선순위     existing >
    existing                          incoming
         
         
   USE_INCOMING    ┌─────────┐    KEEP_EXISTING
                   시간 비교 
                   └────┬────┘
                        
            ┌───────────┼───────────┐
            
       최근       동일        과거
            
            
      USE_INCOMING  Confidence   KEEP_EXISTING
                      비교
                        
                ┌───────┼───────┐
                
              더높음  동일    더낮음
                
                
          USE_INCOMING MERGE KEEP_EXISTING

다음 문서

  • → Importance Scoring: 중요도 점수

  • → BaseNode: SourceType 정의