Skip to content

Commit 558a135

Browse files
committed
feat: v0.2 준비 — 코드 품질 개선 + README + ROADMAP + CI
P1 코드 품질: - Edge direction 타입 강화: str → Literal["both", "incoming", "outgoing"] - ConsolidationCascade 상수 설정 가능하게 (__init__ 파라미터) - SQLite batch 작업 rollback 지원 (save_nodes_batch/save_edges_batch) - __init__.py export 보강 (ResonanceWeights 추가) 문서화: - README.md: Quick start, API 요약, 아키텍처 다이어그램 - docs/ARCHITECTURE.md: 메커니즘 상세 설명 + 백엔드 기능 매트릭스 - docs/ROADMAP.md: v0.2 ~ v0.4 전체 로드맵 (P1~P8, 30+ tasks) CI: - GitHub Actions: ruff + pyright + pytest (Python 3.12/3.13)
1 parent 7d3e1f6 commit 558a135

File tree

9 files changed

+529
-16
lines changed

9 files changed

+529
-16
lines changed

.github/workflows/ci.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
check:
11+
runs-on: ubuntu-latest
12+
strategy:
13+
matrix:
14+
python-version: ["3.12", "3.13"]
15+
16+
steps:
17+
- uses: actions/checkout@v4
18+
19+
- name: Install uv
20+
uses: astral-sh/setup-uv@v4
21+
22+
- name: Set up Python ${{ matrix.python-version }}
23+
run: uv python install ${{ matrix.python-version }}
24+
25+
- name: Install dependencies
26+
run: uv sync --extra dev --extra sqlite
27+
28+
- name: Ruff check
29+
run: uv run ruff check
30+
31+
- name: Ruff format
32+
run: uv run ruff format --check
33+
34+
- name: Pyright
35+
run: uv run pyright
36+
37+
- name: Tests
38+
run: uv run pytest -v

