개인용 AI는 기억하기 전에 물어봐야 한다
요약
개인용 AI의 기억 저장 과정에서 인간의 검토와 승인을 필수적으로 포함하는 오픈 소스 Python SDK, DiaryVault Memory Layer v0.4.0을 소개합니다. AI의 제안이 무비판적으로 사실로 굳어지는 것을 방지하기 위해 초안 생성부터 암호화된 확정까지의 엔드 투 엔드 워크플로우를 제공합니다.
핵심 포인트
- AI 제안과 인간의 명시적 승인을 분리하는 검토 워크플로우 도입
- 변조 방지 및 암호화 기술을 통한 개인 메모 기록의 무결성 보장
- 초안(Draft)과 확정된 메모리(Finalized Memory)의 단계적 구분
- 출처 인지 내보내기 및 RAG 준비 완료된 청크 지원
지속 가능한 초안(persistent drafts), 명시적인 인간의 승인(explicit human approval), 변조 방지 확정(tamper evident finalization), 수정 이력(revision history), 그리고 출처 인식 AI 내보내기(provenance aware AI exports) 기능을 갖춘 오픈 소스 Python 메모리 레이어(memory layer)를 구축한 방법입니다.
개인용 AI 시스템은 기억하는 능력이 점점 더 강력해지고 있습니다.
대화 내용을 요약하고, 반복적으로 등장하는 인물을 식별하며, 사진으로부터 위치를 추론하고, 감정 패턴을 감지하며, 수년에 걸친 사건들을 연결할 수 있습니다.
하지만 이는 더 깊은 질문을 던지게 합니다:
AI의 제안이 언제 한 개인의 개인적 역사(personal history)의 일부가 되는가?
모델은 특정 사진이 서울에서 촬영되었다고 제안할 수 있습니다. 누가 있었는지 식별하거나, 누군가의 기분을 추론하거나, 그 순간을 위한 제목을 만들 수도 있습니다.
그 제안은 도움이 될 수도 있습니다.
하지만 틀릴 수도 있습니다.
어느 쪽이든, 그것이 조용히 사실(fact)이 되어서는 안 됩니다.
이것이 오픈 소스 DiaryVault Memory Layer 버전 0.4.0의 원칙입니다:
AI는 제안하고, 사람은 확인한다.
이번 릴리스는 초기 캡처(capture)부터 명시적 승인(explicit approval), 암호화된 확정(cryptographic finalization), 그리고 출처 인식 내보내기(provenance aware export)에 이르기까지 개인 메모 기록을 위한 엔드 투 엔드(end to end) 검토 워크플로우를 도입합니다.
DiaryVault Memory Layer란 무엇인가?
DiaryVault Memory Layer는 휴대 가능하고 변조 방지가 가능한 개인 메모 기록을 위한 오픈 소스 Python SDK입니다.
이번 릴리스 이전에도 SDK는 이미 다음을 지원했습니다:
로컬 메모리 저장 (Local memory storage)
SHA 256 콘텐츠 해싱 (SHA 256 content hashing)
AES 256 GCM 암호화 (AES 256 GCM encryption)
HMAC SHA 256 무결성 서명 (HMAC SHA 256 integrity signatures)
변조 감지 (Tamper detection)
선택적 컨텍스트 공유 (Selective context sharing)
JSONL 내보내기 (JSONL exports)
RAG 준비 완료된 청크 (RAG ready chunks)
대화 기록 내보내기 (Conversation history exports)
개인 지식 그래프 (Personal knowledge graphs)
휴대 가능한 .dvmem 기록 (Portable .dvmem records)
버전 0.4.0은 캡처와 영구 메모 사이의 누락된 계층을 추가합니다:
인간의 검토 (human review).
AI가 생성한 정보가 영구 기록으로 직접 흘러 들어가게 하는 대신, 이제 애플리케이션은 초안(draft)을 생성하고, 제안을 첨부하며, 명시적인 결정을 기록하고, 결과를 승인한 다음, 검증된 메모리로 확정할 수 있습니다.
검토 워크플로우
생명 주기(lifecycle)는 의도적으로 명시적입니다:
Capture (캡처)
↓
ReviewDraft (검토 초안)
↓
AI suggestions (AI 제안)
↓
Accept, edit, or reject (수락, 수정 또는 거부)
↓
Explicit approval (명시적 승인)
↓
Finalized Memory (확정된 메모리)
↓
Provenance aware exports (출처 인지 내보내기)
각 단계는 뚜렷한 의미를 가집니다.
제안(suggestion)은 확정된 값이 아닙니다.
열려 있는 초안(open draft)은 승인된 메모리가 아닙니다.
승인된 초안(approved draft)이라도 확정(finalized)되기 전까지는 영구적이지 않습니다.
하류(downstream) AI 시스템은 모든 저장된 값을 동일하게 권위 있는 것으로 취급하는 대신, 메모리가 검토되었는지 여부를 판단할 수 있습니다.
초안 생성 및 유지 (Creating and persisting a draft)
검토 워크플로우는 MemoryVault 내부에서 시작됩니다:
from diaryvault_memory import MemoryVault
vault = MemoryVault(
encryption_key="replace-with-a-private-secret",
storage_dir="./memory-data",
)
draft = vault.create_draft(
content="She laughed when the dog sneezed.",
tags=["family"],
)
초안은 확정된 메모리와 별도로 저장됩니다.
이러한 분리는 매우 중요합니다. 초안은 검토 중에 변경될 수 있는 반면, 확정된 메모리는 완료된 기록을 나타내기 때문입니다.
애플리케이션은 초안을 저장, 검색, 목록화 및 삭제할 수 있습니다:
vault.save_draft(draft)
restored = vault.get_draft(draft.draft_id)
open_drafts = vault.list_drafts(state="open")
vault.delete_draft(draft.draft_id)
초안 레코드는 자체 저장 디렉토리에 존재하므로, 확정되기 전에는 일반적인 메모리 검색이나 내보내기에 나타나지 않습니다.
AI 제안은 미확정 상태로 유지됩니다 (AI suggestions remain unconfirmed)
AI 시스템은 사용자의 확정된 기록을 변경하지 않고도 제안을 첨부할 수 있습니다:
draft = draft.add_suggestion(
field_name="location",
value="Seoul",
source="echo",
model="example-model",
process_version="memory-card-v1",
confidence=0.88,
suggestion_id="suggestion-location",
)
draft = draft.add_suggestion(
field_name="title",
value="The first laugh",
source="echo",
suggestion_id="suggestion-title",
)
vault.save_draft(draft)
각 제안에는 다음이 포함될 수 있습니다:
제안된 필드 (The proposed field)
제안된 값 (The proposed value)
그 출처 (Its source)
이를 생성한 모델 (The model that that created it)
프로세스 또는 프롬프트 버전 (A process or prompt version)
신뢰도 (Confidence, 가능한 경우)
생성 타임스탬프 (A creation timestamp)
이러한 제안된 값 중 어느 것도 사람이 수락하기 전까지는 resolved_fields()에 나타나지 않습니다.
제안 수락, 수정 및 거절
검토자(Reviewer)는 제안된 값을 수락할 수 있습니다:
draft = draft.accept(
"suggestion-location",
reviewer="parent",
)
수정 사항과 함께 수락할 수도 있습니다:
draft = draft.accept(
"suggestion-location",
reviewer="parent",
value="Seoul Forest",
)
또는 완전히 거절할 수도 있습니다:
draft = draft.reject_suggestion(
"suggestion-title",
reviewer="parent",
)
수정된 값이 확정된 값(confirmed value)이 됩니다.
원래의 AI 제안은 출처(provenance)로서 보존됩니다.
이러한 구분은 중요합니다. 시스템은 모델이 옳았던 것처럼 보이게 하기 위해 제안 내용을 다시 쓰지 않습니다.
승인은 실제 상태 전이(state transition)입니다
제안이 결정되지 않은 상태에서는 초안(draft)을 승인할 수 없습니다:
draft = draft.approve(
reviewer="parent",
)
승인은 누가 언제 검토를 완료했는지 기록합니다.
검토 객체(review objects)는 자체 불변성(invariants) 또한 검증합니다. 다음과 같은 유효하지 않은 상태는 거부됩니다:
- 중복된 제안 식별자 (Duplicate suggestion identifiers)
- 알 수 없는 제안을 참조하는 결정 (Decisions referencing unknown suggestions)
- 하나의 제안에 대한 여러 결정 (Multiple decisions for one suggestion)
- 동일한 필드에 대한 여러 개의 수락된 값 (Multiple accepted values for the same field)
- 보류 중인 제안이 있는 승인된 초안 (Approved drafts with pending suggestions)
- 완료 메타데이터를 포함하고 있는 오픈된 초안 (Open drafts carrying completion metadata)
- 수락된 값을 포함하고 있는 거절된 결정 (Rejected decisions carrying accepted values)
이러한 체크는 JSON 역직렬화(deserialization) 과정 중에도 실행됩니다.
잘못된 형식의 레코드를 로드하더라도 일반적인 생성 과정에서 사용되는 동일한 규칙을 우회할 수 없습니다.
깊은 불변성 (Deep immutability)
검토 도메인은 동결된 값 객체(frozen value objects)를 사용하지만, 외부 데이터 클래스(dataclass)만 동결하는 것으로는 충분하지 않습니다.
동결되었다고 가정되는 제안이라 할지라도 여전히 가변적인(mutable) 딕셔너리나 리스트를 포함할 수 있기 때문입니다.
버전 0.4.0은 JSON 스타일의 값들을 재귀적으로 동결하여, 호출자가 생성 후 중첩된 데이터를 변경할 수 없도록 합니다.
개념적으로, 이는 더 이상 불가능합니다:
draft.suggestions[0].value["people"].append("Someone else")
직렬화 (Serialization)는 동결된 구조를 다시 일반적인 JSON 호환 값으로 변환합니다.
이를 통해 휴대 가능한 저장 능력을 희생하지 않으면서도, 실행 중인 도메인 모델의 불변성 (Immutability)을 보장할 수 있습니다.
승인된 메모리 확정하기
승인되면 초안 (draft)을 확정할 수 있습니다:
memory = vault.finalize_draft(draft)
확정 과정은 일반적인 메모리 생성과 동일한 처리 파이프라인을 재사용합니다:
콘텐츠 (Content)
↓
SHA 256 해시 (hash)
↓
AES 256 GCM 암호화 (encryption)
↓
HMAC SHA 256 서명 (signature)
↓
로컬 저장소 (Local storage)
결과물인 메모리는 다음 항목 아래에 전체 검토 기록을 포함합니다:
memory.metadata.custom["review"]
해당 기록에는 다음 내용이 포함됩니다:
원본 콘텐츠 (Original content)
제안 사항 (Suggestions)
모델 출처 (Model provenance)
사용자 결정 (User decisions)
수락된 수정 사항 (Accepted corrections)
거부 사항 (Rejections)
검토자 신원 (Reviewer identity)
승인 시간 (Approval time)
명시적으로 수락된 다른 필드들은 확정된 메타데이터 (confirmed metadata) 아래에서 계속 사용할 수 있습니다.
예를 들어, 수락된 위치 정보는 다음과 같이 될 수 있습니다:
memory.metadata.location
확정된 초안은 단 한 번만 확정될 수 있습니다.
확정된 초안은 영구 메모리의 출처 (provenance)가 되었기 때문에 더 이상 교체하거나 삭제할 수 없습니다.
이 규칙은 프로세스 재시작 후에도 유지됩니다.
memory_id = vault.finalized_memory_id(draft.draft_id)
중복 상태 없는 수정 이력
검토 활동은 파생된 수정 이력 (revision history)을 통해 확인할 수 있습니다:
for revision in draft.revision_history():
print(
revision.occurred_at,
revision.action,
revision.actor,
)
전형적인 작업 (actions)에는 다음이 포함됩니다:
draft_created (초안 생성)
suggestion_added (제안 추가)
suggestion_accepted (제안 수락)
suggestion_rejected (제안 거부)
draft_approved (초안 승인)
수정 이력은 별도의 가변적인 이벤트 로그 (mutable event log)로 저장되지 않습니다.
이는 초안, 제안, 결정 및 최종 승인에 이미 존재하는 타임스탬프 (timestamps)로부터 파생됩니다.
이를 통해 신뢰할 수 있는 원천 (sources of truth)이 두 개가 되는 것을 방지합니다.
이력은 자신이 설명하는 기록으로부터 벗어날 수 없습니다.
누락된 조각: 출처를 인식하는 내보내기 (provenance aware exports)
볼트 (vault) 내부에 검토 정보를 보존하는 것만으로는 충분하지 않습니다.
AI의 제안 (suggestion)과 인간이 확인한 값 (human confirmed value) 사이의 구분은 데이터가 다른 시스템으로 들어갈 때도 유지되어야 합니다.
따라서 버전 0.4.0은 검토 출처 (review provenance)를 내보내기 계층 (export layer)까지 전달합니다.
RAG 청크 (RAG chunks)
from diaryvault_memory import VaultExporter
exporter = VaultExporter(vault)
chunks = exporter.to_rag_chunks()
review = chunks[0].metadata["review"]
검토된 메모리는 다음과 같이 압축된 요약 정보를 노출할 수 있습니다:
{
"reviewed": True,
"approved_by": "parent",
"approved_at": "2026-07-19T10:30:00+00:00",
"suggestion_count": 2,
"accepted_count": 1,
"confirmed_fields": ["location"],
}
검토 기록이 없는 일반적인 메모리는 다음과 같이 명확하게 표시됩니다:
{
"reviewed": False,
}
이제 검색 시스템 (retrieval system)은 사람이 명시적으로 검토했는지 여부에 따라 메모리의 순위를 매기거나, 필터링하거나, 라벨을 붙일 수 있습니다.
범용 JSONL (Generic JSONL)
검토 요약은 범용 JSONL 형식에 포함됩니다:
examples = exporter.to_jsonl(
format="generic",
)
각 레코드는 메모리 내용과 확인 상태 (confirmation status)를 모두 담을 수 있습니다.
대화 기록 (Conversation history)
대화 내보내기 (Conversation exports)에는 메타데이터 (metadata)에 검토 요약이 포함됩니다:
history = exporter.to_conversation_history()
review = history[0]["metadata"]["review"]
이를 통해 어시스턴트 (assistant)는 컨텍스트 (context)를 재구성할 때 검토된 개인 기록과 검토되지 않은 정보를 구분할 수 있습니다.
지식 그래프 (Knowledge graphs)
개인 지식 그래프 (personal knowledge graph)의 메모리 노드 (memory nodes) 또한 검토 메타데이터를 포함합니다:
graph = exporter.to_knowledge_graph()
memory_nodes = [
node
for node in graph.nodes
if node.node_type == "memory"
]
따라서 메모리가 노드 (nodes)와 관계 (relationships)가 되어도 출처 (provenance)가 그대로 유지됩니다.
스키마가 깨끗한 미세 조정 (Schema clean fine tuning) 내보내기
OpenAI와 Anthropic의 미세 조정 (fine tuning) 형식은 의도적으로 스키마가 깨끗하게 유지됩니다.
SDK는 특정 메시지 구조를 기대하는 형식에 커스텀 검토 필드를 주입하지 않습니다.
출처가 필요한 애플리케이션은 범용 JSONL, RAG, 대화 또는 그래프 내보내기를 사용할 수 있습니다.
이것이 개인용 AI에 중요한 이유
다음 두 가지 값을 포함하는 검색 시스템(retrieval system)을 상상해 보세요:
위치: 서울
위치: 서울숲
출처(provenance)가 없다면, 다운스트림 모델(downstream model)은 다음을 알 수 없습니다:
어떤 값이 AI로부터 왔는지
사용자가 어떤 값을 수정했는지
두 값 중 어느 것이 검토되었는지
결정이 언제 내려졌는지
누가 승인했는지
검토 기록(review record)이 있다면, 시스템은 다음과 같이 이해할 수 있습니다:
AI 제안: 서울
사용자 확인: 서울숲
검토자: 부모
상태: 승인됨
이것은 단순히 메타데이터가 더 많아지는 것이 아닙니다.
기록의 의미 자체를 변화시킵니다.
전체 예시
from tempfile import TemporaryDirectory
from diaryvault_memory import MemoryVault, VaultExporter
with TemporaryDirectory() as storage_dir:
vault = MemoryVault(
encryption_key="synthetic-example-key",
storage_dir=storage_dir,
)
draft = vault.create_draft(
content="She laughed when the dog sneezed.",
tags=["family"],
...
신뢰 경계(trust boundary) 테스트
버전 0.4.0은 122개의 테스트로 커버됩니다.
테스트 스위트(test suite)에는 다음이 포함됩니다:
검토 상태 전이 (Review state transitions)
깊은 중첩 불변성 (Deep nested immutability)
잘못된 역직렬화 (Invalid deserialization)
초안 영속성 및 다시 불러오기 (Draft persistence and reload)
초안 필터링 및 삭제 (Draft filtering and deletion)
확정 요구 사항 (Finalization requirements)
단일 확정 보장 (Single finalization guarantees)
프로세스 재시작 후 확정 (Finalization after process restart)
파생된 수정 이력 (Derived revision history)
승인 인지 RAG 내보내기 (Approval aware RAG exports)
승인 인지 범용 JSONL (Approval aware generic JSONL)
대화 이력 출처 (Conversation history provenance)
지식 그래프 출처 (Knowledge graph provenance)
검토된 메모리 내보내기 횟수 (Reviewed memory export counts)
기존 메모리 기능과의 호환성 (Compatibility with existing memory features)
이 패키지는 Ruff 체크를 통과하며, 두 가지 공개 예시를 실행하고, 버전화된 소스 및 wheel 배포판을 빌드합니다.
정직한 경계
이것은 아직 알파(Alpha) 소프트웨어입니다.
SDK는 다음을 수행하지 않습니다:
AI 모델 호출
제안이 사실인지 여부 결정
독립적으로 신뢰할 수 있는 타임스탬프 제공
법적 저작권 확립
클라우드 서비스를 통한 데이터 동기화
프로덕션 DiaryVault 모바일 애플리케이션과의 직접적인 통합
내보낸 복사본을 나중에 취소할 수 있다는 보장
Drafts는 로컬 애플리케이션 기록인 반면, 확정된 기억(memories)은 SDK의 해싱 (hashing), 암호화 (encryption), 서명 (signing) 및 저장 파이프라인을 거칩니다.
애플리케이션은 전체 저장 디렉토리를 민감한 정보로 취급해야 하며, 개인 데이터를 내보내기 전에 명시적인 승인을 요구해야 합니다.
이것을 만든 이유
저는 다음과 같은 단순한 아이디어를 중심으로 DiaryVault를 구축하고 있습니다:
개인용 AI는 사용자의 역사를 조용히 다시 쓰지 않으면서, 사람들이 기억하는 것을 도와야 합니다.
AI는 기억을 정리할 수 있습니다.
맥락 (context)을 제안할 수 있습니다.
수천 장의 사진과 일기 기록 속에서 사라져 버릴 수도 있는 패턴을 식별할 수 있습니다.
하지만 최종적인 권한은 인간에게 남아 있어야 합니다.
그 원칙은 단순히 인터페이스 문구나 확인 버튼에만 머물러서는 안 됩니다.
그것은 근본적인 데이터 모델 (data model), 지속성 규칙 (persistence rules), 무결성 검사 (integrity checks), 수정 이력 (revision history) 및 내보내기 형식 (export formats)에 존재해야 합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기