- 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>
13 KiB
13 KiB
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 등록 상태 확인 및 등록
# 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. 개별 모듈 테스트
# 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일 분량 |