whatwasthat 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,29 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ permissions:
9
+ id-token: write
10
+
11
+ jobs:
12
+ publish:
13
+ runs-on: ubuntu-latest
14
+ environment: pypi
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - uses: actions/setup-python@v5
19
+ with:
20
+ python-version: "3.12"
21
+
22
+ - name: Install build tools
23
+ run: pip install build
24
+
25
+ - name: Build package
26
+ run: python -m build
27
+
28
+ - name: Publish to PyPI
29
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,15 @@
1
+ *.pyc
2
+ __pycache__/
3
+ .venv/
4
+ uv.lock
5
+ *.egg-info/
6
+ dist/
7
+ build/
8
+ .wwt/
9
+ week_work/
10
+ .omc/
11
+ .claude/
12
+ .idea/
13
+ .mcp.json
14
+ docs/plans/
15
+ tests/
@@ -0,0 +1,14 @@
1
+ Metadata-Version: 2.4
2
+ Name: whatwasthat
3
+ Version: 1.0.0
4
+ Summary: AI 대화 기억 검색 — LLM 대화 로그를 벡터화하여 시맨틱 검색
5
+ License-Expression: Apache-2.0
6
+ Requires-Python: >=3.12
7
+ Requires-Dist: chromadb>=0.6
8
+ Requires-Dist: einops>=0.8.2
9
+ Requires-Dist: kiwipiepy>=0.23.1
10
+ Requires-Dist: mcp>=1.0
11
+ Requires-Dist: pydantic>=2.10
12
+ Requires-Dist: rank-bm25>=0.2.2
13
+ Requires-Dist: sentence-transformers>=3.3
14
+ Requires-Dist: typer>=0.15
@@ -0,0 +1,347 @@
1
+ # What was that?!
2
+
3
+ > **"그때 그거 뭐였지?"** — AI 대화 기억을 검색하는 시맨틱 엔진
4
+
5
+ [![PyPI version](https://badge.fury.io/py/whatwasthat.svg)](https://pypi.org/project/whatwasthat/)
6
+ [![License: Apache-2.0](https://img.shields.io/badge/License-Apache--2.0-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)
7
+ [![Python 3.12+](https://img.shields.io/badge/python-3.12%2B-blue.svg)](https://www.python.org/downloads/)
8
+
9
+ ---
10
+
11
+ ## 문제
12
+
13
+ AI와 중요한 대화를 하고, 기술적 결정을 내리고, 삽질 끝에 해결책을 찾았는데 — 다음 세션에서 AI는 아무것도 기억하지 못합니다.
14
+
15
+ - "전에 Redis 캐시 설정 어떻게 했었지?"
16
+ - "다른 프로젝트에서 mTLS 인증서 어떻게 구성했지?"
17
+ - "지난번에 비슷한 버그 어떻게 고쳤지?"
18
+
19
+ 물론 `.md` 파일에 기록은 합니다. 그리고 그 파일은 조용히 쌓여갑니다. 그리고 우리는 절대 다시 열어보지 않습니다.
20
+
21
+ 매번 같은 설명을 반복하거나, 대화 로그를 직접 뒤지고 있다면 — WWT가 해결합니다.
22
+
23
+ ## 해결
24
+
25
+ WWT는 여러 AI 코딩 에이전트(Claude Code, Gemini CLI, Codex CLI)의 대화 로그를 자동으로 파싱하고, 시맨틱 벡터로 변환하여 **자연어로 과거 대화를 통합 검색**할 수 있게 합니다.
26
+
27
+ ```
28
+ 세션 종료 → 대화 로그 자동 수집 → 파싱 → 청킹 → 벡터화 → 검색 가능
29
+ ```
30
+
31
+ ## 주요 특징
32
+
33
+ - **하이브리드 검색**: 벡터 시맨틱 검색(60%) + BM25 키워드 검색(40%) 조합
34
+ - **한국어 최적화**: kiwipiepy 형태소 분석 기반 토크나이징
35
+ - **프로젝트별 격리**: 프로젝트 단위 필터링 + 전체 프로젝트 크로스 검색
36
+ - **크로스 플랫폼**: Claude Code, Gemini CLI, Codex CLI 대화 로그 통합 검색
37
+ - **MCP 서버 내장**: Claude Code/Gemini CLI/Codex CLI에서 자연어로 바로 검색
38
+ - **완전 로컬**: 클라우드 API 호출 없음, 데이터가 내 컴퓨터를 떠나지 않음
39
+ - **자동 수집**: 각 플랫폼 Hook으로 세션 종료 시 자동 적재
40
+ - **원커맨드 설정**: `wwt setup` 한 번으로 DB + Hook + MCP 전부 설정 (모든 플랫폼)
41
+
42
+ ---
43
+
44
+ ## 아키텍처
45
+
46
+ ```
47
+ ┌──────────────────────────────────────────┐
48
+ │ CLI (typer) │ MCP Server (FastMCP)│
49
+ │ wwt search │ search_memory │
50
+ │ wwt ingest │ search_all │
51
+ └────────┬─────────┴──────────┬────────────┘
52
+ │ │
53
+ ┌────▼────┐ ┌────▼─────┐
54
+ │ Pipeline │ │ Search │
55
+ ├──────────┤ ├──────────┤
56
+ │ Parser │ │ Engine │ 세션 그룹핑
57
+ │ Chunker │ │ Vector │ 하이브리드 검색
58
+ └────┬─────┘ └────┬─────┘
59
+ │ │
60
+ └────────┬───────────┘
61
+
62
+ ┌───────▼────────┐
63
+ │ ChromaDB │
64
+ │ HNSW + BM25 │
65
+ │ ~/.wwt/data/ │
66
+ └────────────────┘
67
+ ```
68
+
69
+ ### 데이터 플로우
70
+
71
+ ```
72
+ JSONL 대화 로그
73
+ ↓ Parser: 코드블록·시스템태그 제거, 의미 없는 짧은 턴 필터링
74
+ Turn 시퀀스
75
+ ↓ Chunker: 슬라이딩 윈도우 (2-6턴, 2턴 오버랩)
76
+ Chunk 리스트
77
+ ↓ SentenceTransformer: multilingual-e5-small 임베딩
78
+ 벡터 + 메타데이터
79
+ ↓ ChromaDB: HNSW 인덱스 저장
80
+ 검색 가능 상태
81
+ ```
82
+
83
+ ---
84
+
85
+ ## 설치
86
+
87
+ ### pip
88
+
89
+ ```bash
90
+ pip install whatwasthat
91
+ ```
92
+
93
+ ### uv (권장)
94
+
95
+ ```bash
96
+ uv tool install whatwasthat
97
+ ```
98
+
99
+ ### 초기 설정
100
+
101
+ ```bash
102
+ # DB 초기화 + Stop Hook + MCP 서버 자동 등록 (원커맨드)
103
+ wwt setup
104
+ ```
105
+
106
+ 이 명령 하나로:
107
+ 1. ChromaDB 벡터 데이터베이스 초기화 (`~/.wwt/data/vector/`)
108
+ 2. 각 플랫폼 Hook 스크립트 설치 (세션 종료 시 자동 적재)
109
+ 3. 설치된 모든 플랫폼에 MCP 서버 등록 (Claude Code, Gemini CLI, Codex CLI)
110
+ 4. 기존 대화 로그 자동 검색 및 적재
111
+
112
+ > 이미 적재된 대화는 중복 처리되지 않습니다. 증분 upsert 방식으로 변경된 청크만 임베딩하고, 기존 데이터는 건너뜁니다. `wwt setup`을 여러 번 실행해도 안전합니다.
113
+
114
+ > 임베딩 모델(`multilingual-e5-small`, ~470MB)은 **최초 실행 시** HuggingFace에서 자동 다운로드됩니다.
115
+
116
+ ---
117
+
118
+ ## 사용법
119
+
120
+ ### CLI
121
+
122
+ ```bash
123
+ # 대화 로그 수동 적재
124
+ wwt ingest ~/.claude/projects/my-project/sessions/
125
+
126
+ # 단일 파일 적재
127
+ wwt ingest ~/session-abc123.jsonl
128
+
129
+ # 현재 프로젝트 맥락으로 검색
130
+ wwt search "Redis 캐시 설정 어떻게 했지?"
131
+
132
+ # 특정 프로젝트에서 검색
133
+ wwt search "mTLS 인증서 설정" --project keylink_service
134
+
135
+ # 전체 프로젝트 검색
136
+ wwt search "비슷한 버그 해결 방법" --all
137
+ ```
138
+
139
+ ### MCP (Claude Code / Gemini CLI / Codex CLI)
140
+
141
+ `wwt setup` 이후 MCP를 지원하는 모든 플랫폼에서 자연어로 바로 사용:
142
+
143
+ ```
144
+ 사용자: "전에 PostgreSQL 인덱스 최적화 어떻게 했었지?"
145
+ AI: [search_memory 자동 호출] → 모든 플랫폼의 관련 대화 3개 찾음
146
+ ```
147
+
148
+ **MCP 도구 3종:**
149
+
150
+ | 도구 | 설명 |
151
+ |------|------|
152
+ | `search_memory` | 현재 프로젝트 맥락으로 검색 (cwd 자동 감지) |
153
+ | `search_all` | 모든 프로젝트에서 크로스 검색 |
154
+ | `ingest_session` | 대화 로그 적재 (보통 Hook이 자동 처리) |
155
+
156
+ ### 자동 수집 (Hook)
157
+
158
+ `wwt setup`을 실행하면 각 플랫폼에 맞는 Hook이 자동 설치됩니다:
159
+
160
+ | 플랫폼 | Hook 종류 | 동작 |
161
+ |--------|----------|------|
162
+ | **Claude Code** | Stop Hook | 세션 종료 시 자동 적재 |
163
+ | **Gemini CLI** | AfterAgent Hook | 에이전트 완료 시 자동 적재 |
164
+ | **Codex CLI** | Stop Hook | 세션 종료 시 자동 적재 |
165
+
166
+ 별도 조작 없이 대화가 쌓입니다.
167
+
168
+ ---
169
+
170
+ ## 검색 엔진 상세
171
+
172
+ ### 하이브리드 검색 전략
173
+
174
+ 단일 검색 방식의 한계를 보완하기 위해 두 가지 검색을 조합합니다:
175
+
176
+ | 검색 방식 | 가중치 | 강점 | 약점 |
177
+ |-----------|--------|------|------|
178
+ | **벡터 검색** (HNSW, cosine) | 60% | 의미적 유사도, 패러프레이즈 매칭 | 정확한 키워드 놓침 |
179
+ | **BM25 키워드 검색** | 40% | 정확한 용어 매칭, 고유명사 | 의미적 변형 놓침 |
180
+
181
+ **예시:**
182
+ - "DB 설정 방법" → 벡터 검색이 "PostgreSQL 인덱스 구성" 매칭
183
+ - "FastAPI" → BM25가 정확한 키워드 매칭
184
+ - 두 결과를 합산하여 최종 순위 결정
185
+
186
+ ### 한국어 토크나이징
187
+
188
+ kiwipiepy 형태소 분석기를 사용하여 한국어 특성을 반영합니다:
189
+
190
+ ```
191
+ "PostgreSQL 인덱스를 최적화했습니다"
192
+ ↓ CamelCase 분리: "Postgre SQL"
193
+ ↓ 형태소 분석: ["postgre", "sql", "인덱스", "최적화"]
194
+ ↓ 불용어 제거 (조사, 어미 등)
195
+ ```
196
+
197
+ ### 청킹 전략
198
+
199
+ 대화를 의미 단위로 분할하되, 문맥이 끊기지 않도록 오버랩을 둡니다:
200
+
201
+ ```
202
+ 대화: [T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]
203
+
204
+ 청크 1: [T1, T2, T3, T4, T5, T6] ← 6턴
205
+ 청크 2: [T5, T6, T7, T8, T9, T10] ← 2턴 오버랩
206
+ ```
207
+
208
+ - 윈도우 크기: 2~6턴
209
+ - 오버랩: 2턴 (문맥 보존)
210
+ - 최소 조건: 사용자 턴 1개 이상, 200자 이상
211
+
212
+ ---
213
+
214
+ ## 임베딩 모델 선정
215
+
216
+ ### 선정 기준
217
+
218
+ | 기준 | 설명 |
219
+ |------|------|
220
+ | **다국어 지원** | 한국어 + 영어 혼합 대화 처리 필수 |
221
+ | **로컬 실행** | GPU 없이 CPU에서 실용적 속도 |
222
+ | **모델 크기** | 설치 부담 최소화 (1GB 이하) |
223
+ | **임베딩 품질** | 대화 맥락의 시맨틱 유사도 정확도 |
224
+
225
+ ### 후보 모델 비교
226
+
227
+ | 모델 | 파라미터 | 크기 | 차원 | 다국어 | MTEB 평균 | 선정 |
228
+ |------|---------|------|------|--------|-----------|------|
229
+ | `multilingual-e5-small` | 118M | ~470MB | 384 | 100+ 언어 | 57.5 | **채택** |
230
+ | `multilingual-e5-base` | 278M | ~1.1GB | 768 | 100+ 언어 | 59.5 | 크기 부담 |
231
+ | `multilingual-e5-large` | 560M | ~2.2GB | 1024 | 100+ 언어 | 61.5 | 로컬 실행 비현실적 |
232
+ | `paraphrase-multilingual-MiniLM-L12-v2` | 118M | ~470MB | 384 | 50+ 언어 | 53.5 | e5 대비 품질 열세 |
233
+ | `bge-m3` | 568M | ~2.3GB | 1024 | 100+ 언어 | 62.0 | 크기 과대 |
234
+ | `all-MiniLM-L6-v2` | 22M | ~90MB | 384 | 영어만 | 56.3 | 한국어 미지원 |
235
+
236
+ ### 선정 근거: `multilingual-e5-small`
237
+
238
+ 1. **크기 vs 성능 최적점**: 470MB로 e5-base(1.1GB) 대비 절반 크기, MTEB 점수 차이 2점
239
+ 2. **100+ 언어 지원**: 한국어-영어 코드스위칭 대화에 적합
240
+ 3. **384차원**: ChromaDB HNSW 인덱스에서 메모리/속도 효율적
241
+ 4. **CPU 추론 실용적**: M1 MacBook 기준 ~50ms/query
242
+ 5. **SentenceTransformer 호환**: ChromaDB 내장 임베딩 함수로 바로 사용
243
+
244
+ ### 임베딩 품질 실험 (한국어 대화)
245
+
246
+ ```
247
+ Query: "Redis 캐시 TTL 설정"
248
+
249
+ multilingual-e5-small:
250
+ ✓ "Redis expire 시간을 3600초로 설정했습니다" (0.87)
251
+ ✓ "캐시 무효화 정책을 TTL 기반으로 변경" (0.82)
252
+ ✗ "메모리 캐시 구현" (0.51) — 관련은 있지만 낮은 점수
253
+
254
+ paraphrase-multilingual-MiniLM:
255
+ ✓ "Redis expire 시간을 3600초로 설정했습니다" (0.79)
256
+ △ "캐시 무효화 정책을 TTL 기반으로 변경" (0.64)
257
+ ✗ "메모리 캐시 구현" (0.58) — 노이즈 높음
258
+ ```
259
+
260
+ e5-small이 관련 문서에 더 높은 점수를, 비관련 문서에 더 낮은 점수를 부여하여 **검색 정밀도가 우수**합니다.
261
+
262
+ ---
263
+
264
+ ## 설치 요구사항
265
+
266
+ ### 시스템
267
+
268
+ - **Python**: 3.12+
269
+ - **OS**: macOS, Linux (Windows 미테스트)
270
+ - **디스크**: ~1.4GB (의존성 + 임베딩 모델)
271
+ - **RAM**: ~2GB (검색 시)
272
+
273
+ ### 의존성 크기 상세
274
+
275
+ | 패키지 | 크기 | 역할 |
276
+ |--------|------|------|
277
+ | `torch` | ~378MB | 텐서 연산 (임베딩 추론) |
278
+ | `kiwipiepy` + 모델 | ~114MB | 한국어 형태소 분석 |
279
+ | `scipy` | ~81MB | 수학 연산 |
280
+ | `onnxruntime` | ~64MB | 추론 최적화 |
281
+ | `transformers` | ~50MB | 모델 로딩 |
282
+ | `chromadb` | ~47MB | 벡터 DB |
283
+ | 기타 | ~200MB | sentence-transformers, grpc 등 |
284
+ | **임베딩 모델** (최초 실행) | ~470MB | HuggingFace 캐시 |
285
+
286
+ > 참고: PyPI 패키지 자체는 수백 KB입니다. 위 크기는 `pip install` 시 설치되는 의존성입니다.
287
+
288
+ ---
289
+
290
+ ## 데이터 저장 위치
291
+
292
+ ```
293
+ ~/.wwt/
294
+ ├── data/
295
+ │ └── vector/ # ChromaDB 벡터 인덱스
296
+ └── ingest.log # 자동 적재 로그
297
+
298
+ ~/.cache/huggingface/
299
+ └── hub/
300
+ └── models--intfloat--multilingual-e5-small/ # 임베딩 모델 캐시
301
+ ```
302
+
303
+ ---
304
+
305
+ ## 설계 철학 — 왜 벡터 검색인가
306
+
307
+ 지식 베이스를 구축하는 접근(LLM이 원시 자료를 요약/정리하여 위키를 만드는 방식)과 달리, WWT는 **원문 기반 벡터 검색**을 선택했습니다.
308
+
309
+ | | 원문 검색 (WWT) | 지식 컴파일 |
310
+ |---|---|---|
311
+ | **방식** | 원문을 벡터로 임베딩 → 유사도 검색 | LLM이 원시 자료를 요약/정리 |
312
+ | **원문 보존** | 원문 그대로 반환 | 요약 과정에서 정보 손실 가능 |
313
+ | **비용** | 임베딩 1회 (저렴) | 컴파일에 LLM 토큰 대량 소비 |
314
+ | **자동화** | Hook으로 자동 수집 | 새 자료마다 재컴파일 필요 |
315
+ | **확장성** | 수천 세션 처리 가능 | 지식 베이스가 커지면 컨텍스트 한계 |
316
+
317
+ **대화 기록 검색**에서 원문 검색이 적합한 이유:
318
+
319
+ 1. **원문 보존이 핵심** — "정확히 뭐라고 했었지?"에 답하려면 요약이 아니라 원문이 필요
320
+ 2. **자동 수집** — 대화가 끝날 때마다 자동으로 적재, 수동 개입 없음
321
+ 3. **LLM이 정리** — WWT가 원문을 찾아주면, LLM이 컨텍스트를 읽고 정리해서 답변
322
+
323
+ ```
324
+ 유저: "전에 Redis 캐시 어떻게 했지?"
325
+ → WWT: 관련 대화 원문 3개 반환
326
+ → LLM: 원문을 읽고 "TTL 300초, invalidation은 이벤트 기반" 정리해서 답변
327
+ ```
328
+
329
+ WWT는 **정확한 원문을 찾는 것**에 집중하고, **정리/요약은 LLM에게 맡깁니다.**
330
+
331
+ ---
332
+
333
+ ## 플랫폼 지원
334
+
335
+ | 플랫폼 | 자동 수집 | 검색 | 로그 포맷 |
336
+ |--------|----------|------|----------|
337
+ | **Claude Code** | Stop Hook | MCP + CLI | JSONL |
338
+ | **Gemini CLI** | AfterAgent Hook | MCP + CLI | JSON (`messages` 배열) |
339
+ | **Codex CLI** | Stop Hook | MCP + CLI | JSONL (RolloutItem) |
340
+
341
+ > 다운스트림(청킹, 임베딩, 검색)은 포맷 독립적입니다. `SessionParser` Protocol을 구현하면 새 플랫폼을 추가할 수 있습니다.
342
+
343
+ ---
344
+
345
+ ## 라이선스
346
+
347
+ 이 프로젝트는 [Apache License 2.0](LICENSE) 라이선스를 따릅니다.