README.md

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
# Synaptic Memory
2+
3+
Brain-inspired knowledge graph with spreading activation, Hebbian learning, and memory consolidation.
4+
5+
## Features
6+
7+
- **Hybrid Search** — 3-stage fallback: FTS + fuzzy + vector → synonym expansion → LLM query rewrite
8+
- **Hebbian Learning** — Co-activated nodes strengthen connections; failures weaken them
9+
- **Memory Consolidation** — L0 (raw, 72h TTL) → L1 → L2 → L3 (permanent, proven knowledge)
10+
- **Resonance Scoring** — 4-axis ranking: relevance × importance × recency × vitality
11+
- **Korean + English** — Bidirectional synonym map, unicode tokenizers, fuzzy matching
12+
- **Zero Core Deps** — Pure Python core; backends are optional extras
13+
- **Async-first** — All I/O uses async/await
14+
15+
## Install
16+
17+
```bash
18+
pip install synaptic-memory # Core (MemoryBackend only)
19+
pip install synaptic-memory[sqlite] # + SQLite backend
20+
pip install synaptic-memory[postgresql] # + PostgreSQL backend (v0.2)
21+
pip install synaptic-memory[all] # Everything
22+
```
23+
24+
## Quick Start
25+
26+
```python
27+
from synaptic.backends.memory import MemoryBackend
28+
from synaptic import SynapticGraph, NodeKind, EdgeKind
29+
30+
async def main():
31+
backend = MemoryBackend()
32+
await backend.connect()
33+
graph = SynapticGraph(backend)
34+
35+
# Add knowledge
36+
n1 = await graph.add("CI/CD 파이프라인", "배포 자동화 구현", kind=NodeKind.LESSON)
37+
n2 = await graph.add("테스트 커버리지", "80% 이상 유지", kind=NodeKind.RULE)
38+
await graph.link(n1.id, n2.id, kind=EdgeKind.RELATED)
39+
40+
# Search (FTS + fuzzy + synonym expansion + spreading activation)
41+
result = await graph.search("배포")
42+
for activated in result.nodes:
43+
print(f" [{activated.node.kind}] {activated.node.title} (score: {activated.resonance:.2f})")
44+
45+
# Reinforce (Hebbian learning)
46+
await graph.reinforce([n1.id, n2.id], success=True)
47+
48+
# Consolidate (TTL cleanup + level promotion)
49+
await graph.consolidate()
50+
51+
await backend.close()
52+
```
53+
54+
## With SQLite (Persistent)
55+
56+
```python
57+
from synaptic.backends.sqlite import SQLiteBackend
58+
from synaptic import SynapticGraph
59+
60+
backend = SQLiteBackend("knowledge.db")
61+
await backend.connect()
62+
graph = SynapticGraph(backend)
63+
# ... same API as above
64+
```
65+
66+
## Architecture
67+
68+
```
69+
SynapticGraph (Facade)
70+
├── Store (CRUD + tag extraction)
71+
├── HybridSearch (3-stage fallback + spreading activation + resonance)
72+
├── HebbianEngine (co-activation learning)
73+
├── ConsolidationCascade (L0→L3 memory lifecycle)
74+
└── MarkdownExporter
75+
76+
StorageBackend (Protocol)
77+
78+
MemoryBackend │ SQLiteBackend │ PostgreSQLBackend
79+
```
80+
81+
See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for detailed design.
82+
See [docs/ROADMAP.md](docs/ROADMAP.md) for development plan.
83+
84+
## API
85+
86+
### SynapticGraph
87+
88+
| Method | Description |
89+
|--------|-------------|
90+
| `add(title, content, kind=..., tags=..., embedding=...)` | Add a knowledge node |
91+
| `link(source_id, target_id, kind=..., weight=...)` | Link two nodes |
92+
| `search(query, limit=10, embedding=...)` | Hybrid search with resonance scoring |
93+
| `get(node_id)` | Get a node (increments access count) |
94+
| `remove(node_id)` | Delete a node and its edges |
95+
| `reinforce(node_ids, success=True)` | Hebbian learning on co-activated nodes |
96+
| `consolidate(digester=..., context=...)` | Run memory lifecycle (TTL + promotion) |
97+
| `prune()` | Remove weak edges (weight < 0.1) |
98+
| `decay()` | Decay all node vitality (×0.95) |
99+
| `export_markdown()` | Export as Markdown |
100+
| `stats()` | Node counts by kind and level |
101+
102+
### Backends
103+
104+
| Backend | Deps | Use Case |
105+
|---------|------|----------|
106+
| `MemoryBackend` | None | Testing, ephemeral |
107+
| `SQLiteBackend` | aiosqlite | Embedded, single-process |
108+
| `PostgreSQLBackend` | asyncpg, pgvector | Production, multi-process |
109+
110+
### Protocols (Extensible)
111+
112+
| Protocol | Description |
113+
|----------|-------------|
114+
| `StorageBackend` | Pluggable storage (implement for custom DB) |
115+
| `Digester` | Convert structured context → nodes/edges |
116+
| `QueryRewriter` | LLM-based query expansion |
117+
| `TagExtractor` | Auto-tag extraction from text |
118+
119+
## Dev
120+
121+
```bash
122+
uv sync --extra dev --extra sqlite
123+
uv run pytest -v # 93 tests
124+
ruff check --fix && ruff format # Lint
125+
pyright # Type check (strict)
126+
```
127+
128+
## License
129+
130+
MIT

