076c0e1802cd1731ea6e97df4fb81a0613d50524
round-2-review-mighty-starfish.md v2.1 (Phase 2B Reranker Diagnose) plan 실행.
Phase 2A 의 CANDIDATE_BACKEND_MAP 패턴 재사용 + RERANKER_BACKEND_MAP 신규.
코드 변경 (4 파일):
- app/services/search/rerank_service.py:
- RERANKER_BACKEND_MAP allowlist (baseline / cand_gte_ml_base, slug-based resolve)
- _resolve_reranker(slug) → endpoint URL or None
- _rerank_via_candidate_endpoint() — 후보 TEI POST /rerank
- rerank_chunks() 시그니처에 reranker_backend + snapshot_*_id_max 추가 + dispatch log
- app/services/search/search_pipeline.py: run_search() threading
- app/api/search.py: reranker_backend Query parameter + 400 unknown_reranker_backend 에러 매핑
- tests/search_eval/run_eval.py: --reranker-backend flag + call_search/evaluate threading
infra:
- docker-compose.override.rerank-cand.yml: 3 후보 service (gte_ml_base / mxbai_large / bge_v2_gemma_2b),
profile 'rerank-cand' 격리, restart=unless-stopped
측정 산출물 (51 case, scored=46, failure=5):
- reports/v0_2_phase2b_baseline_snapshot_2026-05-23.csv (NDCG 0.659, Phase 2A 와 일치 = 재현성 PASS)
- reports/v0_2_phase2b_gte_ml_base_2026-05-23.csv
- tests/search_eval/baselines/v0_2_phase2b_{baseline_snapshot,gte_ml_base}_2026-05-23.json
- reports/phase_2b_reranker_decision_2026-05-23.md
- tests/fixtures/tei_rerank_response.json (G0-1 한국어+영어 mixed sample sanity PASS)
후보 TEI 1.7 호환성 (Phase 1 smoke gate):
- cand_gte_ml_base : ✅ PASS (xlm-roberta-based, TEI 호환)
- cand_mxbai_large : ❌ deberta-v2 미지원 → Phase 2B-Extended (sentence-transformers wrapper)
- cand_bge_v2_gemma_2b : ❌ LLM-based reranker, 1_Pooling/config.json 부재 → Phase 2B-Extended (FlagEmbedding wrapper)
결과 (1 후보 측정 + baseline rebaseline):
| Candidate | NDCG | Δ baseline | mixed | korean | exam | p50 ms |
|------------------------------------|------:|-----------:|------:|-------:|------:|-------:|
| bge-reranker-v2-m3 (baseline) | 0.659 | — | 0.39 | 0.51 | 0.74 | 454 |
| cand_gte_ml_base | 0.604 | -0.055 | 0.38 | 0.41 | 0.62 | 345 |
Decision (H3): bge-reranker-v2-m3 유지. gte 의 reranker quality 가 production 보다 약함 (korean_only -0.10, exam -0.12, overall -0.055).
후속 PR 백로그 (6건):
- PR-Search-Query-Rewrite-1 (Phase 2Q, korean_only/mixed 보완 권고)
- PR-2B-Extended-Mxbai-Large (sentence-transformers wrapper)
- PR-2B-Extended-Bge-V2-Gemma (FlagEmbedding LayerwiseReranker wrapper)
- PR-2B-Extended-Jina-V2-ML (license 결정 후, 개인 비영리 가정)
- PR-2B-Cloud-Reranker-Scaffold-1 (Cohere scaffold-only, 선택)
- PR-2B-Rerank-Cand-Cleanup-1 (1주 후 cand 컨테이너 정리)
production 영향:
- production reranker (bge-reranker-v2-m3) 변경 0
- config.yaml ai.models.rerank.endpoint 변경 0
- embedding (bge-m3 ollama) 변경 0 (Phase 2A 결정 보존)
- documents / document_chunks 변경 0 (21365 docs / 30605 chunks 그대로)
- 4 smoke PASS (baseline / baseline+snapshot / cand_gte_ml_base / cand_invalid → 400)
- dispatch log 박제 verify (endpoint + snapshot id)
closure gate: 16 항목 PASS (flex closure 조항 적용 — 1 후보 측정, 2 후보 TEI 호환 탈락 사유 명시).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
hyungi_Document_Server
Self-hosted 개인 지식관리(PKM) + 다국 뉴스 비교 분석 웹 애플리케이션.
모델 이름·엔드포인트·머신 정보는 운영 상태에 따라 변하므로 README 에 박지 않습니다. 운영 단일 진실 소스(SSOT):
~/.claude/projects/-Users-hyungiahn/memory/infra_inventory.md. 모델/엔드포인트/포트/SSH 어디서든 README 와 inventory 가 충돌하면 inventory 가 정답입니다.
기술 스택
- 백엔드: FastAPI + SQLAlchemy 2.0 async, APScheduler cron
- DB: PostgreSQL 16 + pgvector + pg_trgm (단일
pkmDB) - 프론트엔드: SvelteKit 5 (runes mode) + Tailwind CSS 4
- 문서 파싱: kordoc 마이크로서비스 (HWP/HWPX/PDF → Markdown), LibreOffice headless (오피스), marker (PDF → markdown Phase 1B)
- AI 파이프라인 (역할별, 자세한 모델 매핑은 inventory):
- 분류/요약 본체: Mac mini MLX 26B (primary)
- Triage / fallback / chat: GPU Ollama 4B
- Embedding: GPU Ollama
bge-m3(1024d) - Reranker: GPU TEI 컨테이너
bge-reranker-v2-m3 - OCR: docker compose
ocr-service(Surya OCR GPU) - STT: Mac mini MLX Whisper large-v3
- Premium (수동 trigger): Anthropic Claude (
require_explicit_trigger)
- 인증: JWT (access) + HttpOnly cookie (refresh) + TOTP 2FA
- 인프라: Docker Compose, Caddy (HTTP only, 앞단 home-caddy 가 HTTPS 종료), Synology NAS NFS
주요 기능
- 문서 자동 분류/태그/요약 — Triage(4B) → Deep summary(26B) tier 분리, 백로그 guard / 텍스트 슬라이스 / inconsistency 감지
- 하이브리드 검색 — pgvector 벡터 + pg_trgm 전문검색 + reranker (bge-reranker-v2-m3) + Ask pipeline (HyDE / evidence_service)
- 다국어 OCR — Surya OCR GPU (한/영/일/중/독/불 등), NFC/NFD 경로 정규화
- 음성/영상 전사 — MLX Whisper large-v3,
/audio/video라우트 + direct play - 법령 변경 모니터링 —
law_monitorcron, freshness decay (365일 반감기) - 이메일 자동 수집 — MailPlus IMAP, NFS 저장
- Phase 4 Global Digest — 매일 04:00 KST 7일 rolling 뉴스 country×topic 2-level 비교 (
/digest) - 야간 뉴스 브리핑 — 매일 05:10 KST KST 자정~05:00 5시간 윈도우, topic×country 비교 분석 1페이지 카드 (
/news) - 자료실 (Library) — 카테고리 facet 분류 + AI 제안 1-click 승인
- 메모/이벤트/공부 — 5초 행동 기록 메모, 일정/할 일/회고 events 도메인, 가스기사 학습 워크스페이스 (274 개념 + 2,100 기출)
- 마크다운 canonical layer — extracted_images NAS 저장 +
document_images메타 + 단기 토큰 인증 (?token=)
Quick Start
git clone https://git.hyungi.net/hyungi/hyungi_document_server.git
cd hyungi_document_server
# 인증 정보 (DB 비밀번호, JWT secret, Claude API key 등)
cp credentials.env.example credentials.env
$EDITOR credentials.env
# AI 모델 / 엔드포인트 / 경로
$EDITOR config.yaml # inventory 참조하면서 채움
$EDITOR .env # POSTGRES_PASSWORD, MAC_MINI_HOST, NAS_NFS_PATH 등
docker compose up -d --build
운영 도메인 (GPU 서버 배포 기준): https://document.hyungi.net
API 문서: https://document.hyungi.net/docs
디렉토리 구조
├── app/ FastAPI 백엔드
│ ├── api/ 라우터 (documents, search, briefing, digest, memos, events, study, …)
│ ├── workers/ APScheduler / queue (briefing_worker, digest_worker, classify_worker, …)
│ ├── services/ 도메인 로직 (briefing/, digest/, search/, clustering_common, …)
│ ├── ai/client.py AIClient (call_triage / call_primary / call_fallback, parse_json_response)
│ ├── prompts/ *.txt 프롬프트 (분류, 요약, briefing_comparative, digest_topic, …)
│ ├── policy/ AI envelope + prompt_render
│ └── models/ SQLAlchemy ORM
├── frontend/ SvelteKit 5 (runes mode) + Tailwind
│ └── src/routes/ /news (아침 브리핑) /library /memos /audio /video /study /digest /ask …
├── services/
│ ├── kordoc/ HWP/HWPX/PDF 파싱 (Node.js)
│ ├── ocr/ Surya OCR GPU 서비스 (FastAPI)
│ └── marker/ PDF → markdown Phase 1B
├── migrations/ 255+ SQL migrations (schema_migrations 추적)
├── docs/ 설계 문서
└── tests/ pytest
gpu-server/ 폴더는 v1 잔재로 deprecated (현재 AI Gateway 는 ~/home-gateway/ 별 repo).
인프라 구성 (운영 기준)
| 머신 | 역할 |
|---|---|
| GPU 서버 (메인) | Docker Compose (fastapi, frontend, postgres pkm, kordoc, ocr-service, marker-service, reranker(TEI), caddy), Ollama (bge-m3, 4B chat), home-gateway 별 compose |
| Mac mini | MLX 26B primary 추론 + MLX Whisper STT (HTTP 추론 endpoint only, ingress 역할 0) |
| Synology NAS | 파일 원본 (/volume4/Document_Server/PKM/), Synology Office/Drive/Calendar/MailPlus, NFS export → GPU |
| VPS-2 (OVH) | 메일 relay (relay.hyungi.net:587 SASL+TLS+DKIM+LE), Gitea bare mirror, Secondary MX |
상세 IP / 모델 / 컨테이너 / drift / verify 명령은 infra_inventory.md 참조.
운영 변경 정책
- inventory 먼저 갱신
config.yaml/credentials.env갱신- deploy (commit → push Gitea → GPU
git pull && docker compose up -d --build) - verify (smoke endpoints, postgres count, 모니터링)
순서를 어기면 drift. drift 발견 시 infra_inventory.md 의 Drift Log 에 등록 후 정정.
문서
Description
Languages
Python
67%
Svelte
23.1%
Swift
5.3%
TypeScript
3.2%
Shell
0.5%
Other
0.9%