# syn-chat-bot Synology Chat + n8n + Claude API 기반 RAG 챗봇 시스템. 3단계 모델 라우팅(local/api_light/api_heavy) + 멀티-컬렉션 RAG + 선택적 메모리. ## 아키텍처 ``` Synology Chat (NAS 192.168.1.227) ↕ 웹훅 bot-n8n (맥미니 Docker) — 51노드 파이프라인 │ ├─⓪ 토큰 검증 + Rate Limit (10초/5건) ├─① 규칙 기반 프리필터 (인사/감사 → 하드코딩 local 응답) │ ├─② GPU Qwen 9B (192.168.1.186) — 분류 v3 │ 출력: {intent, response_tier, needs_rag, rag_target, ...} │ 타임아웃 10초 → fallback: api_light │ ├─③ Route by Intent │ ├─ log_event → Qwen 추출 → tk_company 저장 │ ├─ report → 현장 리포트 DB 저장 │ ├─ calendar → CalDAV Bridge → Synology Calendar │ ├─ reminder → calendar로 통합 │ ├─ mail → 메일 요약 조회 │ ├─ note → KB Writer 저장 │ └─ fallback → 일반 대화 (RAG + 3단계 라우팅) │ ├─④ [needs_rag=true] 멀티-컬렉션 RAG │ documents + tk_company + chat_memory │ bge-m3 임베딩 → Qdrant 검색 → reranker → top-3 │ ├─⑤ response_tier 기반 3단계 라우팅 │ ├─ local → Qwen 9B 직접 답변 (무료) │ ├─ api_light → Claude Haiku (저비용) │ └─ api_heavy → Claude Opus (예산 초과 시 → Haiku 다운그레이드) │ ├── bot-postgres (설정/로그/라우팅/분류기로그/API사용량) └── Qdrant (벡터 검색, 3컬렉션) ⑥ 응답 전송 + chat_logs 저장 + API 사용량 UPSERT ⑦ [비동기] 선택적 메모리 (Qwen 판단 → 가치 있으면 벡터화 + KB 저장) 별도 워크플로우: Mail Processing Pipeline (9노드) — mail_bridge 날짜 기반 조회 → dedup → 분류 → mail_logs Retrospect Capture Pipeline (8노드) — chat_bridge 텍스트 포워딩 → Qwen 분류 → retrospect.entries 저장 → Chat 확인 네이티브 서비스 (맥미니): heic_converter (:8090) — HEIC→JPEG 변환 (macOS sips) chat_bridge (:8091) — DSM Chat API 브릿지 (사진 폴링/다운로드 + 회고 채널 텍스트 폴링) caldav_bridge (:8092) — CalDAV REST 래퍼 (Synology Calendar, VEVENT+VTODO) mail_bridge (:8094) — IMAP 날짜 기반 메일 조회 (MailPlus) kb_writer (:8095) — 마크다운 KB 저장 note_bridge (:8098) — Note Station REST 래퍼 (메모 생성/추가) intent_service (:8099) — 의도 분류 + 날짜 파싱 + Claude fallback inbox_processor (5분) — OmniFocus Inbox 폴링 (LaunchAgent) news_digest (매일 07:00) — 뉴스 번역·요약 (LaunchAgent) morning_briefing (매일 07:30) — 일정·메일·보고·뉴스 모닝 브리핑 (LaunchAgent) NAS (192.168.1.227): Synology Chat / Synology Calendar (CalDAV) / MailPlus (IMAP) ``` ## 인프라 | 구성 요소 | 위치 | 포트 | 비고 | |----------|------|------|------| | bot-n8n | Docker (맥미니) | 5678 | 워크플로우 엔진 | | bot-postgres | Docker (맥미니) | 127.0.0.1:15478 | 설정/로그 DB | | Qdrant | Docker (맥미니, 기존) | 127.0.0.1:6333 | 벡터 DB (3컬렉션) | | Ollama (맥미니) | 네이티브 (기존) | 11434 | bge-m3, bge-reranker-v2-m3 (임베딩/리랭킹 전용, brew services 자동기동) | | Ollama (GPU) | 192.168.1.186 (RTX 4070Ti Super) | 11434 | id-9b:latest (이드 특화 분류+응답), qwen3.5:9b-q8_0 (레거시 백업) | | Claude Haiku Vision | Anthropic API | — | 사진 분석+구조화 (field_report, log_event) | | heic_converter | 네이티브 (맥미니) | 8090 | HEIC→JPEG 변환 (macOS sips) | | chat_bridge | 네이티브 (맥미니) | 8091 | DSM Chat API 브릿지 (사진 폴링/다운로드 + 회고 텍스트 폴링) | | caldav_bridge | 네이티브 (맥미니) | 8092 | CalDAV REST 래퍼 (Synology Calendar) | | mail_bridge | 네이티브 (맥미니) | 8094 | IMAP 날짜 기반 메일 조회 (MailPlus) | | kb_writer | 네이티브 (맥미니) | 8095 | 마크다운 KB 저장 | | note_bridge | 네이티브 (맥미니) | 8098 | Note Station REST 래퍼 (메모 생성/추가) | | intent_service | 네이티브 (맥미니) | 8099 | 의도 분류 + 날짜 파싱 + Claude fallback | | inbox_processor | 네이티브 (맥미니) | — | OmniFocus Inbox 폴링 (LaunchAgent, 5분) | | news_digest | 네이티브 (맥미니) | — | 뉴스 번역·요약 (LaunchAgent, 매일 07:00) | | morning_briefing | 네이티브 (맥미니) | — | 모닝 브리핑 (LaunchAgent, 매일 07:30) | | Synology Chat | NAS (192.168.1.227) | — | 사용자 인터페이스 | | Synology Calendar | NAS (192.168.1.227) | CalDAV | 캘린더 서비스 | | MailPlus | NAS (192.168.1.227) | IMAP | 메일 서비스 | ## 3단계 라우팅 | tier | 모델 | 비용 | 대상 | |------|------|------|------| | **local** | Qwen 9B (GPU) | 무료 | 인사, 잡담, 단순 확인 | | **api_light** | Claude Haiku | 저비용 | 요약, 번역, RAG 정리 | | **api_heavy** | Claude Opus | 고비용 | 법률 해석, 복잡한 추론 | ## 3-컬렉션 RAG | 컬렉션 | 용도 | |--------|------| | `documents` | 개인/일반 문서 + 메일 요약 + 뉴스 요약 | | `tk_company` | TechnicalKorea 회사 문서 + 현장 리포트 | | `tk_qc_issues` | TechnicalKorea 품질 이슈 | | `chat_memory` | 가치 있는 대화 기억 (선택적 저장) | ## DB 스키마 (bot-postgres) **기존**: `ai_configs`, `routing_rules`, `prompts`, `chat_logs`, `mail_accounts` **신규**: `document_ingestion_log`, `field_reports`, `classification_logs`, `mail_logs`, `calendar_events` (+caldav_uid, +description, +created_by), `report_cache`, `api_usage_monthly`, `news_digest_log` **회고**: `retrospect.entries`, `retrospect.reviews`, `retrospect.patterns` (별도 스키마) 상세 스키마는 [docs/architecture.md](docs/architecture.md) 참조. ## Synology Chat 명령어 ``` /모델 <모델명> → 기본 모델 변경 /성격 <설명> → 시스템 프롬프트 변경 /설정 → 현재 설정 확인 /문서등록 [부서] [유형] [제목] → 회사 문서 등록 (Phase 4) /보고서 [영역] [년월] → 월간 보고서 생성 (Phase 5) ``` ## 안전장치 - **웹훅 토큰 검증**: SYNOLOGY_CHAT_TOKEN 불일치 → reject - **Rate Limit**: username별 10초 내 5건 → 거부 - **명령어 권한 체크**: ADMIN_USERNAMES allowlist - **프리필터**: 인사/감사 정규식 → GPU 미호출 - **분류기 fallback**: Qwen 10초 타임아웃 → api_light - **예산 상한**: api_heavy 월간 예산 초과 → api_light 다운그레이드 - **선택적 메모리**: Qwen 판단으로 가치 있는 대화만 벡터화 - **classification_logs**: input 200자 제한, 90일 배치 정리 ## 페르소나: 이드 모든 모델에 공통 적용되는 통합 페르소나. - local tier: 경량 프롬프트 (`chat_local` feature) - api_light/api_heavy: 전체 프롬프트 (`chat` feature) ## 개발 규칙 - docker-compose.yml로 컨테이너 관리 - DB 포트는 127.0.0.1로 바인딩 (외부 노출 금지) - 시크릿(API 키 등)은 .env 파일로 관리, git에 포함하지 않음 - 커밋 전 docker-compose config로 문법 검증 - 네이티브 서비스는 LaunchAgent로 관리 (manage_services.sh) - pip install은 .venv에서 실행 - 세션 시작 시 Plan 모드로 계획 → 확정 후 구현 - 구현 완료 후 `/verify`로 검증, `/simplify`로 코드 리뷰 ## 슬래시 명령어 - `/simplify` — 변경 코드 리뷰 및 단순화 - `/verify` — 전체 검증 (docker, env, sql, 헬스체크) - `/status` — 프로젝트 상태 확인 ## 참고 문서 - [Architecture](docs/architecture.md) — 아키텍처, DB 스키마, 파이프라인 상세 - [Claude Code Playbook](docs/claude-code-playbook.md) — 활용 패턴 상세 정리 ## 실수 방지 (Claude가 틀릴 때마다 여기에 추가) - "오픈클로(OpenClaw)"를 Claude Code로 착각하지 말 것. OpenClaw은 별도의 오픈소스 AI 에이전트 프로젝트임 - tk-mp-postgres는 테스트 서버 전용 DB. 챗봇 인프라와 혼용하지 말 것 - GPU 서버(192.168.1.186)의 Ollama는 분류 + local 응답용. 임베딩/리랭킹은 맥미니 Ollama 사용 - response_tier는 Qwen v2 분류기 출력. 기존 complexity 기반 라우팅은 레거시 호환 - n8n v2.11+ Code 노드는 Task Runner 샌드박스(VM)에서 실행됨. `$http.request()`/`this.helpers.httpRequest()`/`fetch()`/`AbortController`/`URL` 사용 불가. `require('http')`/`require('https')`/`require('url')` 사용 (NODE_FUNCTION_ALLOW_BUILTIN=crypto,http,https,url). 각 Code 노드에 `httpPost`/`httpPut` 헬퍼 함수 인라인 정의 - 샌드박스 사용 가능: `Buffer`, `setTimeout`, `TextEncoder`, `FormData`, `$env`, `$input`, `$()`, `$getWorkflowStaticData()`, `$json`, `require('url').parse()` (new URL 불가), `console` - id-9b:latest가 기본 GPU 모델 (Modelfile: `ollama/Modelfile.id-9b`, FROM qwen3.5:9b-q8_0 + no-think 템플릿). 모든 Ollama 호출에 `system: '/no_think'` 이중 방어 적용