f6f8f3b9d8
stale 영역 정리: - Qwen3.5-35B-A3B / nomic-embed-text / Qwen2.5-VL-7B → 역할별 표기 (실제 모델은 inventory) - Mac mini Tailscale 100.76.254.116 / GPU 100.111.160.84 / NAS 100.101.79.37 → 모두 폐기 (D21 closure 2026-05-12), LAN 표기만 유지 - Mac mini nginx 앞단 프록시 → 폐기 (home-caddy 가 직접 ingress) - "Mac mini 메인 docker compose" → GPU 가 메인 정정 추가: - 운영 변경 정책 (inventory → config → deploy → verify) - 머신 역할 표 / AI 파이프라인 역할 표 / 워커 스케줄 표 - 아침 브리핑 / global digest 진입점 + scheduler timezone - asyncpg multi-statement 1 파일 1 statement 규칙 (PR-MorningBriefing-1 fix 교훈) - 디자인 토큰 only 규칙 - 한국어 NFS 경로 NFC/NFD
163 lines
7.4 KiB
Markdown
163 lines
7.4 KiB
Markdown
# hyungi_Document_Server — Claude Code 작업 가이드
|
||
|
||
## Infrastructure Reference 📌
|
||
|
||
운영 사실 (모델명 / 엔드포인트 / IP / 컨테이너 / 포트 / drift) 의 단일 진실 소스(SSOT):
|
||
|
||
**`~/.claude/projects/-Users-hyungiahn/memory/infra_inventory.md`**
|
||
|
||
이 파일과 inventory 가 충돌하면 **inventory 가 정답**. 본 CLAUDE.md 는 코딩 규칙·워크플로우·코드 구조에 집중하고 운영 값은 박지 않는다.
|
||
|
||
운영 변경 정책 (inventory → config → deploy → verify):
|
||
1. `infra_inventory.md` 먼저 갱신
|
||
2. `config.yaml` / `credentials.env` 갱신
|
||
3. deploy (commit → push → GPU pull → `docker compose up -d --build`)
|
||
4. verify (smoke endpoint, postgres count, 모니터링)
|
||
|
||
순서 어기면 drift. 발견 시 inventory `Drift Log` 등록.
|
||
|
||
**Search experiment soft lock**: Phase 2 search refactor / QueryAnalyzer / run_eval 진행 중일 때 GPU 서버의 `docker compose restart`, `config.yaml` 수정, Ollama pull 금지. flag = `~/.claude/.search-experiment-active`.
|
||
|
||
---
|
||
|
||
## 프로젝트 개요
|
||
|
||
Self-hosted PKM(Personal Knowledge Management) + 다국 뉴스 비교 분석 웹 애플리케이션.
|
||
GPU 서버가 메인 (Docker Compose / DB / 검색 / OCR / 마커), Mac mini = MLX 추론 + Whisper STT, Synology NAS = 파일 원본.
|
||
|
||
## 핵심 문서
|
||
|
||
1. `README.md` — 외부 소개 (기술 스택 / 주요 기능 / Quick Start)
|
||
2. `docs/architecture.md` — 전체 시스템 아키텍처
|
||
3. `docs/deploy.md` — Docker Compose 배포 가이드
|
||
4. `docs/development-stages.md` — Phase roadmap (역사적 맥락)
|
||
|
||
## 기술 스택
|
||
|
||
| 영역 | 기술 |
|
||
|------|------|
|
||
| 백엔드 | FastAPI (Python 3.11+), SQLAlchemy 2.0 async, APScheduler |
|
||
| DB | PostgreSQL 16 + pgvector + pg_trgm (단일 `pkm` DB) |
|
||
| 프론트엔드 | SvelteKit 5 (runes mode) + Tailwind CSS 4 |
|
||
| 문서 파싱 | kordoc (HWP/HWPX/PDF → MD), LibreOffice headless (오피스), marker (PDF → markdown) |
|
||
| OCR | Surya OCR (docker compose `ocr-service`, GPU) |
|
||
| STT | MLX Whisper (Mac mini), GPU faster-whisper 는 legacy profile |
|
||
| 리버스 프록시 | Caddy (HTTP only, 앞단 home-caddy 가 HTTPS 종료) |
|
||
| 인증 | JWT (access) + HttpOnly cookie (refresh) + TOTP 2FA |
|
||
| 컨테이너 | Docker Compose |
|
||
|
||
## 머신 역할 (자세한 IP / 포트 → inventory)
|
||
|
||
| 머신 | 역할 |
|
||
|------|------|
|
||
| GPU 서버 | Docker Compose 메인: fastapi · frontend · postgres `pkm` · kordoc · ocr-service · marker-service · reranker (TEI) · caddy. Ollama (embedding / 4B 추론). home-gateway 별 compose (ingress + 나노클로 + searxng) |
|
||
| Mac mini | MLX 26B 추론 endpoint + MLX Whisper STT. ingress 역할 0 |
|
||
| Synology NAS | 파일 원본 (`/volume4/Document_Server/PKM/` → GPU `/mnt/nas/Document_Server` NFS), Synology Office/Drive/Calendar/MailPlus |
|
||
| VPS-2 (OVH) | 메일 relay (`relay.hyungi.net:587`), Gitea bare mirror, Secondary MX |
|
||
|
||
## AI 파이프라인 (역할 기준 — 실제 모델 매핑은 inventory)
|
||
|
||
| 역할 | 위치 |
|
||
|------|------|
|
||
| 분류/심층 요약 primary | Mac mini MLX 26B |
|
||
| Triage (1차 분류) / Fallback / Chat | GPU Ollama 4B |
|
||
| Embedding | GPU Ollama (1024d, 다국어) |
|
||
| Reranker | GPU TEI 컨테이너 |
|
||
| OCR | docker compose `ocr-service` (Surya OCR GPU) — `ai.models.vision` 미사용 |
|
||
| STT | Mac mini MLX Whisper large-v3 |
|
||
| Premium (수동 trigger) | Anthropic API (`require_explicit_trigger`, 일일 한도) |
|
||
|
||
호출 시 반드시 `app/ai/client.py` 의 `AIClient` 사용 (`call_triage` / `call_primary` / `call_fallback`). 직접 HTTP 호출 금지.
|
||
|
||
## 문서 처리 파이프라인
|
||
|
||
```
|
||
파일 업로드 (드래그 앤 드롭 or file_watcher)
|
||
↓
|
||
extract (텍스트 추출)
|
||
- kordoc: HWP, HWPX, PDF → Markdown
|
||
- LibreOffice: xlsx, docx, pptx 등 → txt/csv
|
||
- 직접 읽기: md, txt, csv, json, xml, html
|
||
↓ ↓
|
||
classify_worker (tier triage) preview / marker
|
||
- 4B Ollama → TriageOutput - LibreOffice → PDF 변환
|
||
- escalate_to_26b 시 deep_summary - marker → PDF → markdown
|
||
- ai_tldr / ai_bullets / inconsistencies
|
||
↓
|
||
embed_worker (bge-m3 1024d, doc-level)
|
||
chunk_worker (문서 유형별 chunking)
|
||
```
|
||
|
||
핵심 원칙:
|
||
- 파일은 업로드 위치에 그대로 유지 (물리적 이동 없음)
|
||
- 분류 (`ai_domain` / `ai_sub_group` / `ai_tags` / `category` / `tier`) 는 DB 메타데이터로만 관리
|
||
- preview / marker 는 classify 와 병렬
|
||
|
||
## 워커 / 스케줄러 (`app/main.py` 의 scheduler.add_job)
|
||
|
||
- queue_consumer (interval 1m), file_watcher (5m), upload_cleanup (10m)
|
||
- study_q_embed (1m), study_q_related_refresh (1m), study_queue (1m), study_session_queue (1m)
|
||
- tier_backfill (30m)
|
||
- law_monitor (07:00 KST), mailplus_archive (07/18:00 KST)
|
||
- daily_digest (20:00 KST)
|
||
- **global_digest** (04:00 KST) — Phase 4 country×topic 7일 rolling
|
||
- **morning_briefing** (05:10 KST) — 야간 KST 0~5h 수집 뉴스 topic×country 비교
|
||
|
||
scheduler timezone = `Asia/Seoul`.
|
||
|
||
## 데이터 계층
|
||
|
||
1. **원본 파일** — NAS `/volume4/Document_Server/PKM/`. 유일한 원본, 위치 변경 없음
|
||
2. **가공 데이터** — PostgreSQL `pkm` (텍스트, AI 분류, 검색 인덱스, 메모, 태그, briefing, digest, …)
|
||
3. **파생물** — pgvector embedding, PDF preview 캐시 (`.preview/`), marker 결과 (markdown + extracted_images NAS 저장)
|
||
|
||
## 코딩 규칙
|
||
|
||
- Python 3.11+, asyncio, type hints
|
||
- SQLAlchemy 2.0+ async 세션
|
||
- Svelte 5 runes mode (`$state`, `$derived`, `$effect` — `$:` 금지)
|
||
- 인증 정보는 `credentials.env` 에서 로딩 (하드코딩 금지)
|
||
- 로그는 `logs/` (Docker 볼륨)
|
||
- AI 호출은 반드시 `app/ai/client.py` 의 `AIClient` 경유
|
||
- 한글 주석 사용
|
||
- Migration: `migrations/NNN_*.sql`, `init_db()` 자동 실행 (`schema_migrations` 추적)
|
||
- SQL 에 `BEGIN/COMMIT` 금지 (외부 트랜잭션 깨짐)
|
||
- asyncpg `prepared statement` 가 multi-statement 불허 → 1 statement 1 파일 분리
|
||
- 기존 DB 에서는 `schema_migrations` 수동 이력 등록 필요할 수 있음
|
||
- 디자인 시스템 토큰 only (`bg-surface`, `text-dim`, `border-default`, `text-accent`, …). `bg-[var(--*)]` 금지 (`lint:tokens` 차단)
|
||
- 커밋 메시지: `type(scope): summary` (`feat` / `fix` / `refactor` / `ops` / `incident` / `docs`)
|
||
|
||
## 개발 / 배포 워크플로우
|
||
|
||
```bash
|
||
# 개발 (MacBook Pro)
|
||
cd ~/Documents/code/hyungi_Document_Server/
|
||
# 코드 작성 → git commit → push (Gitea)
|
||
|
||
# 배포 (GPU 서버)
|
||
ssh gpu
|
||
cd ~/Documents/code/hyungi_Document_Server/
|
||
git pull
|
||
docker compose up -d --build fastapi frontend
|
||
```
|
||
|
||
PR 머지는 Gitea UI **Rebase and merge** 기본 (선형 히스토리 + force-push 충돌 회피). 단독 작업 확증 시만 로컬 rebase+FF.
|
||
|
||
## v1 코드 참조
|
||
|
||
v1 (DEVONthink 기반) 코드는 `v1-final` 태그로 보존:
|
||
```bash
|
||
git show v1-final:scripts/law_monitor.py
|
||
git show v1-final:scripts/pkm_utils.py
|
||
```
|
||
|
||
## 주의사항
|
||
|
||
- `credentials.env` 는 git 에 올리지 않음 (`.gitignore`)
|
||
- NAS NFS 마운트: Docker 컨테이너 내 `/documents`. FastAPI 시작 시 `/documents/PKM` 존재 확인
|
||
- 법령 API (LAW_OC) 는 승인 대기 중
|
||
- Ollama 는 127.0.0.1 바인딩 (외부 접근 차단)
|
||
- Caddy 는 `auto_https off` + `http://` only (HTTPS 종료는 앞단 home-caddy 가 처리)
|
||
- Synology Office 편집은 새 탭 열기 방식 (iframe 미사용, `edit_url` 수동 등록)
|
||
- 한국어 NFS 경로는 NFC↔NFD 비대칭 — 경로 수신 시 NFC→NFD→parent glob fallback 필수
|