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:
hyungi
2026-03-30 13:19:31 +09:00
parent 35062145ed
commit 45cabc9aea
11 changed files with 2068 additions and 277 deletions

View File

@@ -1,18 +1,19 @@
# Claude Code 실행 명령어 — PKM 시스템 구축
> 작업 위치: MacBook Pro ~/Documents/code/DEVONThink_my server/
> Claude Code를 이 디렉토리에서 실행
> 또는 Cowork 모드에서 마운트된 폴더
> 완성 후 Gitea에 push → Mac mini에서 pull
```
개발/배포 흐름:
MacBook Pro (Claude Code)
MacBook Pro (Claude Code / Cowork)
~/Documents/code/DEVONThink_my server/
→ 스크립트/설정 파일 작성
→ git commit & push
Gitea (Synology NAS)
https://git.hyungi.net/hyungi/devonthink_home.git
Mac mini (git pull → 실행)
@@ -20,272 +21,478 @@ MacBook Pro (Claude Code)
---
## 0단계: 프로젝트 구조 생성 + credentials.env 복사
# Phase 1: 초기 구축 (완료)
Claude Code 실행 전에 먼저:
> 2026-03-26 ~ 03-27 작업. 총 15 커밋.
## 0단계: 프로젝트 구조 생성 + credentials.env ✅ 완료
```bash
# MacBook Pro에서
cd ~/Documents/code/DEVONThink_my\ server/
# credentials.env를 프로젝트에 복사 (gitignore 필수!)
cp ~/.config/pkm/credentials.env ./credentials.env.example
# example은 값을 비운 템플릿용, 실제 파일은 Mac mini에서 직접 생성
# Mac mini에서 (SSH 접속 후)
# Mac mini에서
mkdir -p ~/.config/pkm
nano ~/.config/pkm/credentials.env
# → 실제 인증 정보 입력
chmod 600 ~/.config/pkm/credentials.env
```
## 1단계: 프로젝트 구조 + requirements.txt ✅ 완료
생성된 파일: README.md, requirements.txt, .gitignore, credentials.env.example, 전체 디렉토리 구조
## 2단계: AI 분류 프롬프트 ✅ 완료
- MLX 서버(localhost:8800) OpenAI 호환 API로 전환됨
- Qwen3.5 thinking 모드 대응 완료 (JSON 추출 후처리)
- 프롬프트: scripts/prompts/classify_document.txt
## 3단계: AppleScript ✅ 완료
- applescript/auto_classify.scpt — Inbox 자동 분류
- applescript/omnifocus_sync.scpt — OmniFocus 작업 생성
## 4단계: 법령 모니터링 ⚠️ 부분 완료
- scripts/law_monitor.py 작성 완료
- 외국 법령 (US OSHA 1건, JP 厚労省 10건, EU-OSHA 5건) 수집 성공
- ❌ 한국 법령 API: IP 등록 미완 → Phase 2에서 해결
## 5단계: MailPlus 이메일 수집 ❌ 연결 실패
- scripts/mailplus_archive.py 코드 완성
- ❌ IMAP 접속 실패 (Connection refused) → Phase 2에서 해결
## 6단계: Daily Digest ⚠️ 미테스트
- scripts/pkm_daily_digest.py 코드 완성
- 실행 테스트 미진행 → Phase 2 이후 테스트
## 7단계: DEVONagent 가이드 ✅ 완료
- docs/devonagent-setup.md — 9개 검색 세트 설정 가이드
## 8단계: 전체 테스트 ❌ 미진행
- tests/test_classify.py 작성 완료
- docs/test-report.md 미생성 → Phase 4에서 진행
## 추가: PKM API 서버 (계획 외 생성)
- scripts/pkm_api_server.py — Flask REST API (포트 9900)
- DEVONthink + OmniFocus 상태 조회용
- 기본 동작 확인됨, 버그 있음 → Phase 2에서 수정
---
## 1단계: 프로젝트 구조 + requirements.txt
# Phase 1.5: GPU 서버 재구성 (Phase 2와 병행)
> 상세 계획: docs/gpu-restructure.md 참조
> GPU 서버 SSH 작업 + PKM 프로젝트 코드 수정
## GPU-1단계: GPU 서버 Ollama 모델 교체
```bash
# GPU 서버에서 실행 (ssh 192.168.1.186)
# 1. 기존 LLM 모델 제거
ollama rm qwen3.5:9b-q8_0
ollama rm id-9b
# 2. 임베딩/리랭킹 모델 설치
ollama pull bge-m3
ollama pull bge-reranker-v2-m3
# 3. no-think proxy 비활성화
sudo systemctl disable --now ollama-proxy
# 4. Ollama systemd 환경 조정
sudo systemctl edit ollama
# Environment="OLLAMA_MAX_LOADED_MODELS=2"
# Environment="OLLAMA_KEEP_ALIVE=30m"
sudo systemctl daemon-reload && sudo systemctl restart ollama
# 5. 검증
ollama list # → bge-m3, bge-reranker만 존재
curl localhost:11434/api/embed -d '{"model":"bge-m3","input":["테스트"]}' # → 1024차원 벡터
```
## GPU-2단계: tk-ai-service 코드 수정 (Mac Mini)
```
이 프로젝트의 디렉토리 구조를 만들고 기본 설정 파일들을 생성해줘.
작업 디렉토리: 현재 디렉토리 (~/Documents/code/DEVONThink_my server/)
tk-ai-service의 ollama_client.py를 OpenAI API 호환으로 리팩터링해줘.
프로젝트 구조:
./
├── README.md ← 프로젝트 설명
├── requirements.txt ← Python 패키지 목록
├── .gitignore ← credentials.env, venv, logs, __pycache__ 등 제외
├── credentials.env.example ← 인증 정보 템플릿 (값은 비움)
├── scripts/
│ ├── law_monitor.py
│ ├── mailplus_archive.py
│ ├── pkm_daily_digest.py
│ ├── embed_to_chroma.py
│ └── prompts/
│ └── classify_document.txt
├── applescript/
│ ├── auto_classify.scpt
│ └── omnifocus_sync.scpt
├── launchd/
│ ├── net.hyungi.pkm.law-monitor.plist
│ ├── net.hyungi.pkm.mailplus.plist
│ └── net.hyungi.pkm.daily-digest.plist
├── docs/
│ ├── devonagent-setup.md
│ └── deploy.md ← Mac mini 배포 방법
└── tests/
└── test_classify.py
변경 대상:
~/docker/tk-factory-services/ai-service/services/ollama_client.py
→ generate_text(): /api/chat → /v1/chat/completions
→ check_health(): /api/tags → /v1/models
→ generate_embedding(): 변경 없음 (GPU Ollama 유지)
requirements.txt에 넣을 패키지:
- chromadb
- requests
- python-dotenv
- schedule
- markdown
docker-compose.yml 환경변수:
OLLAMA_BASE_URL=http://host.internal:8800 (MLX)
OLLAMA_TEXT_MODEL=mlx-community/Qwen3.5-35B-A3B-4bit
OLLAMA_EMBED_URL=http://192.168.1.186:11434 (GPU)
.gitignore에 반드시 포함:
- credentials.env
- venv/
- logs/
- __pycache__/
- *.pyc
- .DS_Store
검증: docker compose build && docker compose up -d
curl http://localhost:30400/health → 모두 connected
```
deploy.md에는 Mac mini에서의 설치 절차 작성:
1. git pull
2. python3 -m venv venv && source venv/bin/activate
3. pip install -r requirements.txt
4. credentials.env는 ~/.config/pkm/credentials.env에 별도 관리
5. launchd plist 심볼릭 링크 등록 방법
## GPU-3단계: Docker + NFS + Komga 이전
네트워크 환경:
- NAS 도메인: ds1525.hyungi.net (Tailscale: 100.101.79.37, 포트: 15001)
- MailPlus: mailplus.hyungi.net:993 (IMAP SSL)
- WebDAV: webdav.hyungi.net/Document_Server/DEVONThink/
- TKSafety: tksafety.technicalkorea.net (나중에 활성화)
```bash
# GPU 서버에서 실행 (ssh 192.168.1.186)
# 1. Docker 설치
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
sudo usermod -aG docker hyungi
# 2. NFS 마운트
sudo apt install nfs-common
sudo mkdir -p /mnt/comic
echo '192.168.1.227:/volume1/Comic /mnt/comic nfs4 ro,nosuid,noexec,nodev,soft,timeo=15 0 0' | sudo tee -a /etc/fstab
sudo mount -a
ls /mnt/comic # 확인
# 3. Komga 컨테이너 시작
sudo mkdir -p /opt/komga && cd /opt/komga
# docker-compose.yml 생성 (gpu-restructure.md Phase 1.5-3 참조)
docker compose up -d
# Mac Mini에서:
docker stop komga && docker rm komga
# nginx-ssl.conf: komga_backend upstream → 192.168.1.186:25600
docker restart home-service-proxy
# 검증
curl https://komga.hyungi.net # → GPU 서버 경유 접근
```
## GPU-4단계: Surya OCR 설치
```bash
# GPU 서버에서 실행 (ssh 192.168.1.186)
# 1. PyTorch CUDA 확인
python3 -c "import torch; print(torch.cuda.is_available())"
# False면: pip install torch --index-url https://download.pytorch.org/whl/cu124
# 2. Surya OCR 설치
sudo mkdir -p /opt/surya-ocr && cd /opt/surya-ocr
python3 -m venv venv
source venv/bin/activate
pip install surya-ocr fastapi uvicorn python-multipart
# 3. server.py 작성 (FastAPI 래퍼, gpu-restructure.md Phase 2-2 참조)
# 4. systemd 등록
# /etc/systemd/system/surya-ocr.service (gpu-restructure.md Phase 2-3 참조)
sudo systemctl daemon-reload
sudo systemctl enable --now surya-ocr
# 검증
curl -F "file=@test.pdf" http://localhost:8400/ocr
```
## GPU-5단계: Qdrant 통합 + PKM 코드 갱신
```
PKM 프로젝트 코드를 GPU 서버 재구성에 맞게 갱신해줘.
1. scripts/embed_to_chroma.py → scripts/embed_to_qdrant.py 리라이트
- chromadb → qdrant-client
- nomic-embed-text → bge-m3 (GPU 서버 192.168.1.186:11434)
- /api/embed 사용 (배치 지원)
- 텍스트 청킹 (500토큰, 50오버랩)
- 기존 embed_to_chroma.py는 git rm
2. applescript/auto_classify.scpt 수정
- Step 0: OCR 감지 + Surya OCR 호출 추가
- Step 4: embed_to_qdrant.py 호출로 변경
- 버그 픽스: 73행 sourceChannel 이중 설정 삭제
- baseDir 변수 사용 (12단계와 합산)
3. requirements.txt 업데이트 (9단계와 합산)
- chromadb, schedule 제거
+ qdrant-client, flask, gunicorn 추가
4. credentials.env.example: GPU_SERVER_IP 추가
5. Qdrant에 pkm_documents 컬렉션 생성 (1024차원, cosine)
검증: python3 scripts/embed_to_qdrant.py <테스트UUID> → Qdrant 벡터 저장
```
## GPU-6단계: architecture.md 대규모 갱신
```
docs/architecture.md를 GPU 서버 재구성에 맞게 전체 갱신해줘.
변경 규모: ChromaDB 28건, nomic-embed 12건, VL-7B 5건 — 문맥별 수정 필요
주요 변경:
- Tier 3 모델: nomic-embed-text → bge-m3, Qwen2.5-VL-7B → Surya OCR
- 벡터 DB: ChromaDB → Qdrant (모든 언급)
- VRAM 다이어그램: ~11.3GB → ~7-8GB
- Smart Rule 설계: embed_to_chroma → embed_to_qdrant, OCR 단계 추가
- 3-Tier AI 라우팅 전략 표 갱신
- 코드 예시 내 경로/모델명
※ 단순 치환 불가, 전체 문서를 통독하며 문맥에 맞게 수정할 것
※ 별도 커밋으로 분리
```
## GPU-7단계: RAG 파이프라인 구축 (후순위)
```
pkm_api_server.py에 RAG 엔드포인트를 추가해줘.
추가 엔드포인트:
POST /rag/query — 질문 → bge-m3 임베딩 → Qdrant 검색 → 리랭킹 → MLX 답변
POST /devonthink/embed — 단일 문서 임베딩 트리거
POST /devonthink/embed-batch — 배치 임베딩
docstring 갱신: "범위: DEVONthink + OmniFocus + RAG 검색"
scripts/ocr_preprocess.py 신규 작성:
DEVONthink UUID → AppleScript로 파일 경로 추출 → Surya API(GPU:8400) 호출
검증: curl -X POST localhost:9900/rag/query -d '{"q":"산업안전 법령"}'
```
---
## 2단계: Ollama 모델 확인 + 분류 프롬프트 테스트
# Phase 2: 인프라 수정 + 버그 픽스 (Phase 1.5와 병행)
> dev-roadmap.md Phase 2~3 해당
> ※ requirements.txt, AppleScript 경로, credentials.env는 GPU-5단계와 합산 진행
## 9단계: requirements.txt 수정 ← GPU-5단계와 합산
```
Ollama가 정상 동작하는지 확인하고, PKM 문서 분류용 프롬프트를 테스트해줘.
requirements.txt에 flask가 빠져있어. pkm_api_server.py에서 사용 중이니까 추가해줘.
GPU 서버 재구성에 따라 chromadb→qdrant-client 교체도 함께 진행.
gunicorn도 추가해 (프로덕션 WSGI 서버용).
schedule 패키지는 현재 미사용 — 제거할지 유지할지 판단해줘.
anthropic 패키지는 향후 Tier 2 연동용이니 유지.
1. ollama list로 현재 모델 확인
2. qwen3.5:35b-a3b 계열 모델이 있는지 확인 (없으면 알려줘)
3. 테스트 프롬프트 실행 — 아래 내용으로 분류 테스트:
수정할 파일: requirements.txt
테스트 문서: "산업안전보건법 시행규칙 일부개정령안 입법예고 - 고용노동부는 위험성평가에 관한 지침을 개정하여..."
추가:
+ flask>=3.0.0
+ gunicorn>=21.2.0
기대 응답 JSON:
{
"tags": ["위험성평가", "법령개정", "고용노동부"],
"domain_db": "04_Industrial safety",
"sub_group": "10_Legislation/Notice",
"sourceChannel": "inbox_route",
"dataOrigin": "external"
}
확인:
- schedule>=1.2.0 → 사용처 없으면 제거
```
도메인 DB 선택지:
00_Note_BOX, 01_Philosophie, 02_Language, 03_Engineering,
04_Industrial safety, 05_Programming, 07_General Book,
97_Production drawing, 99_Reference Data, 99_Technicalkorea
## 10단계: JP 번역 thinking 오염 수정
sourceChannel 값: tksafety, devonagent, law_monitor, inbox_route, email, web_clip, manual
dataOrigin 값: work (자사 업무), external (외부 참고)
```
법령 모니터링에서 일본어 번역 시 MLX Qwen3.5의 thinking 출력이 결과에 섞이는 문제를 수정해줘.
프롬프트를 최적화해서 ~/Documents/code/DEVONThink_my server/scripts/prompts/ 디렉토리에 저장해줘.
현재 문제:
로그에서 "Wait, I'll check if..." 같은 thinking 텍스트가 번역 결과에 포함됨.
위치: scripts/law_monitor.py의 JP 번역 호출부
수정 방향:
1. 번역 프롬프트에 /nothink 모드 명시 강화
2. llm_generate() 응답에서 thinking 패턴 필터링 추가
- "Wait,", "Let me", "I'll check", "Hmm," 등으로 시작하는 줄 제거
- "Final Output:" 이후 텍스트만 추출하는 로직
3. 또는 pkm_utils.py의 llm_generate()에 strip_thinking=True 옵션 추가
테스트: JP RSS 항목 하나로 번역 테스트하여 깨끗한 한글 출력 확인
```
## 11단계: API 서버 버그 수정
```
PKM API 서버의 두 가지 버그를 수정해줘.
위치: scripts/pkm_api_server.py
버그 1: /devonthink/stats → 500 Internal Server Error
- AppleScript 쿼리가 실패하는 것으로 추정
- 에러 로그 확인: logs/pkm-api.error.log
- AppleScript에서 DB 이름이나 property 접근 방식 수정 필요
버그 2: 한글 쿼리 파라미터 인코딩 에러
- /devonthink/search?q=산업안전 → 400 Bad request syntax
- Flask의 request.args는 UTF-8을 지원하므로, 클라이언트 측 문제일 가능성
- 서버 측에서도 방어 코드 추가: URL 디코딩 처리
추가 개선:
- /omnifocus/overdue 엔드포인트가 404였다가 나중에 추가됨 — 코드 확인
- / (루트) 접근 시 404 → /health로 리다이렉트 또는 엔드포인트 목록 반환
```
## 12단계: AppleScript 경로 변수화 ← GPU-5단계와 합산
```
AppleScript 파일들의 하드코딩된 경로를 변수로 교체해줘.
GPU-5단계의 embed_to_qdrant.py 변경, OCR 단계 추가, sourceChannel 버그 픽스도 함께 진행.
현재 하드코딩:
~/Documents/code/DEVONThink_my server/scripts/prompts/classify_document.txt
~/Documents/code/DEVONThink_my server/venv/bin/python3
~/Documents/code/DEVONThink_my server/scripts/embed_to_chroma.py
수정 대상:
applescript/auto_classify.scpt
applescript/omnifocus_sync.scpt
수정 방향:
- 스크립트 상단에 property baseDir 정의
- 모든 경로를 baseDir 기반으로 조합
- 또는 환경변수 PKM_HOME을 읽어서 사용
※ AppleScript에서 환경변수 읽기:
set pkmHome to do shell script "echo $PKM_HOME"
또는 property로 직접 지정하는 게 안정적
```
---
## 3단계: DEVONthink Smart Rule + AppleScript 배포
# Phase 3: API 서버 개선
## 13단계: gunicorn 전환 + launchd 등록
```
DEVONthink 4 Smart Rule용 AppleScript 모듈들을 만들어줘.
Mac mini에서 DEVONthink가 실행 중이야.
PKM API 서버를 Flask development server에서 gunicorn으로 전환하고,
launchd plist를 만들어 Mac mini 로그인 시 자동 시작되도록 해줘.
모듈 A: Ollama 연동 자동 분류 (~/Documents/code/DEVONThink_my server/applescript/auto_classify.scpt)
- DEVONthink Inbox DB에 새 문서가 들어오면 실행
- Ollama qwen3.5 35B에 문서 텍스트 전송
- 응답에서 tags, domain_db, sub_group, sourceChannel, dataOrigin 파싱
- DEVONthink 태그 설정 + 커스텀 메타데이터(sourceChannel, dataOrigin, lastAIProcess) 설정
- 해당 도메인 DB의 하위 그룹으로 문서 이동
- GPU 서버(Tailscale IP)로 벡터 임베딩 비동기 전송
1. gunicorn 설정:
gunicorn -w 2 -b 127.0.0.1:9900 pkm_api_server:app
※ AppleScript 실행 때문에 GUI 세션에서 실행해야 함
※ launchd의 LimitLoadToSessionType = Aqua 또는 LoginwindowUI
모듈 B: OmniFocus 연동 (~/Documents/code/DEVONThink_my server/applescript/omnifocus_sync.scpt)
- Projects DB에 새 문서 추가 시 TODO 패턴 감지
- OmniFocus에 작업 생성 (DEVONthink 링크 포함)
- 커스텀 메타데이터에 omnifocusTaskID 저장
2. launchd plist 생성:
launchd/net.hyungi.pkm.api-server.plist
- 로그인 시 자동 시작
- KeepAlive: true (크래시 시 재시작)
- WorkingDirectory: ~/Documents/code/DEVONThink_my server/
- StandardOutPath/StandardErrorPath: logs/pkm-api.log, logs/pkm-api.error.log
프롬프트 파일 위치: ~/Documents/code/DEVONThink_my server/scripts/prompts/
인증 정보: ~/.config/pkm/credentials.env
GPU 서버 Tailscale IP는 별도 확인 필요 (나중에 추가)
3. deploy.md에 API 서버 관련 내용 추가
```
## 14단계: API 엔드포인트 추가
```
PKM API 서버에 모니터링/상태 확인용 엔드포인트를 추가해줘.
추가할 엔드포인트:
1. GET /law-monitor/status
- data/law_last_check.json 읽어서 마지막 확인 시간 반환
- logs/law_monitor.log 최근 에러 건수
2. GET /digest/latest
- DEVONthink 00_Note_BOX/Daily_Digest/에서 최신 다이제스트 조회
- 또는 data/ 아래에 최근 다이제스트 캐시
3. GET / → 전체 엔드포인트 목록 반환 (현재 404)
4. GET /health 확장
- MLX 서버 상태 (localhost:8800 연결 가능 여부)
- DEVONthink 실행 상태
- 각 launchd job 상태
```
---
## 4단계: 법령 모니터링 스크립
# Phase 4: 테스
## 15단계: 모듈별 테스트 실행
```
한국 법령 변경 모니터링 스크립트를 만들어줘.
Mac mini에서 각 모듈의 동작을 확인해줘.
스크립트: ~/Documents/code/DEVONThink_my server/scripts/law_monitor.py
인증: ~/.config/pkm/credentials.env의 LAW_OC 값 사용
API: open.law.go.kr OpenAPI
1. AI 분류 테스트 (tests/test_classify.py)
cd ~/Documents/code/DEVONThink_my\ server/
source venv/bin/activate
python tests/test_classify.py
→ 5종 문서 분류 정확도 확인
기능:
1. 산업안전보건법, 중대재해처벌법, 관련 시행령/시행규칙/고시 변경 추적
2. 변경 감지 시:
- 법령 본문(XML) 다운로드 → ~/Documents/code/DEVONThink_my server/data/laws/에 저장
- DEVONthink 04_Industrial Safety/10_Legislation/ 하위에 자동 임포트 (AppleScript 호출)
- 커스텀 메타데이터: sourceChannel=law_monitor, dataOrigin=external
- 로그: ~/Documents/code/DEVONThink_my server/logs/law_monitor.log
3. launchd plist 생성: 매일 07:00 실행
~/Documents/code/DEVONThink_my server/launchd/net.hyungi.pkm.law-monitor.plist
→ ~/Library/LaunchAgents/에 심볼릭 링크
2. 법령 모니터링 (Phase 2 인프라 수정 후)
python scripts/law_monitor.py
→ 한국 법령 API 정상 응답 확인
→ 외국 법령 수집 재확인
※ 법령 API 승인 대기중이라 스크립트만 만들고 실제 테스트는 승인
※ 해외 법령(US OSHA, JP, EU)은 나중에 추가 예정
3. MailPlus 이메일 수집 (Phase 2 연결 수정)
python scripts/mailplus_archive.py
→ IMAP 접속 + 이메일 가져오기 확인
4. Daily Digest
python scripts/pkm_daily_digest.py
→ 다이제스트 MD 파일 생성 확인
5. API 서버 (Phase 2 버그 수정 후)
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"
curl http://localhost:9900/omnifocus/stats
```
## 16단계: E2E 통합 테스트
```
PKM 시스템 End-to-End 테스트를 진행해줘.
시나리오 1: Inbox → 자동분류 플로우
1. DEVONthink Inbox에 테스트 문서 추가
2. Smart Rule 트리거 → auto_classify.scpt 실행 확인
3. 태그, 커스텀 메타데이터(sourceChannel, dataOrigin, lastAIProcess) 확인
4. 올바른 도메인 DB + 하위 그룹으로 이동 확인
시나리오 2: 법령 → 다이제스트 플로우
1. law_monitor.py 수동 실행
2. data/laws/에 파일 생성 + DEVONthink 04_Industrial Safety 임포트 확인
3. pkm_daily_digest.py 실행 → 법령 변경 건 포함 확인
시나리오 3: OmniFocus 연동
1. Projects DB에 TODO 패턴 문서 추가
2. omnifocus_sync.scpt 트리거 확인
3. OmniFocus Inbox에 작업 생성 + DEVONthink 링크 확인
4. 커스텀 메타데이터 omnifocusTaskID 확인
시나리오 4: launchd 스케줄 확인
launchctl list | grep pkm
→ 3개(+API 서버) 등록 확인
각 항목 pass/fail 리포트 → docs/test-report.md
```
---
## 5단계: MailPlus → DEVONthink 이메일 수집
# Phase 5: 운영 안정화 (나중에)
## 17단계: 로그 로테이션 + 알림
```
MailPlus 이메일을 DEVONthink Archive DB로 자동 수집하는 스크립트를 만들어줘.
운영 안정성을 위한 설정을 추가해줘.
스크립트: ~/Documents/code/DEVONThink_my server/scripts/mailplus_archive.py
인증: ~/.config/pkm/credentials.env
1. Python 로그 로테이션
- pkm_utils.py의 setup_logger()에 RotatingFileHandler 적용
- maxBytes=10MB, backupCount=5
접속 정보:
- IMAP 서버: mailplus.hyungi.net:993 (SSL)
- 계정: hyungi
2. Synology Chat 알림 (CHAT_WEBHOOK_URL 설정 후)
- 법령 변경 감지 시 알림
- 에러 발생 시 알림
- Daily Digest 요약 알림
기능:
1. IMAP으로 MailPlus 접속
2. 마지막 동기화 이후 새 메일 가져오기
3. DEVONthink Archive DB에 임포트 (AppleScript 호출)
4. 커스텀 메타데이터: sourceChannel=email
5. 안전 관련 키워드 감지 시 dataOrigin 자동 판별
launchd: 매일 07:00 + 18:00 실행
~/Documents/code/DEVONThink_my server/launchd/net.hyungi.pkm.mailplus.plist
3. 에러 모니터링
- pkm_daily_digest.py에 이미 에러 카운트 로직 있음
- 임계값 초과 시 Chat 알림 추가
```
---
## 6단계: Daily Digest 시스템
## 18단계: 문서 보완
```
PKM 일일 다이제스트를 자동 생성하는 스크립트를 만들어줘.
프로젝트 문서를 보완해줘.
스크립트: ~/Documents/code/DEVONThink_my server/scripts/pkm_daily_digest.py
인증: ~/.config/pkm/credentials.env
기능:
1. DEVONthink에서 오늘 추가/수정된 문서 집계 (AppleScript로 쿼리)
- DB별 신규 건수
- sourceChannel별 구분
2. law_monitor 로그에서 법령 변경 건 파싱
3. OmniFocus 오늘 완료/추가/기한초과 집계 (AppleScript)
4. 상위 뉴스 3건 요약 (Ollama 35B 호출)
5. MD 파일 생성 → DEVONthink 00_Note_BOX/Daily_Digest/에 저장
파일명: YYYY-MM-DD_digest.md
6. OmniFocus 액션 자동 생성 (법령변경, overdue, Inbox 미처리 등)
7. 90일 지난 다이제스트 → 90_Archive 이동 (Smart Rule 대체)
launchd: 매일 20:00 실행
~/Documents/code/DEVONThink_my server/launchd/net.hyungi.pkm.daily-digest.plist
※ Synology Chat 웹훅 알림은 나중에 추가 (CHAT_WEBHOOK_URL 설정 후)
```
---
## 7단계: DEVONagent 검색 세트 (수동 가이드)
```
DEVONagent Pro에서 안전 분야 자동 검색 세트를 설정하는 가이드를 만들어줘.
총 9개 검색 세트 (7 안전 + 2 기술):
1. 국내 산업안전 뉴스 (kosha, moel, safetynews 등)
2. 국내 중대재해 뉴스
3. KOSHA 가이드/지침
4. 국내 산업안전 학술/논문
5. US OSHA / Safety+Health Magazine
6. JP 厚生労働省 / 安全衛生
7. EU-OSHA
8. 기술 뉴스 (AI/서버/네트워크)
9. 프로그래밍 기술 동향
각 세트별로:
- 검색 키워드/연산자
- 사이트 제한
- 스케줄 (매일/주간)
- 수량 제한 (주간 합계 50~85건 수준)
- 결과 → DEVONthink Inbox로 전송 설정 방법
이건 DEVONagent GUI에서 수동 설정해야 하니까,
단계별 가이드 문서를 ~/Documents/code/DEVONThink_my server/docs/devonagent-setup.md로 만들어줘.
```
---
## 8단계: 전체 테스트
```
PKM 시스템 전체 End-to-End 테스트를 진행해줘.
테스트 항목:
1. Ollama 분류 테스트 — 5종 문서(법령, 뉴스, 논문, 메모, 이메일) 분류 정확도
2. DEVONthink Smart Rule — Inbox에 테스트 문서 추가 → 자동 분류 확인
3. sourceChannel/dataOrigin 메타데이터가 정상 설정되는지
4. OmniFocus 연동 — TODO 패턴 문서 → 작업 자동 생성
5. MailPlus IMAP 접속 테스트
6. launchd 스케줄 등록 확인 (launchctl list | grep pkm)
7. Daily Digest 수동 실행 테스트
각 항목 pass/fail 리포트를 ~/Documents/code/DEVONThink_my server/docs/test-report.md로 저장해줘.
1. README.md — 아키텍처 다이어그램, 기능 목록, 시작 가이드 확장
2. deploy.md — API 서버 배포, 트러블슈팅 섹션, macOS 요구사항 추가
3. docs/troubleshooting.md — 자주 발생하는 문제와 해결 방법
```
---
@@ -295,8 +502,29 @@ PKM 시스템 전체 End-to-End 테스트를 진행해줘.
```
Mac mini 접속: SSH (MacBook Pro → Mac mini)
NAS 도메인: ds1525.hyungi.net (Tailscale: 100.101.79.37, 포트: 15001)
MailPlus: mailplus.hyungi.net:993 (IMAP SSL)
MailPlus: mailplus.hyungi.net:993 (IMAP SSL) ← 현재 연결 불가, 확인 필요
WebDAV: webdav.hyungi.net/Document_Server/DEVONThink/
TKSafety: tksafety.technicalkorea.net (나중에 활성화)
내부 네트워크: Tailscale VPN 연결됨
Gitea: https://git.hyungi.net/hyungi/devonthink_home.git
```
## 참고: Git 커밋 히스토리
```
3506214 fix(law_monitor): US 타입 필터 제거 + JP RDF 네임스페이스 수정
c8e30b5 fix: AppleScript POSIX path 변수 방식 + 단일 -e 실행으로 따옴표 문제 해결
f13b998 fix: AppleScript 행별 -e 분할 실행 — 파일 방식 인코딩 문제 회피
735c072 fix: AppleScript를 임시 파일로 실행 — osascript -e 이스케이프 문제 해결
446963c fix(law_monitor): AppleScript f-string 제거 + EU 파일명 고유화
0b950a4 fix(law_monitor): AppleScript 따옴표 이스케이프 수정
6a44b10 fix(law_monitor): JP/EU RSS URL 수정 — news.rdf + rss.xml, RDF 네임스페이스 대응
9dc0694 feat(law_monitor): 외국 법령 지원 추가 — US OSHA, JP 厚労省(MLX 번역), EU-OSHA
ec6074d fix(law_monitor): API 에러 응답 로깅 추가 — 인증 실패 시 조용히 넘어가던 문제
aca4a02 fix: LLM thinking 허용 + 마지막 유효 JSON 추출 방식으로 변경
49c39a1 fix: LLM thinking 출력 대응 — max_tokens 증가 + JSON 추출 강화
948be16 fix: Qwen3.5 /nothink 모드 + json_mode 파라미터 추가
a774771 fix: MLX 서버(localhost:8800) 대응 — Ollama API → OpenAI 호환 변경
084d3a8 feat: 전체 PKM 스크립트 일괄 작성 — 분류/법령/메일/다이제스트/임베딩
bec9579 chore: 프로젝트 구조 + 설계 문서 초기 커밋
```