Files
kebab/docs/release-notes/v0.22.0-draft.md
altair823 6ec4e6809f fix(embed-candle): address round-1 review
- commit track-spec + meta-spec/plan into branch (HIGH: dangling `amends:` ref)
- inline parity evidence (cosine 1.0, max_abs_diff 2.01e-7) into HOTFIXES +
  release notes; drop refs to deleted IMPL_REPORT/SPIKE_REPORT (MEDIUM)
- model guard: reject non-e5-large `model` before the 2GB download so
  model_id() can't mislabel vectors (MEDIUM) + unit test
- parity test now covers BOTH query: and passage: prefixes (MEDIUM)
- guard encodings.first() index; document zero-attention/pooling invariant;
  clarify embed_batch prefixing doc (LOW)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 16:54:20 +00:00

3.6 KiB
Raw Blame History

title, created, status, release_trigger
title created status release_trigger
kebab v0.22.0 release notes (draft) 2026-06-01 draft
신규 config surface (provider=candle, num_threads / KEBAB_EMBED_THREADS) — pre-1.0 minor bump
임베딩 백엔드 다변화 (NUMA-안전 candle provider 추가, opt-in)

kebab v0.22.0 — candle 임베딩 provider (NUMA-안전, opt-in)

v0.21.1 (config 마이그레이션) 후속 minor release. 듀얼소켓 NUMA 서버에서 onnxruntime 의 스레드 하드코딩이 일으키던 ingest 크래시를 피하기 위해, 같은 임베딩 모델을 순수 Rust(candle) 로 돌리는 opt-in provider 를 추가한다. 기본 동작은 그대로다 — 기존 사용자는 아무것도 바꿀 필요가 없다.


핵심 변경

candle 임베딩 provider (provider = "candle")

변경 사실. [models.embedding].provider"candle" 값이 추가됐다. "fastembed"(기본, onnxruntime) / "candle"(순수 Rust) / "none"(lexical-only) 중 하나를 고를 수 있다. candle provider 는 fastembed 와 완전히 같은 모델 (intfloat/multilingual-e5-large, 1024-dim)을 쓰고, e5 prefix → mean pooling → L2 정규화 파이프라인도 동일하다. 첫 사용 시 safetensors(~2GB)를 {model_dir}/candle/ 아래로 자동 다운로드한다.

[models.embedding]
provider = "candle"     # 기본은 "fastembed" — NUMA 서버에서만 candle 권장
num_threads = 8         # candle CPU 스레드 캡 (0 = auto = #cores)
# env 로도 캡 가능 (config 보다 우선)
KEBAB_EMBED_THREADS=8 kebab ingest

Trade-off. candle 는 순수 Rust 라 onnxruntime 의 네이티브 SIMD 커널보다 CPU latency 가 느리다 (Phase 0 스파이크 측정 ~4×). 그래서 기본값은 fastembed 를 유지하고, candle 은 onnxruntime 가 죽는 NUMA 환경에서만 켜는 opt-in 으로 둔다. 단일 워크스테이션 사용자는 fastembed 가 더 빠르다.

Mitigation (왜 안전한가). candle 의 CPU 백엔드는 글로벌 rayon 풀 크기로 스레드를 정한다. num_threads(또는 env KEBAB_EMBED_THREADS)가 그 풀을 한 번 캡하므로, onnxruntime 가 하드코딩하던 48 intra-op 스레드 → NUMA 힙 손상 → double-free 경로를 원천 차단한다. NUMA 노드 바인딩이 더 필요하면 numactl 과 조합한다.

Upgrade 절차. 재색인 불필요. candle 과 fastembed 의 벡터는 사실상 동일(Phase 0 스파이크 코사인 1.000000)해서 embedding_version 을 유지했고, 기존 LanceDB 색인을 그대로 재사용한다. provider 를 바꿔도 검색 결과는 바뀌지 않는다. 기존 config.tomlnum_threads 가 자동으로 0(auto)으로 채워져 그대로 로드된다 — kebab config migrate 도, 수동 편집도 필요 없다.


그 외

  • 신규 crate kebab-embed-candle (candle 의존성 트리를 이 crate 에 격리, kebab-core/kebab-config 외 다른 kebab-* 의존 없음).
  • Phase 0 feasibility 스파이크(spike-embed-candle)는 production 흡수 후 제거.
  • 문서: README Configuration, docs/SMOKE.md config 예시, docs/ARCHITECTURE.md crate 그래프/트리에 candle provider 반영.

잔여 검증 (사용자 실행)

듀얼소켓 NUMA 서버에서 provider=candle 로 5150-doc ingest 가 double-free 없이 EXIT=0 완주하는지가 본 release 의 최종 인수 게이트다 (meta-spec §4.3). 패리티(candle vs onnxruntime): cosine_min = 1.000000, 차원별 max 절대오차 = 2.01e-7 — 벡터가 사실상 동일하므로 embedding_version 유지(재색인 0). 재현은 crates/kebab-embed-candle/tests/parity.rs (--ignored).