Phase 1-3 구현: - init.sql v2: 12테이블 (기존 5 + 신규 7) + 분류기 v2 프롬프트 - migrate-v2.sql: 기존 DB 마이그레이션 스크립트 - setup-qdrant.sh: tk_company 컬렉션 + payload 인덱스 설정 - 워크플로우 v2 (37노드): 토큰검증, Rate Limit, 프리필터, 분류기v2(response_tier), 3-tier 라우팅(local/Haiku/Opus), 멀티-컬렉션 RAG, 예산 체크, 선택적 메모리 - .env.example + docker-compose.yml: 새 환경변수 추가 - CLAUDE.md, QUICK_REFERENCE.md, docs/architecture.md 전면 갱신 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
213 lines
7.9 KiB
Markdown
213 lines
7.9 KiB
Markdown
# 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 모델 확인
|
|
ollama list
|
|
|
|
# GPU 서버 Ollama 상태
|
|
curl -s http://192.168.1.186:11434/api/tags | python3 -m json.tool
|
|
|
|
# GPU 서버 Qwen 9B 헬스체크
|
|
curl -s http://192.168.1.186:11434/api/generate -d '{"model":"qwen3.5:9b-q8_0","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) |
|
|
|
|
## 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
|
|
```
|
|
|
|
## 헬스체크 (전체)
|
|
|
|
```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 "=== 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 ← 이 파일
|
|
├── docs/
|
|
│ ├── architecture.md ← 아키텍처, DB 스키마, 파이프라인 상세
|
|
│ └── claude-code-playbook.md
|
|
├── n8n/
|
|
│ ├── data/ ← n8n 런타임 데이터
|
|
│ └── workflows/
|
|
│ └── main-chat-pipeline.json ← 메인 워크플로우 (37노드)
|
|
├── init/
|
|
│ ├── init.sql ← DB 초기 스키마 v2 (12테이블)
|
|
│ ├── migrate-v2.sql ← 기존 DB 마이그레이션
|
|
│ └── 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":"qwen3.5:9b-q8_0","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
|
|
```
|
|
|
|
## n8n 접속 정보
|
|
|
|
- URL: http://localhost:5678
|
|
- 이메일: ahn@hyungi.net
|
|
- 비밀번호: .env의 N8N_BASIC_AUTH_PASSWORD와 동일
|
|
- 워크플로우: "메인 채팅 파이프라인 v2" (37 노드, 활성 상태)
|
|
- 웹훅 엔드포인트: 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 pull minicpm-v:8b (비전 모델 설치)
|
|
|
|
### 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 (37노드): 토큰검증, 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: 현장 리포팅
|
|
- [x] field_reports 테이블 + SLA 인덱스
|
|
- [ ] 비전 모델 설치 + 사진 분석 노드
|
|
- [ ] /보고서 월간 보고서 생성 구현
|
|
- [ ] SLA 트래킹 스케줄 워크플로우
|
|
|
|
### Phase 6: 메일 + 캘린더
|
|
- [x] mail_logs, calendar_events 테이블
|
|
- [ ] IMAP 폴링 워크플로우
|
|
- [ ] CalDAV 연동
|
|
|
|
## 검증 체크리스트
|
|
|
|
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
|