- embed_to_chroma.py → embed_to_qdrant.py 리라이트 (bge-m3 + Qdrant REST API) - auto_classify.scpt: embed_to_qdrant.py 경로 변경 + sourceChannel 덮어쓰기 버그 수정 - requirements.txt: chromadb/schedule 제거, qdrant-client/flask/gunicorn 추가 - credentials.env.example: GPU_SERVER_IP 항목 추가 - GPU 서버 재구성 계획서 (docs/gpu-restructure.md) + dev-roadmap/commands 통합 - CLAUDE.md, README.md, deploy.md 현행화 GPU 서버 변경사항 (이미 적용됨): - Ollama: qwen3.5:9b, id-9b 제거 → bge-m3 + bge-reranker-v2-m3 - Surya OCR 서비스 (:8400, systemd) - Docker + NFS + Komga 이전 (:25600) - tk-ai-service: Ollama API → OpenAI API 전환 (MLX 35B) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
400 lines
13 KiB
Markdown
400 lines
13 KiB
Markdown
# PKM 시스템 개발 로드맵
|
|
|
|
> 작성일: 2026-03-29 (GPU 서버 재구성 계획 통합: 2026-03-29)
|
|
> 현재 상태: Phase 1 코드 작성 완료(90%), 인프라 일부 미해결 → Phase 1.5(GPU 재구성) + Phase 2 진행 중
|
|
|
|
---
|
|
|
|
## 현재 완료된 것
|
|
|
|
| 단계 | 항목 | 상태 | 비고 |
|
|
|------|------|------|------|
|
|
| 1 | 프로젝트 구조 | ✅ 완료 | README, deploy.md, .gitignore |
|
|
| 2 | AI 분류 프롬프트 | ✅ 완료 | MLX(Qwen3.5) OpenAI 호환 API 전환 완료 |
|
|
| 3 | AppleScript | ✅ 완료 | auto_classify + omnifocus_sync |
|
|
| 4 | 법령 모니터링 | ⚠️ 부분 | 외국(US/JP/EU) OK, 한국 API 인증 실패 |
|
|
| 5 | MailPlus 수집 | ❌ 연결 실패 | IMAP Connection refused |
|
|
| 6 | Daily Digest | ⚠️ 미테스트 | 코드 완성, 실행 기록 없음 |
|
|
| 7 | DEVONagent 가이드 | ✅ 완료 | docs/devonagent-setup.md |
|
|
| 8 | 전체 테스트 | ❌ 미진행 | test_classify.py만 존재 |
|
|
| 추가 | PKM API 서버 | ⚠️ 부분 | 한글 인코딩, stats 500 에러 |
|
|
|
|
---
|
|
|
|
## Phase 1.5: GPU 서버 재구성 (Phase 2와 병행)
|
|
|
|
> 상세 계획: docs/gpu-restructure.md 참조
|
|
|
|
GPU 서버(RTX 4070Ti Super)의 역할을 LLM 추론에서 임베딩/OCR 특화로 전환한다.
|
|
Mac Mini와 중복되는 LLM 모델을 제거하고, Surya OCR + bge-m3를 배치한다.
|
|
|
|
### 1.5-A. GPU 서버 정리 (SSH 작업)
|
|
|
|
```
|
|
작업 내용:
|
|
1. Ollama 모델 제거: qwen3.5:9b-q8_0, id-9b
|
|
2. 새 모델 설치: bge-m3 (임베딩), bge-reranker-v2-m3 (리랭킹)
|
|
3. no-think proxy(11435) 비활성화
|
|
4. paperless-gpt 처리 방침 결정
|
|
5. tk-ai-service 코드 수정 (Ollama API → OpenAI API 전환)
|
|
|
|
검증: ollama list → bge-m3, bge-reranker만 존재
|
|
검증: tk-ai-service /health → MLX(text), GPU(embed) 모두 connected
|
|
```
|
|
|
|
### 1.5-B. Docker + NFS + Komga 이전
|
|
|
|
```
|
|
작업 내용:
|
|
1. GPU 서버에 Docker Engine 설치
|
|
2. NAS NFS 마운트 설정 (192.168.1.227:/volume1/Comic → /mnt/comic, ro)
|
|
3. Komga Docker 컨테이너를 GPU 서버로 이전 (포트 25600 유지)
|
|
4. Mac Mini nginx upstream 변경 → GPU 서버
|
|
5. Mac Mini Komga 제거 (Docker VM 메모리 1.23GB 회수)
|
|
|
|
검증: curl https://komga.hyungi.net → GPU 서버 경유 접근 확인
|
|
```
|
|
|
|
### 1.5-C. Surya OCR 설치
|
|
|
|
```
|
|
작업 내용:
|
|
1. PyTorch CUDA 런타임 확인/설치
|
|
2. Surya OCR FastAPI 서버 구성 (/opt/surya-ocr/, 포트 8400)
|
|
3. systemd 서비스 등록
|
|
|
|
검증: curl -F "file=@test.pdf" http://192.168.1.186:8400/ocr → OCR 텍스트 반환
|
|
```
|
|
|
|
### 1.5-D. PKM 코드 갱신 (Phase 2와 겹치는 항목 포함)
|
|
|
|
```
|
|
작업 내용:
|
|
1. embed_to_chroma.py → embed_to_qdrant.py 리라이트 (Qdrant + bge-m3)
|
|
2. auto_classify.scpt: Step 0(OCR) 추가 + Step 4 Qdrant + sourceChannel 버그 픽스
|
|
3. requirements.txt: chromadb→qdrant-client, flask/gunicorn 추가 ← Phase 2 1-1과 합산
|
|
4. credentials.env: GPU_SERVER_IP=192.168.1.186 추가
|
|
5. architecture.md 대규모 갱신 (ChromaDB 28건, nomic 12건, VL-7B 5건)
|
|
|
|
검증: python3 scripts/embed_to_qdrant.py <테스트UUID> → Qdrant 벡터 저장 확인
|
|
```
|
|
|
|
### 1.5-E. RAG 파이프라인 + OCR 연동 (후순위)
|
|
|
|
```
|
|
작업 내용:
|
|
1. pkm_api_server.py에 RAG 엔드포인트 추가 (/rag/query, /devonthink/embed)
|
|
2. DEVONthink Smart Rule에 OCR 전처리 단계 추가
|
|
3. ocr_preprocess.py 신규 작성
|
|
|
|
검증: curl -X POST localhost:9900/rag/query -d '{"q":"산업안전 법령"}' → 답변 반환
|
|
```
|
|
|
|
---
|
|
|
|
## Phase 2: 인프라 수정 (Phase 1.5와 병행)
|
|
|
|
Mac mini에서 직접 확인/수정이 필요한 항목들.
|
|
※ Phase 1.5(GPU 재구성)과 병행하여 진행. 겹치는 항목(requirements.txt, credentials.env, AppleScript)은 합산.
|
|
|
|
### 1-1. requirements.txt 수정 ← Phase 1.5-D와 합산 진행
|
|
|
|
```
|
|
현재 문제:
|
|
- flask 누락 (pkm_api_server.py에서 사용 중)
|
|
- schedule 패키지 미사용 (제거 고려)
|
|
- chromadb → qdrant-client 교체 (GPU 재구성에 따라)
|
|
|
|
수정 내용:
|
|
+ flask>=3.0.0
|
|
+ gunicorn>=21.2.0 (프로덕션 WSGI)
|
|
+ qdrant-client>=1.7.0
|
|
- chromadb>=0.4.0
|
|
- schedule>=1.2.0 (미사용 확인 후 제거)
|
|
```
|
|
|
|
### 1-2. 한국 법령 API 인증 해결
|
|
|
|
```
|
|
현재 에러:
|
|
"사용자 정보 검증에 실패하였습니다.
|
|
OPEN API 호출 시 사용자 검증을 위하여 정확한 서버장비의 IP주소 및 도메인주소를 등록해 주세요."
|
|
|
|
조치:
|
|
1. open.law.go.kr 접속 → 마이페이지 → 인증키 관리
|
|
2. Mac mini의 외부 IP 확인: curl ifconfig.me
|
|
3. 해당 IP를 API 호출 서버 IP로 등록
|
|
4. Tailscale IP(100.x.x.x)가 아니라 실제 공인 IP여야 함
|
|
5. 등록 후 law_monitor.py 재실행하여 확인
|
|
```
|
|
|
|
### 1-3. MailPlus IMAP 연결 수정
|
|
|
|
```
|
|
현재 에러: [Errno 61] Connection refused (mailplus.hyungi.net:993)
|
|
|
|
확인 순서:
|
|
1. Synology DSM → MailPlus Server → 서비스 상태 확인
|
|
2. IMAP 활성화 여부: DSM → MailPlus Server → 메일 전송 → IMAP 탭
|
|
3. 포트 확인: 993(SSL) vs 143(STARTTLS)
|
|
4. 방화벽: Synology 방화벽에서 993 포트 개방 확인
|
|
5. DNS 확인: nslookup mailplus.hyungi.net → 올바른 IP?
|
|
6. Tailscale 경유 시: 100.101.79.37:993으로 직접 테스트
|
|
python3 -c "import imaplib; m=imaplib.IMAP4_SSL('100.101.79.37', 993); print('OK')"
|
|
7. credentials.env에 MAILPLUS_HOST 값 확인
|
|
```
|
|
|
|
### 1-4. launchd 등록 상태 확인 및 등록
|
|
|
|
```bash
|
|
# Mac mini에서 확인
|
|
launchctl list | grep pkm
|
|
|
|
# 미등록 시 심볼릭 링크 생성
|
|
ln -sf ~/Documents/code/DEVONThink_my\ server/launchd/net.hyungi.pkm.law-monitor.plist ~/Library/LaunchAgents/
|
|
ln -sf ~/Documents/code/DEVONThink_my\ server/launchd/net.hyungi.pkm.mailplus.plist ~/Library/LaunchAgents/
|
|
ln -sf ~/Documents/code/DEVONThink_my\ server/launchd/net.hyungi.pkm.daily-digest.plist ~/Library/LaunchAgents/
|
|
|
|
# 로드
|
|
launchctl load ~/Library/LaunchAgents/net.hyungi.pkm.law-monitor.plist
|
|
launchctl load ~/Library/LaunchAgents/net.hyungi.pkm.mailplus.plist
|
|
launchctl load ~/Library/LaunchAgents/net.hyungi.pkm.daily-digest.plist
|
|
```
|
|
|
|
---
|
|
|
|
## Phase 2: 버그 픽스 (코드 수정)
|
|
|
|
### 2-1. JP 번역 thinking 오염 문제
|
|
|
|
```
|
|
현재: MLX Qwen3.5가 번역 시 "Wait, I'll check if..." 같은 thinking을 출력에 포함
|
|
위치: scripts/law_monitor.py의 JP 번역 호출부
|
|
|
|
수정 방향:
|
|
- 번역 프롬프트에 /nothink 모드 명시 강화
|
|
- llm_generate() 호출 시 thinking 출력 후처리 추가
|
|
- "Wait,", "Let me", "I'll check" 등 패턴 필터링
|
|
- 또는 번역 결과에서 첫 번째 유효 문장만 추출
|
|
```
|
|
|
|
### 2-2. PKM API 서버 한글 인코딩
|
|
|
|
```
|
|
현재: /devonthink/search?q=산업안전 → 400 Bad request syntax
|
|
위치: scripts/pkm_api_server.py
|
|
|
|
수정:
|
|
- Flask 자체는 UTF-8 지원하므로, 클라이언트 측 URL 인코딩 문제일 가능성
|
|
- curl 호출 시 --data-urlencode 사용 또는 퍼센트 인코딩 필요
|
|
- 서버 측에서도 request.args.get('q', '') 기본 인코딩 확인
|
|
```
|
|
|
|
### 2-3. /devonthink/stats 500 에러 수정
|
|
|
|
```
|
|
현재: GET /devonthink/stats → 500 Internal Server Error
|
|
위치: scripts/pkm_api_server.py
|
|
|
|
원인 추정: AppleScript 실행 시 DB 이름이나 경로 문제
|
|
수정: 에러 로그 확인 후 AppleScript 쿼리 수정
|
|
```
|
|
|
|
### 2-4. AppleScript 하드코딩 경로 개선
|
|
|
|
```
|
|
현재:
|
|
- ~/Documents/code/DEVONThink_my server/scripts/prompts/ 하드코딩
|
|
- venv 경로 하드코딩
|
|
|
|
수정:
|
|
- 스크립트 상단에 BASE_DIR 변수 정의
|
|
- 또는 환경변수 PKM_HOME으로 통일
|
|
```
|
|
|
|
### 2-5. requirements.txt 정리
|
|
|
|
```
|
|
추가: flask>=3.0.0, gunicorn>=21.2.0
|
|
유지: anthropic (향후 Tier 2용)
|
|
검토: schedule (미사용이면 제거)
|
|
```
|
|
|
|
---
|
|
|
|
## Phase 3: API 서버 개선
|
|
|
|
### 3-1. 프로덕션 서빙
|
|
|
|
```
|
|
현재: Flask development server
|
|
변경: gunicorn + launchd로 안정 운영
|
|
|
|
launchd plist 추가:
|
|
net.hyungi.pkm.api-server.plist
|
|
→ gunicorn -w 2 -b 127.0.0.1:9900 pkm_api_server:app
|
|
```
|
|
|
|
### 3-2. 엔드포인트 보완
|
|
|
|
```
|
|
현재 엔드포인트:
|
|
GET /health
|
|
GET /devonthink/stats ← 500 에러 수정 필요
|
|
GET /devonthink/search
|
|
GET /devonthink/inbox-count
|
|
GET /omnifocus/stats
|
|
GET /omnifocus/today
|
|
GET /omnifocus/overdue
|
|
|
|
추가 고려:
|
|
GET /law-monitor/status ← 마지막 실행 결과, 다음 실행 시간
|
|
GET /digest/latest ← 최근 다이제스트 조회
|
|
POST /classify ← 수동 분류 요청 (테스트용)
|
|
```
|
|
|
|
### 3-3. 간단한 인증 추가 (선택)
|
|
|
|
```
|
|
localhost 전용이면 불필요하지만, Tailscale 내부에서 접근할 경우:
|
|
- Bearer token 방식 (credentials.env에 API_TOKEN 추가)
|
|
- 또는 IP 화이트리스트 (127.0.0.1 + Tailscale 대역)
|
|
```
|
|
|
|
---
|
|
|
|
## Phase 4: 테스트 & 검증
|
|
|
|
### 4-1. 개별 모듈 테스트
|
|
|
|
```bash
|
|
# Mac mini에서 실행
|
|
|
|
# 1. AI 분류 테스트 (5종 문서)
|
|
cd ~/Documents/code/DEVONThink_my\ server/
|
|
source venv/bin/activate
|
|
python tests/test_classify.py
|
|
|
|
# 2. 법령 모니터링 (한국 API 인증 후)
|
|
python scripts/law_monitor.py
|
|
|
|
# 3. MailPlus (IMAP 수정 후)
|
|
python scripts/mailplus_archive.py
|
|
|
|
# 4. Daily Digest
|
|
python scripts/pkm_daily_digest.py
|
|
|
|
# 5. API 서버
|
|
python scripts/pkm_api_server.py &
|
|
curl http://localhost:9900/health
|
|
curl http://localhost:9900/devonthink/stats
|
|
curl http://localhost:9900/devonthink/inbox-count
|
|
curl "http://localhost:9900/devonthink/search?q=safety&limit=3"
|
|
```
|
|
|
|
### 4-2. E2E 통합 테스트
|
|
|
|
```
|
|
시나리오 1: Inbox → 자동분류 플로우
|
|
1. DEVONthink Inbox에 테스트 문서 추가
|
|
2. Smart Rule 트리거 → auto_classify.scpt 실행 확인
|
|
3. 태그, 메타데이터, DB 이동 확인
|
|
|
|
시나리오 2: 법령 → 다이제스트 플로우
|
|
1. law_monitor.py 수동 실행
|
|
2. data/laws/에 파일 생성 확인
|
|
3. DEVONthink 04_Industrial Safety 확인
|
|
4. pkm_daily_digest.py 실행 → 법령 변경 건 포함 확인
|
|
|
|
시나리오 3: OmniFocus 연동
|
|
1. Projects DB에 TODO 패턴 문서 추가
|
|
2. omnifocus_sync.scpt 트리거 확인
|
|
3. OmniFocus Inbox에 작업 생성 확인
|
|
```
|
|
|
|
### 4-3. 테스트 리포트 작성
|
|
|
|
```
|
|
→ docs/test-report.md
|
|
각 항목별 pass/fail + 스크린샷/로그 첨부
|
|
```
|
|
|
|
---
|
|
|
|
## Phase 5: 운영 안정화 (선택)
|
|
|
|
### 5-1. 모니터링
|
|
|
|
```
|
|
- 로그 로테이션 (logrotate 또는 Python RotatingFileHandler)
|
|
- Synology Chat 웹훅 알림 연동 (CHAT_WEBHOOK_URL 설정 후)
|
|
- 에러 발생 시 즉시 알림
|
|
```
|
|
|
|
### 5-2. 백업
|
|
|
|
```
|
|
- Gitea 리포지토리 자동 백업 (이미 NAS에 있으므로 OK)
|
|
- credentials.env 백업 (Vaultwarden에 보관?)
|
|
- Qdrant 데이터 백업 (pkm_documents + tk_qc_issues 컬렉션)
|
|
```
|
|
|
|
### 5-3. 문서 보완
|
|
|
|
```
|
|
- README.md 상세화 (아키텍처 다이어그램, 기능 목록)
|
|
- 트러블슈팅 가이드 추가
|
|
- deploy.md에 API 서버 + 업데이트 절차 추가
|
|
```
|
|
|
|
---
|
|
|
|
## 작업 순서 요약
|
|
|
|
```
|
|
[GPU] Phase 1.5: GPU 서버 재구성 (Phase 2와 병행)
|
|
1.5-A. GPU 서버 정리 (모델 교체, proxy 제거) ← SSH 작업
|
|
1.5-B. Docker + NFS + Komga 이전 ← SSH 작업
|
|
1.5-C. Surya OCR 설치 ← SSH 작업
|
|
1.5-D. PKM 코드 갱신 (Qdrant, 임베딩) ← 코드 수정 후 push
|
|
1.5-E. RAG + OCR 연동 ← 후순위
|
|
|
|
[즉시] Phase 2: 인프라 수정
|
|
1-1. requirements.txt 수정 ← Phase 1.5-D와 합산
|
|
1-2. 한국 법령 API IP 등록 ← Mac mini에서 공인IP 확인
|
|
1-3. MailPlus IMAP 확인 ← Synology DSM 확인
|
|
1-4. launchd 등록 ← Mac mini에서 실행
|
|
|
|
[코드] Phase 3: 버그 픽스
|
|
2-1. JP 번역 thinking 필터링 ← 코드 수정 후 push
|
|
2-2~3. API 서버 수정 ← 코드 수정 후 push
|
|
2-4. AppleScript 경로 변수화 ← Phase 1.5-D와 합산
|
|
2-5. requirements.txt 정리 ← Phase 1.5-D와 합산
|
|
|
|
[개선] Phase 4: API 서버 개선
|
|
3-1. gunicorn 전환 + launchd plist ← 코드 작성 후 push
|
|
3-2~3. 엔드포인트 추가 ← 필요시
|
|
|
|
[검증] Phase 5: 테스트
|
|
4-1~2. 모듈별 + E2E 테스트 ← Mac mini에서 실행
|
|
4-3. 테스트 리포트 ← 결과 기반 작성
|
|
|
|
[안정] Phase 6: 운영 안정화 ← 여유 있을 때
|
|
```
|
|
|
|
---
|
|
|
|
## 예상 소요 시간
|
|
|
|
| Phase | 예상 시간 | 비고 |
|
|
|-------|-----------|------|
|
|
| Phase 1.5-A~C | 3~4시간 | GPU 서버 SSH 작업 (모델 교체, Docker, Surya) |
|
|
| Phase 1.5-D | 3~4시간 | PKM 코드 갱신 (Qdrant, architecture.md 대규모 수정) |
|
|
| Phase 1.5-E | 2~3시간 | RAG + OCR 연동 (후순위) |
|
|
| Phase 2 | 1~2시간 | 인프라 설정 확인 작업 |
|
|
| Phase 3 | 2~3시간 | 버그 픽스 코드 수정 |
|
|
| Phase 4 | 1~2시간 | gunicorn 전환 중심 |
|
|
| Phase 5 | 2~3시간 | Mac mini에서 테스트 실행 |
|
|
| Phase 6 | 필요시 | 운영하면서 점진적 |
|
|
| **합계** | **~18시간** | 4~5일 분량 |
|