From 90812e981f0ddbecc837fee07c22664a2e7da074 Mon Sep 17 00:00:00 2001 From: altair823 Date: Thu, 4 Jun 2026 13:03:07 +0000 Subject: [PATCH] =?UTF-8?q?docs(config):=20v3=20=EC=9E=AC=ED=8E=B8=20surfa?= =?UTF-8?q?ce=20=EB=8F=99=EA=B8=B0=ED=99=94=20+=20minor=20version=20bump?= =?UTF-8?q?=200.27.0=E2=86=920.28.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit README Configuration([ingest.*] 레이아웃 + migrate 안내), SMOKE config 예시, HOTFIXES dated entry(rename 매핑 + 3 불변식), 선행 마이그레이션 spec 교차링크. 인터페이스 변경(config 레이아웃 rename + env 추가) = minor. Co-Authored-By: Claude Opus 4.8 --- Cargo.lock | 48 +++++++++---------- Cargo.toml | 2 +- README.md | 7 +-- docs/SMOKE.md | 16 ++++--- .../2026-05-31-config-migration-design.md | 3 ++ tasks/HOTFIXES.md | 25 ++++++++++ 6 files changed, 66 insertions(+), 35 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0e97d51..231c2c6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4751,7 +4751,7 @@ dependencies = [ [[package]] name = "kebab-app" -version = "0.27.0" +version = "0.28.0" dependencies = [ "anyhow", "base64 0.22.1", @@ -4799,7 +4799,7 @@ dependencies = [ [[package]] name = "kebab-chunk" -version = "0.27.0" +version = "0.28.0" dependencies = [ "anyhow", "blake3", @@ -4817,7 +4817,7 @@ dependencies = [ [[package]] name = "kebab-cli" -version = "0.27.0" +version = "0.28.0" dependencies = [ "anyhow", "clap", @@ -4838,7 +4838,7 @@ dependencies = [ [[package]] name = "kebab-config" -version = "0.27.0" +version = "0.28.0" dependencies = [ "anyhow", "dirs 5.0.1", @@ -4854,7 +4854,7 @@ dependencies = [ [[package]] name = "kebab-core" -version = "0.27.0" +version = "0.28.0" dependencies = [ "anyhow", "blake3", @@ -4868,7 +4868,7 @@ dependencies = [ [[package]] name = "kebab-embed" -version = "0.27.0" +version = "0.28.0" dependencies = [ "anyhow", "blake3", @@ -4882,7 +4882,7 @@ dependencies = [ [[package]] name = "kebab-embed-candle" -version = "0.27.0" +version = "0.28.0" dependencies = [ "anyhow", "candle-core", @@ -4902,7 +4902,7 @@ dependencies = [ [[package]] name = "kebab-embed-local" -version = "0.27.0" +version = "0.28.0" dependencies = [ "anyhow", "fastembed", @@ -4915,7 +4915,7 @@ dependencies = [ [[package]] name = "kebab-embed-ollama" -version = "0.27.0" +version = "0.28.0" dependencies = [ "anyhow", "kebab-config", @@ -4930,7 +4930,7 @@ dependencies = [ [[package]] name = "kebab-eval" -version = "0.27.0" +version = "0.28.0" dependencies = [ "anyhow", "kebab-app", @@ -4949,7 +4949,7 @@ dependencies = [ [[package]] name = "kebab-llm" -version = "0.27.0" +version = "0.28.0" dependencies = [ "anyhow", "kebab-core", @@ -4958,7 +4958,7 @@ dependencies = [ [[package]] name = "kebab-llm-local" -version = "0.27.0" +version = "0.28.0" dependencies = [ "anyhow", "kebab-config", @@ -4975,7 +4975,7 @@ dependencies = [ [[package]] name = "kebab-mcp" -version = "0.27.0" +version = "0.28.0" dependencies = [ "anyhow", "kebab-app", @@ -4993,7 +4993,7 @@ dependencies = [ [[package]] name = "kebab-nli" -version = "0.27.0" +version = "0.28.0" dependencies = [ "anyhow", "hf-hub", @@ -5008,7 +5008,7 @@ dependencies = [ [[package]] name = "kebab-parse-code" -version = "0.27.0" +version = "0.28.0" dependencies = [ "anyhow", "gix", @@ -5031,7 +5031,7 @@ dependencies = [ [[package]] name = "kebab-parse-image" -version = "0.27.0" +version = "0.28.0" dependencies = [ "ab_glyph", "anyhow", @@ -5059,7 +5059,7 @@ dependencies = [ [[package]] name = "kebab-parse-md" -version = "0.27.0" +version = "0.28.0" dependencies = [ "anyhow", "kebab-core", @@ -5076,7 +5076,7 @@ dependencies = [ [[package]] name = "kebab-parse-pdf" -version = "0.27.0" +version = "0.28.0" dependencies = [ "anyhow", "blake3", @@ -5091,7 +5091,7 @@ dependencies = [ [[package]] name = "kebab-rag" -version = "0.27.0" +version = "0.28.0" dependencies = [ "anyhow", "blake3", @@ -5113,7 +5113,7 @@ dependencies = [ [[package]] name = "kebab-search" -version = "0.27.0" +version = "0.28.0" dependencies = [ "anyhow", "globset", @@ -5132,7 +5132,7 @@ dependencies = [ [[package]] name = "kebab-source-fs" -version = "0.27.0" +version = "0.28.0" dependencies = [ "anyhow", "blake3", @@ -5150,7 +5150,7 @@ dependencies = [ [[package]] name = "kebab-store-sqlite" -version = "0.27.0" +version = "0.28.0" dependencies = [ "anyhow", "blake3", @@ -5170,7 +5170,7 @@ dependencies = [ [[package]] name = "kebab-store-vector" -version = "0.27.0" +version = "0.28.0" dependencies = [ "anyhow", "arrow", @@ -5194,7 +5194,7 @@ dependencies = [ [[package]] name = "kebab-tui" -version = "0.27.0" +version = "0.28.0" dependencies = [ "anyhow", "crossterm", diff --git a/Cargo.toml b/Cargo.toml index cdd068a..5e1ca25 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,7 +32,7 @@ edition = "2024" rust-version = "1.85" license = "MIT OR Apache-2.0" repository = "https://github.com/altair823/kebab" -version = "0.27.0" # v0.27.0 — PP-OCRv5 ONNX Rust 네이티브 OCR 엔진: `[image.ocr] engine = "paddle-onnx"` (default 여전히 "ollama-vision") 로 in-process 검출+인식(`ort` =2.0.0-rc.9, Python 런타임 0). DBNet det + CTC rec, 후처리(min-area rect/unclip)는 pure-Rust. e2e CER 0.005(synthetic 한/영, PoC 0.024 대비 우수), 큰 페이지 CPU <4초(Ollama vision ~50초 대비). 신규 config `det_model`/`rec_model`/`dict`/`score_thresh`/`unclip_ratio`/`max_boxes` + `KEBAB_IMAGE_OCR_*` env. ingest 서명 `|ocr:1:{engine}:{engine_version}` 로 engine/모델 변경 시 자동 재색인. 신규 인터페이스(engine 값/config 키) → minor. — CLAUDE.md §Release +version = "0.28.0" # v0.28.0 — config 스키마 v2→v3 재편: 미디어 형식 설정을 `[ingest.*]` 우산으로 통합(`[indexing]`→`[ingest]` 스칼라, `[chunking]`/`[image.ocr]`/`[image.caption]`/`[pdf.ocr]`→`[ingest.*]`). 기존 v2 파일은 load 시 메모리 자동 변환(디스크 미변경), 파일 갱신은 `kebab config migrate`(값·주석 보존). env 이름(LHS) 100% 보존 + RHS 만 새 경로, 신규 `KEBAB_PDF_OCR_{DET_MODEL,REC_MODEL,DICT,SCORE_THRESH,UNCLIP_RATIO,MAX_BOXES}`. `ingest_config_signature` 바이트 불변(재색인 0). PdfOcrCfg paddle 대칭 키. 신규 인터페이스(config 레이아웃 rename + env 추가) → minor. — 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 5b18783..89b09af 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ rsync -a /lancedb/ user@server:/lancedb/ ### 멀티미디어 색인 -Markdown · PDF · 이미지(OCR + caption) · 소스코드(Rust/Python/TS/JS/Go/Java/Kotlin/C/C++ AST) · 리소스(YAML/Dockerfile/TOML/JSON/XML 등)를 확장자에 따라 자동으로 적절한 chunker 에 라우팅한다. embedded text 가 없는 scanned PDF 는 `[pdf.ocr]` 로 page-단위 OCR (opt-in). 전체 확장자→chunker 매핑은 [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md). +Markdown · PDF · 이미지(OCR + caption) · 소스코드(Rust/Python/TS/JS/Go/Java/Kotlin/C/C++ AST) · 리소스(YAML/Dockerfile/TOML/JSON/XML 등)를 확장자에 따라 자동으로 적절한 chunker 에 라우팅한다. embedded text 가 없는 scanned PDF 는 `[ingest.pdf.ocr]` 로 page-단위 OCR (opt-in). 전체 확장자→chunker 매핑은 [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md). ### RAG (근거 인용 + 거절) @@ -182,10 +182,11 @@ prompt_template_version = "rag-v3" # 답변 언어 = 질문 언어. rag-v1/v2 nli_threshold = 0.0 # >0 (예: 0.5) 면 mDeBERTa XNLI groundedness 검증. ``` +- **`[ingest]`** (v0.28.0) — 모든 형식 ingest 설정의 우산. 병렬도(`max_parallel_extractors`/`max_parallel_embeddings`/`watch_filesystem`, ← 옛 `[indexing]`)와 형식별 하위 절(`[ingest.chunking]` ← 옛 `[chunking]`, `[ingest.code]`, `[ingest.image.ocr]` ← 옛 `[image.ocr]`, `[ingest.pdf.ocr]` ← 옛 `[pdf.ocr]`)이 전부 이 아래로 모인다. 기존 v2 `config.toml` 은 그대로 둬도 로드 시 메모리에서 자동 변환되며, 파일을 새 레이아웃으로 갱신하려면 `kebab config migrate` (값·주석 보존). - **파생물 캐시** — embedding 결과를 내용 해시로 자동 캐싱한다 (위 「핵심 기능」 참고). 설정 항목 없음. - **`[ingest.code]`** — code ingest 의 skip 정책 (`skip_generated_header`, `max_file_bytes`, `extra_skip_globs`). `.gitignore` 자동 honor, `.kebabignore` 는 추가 layer. -- **`[image.ocr]`** — 이미지 OCR (default off / opt-in). `engine` 으로 백엔드 선택: `"ollama-vision"` (default, 원격 vision LM) 또는 `"paddle-onnx"` (v0.27.0 신규 — PP-OCRv5 ONNX 를 in-process 로 실행, Python 런타임 불필요, 큰 페이지 CPU <4초, 오프라인). `paddle-onnx` 는 워크스페이스에 번들된 모델을 쓰며 `det_model`/`rec_model`/`dict` 로 경로 override, `score_thresh`(0.3)/`unclip_ratio`(1.5)/`max_boxes`(1000) 로 검출 튜닝 가능 (`KEBAB_IMAGE_OCR_*` env 동일 지원). engine 또는 모델을 바꾸면 영향 이미지가 자동 재색인된다. -- **`[pdf.ocr]`** — scanned PDF 의 page-단위 OCR (default off / opt-in, page 당 ~수십 초 cost). `engine` 은 `[image.ocr]` 과 동일하게 `"ollama-vision"`/`"paddle-onnx"` 선택. 활성화 후 v0.19 시절 색인분은 `kebab ingest --force-reingest` 로 재처리. +- **`[ingest.image.ocr]`** — 이미지 OCR (default off / opt-in). `engine` 으로 백엔드 선택: `"ollama-vision"` (default, 원격 vision LM) 또는 `"paddle-onnx"` (PP-OCRv5 ONNX 를 in-process 로 실행, Python 런타임 불필요, 큰 페이지 CPU <4초, 오프라인). `paddle-onnx` 는 워크스페이스에 번들된 모델을 쓰며 `det_model`/`rec_model`/`dict` 로 경로 override, `score_thresh`(0.3)/`unclip_ratio`(1.5)/`max_boxes`(1000) 로 검출 튜닝 가능 (`KEBAB_IMAGE_OCR_*` env 동일 지원 — env 이름은 v3 에서도 불변). engine 또는 모델을 바꾸면 영향 이미지가 자동 재색인된다. +- **`[ingest.pdf.ocr]`** — scanned PDF 의 page-단위 OCR (default off / opt-in, page 당 ~수십 초 cost). `engine` 은 `[ingest.image.ocr]` 과 동일하게 `"ollama-vision"`/`"paddle-onnx"` 선택. v3 에서 paddle 모델 경로 키(`det_model`/`rec_model`/`dict`/`score_thresh`/`unclip_ratio`/`max_boxes`)를 PDF 자체적으로 가질 수 있다(`KEBAB_PDF_OCR_*` env 동일). 활성화 후 옛 색인분은 `kebab ingest --force-reingest` 로 재처리. - **`--config `** — 임시 워크스페이스 / 격리 테스트용 (CLI · TUI 모두 honor). - **`kebab config migrate`** — 새 버전에서 추가된 config 섹션을 기존 `config.toml` 에 설명 주석과 함께 채워 넣는다 (사용자가 손본 값·주석·순서는 보존, 멱등, 변경 시 자동 `.bak` 백업). `--dry-run` 으로 변경 미리보기. `kebab doctor` 가 갱신 필요 시 안내한다. `kebab init` 으로 새로 생성되는 config.toml 도 섹션별 주석을 포함한다. - **`KEBAB_*` env** — 일부 키 override (`KEBAB_RAG_SCORE_GATE`, `KEBAB_EVAL_GOLDEN` 등). diff --git a/docs/SMOKE.md b/docs/SMOKE.md index 2dbbb67..692d51c 100644 --- a/docs/SMOKE.md +++ b/docs/SMOKE.md @@ -95,12 +95,14 @@ model_dir = "{data_dir}/models" runs_dir = "{data_dir}/runs" copy_threshold_mb = 100 -[indexing] +# v0.28.0: 모든 형식 ingest 설정의 우산. 병렬도(← 옛 [indexing])는 [ingest] 스칼라로, +# chunking/code/image/pdf 는 [ingest.*] 하위로 통합. 옛 v2 파일은 로드 시 자동 변환됨. +[ingest] max_parallel_extractors = 2 max_parallel_embeddings = 1 watch_filesystem = false -[chunking] +[ingest.chunking] target_tokens = 500 overlap_tokens = 80 respect_markdown_headings = true @@ -329,7 +331,7 @@ MCP tool 동등: [workspace] include = ["**/*.md", "**/*.png", "**/*.jpg"] -[image.ocr] +[ingest.image.ocr] enabled = true # vision LM 으로 이미지 안 텍스트 전사 engine = "ollama-vision" model = "gemma4:e4b" # 사용자 환경의 비전 모델 @@ -337,12 +339,12 @@ endpoint = "http://192.168.0.47:11434" # 비우면 models.llm.endpoint fallback languages = ["eng", "kor"] max_pixels = 1600 # long-edge cap -[image.caption] +[ingest.image.caption] enabled = true # vision LM 으로 한 문장 객관 설명 생성 max_pixels = 768 prompt_template_version = "caption-v1" -[pdf.ocr] +[ingest.pdf.ocr] enabled = true # smoke test 의 OCR path 활성화 (manual invoke) always_on = false engine = "ollama-vision" @@ -358,13 +360,13 @@ lang_hint = "kor" 이미지 자산 한 장당 OCR 1 호출 + Caption 1 호출 → ~3-6초 (`gemma4:e4b` 기준). 다이어그램 / 카메라 사진 / 스크린샷 위주 워크스페이스에 권장. 책 / 스캔본은 P7 PDF 라인으로. -**v0.27.0 — paddle-onnx 엔진 (오프라인, Ollama 불필요).** `[image.ocr] engine = "paddle-onnx"` 로 바꾸면 PP-OCRv5 ONNX 를 in-process 로 실행한다 (원격 vision LM 불필요, 큰 페이지 CPU <4초). embedding 까지 끄려면 `[models.embedding] provider = "none"` (lexical-only) 로 두면 Ollama 없이 OCR→FTS5 검색 전체 경로를 스모크할 수 있다: +**v0.27.0 — paddle-onnx 엔진 (오프라인, Ollama 불필요).** `[ingest.image.ocr] engine = "paddle-onnx"` 로 바꾸면 PP-OCRv5 ONNX 를 in-process 로 실행한다 (원격 vision LM 불필요, 큰 페이지 CPU <4초). embedding 까지 끄려면 `[models.embedding] provider = "none"` (lexical-only) 로 두면 Ollama 없이 OCR→FTS5 검색 전체 경로를 스모크할 수 있다: ```toml [models.embedding] provider = "none" # lexical-only — Ollama 불필요 -[image.ocr] +[ingest.image.ocr] enabled = true engine = "paddle-onnx" # PP-OCRv5 ONNX in-process (Python/원격 0) model = "ppocrv5-mobile-kor" diff --git a/docs/superpowers/specs/2026-05-31-config-migration-design.md b/docs/superpowers/specs/2026-05-31-config-migration-design.md index 37ed10c..aff2d29 100644 --- a/docs/superpowers/specs/2026-05-31-config-migration-design.md +++ b/docs/superpowers/specs/2026-05-31-config-migration-design.md @@ -266,3 +266,6 @@ config load 체크 직후 `config_migration` 체크 1개 추가: - kickoff 인계 문서와의 차이: kickoff §4.2 는 "버전별 변환 함수 체인"만 제안했으나, kebab 의 serde-default 특성상 additive 변경은 step 으로 표현하기 부적절(버전 무관) → **reconciliation 을 1급 메커니즘으로 승격**하고 step 은 non-additive 전용으로 한정. +- 2026-06-04 v3 재편(첫 non-additive rename)에서 `step_2_to_3`(미디어 테이블 + `[ingest.*]` relocation) + `Config::from_file` load 시 메모리 자동변환 추가 — + `docs/superpowers/specs/2026-06-04-config-schema-reorg-design.md`. diff --git a/tasks/HOTFIXES.md b/tasks/HOTFIXES.md index 4c2b678..c2d3ce0 100644 --- a/tasks/HOTFIXES.md +++ b/tasks/HOTFIXES.md @@ -14,6 +14,31 @@ 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-04 — config 스키마 v2→v3 재편: 미디어 ingest 통합 (v0.28.0) + +**무엇을 바꿨나.** `config.toml` 의 미디어 형식 설정을 `[ingest.*]` 우산 아래로 통합했다. 첫 non-additive rename 마이그레이션. + +rename 매핑: + +| v2 (top-level) | v3 (`[ingest.*]`) | +|---|---| +| `[indexing]` (스칼라 키) | `[ingest]` 스칼라 (`max_parallel_extractors`/`max_parallel_embeddings`/`watch_filesystem`) | +| `[chunking]` | `[ingest.chunking]` | +| `[image.ocr]` | `[ingest.image.ocr]` | +| `[image.caption]` | `[ingest.image.caption]` | +| `[pdf.ocr]` | `[ingest.pdf.ocr]` | +| `[ingest.code]` | `[ingest.code]` (불변) | + +**보장한 3가지 불변식.** + +1. **signature 바이트 불변** — `ingest_config_signature` 출력은 값 기반이라 struct 경로 재편 후에도 v2 와 바이트 동일. 업그레이드 시 전체 재색인 발생 안 함. paddle 경로(det/rec/dict)는 미디어별로 호출자가 넘기도록 인자화(`ocr_engine_version_for_sig` + `engine_version_for_paths`); v2 의 "pdf 가 image paddle 을 빌려쓰던" 비대칭은 `step_2_to_3` 의 값 복사(`copy_image_paddle_to_pdf`)로 보존. +2. **env override 이름 100% 보존** — `apply_env` whitelist 의 키 문자열(LHS, 예 `KEBAB_CHUNKING_TARGET_TOKENS`/`KEBAB_INDEXING_MAX_PARALLEL_EXTRACTORS`)은 불변, 대입 대상(RHS)만 `self.ingest.*` 로. 기존 `KEBAB_*` 스크립트 무파손. 신규 `KEBAB_PDF_OCR_{DET_MODEL,REC_MODEL,DICT,SCORE_THRESH,UNCLIP_RATIO,MAX_BOXES}` 6키 추가(image.ocr paddle 대칭). +3. **load 시 메모리 내 자동 변환** — `Config::from_file` 이 `schema_version < 3` 파일을 디스크 미변경으로 메모리에서 v3 변환(`migrate_document` 경유). 미변환 v2 파일도 설정 유실 0. 파일 갱신은 `kebab config migrate` (값·주석·대안 줄 보존, 멱등). + +`PdfOcrCfg` 에 paddle 대칭 6키 추가. `ser_f32_clean` 으로 f32 직렬화 정리(`0.30000001192092896`→`0.3`). per-option 인라인 주석(`key_comment`)을 init/migrate 산출 config 에 부착. + +**도그푸딩.** (T10 후 채움) + ## 2026-06-04 — PP-OCRv5 ONNX Rust 네이티브 OCR 엔진 (v0.27.0) **무엇을 추가했나.** 이미지 OCR 에 두 번째 백엔드 `paddle-onnx` 를 붙였다. 기존 `ollama-vision`