Skip to content

Commit a9a3b42

Browse files
ihwooclaude
authored andcommitted
Add architecture docs and blog post
- docs/ARCHITECTURE.md: Technical documentation (6-layer system design) - docs/BLOG_POST.md: Medium blog post draft Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 9b15fab commit a9a3b42

File tree

2 files changed

+507
-0
lines changed

2 files changed

+507
-0
lines changed

docs/ARCHITECTURE.md

Lines changed: 353 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,353 @@
1+
# AIMemory Architecture
2+
3+
> mcp-memory-server 내부 구조와 설계 결정을 설명하는 기술 문서
4+
5+
## 시스템 개요
6+
7+
AIMemory는 AI 어시스턴트에 **영구적이고 자기 관리되는 기억**을 부여하는 MCP 서버입니다.
8+
9+
기존 `.md` 파일 기반 기억의 두 가지 한계를 해결합니다:
10+
11+
1. **수동 검색 문제**`.md`에 적어둬도 AI가 매번 확인하지 않음
12+
2. **토큰 낭비 문제** — 전체 파일을 context에 넣으면 불필요한 내용까지 포함
13+
14+
## 아키텍처 다이어그램
15+
16+
```
17+
┌──────────────────────────────────────────────────────┐
18+
│ MCP Client │
19+
│ (Claude Desktop / Claude Code) │
20+
└──────────────────────┬───────────────────────────────┘
21+
│ stdio (JSON-RPC)
22+
┌──────────────────────▼───────────────────────────────┐
23+
│ FastMCP Server (12 tools) │
24+
│ src/aimemory/mcp/server.py │
25+
├──────────────────────────────────────────────────────┤
26+
│ MemoryBridge (orchestrator) │
27+
│ src/aimemory/mcp/bridge.py │
28+
├─────────┬───────────┬───────────┬────────────────────┤
29+
│ Decision│ Retrieval │ Storage │ Maintenance │
30+
│ Layer │ Layer │ Layer │ Layer │
31+
├─────────┼───────────┼───────────┼────────────────────┤
32+
│ Online │ Graph │ Graph │ Sleep Cycle │
33+
│ Policy │ Retriever │ Memory │ Runner │
34+
│ + Agent │ (GraphRAG)│ Store │ │
35+
│ │ │ (ChromaDB)│ ├─ Consolidation │
36+
│ ReRanker│ Knowledge │ │ ├─ Forgetting │
37+
│ (11d) │ Graph │ │ ├─ Resolution Regen │
38+
│ │ (NetworkX)│ │ └─ Checkpoint │
39+
│ Feedback│ │ │ │
40+
│ Detector│ Context │ │ │
41+
│ │ Composer │ │ │
42+
└─────────┴───────────┴───────────┴────────────────────┘
43+
```
44+
45+
## 6개 레이어 상세
46+
47+
---
48+
49+
### Layer 1: Decision — RL 메모리 정책
50+
51+
**파일**: `src/aimemory/online/policy.py`, `enhanced_policy.py`
52+
53+
매 대화 턴마다 **SAVE / SKIP / RETRIEVE** 중 하나를 결정합니다.
54+
55+
#### 3단계 결정 파이프라인
56+
57+
```
58+
사용자 메시지 입력
59+
60+
61+
Phase 0: RETRIEVE 판단 (rule-based)
62+
질문 패턴? discourse marker? → 저장된 메모리 있으면 RETRIEVE
63+
64+
65+
Phase 1: 고/저확신 직접 결정 (rule-based)
66+
importance ≥ 0.7 → SAVE (개인정보, 강한 선호 등)
67+
importance ≤ 0.1 → SKIP (인사, 짧은 응답 등)
68+
69+
70+
Phase 2: 중간 영역 → MLP Bandit 결정
71+
10d feature vector → Linear(10,64) → ReLU → Linear(64,3)
72+
epsilon-greedy (ε=0.1) action selection
73+
```
74+
75+
#### Importance 가중합
76+
77+
| 패턴 | 가중치 | 예시 |
78+
|------|--------|------|
79+
| 개인정보 | +0.4 | "내 이름은...", "나는 서울에 살아" |
80+
| 선호 | +0.35 | "나는 Python을 좋아해" |
81+
| 기술 | +0.3 | "React 18에서 Suspense는..." |
82+
| 감정 | +0.2 | "요즘 번아웃이 심해" |
83+
| 키워드 밀도 | +0.15 | 명사 비율이 높은 문장 |
84+
85+
#### StateEncoder (10d feature vector)
86+
87+
```
88+
[turn_position, memory_count, keyword_count, is_question,
89+
has_personal_info, has_preference, has_tech, has_emotion,
90+
recent_save_count, recent_retrieve_count]
91+
```
92+
93+
#### Enhanced Policy (opt-in)
94+
95+
- 778d state: SentenceTransformer 768d + hand-crafted 10d
96+
- 더 큰 MLP: 778d → 256 → 128 → 3 (dropout 0.1)
97+
- Experience Replay Buffer (capacity=5000, batch=32)
98+
- Progressive Autonomy: 긍정 피드백 누적 → RL 영역 점진적 확장
99+
100+
---
101+
102+
### Layer 2: Retrieval — GraphRAG 하이브리드 검색
103+
104+
**파일**: `src/aimemory/memory/graph_retriever.py`, `online/reranker.py`
105+
106+
#### 검색 파이프라인
107+
108+
```
109+
사용자 메시지
110+
111+
├─→ ChromaDB 벡터 검색 (cosine similarity)
112+
│ 상위 20개 후보 (reranker_pool_size)
113+
114+
├─→ KnowledgeGraph 탐색 (opt-in)
115+
│ 엔티티 추출 → multi-hop traversal
116+
117+
118+
Score Fusion: final = vector × 0.6 + graph × 0.4
119+
120+
121+
RL Re-ranker (11d feature → 32h → 1 score)
122+
123+
124+
Context Composer (token budget 내 top-K 선별)
125+
```
126+
127+
#### Re-ranker Features (11d)
128+
129+
| # | Feature | 설명 |
130+
|---|---------|------|
131+
| 0 | chroma_similarity | 원본 벡터 유사도 |
132+
| 1 | keyword_overlap | 쿼리-메모리 키워드 Jaccard |
133+
| 2 | category_match | 추론된 카테고리 일치 |
134+
| 3 | recency | 카테고리별 시간 감쇠 |
135+
| 4 | access_frequency | log1p(access_count) |
136+
| 5 | content_length_ratio | 정규화된 길이 비율 |
137+
| 6 | has_related | 그래프 연결 여부 |
138+
| 7 | resolution_available | 가용 해상도 수 |
139+
| 8 | graph_connection_count | KG 엔티티 연결 수 |
140+
| 9 | graph_hop_distance | KG 홉 거리 |
141+
| 10 | has_negative_relation | 부정 관계 여부 |
142+
143+
#### Context Composer — 다해상도 선택
144+
145+
토큰 budget(기본 1024) 내에서 MMR(Maximal Marginal Relevance) 알고리즘으로 다양성과 관련성을 균형 있게 선택합니다.
146+
147+
```
148+
메모리 A: Level 0 (전문 60토큰) → budget 초과 시 Level 1 (요약 25토큰) → Level 2 (트리플 10토큰)
149+
메모리 B: Level 0 (전문 40토큰) → budget 내이면 그대로 사용
150+
```
151+
152+
3가지 해상도:
153+
- **Level 0**: 원문 그대로
154+
- **Level 1**: 키워드 포함 1-2문장 요약 (max 100자)
155+
- **Level 2**: entity triple (subject, predicate, object)
156+
157+
---
158+
159+
### Layer 3: Storage — GraphMemoryStore
160+
161+
**파일**: `src/aimemory/memory/graph_store.py`, `knowledge_graph.py`
162+
163+
#### MemoryNode 구조
164+
165+
```python
166+
MemoryNode(
167+
memory_id="a1b2c3d4e5f6", # 12-char hex
168+
content="사용자는 Python을 좋아함",
169+
keywords=["Python", "선호"],
170+
category="preference", # fact/preference/experience/emotion/technical/core_principle
171+
related_ids=["x1y2z3..."], # 양방향 그래프 엣지
172+
created_at="2026-02-28T...",
173+
access_count=5, # 검색 시 자동 증가
174+
level1_text="Python 선호", # Level 1 요약
175+
level2_text="사용자,좋아함,Python", # Level 2 트리플
176+
immutable=False, # True이면 수정/삭제 불가
177+
pinned=False, # True이면 망각 보호
178+
active=True, # False이면 검색 제외
179+
)
180+
```
181+
182+
#### ChromaDB 설정
183+
184+
- Embedding model: `intfloat/multilingual-e5-small` (384d, 한/영 지원)
185+
- Distance metric: cosine (HNSW)
186+
- 영속 저장: SQLite 기반 (서버 재시작 후에도 유지)
187+
188+
#### KnowledgeGraph (NetworkX DiGraph)
189+
190+
Level 2 텍스트(`subject,predicate,object`)를 자동 파싱하여 엔티티-관계 그래프를 구축합니다.
191+
192+
```
193+
사용자 ──좋아함──→ Python
194+
사용자 ──싫어함──→ Java
195+
Python ──관련──→ FastAPI
196+
```
197+
198+
- multi-hop 탐색 (깊이 1~3)
199+
- 부정 관계 감지 ("싫어함", "dislike" 등)
200+
- 메모리 저장/삭제 시 자동 동기화
201+
202+
---
203+
204+
### Layer 4: Maintenance — 수면 사이클
205+
206+
**파일**: `src/aimemory/memory/sleep_cycle.py`, `forgetting.py`, `consolidation.py`
207+
208+
주기적으로 실행되는 4단계 유지보수:
209+
210+
```
211+
Sleep Cycle
212+
213+
├─ 1. Consolidation (통합)
214+
│ 유사도 ≥ 0.92인 메모리 쌍 탐지 → 병합
215+
│ access_count 높은 쪽이 생존
216+
217+
├─ 2. Resolution Regeneration (해상도 재생성)
218+
│ level1_text / level2_text 누락된 메모리 재생성
219+
220+
├─ 3. Forgetting (망각)
221+
│ importance = (1 + access_count) × e^(-λ×days) + related_boost × edges
222+
223+
│ importance < 0.3 → Level 2로 압축
224+
│ importance < 0.1 → 비활성화 (검색 제외)
225+
│ 비활성 30일 경과 → 영구 삭제 + 감사 기록
226+
227+
│ ※ pinned / immutable 메모리는 보호됨
228+
229+
└─ 4. Checkpoint (체크포인트)
230+
RL 모델 파라미터 저장
231+
```
232+
233+
---
234+
235+
### Layer 5: Reward — 보상 신호
236+
237+
**파일**: `src/aimemory/reward/`, `online/reranker.py`
238+
239+
RL 정책을 실시간으로 개선하기 위한 보상 수집:
240+
241+
#### 명시적 피드백 (FeedbackDetector)
242+
243+
한국어/영어 패턴으로 사용자 피드백 감지:
244+
- 긍정: "맞아", "좋아", "exactly", "perfect" → +1.0
245+
- 부정: "아니야", "틀렸어", "wrong", "no" → -1.0
246+
247+
#### 암묵적 보상 (ImplicitRewardDetector)
248+
249+
대화 흐름 패턴으로 보상 추론:
250+
- 대화 지속 (2+ 턴 이어감) → +0.3
251+
- 화제 확장 (기억 키워드 재등장) → +0.2
252+
- 짧은 무관심 응답 → -0.1
253+
254+
---
255+
256+
### Layer 6: P2P Federated Learning (opt-in)
257+
258+
**파일**: `src/aimemory/online/gossip.py`, `transport.py`, `rule_verifier.py`
259+
260+
여러 사용자의 RL 정책을 P2P로 공유하여 학습 속도 향상:
261+
262+
```
263+
Node A ←──gossip──→ Node B ←──gossip──→ Node C
264+
│ │ │
265+
└── 각자의 OnlinePolicy 파라미터 교환 ──┘
266+
```
267+
268+
#### 보안
269+
270+
- **L2 Norm Clipping**: 파라미터 업데이트 크기 제한
271+
- **Differential Privacy**: Gaussian noise 추가 (선택적)
272+
- **Krum Aggregation**: Byzantine-tolerant 집계 (악의적 노드 필터링)
273+
- **Rule Hash Verification**: SHA-256으로 보안 규칙 변조 탐지
274+
275+
---
276+
277+
## MCP 도구 (12개)
278+
279+
| 도구 | 레이어 | 설명 |
280+
|------|--------|------|
281+
| `auto_search` | Retrieval | 매 턴 관련 기억 자동 검색 + 다해상도 컨텍스트 조합 |
282+
| `memory_save` | Storage | 새 기억 저장 (키워드, 카테고리, 관계 지정) |
283+
| `memory_search` | Retrieval | 시맨틱 유사도 검색 |
284+
| `memory_update` | Storage | 기존 기억 내용/키워드 수정 |
285+
| `memory_delete` | Storage | 기억 삭제 (immutable 존중) |
286+
| `memory_get_related` | Retrieval | BFS 그래프 탐색 (depth 1~3) |
287+
| `memory_pin` | Storage | 망각 보호 설정 |
288+
| `memory_unpin` | Storage | 망각 보호 해제 |
289+
| `memory_stats` | Storage | 총 개수 + 카테고리별 분포 |
290+
| `sleep_cycle_run` | Maintenance | 수면 사이클 실행 (통합+망각+체크포인트) |
291+
| `policy_status` | Decision | RL 정책 상태 (epsilon, action 분포, 업데이트 수) |
292+
| `policy_decide` | Decision | RL 정책 결정 트레이스 (SAVE/SKIP/RETRIEVE + 이유) |
293+
294+
---
295+
296+
## 설정
297+
298+
### 환경변수
299+
300+
| 변수 | 기본값 | 설명 |
301+
|------|--------|------|
302+
| `AIMEMORY_DB_PATH` | `./memory_db` | ChromaDB 저장 경로 |
303+
| `AIMEMORY_LANGUAGE` | `ko` | 패턴 매칭 언어 (`ko`/`en`) |
304+
| `AIMEMORY_EMBEDDING_MODEL` | `intfloat/multilingual-e5-small` | 임베딩 모델 |
305+
| `AIMEMORY_LOG_LEVEL` | `INFO` | 로깅 레벨 |
306+
| `AIMEMORY_ENHANCED_POLICY` | `0` | Enhanced RL 정책 활성화 |
307+
| `AIMEMORY_GRAPH_RAG` | `0` | GraphRAG 하이브리드 검색 활성화 |
308+
309+
### Config 클래스 체계
310+
311+
```
312+
AppConfig
313+
├── OnlinePolicyConfig — RL 정책 (thresholds, epsilon, lr)
314+
├── ReRankerConfig — Re-ranker (feature_dim, latency budget)
315+
├── MCPServerConfig — MCP 서버 (token_budget, top_k)
316+
├── ForgettingConfig — 망각 파이프라인 (thresholds, decay_lambda)
317+
├── ComposerConfig — Context Composer (budget, level별 평균 토큰)
318+
├── SleepCycleConfig — 수면 사이클 (간격, 리포트 저장)
319+
├── GossipConfig — P2P 학습 (interval, DP 설정)
320+
├── SecurityConfig — 불변 규칙 (비밀번호/API키 차단)
321+
├── RewardConfig — 보상 가중치
322+
├── SelfPlayConfig — Self-play 시뮬레이션
323+
├── OllamaConfig — 로컬 LLM (모델명, max_tokens)
324+
├── DatasetConfig — 데이터셋 분할 비율
325+
└── DataPaths — 파일 경로
326+
```
327+
328+
---
329+
330+
## 기술 스택
331+
332+
| 영역 | 기술 | 용도 |
333+
|------|------|------|
334+
| MCP 프로토콜 | FastMCP | MCP 서버 구현 |
335+
| 벡터 DB | ChromaDB | 시맨틱 검색 + 영속 저장 |
336+
| 임베딩 | sentence-transformers | 다국어 텍스트 임베딩 |
337+
| 지식 그래프 | NetworkX | 엔티티-관계 그래프 |
338+
| 데이터 모델 | Pydantic v2 | 스키마 검증 + 직렬화 |
339+
| RL | PyTorch (via MLP) | 순수 Python MLP (경량) |
340+
| 테스트 | pytest | 590개 테스트 |
341+
| 린트 | ruff | 포맷팅 + 린팅 |
342+
| CI | GitHub Actions | Python 3.11/3.12/3.13 매트릭스 |
343+
| 패키지 | hatchling + uv | 빌드 + 의존성 관리 |
344+
345+
---
346+
347+
## 설계 원칙
348+
349+
1. **"저장 품질 > 검색 알고리즘"** — 무엇을 저장할지가 가장 중요
350+
2. **Additive 확장** — 기존 클래스 수정 최소화, opt-in config flags
351+
3. **Graceful Degradation** — Enhanced/GraphRAG 비활성 시 기본 모드로 동작
352+
4. **로컬 우선** — 외부 API 불필요, 모든 데이터 로컬 저장
353+
5. **다국어 설계** — i18n 모듈로 언어별 패턴 분리

0 commit comments

Comments
 (0)