# 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일 분량 |