# Quick Reference 작업 시작 전 체크리스트. ## 현재 상태 확인 ```bash # 챗봇 컨테이너 상태 docker ps -a --filter "name=bot-" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" # Qdrant 상태 + 3컬렉션 확인 docker ps --filter "name=qdrant" --format "table {{.Names}}\t{{.Status}}" curl -s http://localhost:6333/collections | python3 -c "import sys,json; [print(f' {c[\"name\"]}') for c in json.loads(sys.stdin.read())['result']['collections']]" # 맥미니 Ollama 모델 확인 (brew services로 자동기동, 임베딩/리랭킹 전용) # 중지 상태일 때: brew services start ollama ollama list # GPU 서버 Ollama 상태 curl -s http://192.168.1.186:11434/api/tags | python3 -m json.tool # GPU 서버 id-9b 헬스체크 curl -s http://192.168.1.186:11434/api/generate -d '{"model":"id-9b:latest","prompt":"hi","stream":false}' | python3 -m json.tool ``` ## 접속 정보 | 서비스 | URL | |--------|-----| | n8n 편집기 | http://localhost:5678 | | Qdrant 대시보드 | http://localhost:6333/dashboard | | bot-postgres | localhost:15478 | | Ollama API (맥미니) | http://localhost:11434 | | Ollama API (GPU) | http://192.168.1.186:11434 | | Synology Chat | NAS (192.168.1.227) | | chat_bridge | http://localhost:8091 | | HEIC converter | http://localhost:8090 | | caldav_bridge | http://localhost:8092 | ## Docker 명령어 ```bash # 프로젝트 경로 cd ~/Documents/code/syn-chat-bot # 시작/종료 docker compose up -d docker compose down # 로그 확인 docker compose logs -f bot-n8n docker compose logs -f bot-postgres # n8n만 재시작 docker compose restart bot-n8n # DB 접속 docker exec -it bot-postgres psql -U bot -d chatbot # DB 테이블 확인 docker exec bot-postgres psql -U bot -d chatbot -c '\dt' # v2 마이그레이션 실행 (기존 DB가 있을 때) docker exec -i bot-postgres psql -U bot -d chatbot < init/migrate-v2.sql # Qdrant tk_company 컬렉션 + 인덱스 설정 bash init/setup-qdrant.sh # v3 마이그레이션 실행 (Phase 5-6 테이블 추가) docker exec -i bot-postgres psql -U bot -d chatbot < init/migrate-v3.sql ``` ## 헬스체크 (전체) ```bash # 한 번에 전체 확인 echo "=== Docker ===" && \ docker ps -a --filter "name=bot-" --filter "name=qdrant" --format "table {{.Names}}\t{{.Status}}" && \ echo "=== 맥미니 Ollama ===" && \ curl -s http://localhost:11434/api/tags | python3 -c "import sys,json; [print(f' {m[\"name\"]}') for m in json.loads(sys.stdin.read())['models']]" && \ echo "=== GPU 서버 Ollama ===" && \ curl -s http://192.168.1.186:11434/api/tags | python3 -c "import sys,json; [print(f' {m[\"name\"]}') for m in json.loads(sys.stdin.read())['models']]" && \ echo "=== Qdrant 컬렉션 ===" && \ curl -s http://localhost:6333/collections | python3 -c "import sys,json; [print(f' {c[\"name\"]}') for c in json.loads(sys.stdin.read())['result']['collections']]" && \ echo "=== tk_company ===" && \ curl -s http://localhost:6333/collections/tk_company | python3 -c "import sys,json; r=json.loads(sys.stdin.read())['result']; print(f' 벡터수: {r[\"points_count\"]}, 상태: {r[\"status\"]}')" 2>/dev/null || echo " (미생성)" && \ echo "=== 네이티브 서비스 ===" && \ curl -s http://localhost:8090/health && echo && \ curl -s http://localhost:8091/health && echo && \ curl -s http://localhost:8092/health && echo && \ ./manage_services.sh status && \ echo "=== n8n ===" && \ curl -s -o /dev/null -w ' HTTP %{http_code}' http://localhost:5678 && echo && \ echo "=== API 사용량 ===" && \ docker exec bot-postgres psql -U bot -d chatbot -t -c "SELECT tier, call_count, estimated_cost FROM api_usage_monthly WHERE year=EXTRACT(YEAR FROM NOW()) AND month=EXTRACT(MONTH FROM NOW())" 2>/dev/null || echo " (테이블 없음)" ``` ## 디렉토리 구조 ``` syn-chat-bot/ ├── docker-compose.yml ← 컨테이너 정의 ├── .env ← API 키, DB 비밀번호, 토큰, 예산 (git 제외) ├── .env.example ← 환경변수 템플릿 ├── CLAUDE.md ← 프로젝트 문서 ├── QUICK_REFERENCE.md ← 이 파일 ├── heic_converter.py ← HEIC→JPEG 변환 API (macOS sips, port 8090) ├── chat_bridge.py ← DSM Chat API 브릿지 (사진 폴링/다운로드, port 8091) ├── caldav_bridge.py ← CalDAV REST 래퍼 (Synology Calendar, port 8092) ├── inbox_processor.py ← OmniFocus Inbox 폴링 (LaunchAgent, 5분) ├── news_digest.py ← 뉴스 번역·요약 (LaunchAgent, 매일 07:00) ├── morning_briefing.py ← 모닝 브리핑 (LaunchAgent, 매일 07:30) ├── manage_services.sh ← 네이티브 서비스 관리 (start/stop/status) ├── deploy_workflows.sh ← n8n 워크플로우 자동 배포 (REST API) ├── start-bridge.sh ← 브릿지 서비스 시작 헬퍼 ├── com.syn-chat-bot.*.plist ← LaunchAgent 설정 (6개) ├── docs/ │ ├── architecture.md ← 아키텍처, DB 스키마, 파이프라인 상세 │ └── claude-code-playbook.md ├── n8n/ │ ├── data/ ← n8n 런타임 데이터 │ └── workflows/ │ ├── main-chat-pipeline.json ← 메인 워크플로우 (51노드) │ └── mail-processing-pipeline.json ← 메일 처리 파이프라인 (7노드) ├── init/ │ ├── init.sql ← DB 초기 스키마 v2 (12테이블) │ ├── migrate-v2.sql ← 기존 DB 마이그레이션 │ ├── migrate-v3.sql ← v3 마이그레이션 (Phase 5-6 테이블) │ └── setup-qdrant.sh ← Qdrant 컬렉션/인덱스 설정 └── postgres/data/ ← DB 데이터 ``` ## 트러블슈팅 ```bash # n8n 웹훅 안 올 때 — NAS에서 맥미니 접근 가능한지 확인 curl http://<맥미니IP>:5678/webhook-test/chat # Ollama 임베딩 테스트 (맥미니) curl http://localhost:11434/api/embeddings -d '{"model":"bge-m3","prompt":"test"}' # GPU 서버 분류 테스트 curl http://192.168.1.186:11434/api/generate -d '{"model":"id-9b:latest","prompt":"안녕하세요","stream":false}' # Qdrant 컬렉션 확인 curl http://localhost:6333/collections # tk_company 검색 테스트 curl -X POST http://localhost:6333/collections/tk_company/points/search \ -H 'Content-Type: application/json' \ -d '{"vector": [0.1, ...], "limit": 3, "with_payload": true}' # bot-postgres 접속 docker exec -it bot-postgres psql -U bot -d chatbot # 분류기 로그 확인 docker exec bot-postgres psql -U bot -d chatbot -c "SELECT created_at, output_json->>'intent', output_json->>'response_tier', fallback_used FROM classification_logs ORDER BY created_at DESC LIMIT 10" # API 사용량 확인 docker exec bot-postgres psql -U bot -d chatbot -c "SELECT * FROM api_usage_monthly ORDER BY year DESC, month DESC" # GPU 서버 연결 안 될 때 ping 192.168.1.186 curl -s http://192.168.1.186:11434/api/tags # chat_bridge 상태 확인 curl -s http://localhost:8091/health | python3 -m json.tool # chat_bridge 사진 조회 테스트 curl -s -X POST http://localhost:8091/chat/recent-photo \ -H 'Content-Type: application/json' \ -d '{"channel_id":17,"user_id":6,"before_timestamp":9999999999999}' | python3 -m json.tool # chat_bridge 로그 tail -50 /tmp/chat-bridge.log tail -50 /tmp/chat-bridge.err # caldav_bridge 상태 확인 curl -s http://localhost:8092/health | python3 -m json.tool # inbox_processor 로그 tail -50 /tmp/inbox-processor.log # news_digest 로그 tail -50 /tmp/news-digest.log # morning_briefing 로그 tail -50 /tmp/morning-briefing.log ``` ## n8n 접속 정보 - URL: http://localhost:5678 - 이메일: ahn@hyungi.net - 비밀번호: .env의 N8N_BASIC_AUTH_PASSWORD와 동일 - 워크플로우: "메인 채팅 파이프라인 v3" (51 노드, 활성 상태) - 메일 처리 워크플로우: "메일 처리 파이프라인" (7 노드) - 웹훅 엔드포인트: POST http://localhost:5678/webhook/chat ## Synology Chat 연동 NAS에서 Outgoing Webhook 설정 필요: 1. Synology Chat > 통합 > 봇 > 만들기 2. 발신 웹훅(Outgoing Webhook) URL: `http://<맥미니IP>:5678/webhook/chat` 3. 토큰은 자동 생성됨 → .env의 `SYNOLOGY_CHAT_TOKEN`에 설정 수신 웹훅(Incoming Webhook)은 .env의 `SYNOLOGY_CHAT_WEBHOOK_URL`에 이미 설정됨. ## 진행 상황 ### Phase 0: 맥미니 정리 - [ ] ollama rm qwen3.5:35b-a3b (삭제) - [ ] ollama rm qwen3.5:35b-a3b-think (삭제) ### Phase 1: 기반 (Qdrant + DB) - [x] init.sql v2 (12테이블 + 분류기 v2 프롬프트 + 메모리 판단 프롬프트) - [x] migrate-v2.sql (기존 DB 마이그레이션) - [x] setup-qdrant.sh (tk_company 컬렉션 + 인덱스) - [ ] DB 마이그레이션 실행 - [ ] Qdrant 설정 실행 ### Phase 2: 3단계 라우팅 + 검색 라우팅 - [x] 워크플로우 v2 (42노드): 토큰검증, Rate Limit, 프리필터, 분류기v2, 3-tier, 멀티-컬렉션 RAG - [x] .env + docker-compose.yml 환경변수 추가 - [ ] n8n에 워크플로우 임포트 + 활성화 - [ ] 테스트: "안녕" → local, "요약해줘" → Haiku, "법률 해석" → Opus ### Phase 3: 선택적 메모리 - [x] Memorization Check 노드 (비동기, 응답 후) - [x] Should Memorize? + Embed & Save Memory - [ ] 테스트: 인사 → 미저장, 기술질문 → 저장 ### Phase 4: 회사 문서 등록 - [x] /문서등록 명령어 파서 (placeholder) - [ ] 텍스트 청킹 + 임베딩 + tk_company 저장 구현 - [ ] 문서 버전 관리 (deprecated + version++) ### Phase 5: 현장 리포팅 + API 사용량 추적 - [x] field_reports 테이블 + SLA 인덱스 - [x] 비전 모델 사진 분석 (base64 변환 + HEIC 자동 변환) - [x] HEIC→JPEG 변환 서비스 (heic_converter.py, macOS sips) - [x] chat_bridge.py — DSM Chat API 브릿지 (사진 폴링 + 다운로드 + ack) - [x] n8n Handle Log Event / Handle Field Report → bridge 연동 - [x] API 사용량 추적 (api_usage_monthly UPSERT) - [x] /보고서 월간 보고서 생성 구현 - [x] report_cache 캐시 + --force 재생성 ### Phase 6: 캘린더·메일·OmniFocus·뉴스 - [x] mail_logs, calendar_events 테이블 - [x] 분류기 v3 (calendar, reminder, mail, note intent 추가) - [x] caldav_bridge.py — CalDAV REST 래퍼 (Synology Calendar) - [x] inbox_processor.py — OmniFocus Inbox 폴링 (LaunchAgent, 5분) - [x] news_digest.py — 뉴스 번역·요약 (LaunchAgent, 매일 07:00) - [x] manage_services.sh — 네이티브 서비스 관리 - [x] LaunchAgent plist 6개 - [x] n8n 파이프라인 51노드 (calendar/mail/note 핸들러 추가) - [x] Mail Processing Pipeline (7노드, IMAP 폴링) - [x] migrate-v3.sql (news_digest_log + calendar_events 확장) ### 서비스 기동 전제조건 - Synology Calendar (CalDAV) — NAS에서 활성화 필요 - Synology MailPlus — NAS에서 활성화 + 계정 설정 필요 - OmniFocus — 맥미니에 설치 필요 (Inbox 폴링) ## 검증 체크리스트 1. `curl localhost:6333/collections` → documents, tk_company, chat_memory 존재 2. "안녕" → 프리필터 → local 응답 (GPU 미호출) 3. "이거 요약해줘" → Haiku 답변 4. "이 법률 해석해줘" → Opus 답변 5. 인사 → chat_memory 미저장 (chat_logs에는 기록) 6. 기술 질문 → chat_memory 저장 7. "아까 물어본 거" → chat_memory 검색 성공 8. GPU 서버 다운 → fallback Haiku 답변 9. 잘못된 토큰 → reject 10. 10초 내 6건 → rate limit 11. "내일 회의 잡아줘" → calendar intent → CalDAV 이벤트 생성 12. "최근 메일 확인" → mail intent → 메일 요약 반환 13. "이거 메모해둬" → note intent → KB Writer 저장