docs/ARCHITECTURE.md

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
# Synaptic Memory — Architecture
2+
3+
## 개요
4+
5+
뇌의 신경망에서 영감받은 knowledge graph 라이브러리.
6+
FTS 키워드 매칭만으로 못 잡는 연관 지식을 Spreading Activation으로 발견하고,
7+
성공/실패 경험에서 Hebbian Learning으로 자동 학습하며,
8+
L0→L3 Memory Consolidation으로 원시 데이터는 소멸, 검증된 지식은 영구 보존.
9+
10+
## 아키텍처
11+
12+
```
13+
┌──────────────────────────────────────────────────────────┐
14+
│ SynapticGraph (Facade) │
15+
│ add() · link() · search() · reinforce() · consolidate() │
16+
└──────┬───────────┬──────────┬───────────┬────────────────┘
17+
│ │ │ │
18+
┌────▼───┐ ┌───▼──────┐ ┌▼────────┐ ┌▼──────────────┐
19+
│ Store │ │ Hybrid │ │Hebbian │ │Consolidation │
20+
│ (CRUD) │ │ Search │ │Engine │ │Cascade │
21+
│ │ │ │ │ │ │ │
22+
│ tag │ │ 3-stage │ │ co-act │ │ L0 → L1 → L2 │
23+
│ extract│ │ fallback │ │ +/- wt │ │ → L3 │
24+
└───┬────┘ └────┬─────┘ └────┬────┘ └───────┬───────┘
25+
│ │ │ │
26+
│ ┌────▼─────┐ │ │
27+
│ │Resonance │ │ │
28+
│ │ 4-axis │ │ │
29+
│ │ scoring │ │ │
30+
│ └──────────┘ │ │
31+
│ │ │
32+
└──────────┬───────────────┴────────────────┘
33+
34+
StorageBackend (Protocol)
35+
36+
┌────────────┼────────────────┐
37+
│ │ │
38+
┌───▼────┐ ┌───▼──────┐ ┌─────▼───────┐
39+
│Memory │ │SQLite │ │PostgreSQL │
40+
│Backend │ │Backend │ │Backend │
41+
│(dict) │ │(FTS5+CTE)│ │(AGE+pgvec) │
42+
└────────┘ └──────────┘ └─────────────┘
43+
```
44+
45+
## 핵심 메커니즘
46+
47+
### 1. 하이브리드 3단계 검색
48+
49+
```
50+
Query: "배포 실패 원인"
51+
52+
├─ Stage 1: FTS + Fuzzy + Vector (병렬)
53+
│ ├─ FTS5 "배포" OR "실패" OR "원인" → score 0.8
54+
│ ├─ Fuzzy LIKE '%배포%' → score 0.6
55+
│ └─ Vector cosine(embedding) → score 0.7
56+
│ (결과 부족하면 ↓)
57+
58+
├─ Stage 2: 동의어 확장
59+
│ └─ "배포" → "deploy", "deployment", "릴리즈"
60+
│ 재검색 → score 0.5
61+
│ (결과 부족하면 ↓)
62+
63+
└─ Stage 3: Query Rewriter (LLM, optional)
64+
└─ Haiku: "배포 실패 원인" → ["CI/CD 파이프라인 에러", "rollback 이슈"]
65+
재검색 → score 0.4
66+
67+
→ Spreading Activation: top-5 → depth-1 이웃 확장
68+
→ Resonance Scoring: 4축 점수로 최종 정렬
69+
```
70+
71+
### 2. Hebbian Learning
72+
73+
"함께 활성화된 뉴런은 연결이 강화된다" (Hebb's Rule)
74+
75+
```
76+
reinforce([node_A, node_B, node_C], success=True)
77+
78+
├─ 각 노드: success_count += 1, access_count += 1
79+
80+
└─ 노드 쌍 간 edge:
81+
A↔B: weight += 0.1 (성공)
82+
A↔C: weight += 0.1
83+
B↔C: weight += 0.1
84+
(엣지 없으면 새로 생성)
85+
86+
reinforce([node_A, node_B], success=False)
87+
88+
├─ 각 노드: failure_count += 1
89+
90+
└─ A↔B: weight -= 0.15 (실패가 더 강하게 학습)
91+
weight 범위: [-2.0, 5.0] (Anti-resonance 지원)
92+
```
93+
94+
### 3. 4축 Resonance Scoring
95+
96+
```
97+
Score = 0.40 × relevance (검색 점수)
98+
+ 0.25 × importance (성공률)
99+
+ 0.20 × recency (최신성, 일별 5% 감쇠)
100+
+ 0.15 × vitality (생존력)
101+
```
102+
103+
- **Relevance**: 검색 엔진이 매긴 원점수 [0, 1]
104+
- **Importance**: (success - failure) / access → 정규화 [0, 1]
105+
- **Recency**: exp(-0.05 × days_since_update)
106+
- **Vitality**: 주기적 decay (매일 ×0.95), 접근 시 회복
107+
108+
### 4. Memory Consolidation (L0 → L3)
109+
110+
```
111+
L0_RAW (72시간 TTL)
112+
├─ 72시간 내 3회 이상 접근 → L1 승격
113+
└─ 72시간 후 미접근 → 삭제
114+
115+
L1_SPRINT (90일 TTL)
116+
├─ 10회 이상 접근 → L2 승격
117+
└─ 90일 후 미접근 → 삭제
118+
119+
L2_MONTHLY (365일 TTL)
120+
├─ 성공 10회 이상 + 성공률 80%+ → L3 승격
121+
└─ 365일 후 미달 → 삭제
122+
123+
L3_PERMANENT
124+
└─ 영구 보존 (검증된 지식)
125+
```
126+
127+
## 데이터 모델
128+
129+
### Node
130+
131+
| 필드 | 타입 | 설명 |
132+
|------|------|------|
133+
| id | str (16 hex) | UUID 기반 고유 ID |
134+
| kind | NodeKind | concept, entity, lesson, decision, rule, artifact, agent, task, sprint |
135+
| title | str | 노드 제목 |
136+
| content | str | 본문 내용 |
137+
| tags | list[str] | 태그 목록 |
138+
| level | ConsolidationLevel | L0 → L3 |
139+
| embedding | list[float] | 벡터 임베딩 (optional) |
140+
| vitality | float [0,1] | 생존력 (주기적 decay) |
141+
| access_count | int | 접근 횟수 |
142+
| success_count | int | 성공 사용 횟수 |
143+
| failure_count | int | 실패 사용 횟수 |
144+
| source | str | 출처 (예: "sprint:sprint-123") |
145+
| created_at | float | 생성 시간 (epoch) |
146+
| updated_at | float | 최종 갱신 시간 |
147+
148+
### Edge
149+
150+
| 필드 | 타입 | 설명 |
151+
|------|------|------|
152+
| id | str | 고유 ID |
153+
| source_id | str | 시작 노드 |
154+
| target_id | str | 끝 노드 |
155+
| kind | EdgeKind | related, caused, learned_from, depends_on, produced, contradicts, supersedes |
156+
| weight | float [-2, 5] | 연결 강도 (Hebbian 학습으로 조정) |
157+
| created_at | float | 생성 시간 |
158+
159+
## 백엔드별 기능 매트릭스
160+
161+
| 기능 | MemoryBackend | SQLiteBackend | PostgreSQLBackend |
162+
|------|:---:|:---:|:---:|
163+
| FTS 검색 | ✅ (word match) | ✅ (FTS5) | ✅ (tsvector) |
164+
| Fuzzy 검색 | ✅ (SequenceMatcher) | ⚠️ (LIKE) | ✅ (pg_trgm) |
165+
| Vector 검색 | ✅ (cosine) || ✅ (pgvector HNSW) |
166+
| 그래프 순회 | ✅ (BFS) | ✅ (recursive CTE) | ✅ (AGE Cypher) |
167+
| 영속성 | ❌ (메모리) | ✅ (파일) | ✅ (서버) |
168+
| 동시성 || ⚠️ (WAL) | ✅ (MVCC) |
169+
| 한글 지원 || ✅ (unicode61) | ✅ (simple + trgm) |
170+
| 의존성 | 없음 | aiosqlite | asyncpg + pgvector |

0 commit comments

Comments
 (0)