From 581e1d5d556d4b00403a9785e830146ee9b69dd3 Mon Sep 17 00:00:00 2001 From: altair823 Date: Tue, 2 Jun 2026 12:25:45 +0000 Subject: [PATCH] =?UTF-8?q?feat(cli):=20ingest=20=EC=8B=9C=20=EC=9E=84?= =?UTF-8?q?=EB=B2=A0=EB=94=A9=20=EB=B0=B1=EC=97=94=EB=93=9C/=EB=94=94?= =?UTF-8?q?=EB=B0=94=EC=9D=B4=EC=8A=A4=20=ED=95=9C=20=EC=A4=84=20=ED=91=9C?= =?UTF-8?q?=EC=8B=9C=20+=20README=20KB=20=EC=9D=B4=EC=A0=84=20=EB=AC=B8?= =?UTF-8?q?=EC=84=9C=20(v0.23.1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - kebab-cli ingest: 시작 시 `임베딩 백엔드: (Metal/GPU 빌드|CPU) · 모델 …` 를 stderr 로 표시 (--json/--quiet 억제). Metal 표기는 cfg!(feature=embed_metal) 기반; 확정 런타임 디바이스는 kb.log(`candle device = …`). - README: '외부 계산 + 로컬 검색' 절에 복사 대상(kebab.sqlite/sqlite, lancedb/vector_dir) + [storage] config 키 + models/assets 복사 불필요 + 동일 버전/모델 조건 + rsync 예시. - 버전 0.23.0 → 0.23.1 (CLI 출력 + 문서만, 동작/schema 불변). Co-Authored-By: Claude Opus 4.8 (1M context) --- Cargo.lock | 46 ++++++++++++++++++------------------ Cargo.toml | 2 +- README.md | 19 ++++++++++++++- crates/kebab-cli/src/main.rs | 18 ++++++++++++++ tasks/HOTFIXES.md | 16 +++++++++++++ 5 files changed, 76 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0d73ef2..aae0e90 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4724,7 +4724,7 @@ dependencies = [ [[package]] name = "kebab-app" -version = "0.23.0" +version = "0.23.1" dependencies = [ "anyhow", "base64 0.22.1", @@ -4771,7 +4771,7 @@ dependencies = [ [[package]] name = "kebab-chunk" -version = "0.23.0" +version = "0.23.1" dependencies = [ "anyhow", "blake3", @@ -4789,7 +4789,7 @@ dependencies = [ [[package]] name = "kebab-cli" -version = "0.23.0" +version = "0.23.1" dependencies = [ "anyhow", "clap", @@ -4810,7 +4810,7 @@ dependencies = [ [[package]] name = "kebab-config" -version = "0.23.0" +version = "0.23.1" dependencies = [ "anyhow", "dirs 5.0.1", @@ -4826,7 +4826,7 @@ dependencies = [ [[package]] name = "kebab-core" -version = "0.23.0" +version = "0.23.1" dependencies = [ "anyhow", "blake3", @@ -4840,7 +4840,7 @@ dependencies = [ [[package]] name = "kebab-embed" -version = "0.23.0" +version = "0.23.1" dependencies = [ "anyhow", "blake3", @@ -4854,7 +4854,7 @@ dependencies = [ [[package]] name = "kebab-embed-candle" -version = "0.23.0" +version = "0.23.1" dependencies = [ "anyhow", "candle-core", @@ -4873,7 +4873,7 @@ dependencies = [ [[package]] name = "kebab-embed-local" -version = "0.23.0" +version = "0.23.1" dependencies = [ "anyhow", "fastembed", @@ -4886,7 +4886,7 @@ dependencies = [ [[package]] name = "kebab-eval" -version = "0.23.0" +version = "0.23.1" dependencies = [ "anyhow", "kebab-app", @@ -4905,7 +4905,7 @@ dependencies = [ [[package]] name = "kebab-llm" -version = "0.23.0" +version = "0.23.1" dependencies = [ "anyhow", "kebab-core", @@ -4914,7 +4914,7 @@ dependencies = [ [[package]] name = "kebab-llm-local" -version = "0.23.0" +version = "0.23.1" dependencies = [ "anyhow", "kebab-config", @@ -4931,7 +4931,7 @@ dependencies = [ [[package]] name = "kebab-mcp" -version = "0.23.0" +version = "0.23.1" dependencies = [ "anyhow", "kebab-app", @@ -4949,7 +4949,7 @@ dependencies = [ [[package]] name = "kebab-nli" -version = "0.23.0" +version = "0.23.1" dependencies = [ "anyhow", "hf-hub", @@ -4964,7 +4964,7 @@ dependencies = [ [[package]] name = "kebab-parse-code" -version = "0.23.0" +version = "0.23.1" dependencies = [ "anyhow", "gix", @@ -4987,7 +4987,7 @@ dependencies = [ [[package]] name = "kebab-parse-image" -version = "0.23.0" +version = "0.23.1" dependencies = [ "ab_glyph", "anyhow", @@ -5011,7 +5011,7 @@ dependencies = [ [[package]] name = "kebab-parse-md" -version = "0.23.0" +version = "0.23.1" dependencies = [ "anyhow", "kebab-core", @@ -5028,7 +5028,7 @@ dependencies = [ [[package]] name = "kebab-parse-pdf" -version = "0.23.0" +version = "0.23.1" dependencies = [ "anyhow", "blake3", @@ -5043,7 +5043,7 @@ dependencies = [ [[package]] name = "kebab-rag" -version = "0.23.0" +version = "0.23.1" dependencies = [ "anyhow", "blake3", @@ -5065,7 +5065,7 @@ dependencies = [ [[package]] name = "kebab-search" -version = "0.23.0" +version = "0.23.1" dependencies = [ "anyhow", "globset", @@ -5084,7 +5084,7 @@ dependencies = [ [[package]] name = "kebab-source-fs" -version = "0.23.0" +version = "0.23.1" dependencies = [ "anyhow", "blake3", @@ -5102,7 +5102,7 @@ dependencies = [ [[package]] name = "kebab-store-sqlite" -version = "0.23.0" +version = "0.23.1" dependencies = [ "anyhow", "blake3", @@ -5122,7 +5122,7 @@ dependencies = [ [[package]] name = "kebab-store-vector" -version = "0.23.0" +version = "0.23.1" dependencies = [ "anyhow", "arrow", @@ -5146,7 +5146,7 @@ dependencies = [ [[package]] name = "kebab-tui" -version = "0.23.0" +version = "0.23.1" dependencies = [ "anyhow", "crossterm", diff --git a/Cargo.toml b/Cargo.toml index 390ba06..02fc277 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,7 +31,7 @@ edition = "2024" rust-version = "1.85" license = "MIT OR Apache-2.0" repository = "https://github.com/altair823/kebab" -version = "0.23.0" # v0.23.0 — candle Metal(Apple Silicon GPU) opt-in build feature (`--features embed_metal`): M-series 맥에서 e5-large 임베딩을 GPU 로 → 대용량 ingest 가속. macOS 전용, 벡터는 CPU candle 과 호환. default(비-metal) 동작 불변. — CLAUDE.md §Release 도그푸딩 트리거 +version = "0.23.1" # v0.23.1 — ingest 시작 시 임베딩 백엔드/디바이스 한 줄 표시(터미널, --json/--quiet 존중) + README 에 KB 이전(어떤 파일/어느 config 키) 설명. 동작·schema 변경 없음. — CLAUDE.md §Release # pre-v0.18 workspace-wide cleanup: enable clippy::pedantic group with # intentional allow-list. The allowed lints are either cosmetic (doc style), diff --git a/README.md b/README.md index ad890d0..10f6d0e 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,24 @@ embedding 벡터와 별칭 LLM 결과를 청크 **내용 해시** 로 캐싱한 ### 외부 계산 + 로컬 검색 워크플로 -search/ask 는 asset 파일 없이 `kebab.sqlite` + `lancedb` 만으로 동작한다. 비싼 색인(임베딩·OCR·별칭 생성)을 성능 좋은 서버에서 수행한 뒤, 이 두 산출물만 로컬로 복사하면 그대로 검색·질문할 수 있다. +search/ask 는 원본 파일 없이 KB 산출물만으로 동작한다 (청크 본문이 SQLite 에 저장되고 문서 경로는 상대경로로 기록됨). 비싼 색인(임베딩·OCR·별칭 생성)을 성능 좋은 머신에서 수행한 뒤(예: Apple Silicon 맥에서 candle Metal GPU), **두 산출물만** 다른 머신(예: NUMA 서버)으로 복사하면 그대로 검색·질문할 수 있다. + +**무엇을 복사하나 — `[storage]` 에서 정의된 두 경로:** + +| 복사 대상 | config 키 (`[storage]`) | 기본 경로 | 내용 | +|-----------|------------------------|-----------|------| +| `kebab.sqlite` | `sqlite = "{data_dir}/kebab.sqlite"` | `{data_dir}/kebab.sqlite` | 문서·청크·본문·FTS5·메타 | +| `lancedb/` | `vector_dir = "{data_dir}/lancedb"` | `{data_dir}/lancedb/` | 임베딩 벡터 | + +`{data_dir}` 는 `[storage].data_dir` (예: `~/.local/share/kebab`). `models/`(`model_dir`)·`assets/`(`asset_dir`)는 **복사 불필요** — 모델은 각 머신이 자기 캐시를 받고, asset 원본 바이트는 검색·질문에 쓰이지 않는다 (단일파일/`stdin` 색인의 원본 재읽기·재색인까지 보존하려면 `assets/` 도 함께 복사). + +```bash +# ingest 가 끝난(쓰기 없는) 상태에서 복사 +rsync -a /kebab.sqlite user@server:/ +rsync -a /lancedb/ user@server:/lancedb/ +``` + +조건: **양쪽 동일 `kebab` 버전 + 동일 임베딩 모델/차원** (`[models.embedding].model`·`dimensions`). provider 는 달라도 됨 (예: 맥 `candle`/Metal ↔ 서버 `candle`/CPU 또는 `fastembed` — 같은 모델이면 벡터 호환). 복사는 반드시 ingest 가 돌지 않을 때. ### 멀티미디어 색인 diff --git a/crates/kebab-cli/src/main.rs b/crates/kebab-cli/src/main.rs index e1c1960..5235c25 100644 --- a/crates/kebab-cli/src/main.rs +++ b/crates/kebab-cli/src/main.rs @@ -632,6 +632,24 @@ fn run(cli: &Cli) -> anyhow::Result<()> { .map(|v| v.eq_ignore_ascii_case("plain")) .unwrap_or(false); let mode = progress::ProgressMode::from_flags(cli.json, cli.quiet, plain_env); + + // Surface the active embedding backend/device on the terminal so the + // user sees it without grepping kb.log (the per-device tracing line + // only lands in the log file at --verbose). Suppressed under + // --json/--quiet. The Metal note reflects the build (`embed_metal`); + // the confirmed runtime device is in kb.log (`candle device = ...`). + if !cli.json && !cli.quiet { + let backend = match cfg.models.embedding.provider.as_str() { + "candle" if cfg!(feature = "embed_metal") => "candle (Metal/GPU 빌드)", + "candle" => "candle (CPU, 순수 Rust)", + "fastembed" | "onnx" | "" => "fastembed (onnxruntime)", + "none" => "비활성 (lexical-only)", + other => other, + }; + eprintln!("임베딩 백엔드: {backend} · 모델 {} ({}-dim)", + cfg.models.embedding.model, cfg.models.embedding.dimensions); + } + let (tx, rx) = std::sync::mpsc::channel::(); let display_handle = std::thread::spawn(move || progress::ProgressDisplay::new(mode).run(rx)); diff --git a/tasks/HOTFIXES.md b/tasks/HOTFIXES.md index 3230f97..f27f311 100644 --- a/tasks/HOTFIXES.md +++ b/tasks/HOTFIXES.md @@ -14,6 +14,22 @@ historical contract that was implemented; this file accumulates the deltas so phase 5+ readers can find the live behavior without diffing git history. +## 2026-06-02 — ingest 백엔드/디바이스 표시 + KB 이전 문서 (v0.23.1) + +**동기.** Metal 빌드가 실제로 GPU 를 쓰는지 사용자가 터미널에서 못 봐서 Activity +Monitor 로 확인해야 했다(`select_device()` 의 device 로그는 kb.log 파일로만, 기본 +EnvFilter=warn 이라 `--verbose` 필요). 또 "어떤 DB 파일을 옮기나" 가 README 에 +구체적이지 않았다. + +**무엇.** (1) `kebab-cli` ingest 시작 시 임베딩 백엔드/모델/차원을 stderr 한 줄로 +표시(`임베딩 백엔드: candle (Metal/GPU 빌드) · 모델 …`), `--json`/`--quiet` 에선 +억제. Metal 표기는 `cfg!(feature="embed_metal")` 기반(빌드 사실); 확정 런타임 +디바이스는 여전히 kb.log(`candle device = …`). (2) README "외부 계산 + 로컬 검색" +절에 복사 대상 2개(`kebab.sqlite`/`sqlite`, `lancedb/`/`vector_dir`)와 `[storage]` +config 키·`models/`·`assets/` 복사 불필요·동일 버전/모델 조건·rsync 예시 추가. + +**범위.** CLI 출력 + 문서만. 동작·wire·schema·벡터 변경 없음. 버전 0.23.0 → 0.23.1. + ## 2026-06-02 — candle Metal(Apple Silicon GPU) opt-in build feature **동기.** candle CPU 임베딩은 e5-large/512-tok 에서 ~1.5~1.9 s/chunk 로 느리고,