-
released this
2026-08-16 21:23:27 +00:00 | 0 commits to main since this releasev0.33.0 — 28.4k 문서 도그푸딩이 드러낸 다섯 결함
v0.32.0 이후 실제 코퍼스(나무위키 18,282 + Apache Jira 10,146 = 28,427 문서 / 600,808 청크)로 도그푸딩하면서 등록한 이슈 #228~#232 를 전부 처리한 릴리스. 다섯 건 모두 단위 테스트가 잡지 못하는 종류였다 — 규모에서만 드러나는 성능 붕괴, 조용히 사라지는 내용, 멈춘 것처럼 보이는 진행 표시.
minorbump 트리거는 두 가지다. #232 의parser_versioncascade(pdf-text-v1→pdf-text-v2, 기존 색인 PDF 재처리 유발)와 신규 config 키([ingest.pdf.ocr] render_library/render_dpi). 나머지 셋은 additive wire 변경 + 관측성 개선이라 자체로는 patch 급이다.실측 evidence 는 전부
tasks/HOTFIXES.md의 2026-08-16 / 2026-08-17 dated entry 에 있다.
1. 스캔 PDF 가 인코딩에 따라 통째로 버려지던 문제 (#232) — minor
변경 사실. 스캔 페이지를 래스터화하는 방식이 "페이지에 박힌 JPEG 을 그대로 꺼내기" 에서 "페이지를 렌더링하기" 로 바뀌었다. 예전에는
/Filter가 정확히 DCTDecode 인 이미지 하나뿐인 페이지만 OCR 됐다. 실제 스캔본에서 흔한 CCITTFaxDecode·JBIG2Decode·FlateDecode·JPXDecode, 필터 체인, 그리고 "배경 + 마스크" 로 나뉜 구조는 전부 걸러졌다.걸러진 페이지는 조용히 사라졌다. 색인은 "성공" 으로 끝나고, 검색이 안 되는 시점에야 알게 되며, 그때 원인이 PDF 인코더라는 걸 역추적할 방법이 없었다.
trade-off. 렌더러(pdfium)는 공유 라이브러리로만 배포되고 정적 빌드가 없다. 바이너리에 넣으면 kebab 의 단일 실행 파일 성질이 깨지므로 런타임에 찾아 쓰는 방식으로 붙였다. 즉 스캔본 커버리지가 환경에 따라 달라진다 — 라이브러리가 있으면 전부, 없으면 예전과 같이 DCTDecode 페이지만 처리한다.
mitigation. 없을 때 조용히 넘어가지 않는다.
- 페이지마다 이유를 찍는다:
⊘ OCR page 5 건너뜀 — 래스터 없음 — 이 페이지의 인코딩은 페이지 렌더러 없이 읽을 수 없다 - run 요약에 건수가 나온다:
scanned 1 new 1 … ocr-skipped 1 --json에ingest_report.ocr_skipped_pages와pdf_ocr_finished.failure_reason(no_renderer/render_error/unopenable_pdf/ocr_error)kebab doctor의pdf_render가 지금 어느 쪽인지 보고한다
upgrade 절차. 스캔 PDF 를 쓰지 않으면 할 일이 없다. 쓴다면:
libpdfium을 로더가 찾는 곳에 두거나[ingest.pdf.ocr] render_library = "/경로/libpdfium.so"로 지정한다. 공개 빌드는 bblanchon/pdfium-binaries 에 있고 리눅스 x64 기준 7.4 MB 다.kebab doctor로pdf_render가 경로를 보고하는지 확인한다.- 재색인은 자동이다.
parser_version이pdf-text-v2로 올라가서 다음kebab ingest가 기존 PDF 를 다시 처리한다 —--force-reingest를 떠올릴 필요가 없다.
해상도 노브.
render_dpi(기본 300) 가 렌더 해상도 요청이고,max_pixels가 실제 상한이다. PDF 기본값max_pixels = 2048이면 A4 는 175 DPI 언저리에서 잘린다. 더 선명하게 읽히고 싶으면max_pixels를 올려야 하는데(A4 300 DPI 는 약 3500), 그만큼 큰 이미지를 OCR 엔진이 받는다. 엔진 자체도 256~4096 으로 다시 조인다.도그푸딩. 정답 텍스트를 아는 한국어 스캔 합성 픽스처(CCITT 3건, 22쪽)를 config 기본 모델
qwen2.5vl:3b로 읽혔다.문서 페이지 문자 오류율 브렌다(메이즈 러너 시리즈) 8 15.65% 비행대 스토리 8 12.55% 구 아놀리엔 6 15.08% 22쪽 전부 OCR 성공, 건너뜀 0. 이 릴리스 이전에는 세 문서 모두 본문이 0자였으므로 비교 대상 오류율은 100% 다.
엔진 선택 주의. 범용 멀티모달 모델은 OCR 엔진이 아니다. 같은 픽스처를
gemma3:4b로 읽혔더니 래스터는 정상인데 출력이 원문과 무관한 환각이었고("이 문서에 스무어라가 포함되어 있습니다"), 해상도가 올라가자 밀집 한국어 페이지에서 180초 타임아웃까지 났다. config 기본값이qwen2.5vl:3b인 이유가 이것이다.
2. 어휘 인덱스 삭제가 코퍼스 전체 스캔이던 문제 (#229) — patch (동작 불변)
변경 사실.
chunks_fts의 삭제 트리거가 행을 찾는 기준이chunk_id에서rowid로 바뀌었다 (마이그레이션 V016, 자동).chunk_id는 FTS5 에서 색인되지 않는 컬럼이라 조건을 만족할 색인이 없었고, 청크 한 건 삭제가 인덱스 전체를 훑었다. 문서 삭제·수정 등 chunk 를 지우는 모든 경로가 이 비용을 냈고, 코퍼스가 커질수록 증분 재색인이 느려지는 형태였다.trade-off. 없다. 컬럼 구성과 토크나이저가 그대로라 검색 결과가 바뀌지 않는다. 실제 KB 에서 네 질의의 상위 20건을 점수와 스니펫까지 해시로 비교했고 마이그레이션 전후가 동일했다.
mitigation / upgrade. 다음 실행 때 자동 적용된다. 60만 청크 기준 32초가 걸리고 재색인은 필요 없다 —
chunks와 임베딩은 손대지 않는다.도그푸딩. 문서 28,427건 / 청크 600,808개 KB 에서 문서 200건 삭제:
소요 이전 1,590초 이후 2.0초 약 800배다.
3. LanceDB 메타데이터가 제곱으로 불어나던 문제 (#230) — patch (동작 불변)
변경 사실. 벡터 스토어에 압축 정책이 생겼고, 삭제가 파일 단위에서 배치 단위로 바뀌었다.
압축이 없던 동안 매 쓰기가 fragment 와 "지금까지의 모든 fragment 를 나열한" manifest 를 남겼고, 메타데이터가 실데이터보다 빠르게 커졌다. 문서 1.1만 건에서 2.5배였던 비율이 1.7만 건에서 7.2배였다.
trade-off. 압축이 도는 순간에는 I/O 를 쓴다. 실측으로 15 GB 를 1.7 GB 로 되돌리는 데 153초였다.
mitigation / upgrade. 자동이다. 별도 조치가 없다.
도그푸딩. 2.8만 문서를 넣는 동안 색인 속도가 분당 32~36건으로 평평하게 유지됐다. 이전에는 30.7건에서 4.3건까지 단조롭게 떨어졌다. LanceDB 크기는 문서가 1.7배 늘었는데도 15 GB 에서 2.8 GB 로 줄었다. 문서 364건 삭제가 만드는 커밋은 364회에서 33회가 됐다.
kebab doctor에vector_store정보성 체크가 생겨 fragment·���전 수를 보여준다(종료 코드 영향 없음).
4. 삭제 구간이 멈춘 것처럼 보이던 문제 (#228) — patch (관측성)
변경 사실. 파일이 지워진 문서를 정리하는 구간(sweep)이 진행 표시와 로그에 나온다.
이 구간은 신호를 하나도 내지 않았다. 진행바는 색인 총계를 표시한 채 멈춰 보이고 ndjson 로그는 0바이트로 남았다. 프로세스는 정상 동작 중인데 밖에서는 hang 과 구별할 수 없었고, 실제로 세 번 연속 Ctrl-C 로 죽인 기록이 이슈에 남아 있다.
trade-off. 없다.
--json에 이벤트 세 종(sweep_started/sweep_progress/sweep_completed)과 ndjson 로그에 세 종(purge/purge_failed/sweep_summary)이 추가된다. 기존 소비자는 모르는 종류를 무시하므로 영향이 없다.mitigation / upgrade. 자동이다.
곁들여, sweep 이 취소 플래그를 보게 했다. 첫 Ctrl-C 가 "현재 파일까지만 하고 중단한다" 고 안내하는데 이 구간에서는 사실이 아니었다 — 유일한 수단인 두 번째 Ctrl-C 는 강제 종료라 버퍼에 쌓인 삭제가 고아로 남았다. 스캔 결과가 0건일 때 취소가 "완료" 로 보고되던 것도 함께 고쳤다.
5. 임베딩 캐시 (#231) — patch, 그리고 가설이 재현되지 않았다
이슈는 "캐시가 히트하는데도 우회하고 전량 재임베딩하는 편이 더 빠르다" 고 보고하면서 실측 표를 비워 뒀다. 그 표를 채웠는데 재현되지 않는다.
문서 792건 / 청크 16,379개를 강제 재처리한 결과, 캐시 히트 경로가 139초, 캐시 우회가 1,180초로 히트가 8.5배 빠르다. 새로 넣은 계측으로 뜯어보면 캐시 경로 전체가 run 의 1.5% 이하다.
다만 보고가 틀렸다고 단정하지 않는다. 보고 이후 #229 와 #230 이 머지됐고, 이슈 본문 스스로 #229 와 같은 뮤텍스를 공유해 서로를 증폭한다고 적어 뒀다. 그러니 "#229 이후에는 재현되지 않는다" 로 읽는 것이 맞다.
변경 사실. 캐시 조회를 배치로 접고(문서당 왕복 21회 → 1회), 삽입을 한 트랜잭션으로 묶고, 구문 캐시를 쓴다. 다만 벽시계 차이는 측정 오차 안이다 — 이 코퍼스에서는 체감이 없다.
실질적인 산출물은 계측 쪽이다.
--json의asset_timings에cache_hit/cache_miss/cache_ms가 실린다. 이전에는 stderr 로만 흘러 run 이 끝나면 사라졌고, "내 코퍼스에서 캐시가 이득인가" 를 확인할 방법이 없었다. TTY 에서는⏱ … embed 75ms · cache 21/21 0ms · store 36ms로 보인다.trade-off / upgrade. 없다. 자동이다.
그 밖
cargo clippy --workspace --all-targets -- -D warnings가 main 에서 실패하고 있었다(툴체인 상승으로 새 lint 두 개가 기존 코드에 걸림). 고쳤다. 방치하면 새 위반이 그 그늘에 숨는다는 것을 실제로 겪었다.kebab doctor에 체크 세 개가 추가됐다:pdf_render(정보성),vector_store(정보성),fts_shadow(어긋나면 exit 3 — 이 상태에서는 문서 삭제가 엉뚱한 인덱스 행을 지운다).
Downloads
- 페이지마다 이유를 찍는다:
-
released this
2026-06-27 03:33:44 +00:00 | 44 commits to main since this releaseponytail-audit over-engineering 정리 arc (#219–#222). 능력(검색·청킹·RAG) 불변, 표면·구조·crate 수만 단순화.
- #219 죽은 search-cache scaffold 제거 —
search()byte-identical,kebab search --no-cache/--explain플래그 +[rag] explain_defaultconfig 키 제거 (ask --explain/search --trace는 live). - #220 9개 동일 code AST chunker → 단일
CodeAstV1Chunker통합 (−3030줄) —chunker_version라벨 verbatim 유지 → chunk_id byte-identical → 재인덱싱 0. - #221 빈 re-export shim
kebab-embed/kebab-llm→kebab-core의 default-OFFmockfeature 흡수 — crate 22→20, 동작 불변. - #222
FusionPolicy1-arm enum inline +serde_yaml→serde_yaml_ng일원화 +NliVerifierdefault 제거 — 출력 불변.
minor 트리거 = #219 의 CLI 플래그/config 키 제거(인터페이스 변경). 누적 −3414줄 / 이 arc crate 22→20.
도그푸딩(2026-06-27): pre-arc(v0.31.0, 9-chunker) vs post-arc(consolidated) 실코퍼스 ingest → 120 chunks, chunk_id+chunker_version diff 완전 비어있음(byte-identical 종단 확증). GPU r9700 ollama(arctic-embed2) ingest + lexical 검색 정상, lemonade 복구 확인.
상세: docs/release-notes/v0.32.0-draft.md · HOTFIXES 2026-06-27.
Downloads
- #219 죽은 search-cache scaffold 제거 —
-
v0.31.0 — 척추 단순화 + 캐시 전면화 Stable
released this
2026-06-25 02:08:11 +00:00 | 61 commits to main since this releasev0.31.0 — 척추 단순화 + 캐시 전면화.
척추 재작성(#214, breaking: tui·세션·rag-v1/v2·search캐시·candle 제거, config v4→v5 마이그레이션, V015 drop chat_sessions) + 임베딩 캐시 전면화(#216) + OCR/caption derivation 캐시(#217). 캐시는 출력 byte-identical; minor = 척추의 breaking 마이그레이션.
상세: docs/release-notes/v0.31.0-draft.md
도그푸딩: tasks/HOTFIXES.md 2026-06-25 (OCR 캐시 17 jira PNG 재인덱싱 7× + 실 v3 KB 마이그레이션).Downloads
-
released this
2026-06-24 06:01:38 +00:00 | 111 commits to main since this releasev0.30.0(
md-heading-v2) 후속 patch release — 후속 3건.전체 릴리스 노트(정밀/정직 버전):
docs/release-notes/v0.30.1-draft.md변경 요약
pdf-page-v1.2— md-heading-v2 의 oversize 분할을 PDF 청커로 확장. 거대 PDF 페이지(> max_chunk_tokens)만 공유crate::oversize모듈로 재분할, 미분할 페이지는 v1.1 과 byte-identical.chunker_versionpdf-page-v1.1→v1.2.rag-v4— RAG 컨텍스트에source=/trust=provenance 라벨 + 신뢰도 우선·[#번호]귀속 2규칙.prompt_template_version기본rag-v3→rag-v4(multi-hopv1→v2).search_hit.v1에source_id/trust_leveladditive optional 필드.- config
[ingest.chunking]budget floor 검증 —target ≥ 16,overlap < target,max_chunk ≥ target위반 시 load 거부. valid config 동작 불변.
도그푸딩(rag-v4, 정직)
gemma3:4b@R9700 + competing 66 질의로 rag-v3 vs rag-v4 LLM-judge. 타깃 실패 모드(저신뢰 jira 가 권위 wiki 를 덮어씀)는 두 버전 모두 0/34(실패 모드 미재현) — 품질 지표 표본오차 내 구분 불가. rag-v4 는 무해(회귀 0) + 라벨 도달 확인이나 trust-steering 효과는 미입증. 본 릴리스는 그 효능을 주장하지 않는다.
업그레이드
새 바이너리로 교체 후 다음
kebab ingest(PDF 1회 자동 재청크) /kebab ask(자동rag-v4) 면 적용. 새 명령·플래그·필수 config 키 없음. single-hop 은prompt_template_version = "rag-v3"로 opt-out 가능(multi-hop 은 불가).answer.v1.prompt_template_version(required 필드)의 값이rag-v3→rag-v4로 바뀌므로 이 필드를 파싱하는 통합은 반영 필요(schema shape 불변, v2 bump 아님).NB (버전)
chunker_version·prompt_template_version변경은 §Versioning 상 minor(0.31.0) 트리거지만, 결과 실질 변화가 없고 도그푸딩 회귀 0 이라 사용자 재량으로 patch(0.30.1) 처리.Downloads
-
released this
2026-06-24 01:28:03 +00:00 | 121 commits to main since this releasekebab v0.30.0 — md-heading-v2: 거대 청크가 임베딩을 깨지 않도록
v0.29.0(provenance 출처 필터) 후속 minor release. markdown 청커가 하나의 거대
블록이 임베더 컨텍스트를 초과해 임베딩을 통째로 실패시키던 문제를 해소한다.
긴 로그·스택트레이스·표가 통으로 들어간 문서(예: jira 이슈)를 색인할 때 그
문서가 검색에서 통째로 사라지던 회귀를 막는다. 일반 사용자는 업그레이드 후
다음kebab ingest한 번이면 끝 — markdown 자산만 1회 자동 재청크된다.
변경 사실
1)
md-heading-v2청커가 기본값이 됐다. v1은 코드/테이블 블록을 (크기와
무관하게) 절대 분할하지 않았고, list·paragraph도 블록 하나가 곧 청크 하나였다.
그래서 거대한 단일 블록 — 예컨대 로그 덤프가 1000줄짜리 불릿 리스트로 변환된 것 —
이 임베더의 입력 한도를 넘으면 그 문서 전체의 벡터 색인이 실패했다. v2는 v1과
모든 출력이 동일하되, 마지막에 예산을 넘는 청크만 줄(\n) 경계로,
한 줄이 홀로 예산을 넘으면 UTF-8 문자 경계로 잘라 각 조각이 예산 이하가 되게 한다.2) 신규 config
[ingest.chunking] max_chunk_tokens(byte/3 토큰, default
4000). 이 값을 넘는 청크가 분할 대상이 된다. 4000은 8192-context 임베더(예:
snowflake-arctic-embed2)에 약 2배 안전마진을 두면서 일반적인 코드·문단은 그대로
한 청크로 유지하는 값이다.kebab config migrate로 기존 config에 additive 주입.[ingest.chunking] chunker_version = "md-heading-v2" max_chunk_tokens = 40003) 분할 조각의 chunk_id·citation. 한 블록에서 나온 분할 조각들은 같은
block_ids를 공유하므로 chunk_id에#seg{i}접미사를 붙여 충돌을 막는다. 분할
조각의 citation은 블록 단위(원 블록 범위) — sub-line 정밀도는 아니다.
미분할 청크(대다수)는 v0.29.0과 출력·citation이 완전히 동일하다.Trade-off
- 거대 블록이 여러 검색 hit로 나뉜다. 이전엔 그 문서가 (임베딩 실패로)
벡터 검색에서 아예 안 나왔거나, ollama처럼 조용히 잘린 채 한 hit였다. 이제는
여러 조각으로 정상 색인되어 각각 hit로 잡힐 수 있다 — 같은 문서가 상위에 여러
번 보일 수 있다. - 분할 조각 citation은 블록 단위다. fenced 코드의 줄 span이 fence를 포함하는
비대칭 때문에 조각별 정확한 줄 범위를 (span, code)만으로 복원할 수 없어,
"절대 틀리지 않되 블록 단위"를 택했다. 정밀 sub-line citation이 필요하면 향후
파서가 content 줄 범위를 직접 제공하는 개선이 필요하다. - byte/3 휴리스틱. 토큰 수는 실제 토크나이저가 아니라 바이트/3 근사다. CJK는
과대추정(더 안전), 영문 코드는 실토큰과 비슷. strict 임베더에 대해 보수적이다.
Mitigation
- 결과·CLI·wire 포맷 불변.
--json스키마, exit code, citation 모양 모두
동일. 내부적으로 거대 블록이 분할될 뿐이다. - 공유
ChunkPolicy미변경.max_chunk_tokens는 v2 청커의 policy_hash에만
fold되어 코드·PDF 청커의 cascade를 건드리지 않는다 — 코드/PDF 자산은 재청크되지
않는다. - strict 임베더 호환. v1 시절 ollama가 조용히 truncate하던 것을 청커가 애초에
예산 이하로 만들므로, oversize 입력을 truncate가 아닌 거부(500 too large)로
처리하는 백엔드(예: AMD Lemonade)에서도 색인이 깨지지 않는다. - 이미지 OCR 텍스트도 보호. 분할 판정은 청크의 실제 임베드 text 크기로 한다 —
이미지 청크는 내부적으로 token_estimate가 0이지만 그 OCR/캡션 text는 클 수 있어
(빽빽한 스크린샷), 실제 text 길이로 판정해야 oversize 이미지 OCR도 분할된다.
Known limitation
PDF는 별도 청커(
pdf-page-v1.1)를 쓰므로 이 oversize-split이 적용되지 않는다 —
초고밀도 scanned page 한 장의 OCR이 한 청크로 예산을 넘으면 그대로 임베드된다
(일반 PDF는 무관). 후속 작업으로 PDF 청커에도 동일 분할을 넣을 수 있다.업그레이드 절차
- 새 바이너리로 교체.
- (선택)
kebab config migrate— config 파일에max_chunk_tokens = 4000을
additive 주입(주석·값 보존). 안 해도 기본값으로 동작한다. kebab ingest—chunker_version이md-heading-v1→md-heading-v2로
바뀌었으므로 markdown 자산이 1회 자동 재청크된다(--force-reingest
불필요). 코드/PDF 자산은 영향 없음. embedding은 파생물 캐시(V012) 히트로
대부분 재계산을 피하지만, 분할된 거대 블록의 새 조각은 새로 임베드된다.- 대용량 KB라면 첫 ingest가 markdown 재청크로 평소보다 길어질 수 있다(1회성).
도그푸딩 evidence
실험 KB(MongoDB 문서 220 + jira 400, arctic-embed-l-v2 @ Lemonade GPU). v2 전:
620 문서 중 2개(SERVER-22906=76189토큰 list,SERVER-23097=20643토큰 list)가
임베드 실패. v2 후: 620/620, errors=0, 전 코퍼스 7114 청크가 모두 ≤ 4000
(초과 0).SERVER-22906은 14 청크로,SERVER-23097은 5 청크로 분할. "WiredTiger
excessive memory cache size" 질의에서 그동안 색인조차 안 되던SERVER-22906이
**1위 결과(0.977)**로 — "임베드 불가"에서 "최상위 검색 결과"로 전환됐다. 출처
필터(--trust-min primary등)는 정상 유지.Downloads
- 거대 블록이 여러 검색 hit로 나뉜다. 이전엔 그 문서가 (임베딩 실패로)
-
released this
2026-06-04 22:34:52 +00:00 | 125 commits to main since this releasekebab v0.28.0 — config 스키마 v2→v3: 미디어 ingest 통합
v0.27.0(PP-OCRv5 ONNX OCR) 후속 minor release.
config.toml에 흩어져
있던 미디어 형식 설정을[ingest.*]우산 하나로 모은다. 기존 사용자는
아무것도 손대지 않아도 된다 — 옛 v2 파일은 로드 시 메모리에서 자동 변환되고,
검색·색인 결과는 바이트 단위로 동일하다(재색인 0).
변경 사실
미디어 형식 설정이 top-level 에서
[ingest.*]하위로 이동했다.v2 (top-level) v3 ( [ingest.*])[indexing](스칼라)[ingest]스칼라 (max_parallel_extractors등)[chunking][ingest.chunking][image.ocr][ingest.image.ocr][image.caption][ingest.image.caption][pdf.ocr][ingest.pdf.ocr][ingest.code][ingest.code](변화 없음)부수적으로
[ingest.pdf.ocr]가 paddle-onnx 모델 경로 키(det_model/rec_model/
dict/score_thresh/unclip_ratio/max_boxes)를 PDF 자체적으로 가질 수 있게
됐다(v2 는 image.ocr 의 값을 빌려썼다). 신규 envKEBAB_PDF_OCR_*6키.Trade-off
비-additive rename 마이그레이션이라(첫 사례), 옛 섹션 이름을 그대로 두면
serde 가 모르는 키로 무시될 수 있다. 이를 피하려고 두 겹의 안전장치를 깔았다:
(1)Config::from_file이 load 시 메모리에서 v3 로 자동 변환 — 미변환 v2 파일도
설정 유실 0. (2)kebab config migrate가 디스크 파일을 새 레이아웃으로 갱신하되
값·주석·대안(commented) 줄을 전부 보존하고 멱등이다.env override 이름(예
KEBAB_CHUNKING_TARGET_TOKENS,
KEBAB_INDEXING_MAX_PARALLEL_EXTRACTORS)은 그대로 유지된다 — 대입 대상만
새 경로로 바뀌므로 기존KEBAB_*스크립트는 손댈 필요가 없다.Mitigation — 재색인 0 보장
ingest_config_signature는 값 기반이라 struct 경로가 바뀌어도 출력 문자열이
v2 와 바이트 동일하다. paddle 모델 경로는 미디어별(image/pdf)로 호출자가
넘기도록 인자화했고, 마이그레이션이 v2 의 image↔pdf paddle 비대칭을 값 복사로
보존한다. 도그푸딩(v0.28.0 release 빌드)에서 v2 config 로 first ingest 후
(a) 동일 v2 config 재ingest(자동변환), (b) v3 로config migrate후 재ingest
모두new=0 updated=0 unchanged=2— 업그레이드 시 재색인이 발생하지 않음을
실증했다.Upgrade 절차
- 아무것도 안 해도 된다 — 옛
config.toml은 그대로 로드된다(자동 변환,
디스크 미변경, 일회성 warn 으로 안내). - 파일을 새 레이아웃으로 정리하려면:
kebab config migrate(자동.bak백업,
--dry-run으로 미리보기).kebab doctor가 갱신 필요 시 안내한다. kebab init으로 새로 만드는 config 는 v3 레이아웃 + per-option 주석 포함.
검색·RAG 결과와 색인은 변하지 않는다.
Downloads
- 아무것도 안 해도 된다 — 옛
-
released this
2026-06-03 14:35:20 +00:00 | 147 commits to main since this releasev0.26.2 — ingest 설정 변경 시 영향 자산 자동 재색인
지금까지 증분 ingest 의 "변경 안 됨(skip)" 판정은 파일 내용 + parser/chunker/embedding 버전만 봤습니다. 그래서
config.toml에서 색인 결과를 바꾸는 설정(이미지 OCR/caption, 청킹 파라미터, PDF OCR, 코드 ingest 옵션)을 바꾼 뒤 다시kebab ingest해도, 파일 자체는 그대로니 자산이 그냥 건너뛰어졌습니다 — 바뀐 설정이 반영되지 않았죠. 이번 patch 가 그 갭을 일반화해 고칩니다.무엇이 바뀌나. 자산 타입별로 "그 자산의 색인 결과에 영향을 주는 설정"의 결정적 서명을 계산해 skip 판정에 포함시킵니다. 이제 해당 설정을 바꾸면
--force-reingest없이도 영향 받는 자산만 자동으로 다시 색인됩니다:[chunking](target_tokens/overlap_tokens/respect_markdown_headings/chunker_version) → 모든 자산 재색인[image.ocr]·[image.caption]→ 이미지만[pdf.ocr]→ PDF만[ingest.code]→ 코드 파일만
무엇은 안 바뀌나(중요). 색인 산출물과 무관한 설정 —
[search]/[rag]/[models.nli]/[ui]/[logging]/ 저장 경로, 그리고max_pixels/languages/*_timeout_secs같은 런타임 파라미터 — 는 바꿔도 재색인을 유발하지 않습니다(불필요한 전체 재색인 회피). 동일한 설정으로 다시 ingest 하면 종전처럼 전부 skip 됩니다.업그레이드 시 1회 재색인. 이 버전으로 올린 뒤 첫
kebab ingest에서는 기존 자산이 현재 설정대로 한 번 재색인됩니다(저장돼 있던 옛 parser_version 이 새 서명과 달라서). 임베딩은 내용 해시 기반 파생물 캐시(V012)가 그대로라 캐시 히트로 저렴하고, 그 1회 이후로는 설정을 바꾸지 않는 한 다시 skip 됩니다.--force-reingest는 전체 강제 재색인용으로 그대로 유지됩니다.호환성. CLI·config 키·wire schema·검색 결과 포맷에는 변화가 없습니다(내부 skip 판정만 정정) — 그래서 patch 릴리스입니다. 검증: clippy 0, 관련 크레이트 테스트 67 그룹 0 실패(토글/skip/제외 e2e 포함). 상세:
tasks/HOTFIXES.md2026-06-03 entry.Downloads
-
v0.26.1 — ingest 진행 로그 개선 Stable
released this
2026-06-03 11:07:20 +00:00 | 152 commits to main since this releasev0.26.1 — ingest 진행 로그 개선
OCR/caption 이 켜진 볼트(이미지·PDF 혼재)를 색인할 때, 진행바가 멈춘 것처럼 보이는데 무엇 때문에 느린지 알 수 없던 문제를 해결합니다. 검색·색인 결과나 명령/설정은 전혀 바뀌지 않는 관측성(observability) 개선이라 patch 릴리스입니다(기본 동작 불변).
무엇이 보이게 되었나.
- 현재 파일명 — 진행바에 지금 처리 중인 파일이 표시됩니다 (
ingest [===>] 142/997 · vault/foo.png). - 느린 phase + 모델 — 이미지 OCR·caption·임베딩이 도는 동안 그 사실과 사용 모델이 실시간으로 보입니다 (
· OCR(gemma4:e4b)…). 이전엔 이미지 OCR/caption 에 진행 이벤트가 없어 "정지"처럼 보였습니다. - 경과시간 heartbeat — 한 파일이 오래 걸려도
(45s)처럼 경과초가 이벤트 사이에도 계속 갱신되어, 멈춘 게 아니라 무거운 작업 중임이 드러납니다. - 종료 요약 — 끝에 가장 오래 걸린 파일 top-5 가 출력되어 병목 파일을 사후에 바로 파악할 수 있습니다.
Trade-off / 호환성. 사람용 진행바(stderr) 표시만 풍부해졌고,
--json출력에는 additive wire 이벤트가 더해졌습니다 — 신규asset_phase(ingest_progress.v1) +asset_timings의ocr_ms/caption_ms필드. 모두 backward-compat(기존 소비자는 새 필드를 무시하면 그만)이라 wire major bump 없이 v1 유지. 미디어가 없는 텍스트 위주 ingest 의 표시·성능에는 변화가 없습니다.검증. clippy 0, kebab-app/cli 61 그룹·parse-image/tui 14 그룹 테스트 0 failed. 상세:
tasks/HOTFIXES.md2026-06-03 entry.참고: 색인이 느린 근본 원인이 미디어 OCR/caption 인 경우, 텍스트 위주 볼트라면
[image.ocr]/[image.caption]/[pdf.ocr]를enabled = false로 두면 크게 빨라집니다(이 릴리스의 로그가 그 판단을 돕습니다).Downloads
- 현재 파일명 — 진행바에 지금 처리 중인 파일이 표시됩니다 (
-
released this
2026-06-03 07:20:27 +00:00 | 158 commits to main since this releasev0.26.0 — arctic-embed 임베더 + doc-side expansion(별칭) 제거
v0.24.0 이후 두 개의 큰 변화가 쌓였습니다. 검색 임베더를 더 강한 모델로 교체할 수 있게 되었고(설명형/풀어쓴 질의의 검색 품질이 크게 올라갑니다), 그 과정에서 유지보수 부담만 크고 효과는 미미했던 별칭(doc-side expansion) 기능을 제거했습니다. 두 변화 모두 측정(나무위키 ~1000 문서, 132개 변형 질의 골든)으로 근거를 잡았습니다.
1. 새 임베더: arctic-embed-l-v2.0 (provider
candle/ollama) — opt-in무엇이 바뀌나.
[models.embedding]에서 기본 multilingual-e5-large 대신 Snowflake arctic-embed-l-v2.0 임베더를 선택할 수 있습니다. 측정에서 같은 골든의 recall@10 이 e5 123/132 → arctic 130/132 (+7), recall@50 은 132/132(완벽) 으로 올랐고, 결정적으로 용어·약어·영어·동의어 질의는 손실 없이(72/72 유지) 설명형/풀어쓴 질의만 끌어올렸습니다(예: "마지막에 넣은 것을 먼저 꺼내는 자료구조" → 스택 문서). 두 백엔드를 제공합니다:# (A) candle — 순수 Rust, in-process (NUMA 안전, macOS Metal GPU 가능) [models.embedding] provider = "candle" model = "snowflake-arctic-embed-l-v2.0" # CLS pooling, query 에 "query: " 접두어 dimensions = 1024 # (B) ollama — 로컬/원격 Ollama 데몬에 위임 (POST /api/embed) [models.embedding] provider = "ollama" model = "snowflake-arctic-embed2" # ollama pull 필요 dimensions = 1024 endpoint = "http://127.0.0.1:11434" # 생략 시 [models.llm].endpoint 로 폴백Trade-off. arctic 으로 바꾸면 임베딩 벡터 공간이 달라지므로(
embedding_versioncascade) 기존 e5 KB 와 혼용할 수 없습니다 — 전환하려면 한 번 재색인이 필요합니다. 별칭과 달리 이 비용은 색인 1회뿐이고, per-query 추가 비용도 LLM 호출도 없어 살아있는(계속 갱신되는) KB 에 지속 가능합니다.Mitigation / 검증. 기본값은 그대로 e5-large 이므로 아무것도 안 바꾸면 동작·벡터가 100% 동일합니다(arctic 은 완전 opt-in). candle 백엔드의 정확성은 측정에 쓴 Ollama 경로와 코사인 0.999984 일치로 검증했고(같은 pooling/prefix), v0.26.0 실제 바이너리로 namu 를 재색인해 recall@10 130/132 를 종단 재현했습니다. 새 크레이트
kebab-embed-ollama가 추가됐습니다.Upgrade 절차. (1)
ollama pull snowflake-arctic-embed2(ollama 경로) 또는 candle 경로는 첫 색인 시 safetensors(~2GB) 자동 다운로드. (2) 위 config 로 변경 +dimensions = 1024. (3)kebab reset후 재 ingest. macOS 는cargo install --path crates/kebab-cli --features embed_metal --locked로 candle GPU 가속.
2. doc-side expansion(별칭) 기능 제거
무엇이 바뀌나. 청크마다 LLM 을 호출해 "검색용 별칭"을 생성하던 기능(
[ingest.expansion])을 완전히 제거했습니다. 측정 결과 이 기능의 실효는 설명형 질의 +2 그룹뿐인데, 그 대가가 색인할 때마다 청크당 LLM 호출(나무위키 18문서 cold 2.5시간)이라 계속 갱신되는 KB 에서는 지속 불가능했습니다. 별칭이 노렸던 한↔영 교차언어 recall 은 임베더 단독으로 이미 충분했고, 남은 설명형 약점은 위 arctic 교체가 더 깔끔하게 해결합니다.Trade-off / 영향. 별칭은 이미 기본 비활성(default-off)이었으므로 일반 사용자 체감은 0 입니다.
config.toml에[ingest.expansion]섹션이 남아 있어도 무시되며(forward-compat), 신규 마이그레이션 V013 이 사용되지 않던chunk_aliases_fts테이블과chunks.aliases컬럼을 정리합니다. wire 의ingest_progress.v1에서expansion_progress이벤트가 빠졌습니다(추가 직후라 호환 영향 없음).
기타
- 상세 측정·방법 비교(리랭크 / query-side expansion / heading enrichment / bge-m3 등 대안 포함):
tasks/HOTFIXES.md(2026-06-03 두 entry) + 연구 문서docs/superpowers/research/2026-06-03-expansion-cost-rethink-research.md. - 잔존 설명형 약점 2개(추상적 정의 질의)는 후속 query-side 보강 후보로 남겨둠.
- 문서 동기화: README Configuration, docs/SMOKE.md, docs/ARCHITECTURE.
Downloads
- 상세 측정·방법 비교(리랭크 / query-side expansion / heading enrichment / bge-m3 등 대안 포함):
-
released this
2026-06-02 17:46:47 +00:00 | 178 commits to main since this releasev0.24.0 — 상세 ingest 진행 로깅 (asset 내부 phase 가시화)
변경 사실
ingest 진행 표시가 asset(문서) 단위뿐이라, 한 문서 내부의 parse / chunk / expansion(별칭 LLM, 청크당 순차 호출) / embed / store 가 보이지 않았다. 큰 문서 하나가 expansion 으로 수십 분 걸려도 진행바가
1/N에 멈춘 듯 보여 병목을 찾기 어려웠다. 이번 릴리스는 asset 내부 phase 를 노출한다.추가된 것 (wire
ingest_progress.v1additive — 기존 consumer 호환)asset_chunked { idx, total, chunks }— 청킹 직후 즉시 "이 문서가 N청크" 표시 (큰 첫 문서가 멈춘 게 아님을 바로 확인).expansion_progress { idx, total, done, chunks }— 별칭 확장 중 라이브 카운터 (스로틀: 25청크 또는 1s).asset_timings { idx, total, parse_ms, chunk_ms, expansion_ms, embed_ms, store_ms }— 문서 종료 시 phase 별 소요시간 (markdown 경로).
사용자 체감
- 사람용 출력:
→ N chunks,별칭 확장 450/1843(라이브), 종료 시⏱ parse 3ms · chunk 673ms · expand 1980s · embed 12s · store 33ms. → 어느 phase 가 병목인지(expansion vs embed) 한눈에. --json: 새 이벤트가 line-delimited 로 흐름.--quiet억제.
호환 / 한계
- wire v1 backward-compat (신규
kind만 추가, 기존 필드 무변경). 동작/벡터/schema 메이저 변경 없음. - image/pdf 경로는 phase timing 없음(
asset_chunked만).expansion_progress비-TTY human 은 기본 억제(--json은 전량). store_ms= SQLite persist 전용,embed_ms= 임베딩 + 벡터 upsert + stale-vector purge (정확한 귀속).
Downloads