refactor: GPU 서버 재구성 + ChromaDB→Qdrant 마이그레이션
- 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>
This commit is contained in:
199
docs/deploy.md
199
docs/deploy.md
@@ -1,5 +1,17 @@
|
||||
# Mac mini 배포 가이드
|
||||
|
||||
> 마지막 업데이트: 2026-03-29
|
||||
> 대상: Mac mini M4 Pro (macOS, Python 3.11+)
|
||||
|
||||
## 요구사항
|
||||
|
||||
- macOS 14+ (Sonoma 이상)
|
||||
- Python 3.11+ (Homebrew 설치 권장)
|
||||
- DEVONthink 4 — 실행 중이어야 AppleScript 동작
|
||||
- OmniFocus 4 — 실행 중이어야 AppleScript 동작
|
||||
- MLX 서버 — Qwen3.5-35B-A3B, localhost:8800에서 실행 중
|
||||
- Tailscale — NAS 및 GPU 서버 접근용
|
||||
|
||||
## 1. 초기 설치
|
||||
|
||||
```bash
|
||||
@@ -22,9 +34,44 @@ nano ~/.config/pkm/credentials.env
|
||||
chmod 600 ~/.config/pkm/credentials.env
|
||||
```
|
||||
|
||||
credentials.env.example을 참고하여 실제 값 입력.
|
||||
credentials.env.example을 참고하여 실제 값 입력:
|
||||
|
||||
## 3. launchd 스케줄 등록
|
||||
```
|
||||
# 필수
|
||||
LAW_OC=<법령API키>
|
||||
MAILPLUS_HOST=mailplus.hyungi.net
|
||||
MAILPLUS_PORT=993
|
||||
MAILPLUS_USER=hyungi
|
||||
MAILPLUS_PASS=<비밀번호>
|
||||
NAS_DOMAIN=ds1525.hyungi.net
|
||||
NAS_TAILSCALE_IP=100.101.79.37
|
||||
NAS_PORT=15001
|
||||
|
||||
# 선택 (향후)
|
||||
CLAUDE_API_KEY=<키>
|
||||
#CHAT_WEBHOOK_URL=<Synology Chat 웹훅>
|
||||
#GPU_SERVER_IP=<Tailscale IP>
|
||||
```
|
||||
|
||||
## 3. 한국 법령 API IP 등록
|
||||
|
||||
법령 API 호출 전에 Mac mini의 공인 IP를 등록해야 합니다.
|
||||
|
||||
```bash
|
||||
# Mac mini에서 공인 IP 확인
|
||||
curl -s ifconfig.me
|
||||
|
||||
# open.law.go.kr → 로그인 → 마이페이지 → 인증키 관리
|
||||
# 위에서 확인한 IP를 서버 IP로 등록
|
||||
# ※ Tailscale IP(100.x.x.x)가 아니라 실제 공인 IP
|
||||
|
||||
# 등록 후 테스트
|
||||
source venv/bin/activate
|
||||
python scripts/law_monitor.py
|
||||
# → "법령 API 에러" 없이 정상 동작 확인
|
||||
```
|
||||
|
||||
## 4. launchd 스케줄 등록
|
||||
|
||||
```bash
|
||||
# 심볼릭 링크 생성
|
||||
@@ -41,7 +88,38 @@ launchctl load ~/Library/LaunchAgents/net.hyungi.pkm.daily-digest.plist
|
||||
launchctl list | grep pkm
|
||||
```
|
||||
|
||||
## 4. 수동 테스트
|
||||
## 5. PKM API 서버 실행
|
||||
|
||||
```bash
|
||||
# 개발 모드 (수동 실행)
|
||||
cd ~/Documents/code/DEVONThink_my\ server/
|
||||
source venv/bin/activate
|
||||
python scripts/pkm_api_server.py
|
||||
|
||||
# 프로덕션 모드 (gunicorn, Phase 3 이후)
|
||||
# gunicorn -w 2 -b 127.0.0.1:9900 scripts.pkm_api_server:app
|
||||
|
||||
# 동작 확인
|
||||
curl http://localhost:9900/health
|
||||
curl http://localhost:9900/devonthink/inbox-count
|
||||
```
|
||||
|
||||
API 서버는 GUI 세션에서 실행해야 합니다 (AppleScript가 DEVONthink/OmniFocus GUI에 접근).
|
||||
|
||||
## 6. DEVONthink Smart Rule 설정
|
||||
|
||||
1. DEVONthink → Preferences → Smart Rules
|
||||
2. 새 Rule: **"AI Auto Classify"**
|
||||
- Event: On Import
|
||||
- Database: Inbox
|
||||
- Condition: Tags is empty
|
||||
- Action: Execute Script → External → `applescript/auto_classify.scpt`
|
||||
3. 새 Rule: **"OmniFocus Sync"**
|
||||
- Event: On Import
|
||||
- Database: Projects
|
||||
- Action: Execute Script → External → `applescript/omnifocus_sync.scpt`
|
||||
|
||||
## 7. 수동 테스트
|
||||
|
||||
```bash
|
||||
cd ~/Documents/code/DEVONThink_my\ server/
|
||||
@@ -51,31 +129,26 @@ source venv/bin/activate
|
||||
python3 scripts/law_monitor.py
|
||||
python3 scripts/mailplus_archive.py
|
||||
python3 scripts/pkm_daily_digest.py
|
||||
|
||||
# AI 분류 테스트
|
||||
python3 tests/test_classify.py
|
||||
```
|
||||
|
||||
## 5. DEVONthink Smart Rule 설정
|
||||
|
||||
1. DEVONthink → Preferences → Smart Rules
|
||||
2. 새 Rule: "AI Auto Classify"
|
||||
- Event: On Import
|
||||
- Database: Inbox
|
||||
- Condition: Tags is empty
|
||||
- Action: Execute Script → External → `applescript/auto_classify.scpt`
|
||||
3. 새 Rule: "OmniFocus Sync"
|
||||
- Event: On Import
|
||||
- Database: Projects
|
||||
- Action: Execute Script → External → `applescript/omnifocus_sync.scpt`
|
||||
|
||||
## 6. 업데이트
|
||||
## 8. 업데이트
|
||||
|
||||
```bash
|
||||
cd ~/Documents/code/DEVONThink_my\ server/
|
||||
git pull
|
||||
source venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
|
||||
# launchd 재로드 (plist가 변경된 경우만)
|
||||
launchctl unload ~/Library/LaunchAgents/net.hyungi.pkm.law-monitor.plist
|
||||
launchctl load ~/Library/LaunchAgents/net.hyungi.pkm.law-monitor.plist
|
||||
# (나머지도 동일)
|
||||
```
|
||||
|
||||
## 7. 로그 확인
|
||||
## 9. 로그 확인
|
||||
|
||||
```bash
|
||||
# 스크립트 로그
|
||||
@@ -83,14 +156,94 @@ tail -f logs/law_monitor.log
|
||||
tail -f logs/mailplus.log
|
||||
tail -f logs/digest.log
|
||||
|
||||
# launchd 로그
|
||||
tail -f logs/law_monitor_launchd.log
|
||||
# API 서버 로그
|
||||
tail -f logs/pkm-api.log
|
||||
tail -f logs/pkm-api.error.log
|
||||
|
||||
# launchd 시스템 로그
|
||||
log show --predicate 'process == "python3"' --last 1h
|
||||
```
|
||||
|
||||
## 10. 일일 운영 점검
|
||||
|
||||
```bash
|
||||
# 1. launchd 작업 상태
|
||||
launchctl list | grep pkm
|
||||
|
||||
# 2. 오늘의 로그 에러 확인
|
||||
grep -c ERROR logs/law_monitor.log
|
||||
grep -c ERROR logs/mailplus.log
|
||||
|
||||
# 3. 법령 마지막 확인 시간
|
||||
cat data/law_last_check.json | python3 -m json.tool
|
||||
|
||||
# 4. DEVONthink Inbox 미처리 건수 (API 서버 실행 중이면)
|
||||
curl -s http://localhost:9900/devonthink/inbox-count
|
||||
|
||||
# 5. MLX 서버 상태
|
||||
curl -s http://localhost:8800/v1/models | python3 -m json.tool
|
||||
```
|
||||
|
||||
## 실행 스케줄
|
||||
|
||||
| 스크립트 | 시간 | 용도 |
|
||||
|---------|------|------|
|
||||
| law_monitor.py | 매일 07:00 | 법령 변경 모니터링 |
|
||||
| mailplus_archive.py | 매일 07:00, 18:00 | 이메일 수집 |
|
||||
| pkm_daily_digest.py | 매일 20:00 | 일일 다이제스트 |
|
||||
| law_monitor.py | 매일 07:00 | 법령 변경 모니터링 (한국+US/JP/EU) |
|
||||
| mailplus_archive.py | 매일 07:00, 18:00 | MailPlus 이메일 수집 |
|
||||
| pkm_daily_digest.py | 매일 20:00 | 일일 다이제스트 생성 |
|
||||
| pkm_api_server.py | 상시 (수동/launchd) | REST API (포트 9900) |
|
||||
|
||||
## 트러블슈팅
|
||||
|
||||
### 법령 API "사용자 정보 검증 실패"
|
||||
|
||||
```
|
||||
원인: Mac mini 공인 IP가 open.law.go.kr에 등록되지 않음
|
||||
해결:
|
||||
1. curl -s ifconfig.me 로 현재 공인 IP 확인
|
||||
2. open.law.go.kr → 마이페이지 → 인증키 관리 → IP 등록
|
||||
3. IP가 변경되면 다시 등록 필요 (고정 IP 아닌 경우)
|
||||
```
|
||||
|
||||
### MailPlus IMAP Connection refused
|
||||
|
||||
```
|
||||
확인 순서:
|
||||
1. Synology DSM → MailPlus Server → 서비스 상태 확인
|
||||
2. IMAP 활성화: DSM → MailPlus Server → 메일 전송 → IMAP 탭
|
||||
3. 포트: 993(SSL) vs 143(STARTTLS)
|
||||
4. 방화벽: Synology 방화벽에서 993 포트 확인
|
||||
5. Tailscale 직접:
|
||||
python3 -c "import imaplib; m=imaplib.IMAP4_SSL('100.101.79.37', 993); print('OK')"
|
||||
```
|
||||
|
||||
### AppleScript 실행 오류
|
||||
|
||||
```
|
||||
확인:
|
||||
1. DEVONthink, OmniFocus가 GUI로 실행 중인지 확인
|
||||
2. 접근성 권한: 시스템 설정 → 개인정보 보호 → 접근성 → python/osascript 허용
|
||||
3. 수동 테스트:
|
||||
osascript -e 'tell application "DEVONthink 3" to get name of databases'
|
||||
```
|
||||
|
||||
### MLX 서버 응답 없음
|
||||
|
||||
```
|
||||
확인:
|
||||
1. MLX 서버 프로세스 확인: ps aux | grep mlx
|
||||
2. 포트 확인: lsof -i :8800
|
||||
3. 모델 로드 확인: curl http://localhost:8800/v1/models
|
||||
4. 재시작 필요 시: (MLX 서버 시작 명령어 실행)
|
||||
```
|
||||
|
||||
### Daily Digest에 데이터가 비어있음
|
||||
|
||||
```
|
||||
확인:
|
||||
1. DEVONthink이 실행 중인지 확인
|
||||
2. OmniFocus가 실행 중인지 확인
|
||||
3. 로그 확인: tail -20 logs/digest.log
|
||||
4. AppleScript 직접 테스트:
|
||||
osascript -e 'tell application "DEVONthink 3" to get count of databases'
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user