RAG CLI 도구 운영 가이드
너홀로프로 RAG (Retrieval-Augmented Generation) 운영 도구. PR-Sync-1~9 + followup (2026-05-08 자율 세션) 으로 ship. Cloud Function 의존 제거, 사용자 명시적 수동 sync, Claude Code 슬래시 커맨드로 일원화.
아키텍처 (요약)
[네트워크] [로컬] [Firestore] [Vertex AI] [findNearest]
법제처 Open API ─→ scripts/sync-law-go-kr.ts ─→ in-memory ─→ publicDocuments ─→ Vertex AI 직접 호출 ─→ findNearest (web 검색)
(download + embed + upload) publicDocumentsRaw
publicRagSyncWatermark
Claude Code 슬래시 커맨드 (사용자 직접 호출)
| 커맨드 | 백엔드 | 핵심 동작 |
|---|---|---|
/sync-law | scripts/sync-law-go-kr.ts | 법제처 → Firestore incremental sync (워터마크 기반) |
/rag-status | scripts/rag-status.ts | 임베딩 인벤토리 + 워터마크 + 모델 drift 시각화 |
/rag-eval | scripts/rag-eval.ts | 인용 환각 탐지 (verify_citations 패턴) |
/rag-impact | scripts/rag-impact.ts | 조문 영향 그래프 + mermaid (impact_map 패턴) |
/rag-vs-mcp | (가이드 위주) | 우리 RAG vs korean-law-mcp 비교 |
/mcp-update-watch | scripts/mcp-update-watch.ts | MCP GitHub 변경 분석 |
/neohollo | (메타 hub) | 위 6개 통합 reference + 사용 예문 |
필수 환경
# 모든 CLI 공통 (또는 .env.local 에 자동 주입)
NODE_PATH=apps/web/node_modules
GCLOUD_PROJECT=neohollo-pro
# 법제처 OC 키 — env 또는 gcloud Secret Manager 자동 fallback
LAW_GO_KR_OC=<env 우선, 없으면 `gcloud secrets versions access latest --secret=LAW_GO_KR_OC`>
# Vertex AI / Firestore Admin SDK — ADC 필요
gcloud auth application-default login
핵심 흐름 (5단계 RAG 파이프라인)
┌─────────────┐ ① ┌─────────────┐ ② ┌─────────────┐ ③ ┌─────────────┐ ④ ┌─────────────┐ ⑤
│ 법제처 │ ───→ │ download │ ───→ │ 변환 │ ───→ │ embed │ ───→ Firestore 적재 ─→ │ findNearest│
│ Open API │ │ (in-memory)│ │ (어댑터) │ │ (Vertex AI) │ publicDocuments │ (web 검색) │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ publicDocumentsRaw └─────────────┘
publicRagSyncWatermark
① download (외부 → 로컬 메모리)
scripts/sync-law-go-kr.ts가 법제처lawSearch.do(목록) +lawService.do(본문)- 카테고리별 page=1..N 호출 (기본 N=10)
- nativeId set diff 로 신규만
② 변환 (어댑터 SSoT 3 곳 미러)
scripts/lib/law-go-kr-convert.ts(CLI)functions/src/law-go-kr-adapter.ts(Cloud Function —fetchAndIngestLawGoKr만 사용)apps/ops/.../adapter-law-go-kr.ts(ops paste UI)
③ embed (Vertex AI text-embedding-004 직접 호출)
- chunk 분할 + meanPool (
scripts/lib/embed-input-prepare.ts4 곳 미러, drift gate 32 테스트 보호) - 429 burst 자동 재시도 (10s, 30s)
- 차원 768
④ Firestore 적재
publicDocuments: 정제 +embedding.vector·version·dims등publicDocumentsRaw: 원본 보존 (변환 규칙 변경 시 rebuild 가능)publicRagSyncWatermark/<watermarkId>: nativeId set 기록 → 다음 sync 의 incremental 기준
⑤ findNearest (web 검색)
- web app (apps/web) Server Action 이
findNearest()호출 - 검색 흐름은 그대로 유지 (Cloud Function 폐기는 적재 자동 trigger 만 영향)
워터마크 (publicRagSyncWatermark)
interface WatermarkDoc {
watermarkId: string; // categoryId 또는 lawId
type: "category" | "statute";
lastSyncedAt: Timestamp;
lastSyncedNativeIds: string[]; // 다음 sync 의 set diff 기준
totalEverIngested: number;
lastRunStats: RunStats; // fetched / newIds / uploaded / embedFailed / elapsedMs / errors
}
폐기된 인프라 (PR-Sync-2/3)
scheduledFetchLawGoKrCloud Scheduler cron — 폐기manualIncrementalFetchLawGoKrcallable — 폐기onPublicDocumentCreated자동 임베딩 trigger — 폐기apps/ops/.../PublicRagScheduleStatusCard.tsx— 삭제publicRagScheduleLog컬렉션 — 더 안 채워짐 (기존 데이터 보존)
대체 흐름:
- 적재 = 사용자가
/sync-law명시 호출 (또는 ops 의fetchAndIngestLawGoKr단건 callable 도 유지) - 임베딩 = 적재 경로가 직접 처리 (sync CLI lib/vertex-embed · fetchAndIngest embedAndUpdateDoc)
데이터 카테고리 (SSoT)
판례 (scripts/law-go-kr-categories.ts)
- core 21 카테고리 (대여금·공사·구상금·약정·임대차·양수·집행 등)
- extra 6 카테고리 (소비대차·부당이득·내용증명·지급명령·불법행위·시효)
법령 (scripts/law-go-kr-statute-list.ts)
- core 6 (민법·상법·민사소송법·민사집행법·이자제한법·주택임대차보호법)
- extra 3 (헌법·형법·형사소송법)
각 카테고리/법령에 대해 lawId 또는 params (query · JO · curt · org) 명시.
사용 예시 — 운영 시나리오
일일 운영
/rag-status # 상태 점검
/sync-law # 신규 sync
/mcp-update-watch --since=$(date -u -v-1d +%Y-%m-%d) # MCP 변경 인지
새 카테고리 sync
scripts/law-go-kr-categories.ts에 카테고리 추가 (PR 별도)/sync-law --category=<신규-id> --max-new=50시범/rag-eval --verify="<영역 5건 인용>"환각 측정/rag-impact --statute="<핵심 조문>"영향 그래프 검증
대량 신규 (월 1회)
/sync-law --pages=30 --target=all
# 임베딩 quota burst 시:
npx tsx scripts/reembed-public-docs.ts --only-failed --throttle-ms=500
모델 교체 (text-embedding-004 → 005)
- 코드 상수 교체 (
scripts/lib/embed-input-prepare.ts) - 일괄 재임베딩 (
scripts/reembed-public-docs.ts --all) /rag-status검증
진단 스크립트 (slash 백엔드 외)
| 스크립트 | 용도 |
|---|---|
scripts/count-public-doc-embeddings.ts | 임베딩 인벤토리 (rag-status.ts 의 모태) |
scripts/count-citation-distribution.ts | citedStatutes 분포 + hub 후보 |
scripts/inspect-failed-embeddings.ts | embeddingError 분류 |
scripts/migrate-embedding-field-name.ts | 1회용 — modelVersion → version 통합 |
scripts/cleanup-deleted-statutes.ts | 삭제 조문 정리 + 짧은 조문 임베딩 회복 |
scripts/reembed-public-docs.ts | 임베딩 일괄 재시도 (4 모드) |
scripts/reembed-legacy-docs.ts | tenant legacyDocuments 재임베딩 백필 (--only-failed / --only-missing — embeddingError 마커 소비자, 사무소 기억 학습 루프 복구) |
scripts/rebuild-public-docs-from-raw.ts | 변환 규칙 변경 후 raw → publicDocuments 재구축 |
scripts/migrate-vector-storage-format.ts | 1회용 (2026-05-05) plain array → FieldValue.vector |
검증된 데이터 (2026-05-08 기준)
- publicDocuments: 7,853 docs (3,495 판례 + 4,358 법령)
- 임베딩: 100% embedded · pending 0 · error 0
- 모델: text-embedding-004 (768-dim) — drift 0 (필드명 통일 후)
- 워터마크: 1 트랙 (interest-limit, sync 검증 완료)
관련 문서
- Platform RAG 운영 — Vertex AI · findNearest 운영
- Public RAG 수집 (legacy bulk) — 1회성 대량 수집 가이드
- 환경변수 — LAW_GO_KR_OC · GCLOUD_PROJECT 등
- ADR 0021 Platform RAG — 초기 architecture
- ADR 0039 RAG CLI 마이그레이션 — 본 PR 배경 + 결정
한계 + 후속 PR 후보
- PR-Sync-7b: impact_map 정방향 + 사무소 layer (legacyDocuments) — MCP 차별화 핵심
- PR-Sync-8b: korean-law-mcp stdio 자동 spawn (paste 없이 자동 비교)
- PR-A 추가: 정규화 lawName 컨텍스트 추론 (raw "제664조" 만 있을 때 lawName 추출)
- 호·목 환각 탐지: 현재 항까지만, 호/목 단위 후속
- 사무소 RAG 집계: tenant-isolated
legacyDocuments검색 quality 측정 (ADR 0024 V2 위에)