feat(embed): arctic-embed-l-v2.0 임베더(candle+ollama) #203

Merged
altair823 merged 5 commits from feat/arctic-embedder into main 2026-06-03 06:27:58 +00:00
Owner

요약

별칭(doc-side expansion) 제거(#202) 후 설명형 recall 보강의 최선책으로 arctic-embed-l-v2.0 임베더를 통합한다. Phase4 측정(/build/dogfood/logs/2026-06-03-method-measurements.md)에서 arctic 은 확장 골든 recall@10 130/132(e5 123 대비 +7), recall@50 132/132, 그리고 bge-m3 와 달리 용어(syn/abbr/en) 무손실 — 색인 1회·per-query 0·LLM 0 으로 살아있는 KB 에 최적합. 사용자 결정에 따라 candle 우선 + Ollama embed provider 폴백 둘 다 추가한다. 기본 동작 불변(provider 기본 fastembed e5, arctic 은 opt-in).

설계: docs/superpowers/specs/2026-06-03-arctic-embedder-spec.md
계획: docs/superpowers/plans/2026-06-03-arctic-embedder-plan.md

변경

  • kebab-embed-ollama (신규 크레이트): Embedder 구현, reqwest::blocking POST /api/embed, batch 48 + fail-soft 재시도, L2 정규화, dim 검증. wiremock 테스트 3.
  • kebab-embed-candle: e5 하드코딩 → 모델 레지스트리 EmbedModelSpec{name,hf_repo,pooling,query_prefix,doc_prefix,dim,version_tag}. e5(mean, query:/passage:) + arctic(CLS, query:/무접두어). pooling 모델별 분기, 나머지(tokenize/forward/L2) 공유.
  • kebab-config: EmbeddingModelCfg.endpoint: Option<String>(ollama 용, 미설정 시 llm endpoint fallback) + provider 에 ollama.
  • kebab-app: embedder() provider match 에 ollama 분기(facade 경유).
  • version 0.25.0 → 0.26.0, workspace member += kebab-embed-ollama.

검증

  • cargo clippy --workspace --all-targets -j 4 -- -D warnings → exit 0 (리더 독립 재실행).
  • cargo test --workspace --no-fail-fast -j 1 → 199 group ok, 0 failed (기존 e5/fastembed 회귀 0).
  • correctness 핵심 (리더 독립 재현): candle arctic 임베딩 vs Ollama snowflake-arctic-embed2 임베딩 코사인 min 0.999984 (16벡터, 한/영/약어/설명형 전 카테고리 >0.99998). CLS pooling(1_Pooling/config.json pooling_mode_cls_token:true)+query: prefix 가 측정 경로와 정확 일치 → recall 130 재현 보장.
  • provider 로드 스모크: candle+arctic / ollama+arctic / fastembed+e5(기본) 각 성공.

호환성 / 비범위

  • e5 → arctic 전환 = embedding_version cascade(모델별 벡터 상이) → 재색인 필요(혼용 불가, 명확). dim 1024 동일이나 LanceDB 테이블명에 모델명 포함이라 충돌 없음.
  • A(heading enrichment) 미적용(측정상 arctic 에서 악화). dragonkue ko 파인튠 / D(query-side) / C(reranker) / Mac Metal 도그푸딩(recall 130 재현) 은 후속.

시험 항목 (Test Plan)

  • provider=candle+arctic 로드 → 1024-dim 정규화 벡터
  • provider=ollama+arctic 로드(endpoint fallback 포함)
  • candle arctic ≈ Ollama arctic 코사인>0.99 (수동, live Ollama)
  • 기본 fastembed e5 동작 불변

Assisted-by: Claude Code

## 요약 별칭(doc-side expansion) 제거(#202) 후 설명형 recall 보강의 최선책으로 **arctic-embed-l-v2.0** 임베더를 통합한다. Phase4 측정(`/build/dogfood/logs/2026-06-03-method-measurements.md`)에서 arctic 은 확장 골든 recall@10 **130/132**(e5 123 대비 +7), recall@50 **132/132**, 그리고 bge-m3 와 달리 **용어(syn/abbr/en) 무손실** — 색인 1회·per-query 0·LLM 0 으로 살아있는 KB 에 최적합. 사용자 결정에 따라 **candle 우선 + Ollama embed provider 폴백** 둘 다 추가한다. 기본 동작 불변(provider 기본 fastembed e5, arctic 은 opt-in). 설계: docs/superpowers/specs/2026-06-03-arctic-embedder-spec.md 계획: docs/superpowers/plans/2026-06-03-arctic-embedder-plan.md ## 변경 - **kebab-embed-ollama (신규 크레이트)**: `Embedder` 구현, `reqwest::blocking` POST `/api/embed`, batch 48 + fail-soft 재시도, L2 정규화, dim 검증. wiremock 테스트 3. - **kebab-embed-candle**: e5 하드코딩 → 모델 레지스트리 `EmbedModelSpec{name,hf_repo,pooling,query_prefix,doc_prefix,dim,version_tag}`. e5(mean, `query:`/`passage:`) + arctic(**CLS**, `query:`/무접두어). pooling 모델별 분기, 나머지(tokenize/forward/L2) 공유. - **kebab-config**: `EmbeddingModelCfg.endpoint: Option<String>`(ollama 용, 미설정 시 llm endpoint fallback) + provider 에 `ollama`. - **kebab-app**: `embedder()` provider match 에 ollama 분기(facade 경유). - version 0.25.0 → **0.26.0**, workspace member += kebab-embed-ollama. ## 검증 - `cargo clippy --workspace --all-targets -j 4 -- -D warnings` → exit 0 (리더 독립 재실행). - `cargo test --workspace --no-fail-fast -j 1` → 199 group ok, 0 failed (기존 e5/fastembed 회귀 0). - **correctness 핵심 (리더 독립 재현)**: candle arctic 임베딩 vs Ollama `snowflake-arctic-embed2` 임베딩 코사인 **min 0.999984** (16벡터, 한/영/약어/설명형 전 카테고리 >0.99998). CLS pooling(`1_Pooling/config.json` `pooling_mode_cls_token:true`)+`query:` prefix 가 측정 경로와 정확 일치 → recall 130 재현 보장. - provider 로드 스모크: candle+arctic / ollama+arctic / fastembed+e5(기본) 각 성공. ## 호환성 / 비범위 - e5 → arctic 전환 = `embedding_version` cascade(모델별 벡터 상이) → 재색인 필요(혼용 불가, 명확). dim 1024 동일이나 LanceDB 테이블명에 모델명 포함이라 충돌 없음. - A(heading enrichment) 미적용(측정상 arctic 에서 악화). dragonkue ko 파인튠 / D(query-side) / C(reranker) / Mac Metal 도그푸딩(recall 130 재현) 은 후속. ## 시험 항목 (Test Plan) - [ ] provider=candle+arctic 로드 → 1024-dim 정규화 벡터 - [ ] provider=ollama+arctic 로드(endpoint fallback 포함) - [ ] candle arctic ≈ Ollama arctic 코사인>0.99 (수동, live Ollama) - [ ] 기본 fastembed e5 동작 불변 Assisted-by: Claude Code
altair823 added 4 commits 2026-06-03 05:03:19 +00:00
arctic-embed-l-v2.0 의 폴백 백엔드(측정에 쓴 경로 그대로). reqwest::blocking
POST {endpoint}/api/embed {model,input:[...]} → embeddings. batch 48 +
fail-soft 재시도 3, 결과 L2 정규화(Ollama raw 반환 → 일관성), dim 검증.
query/doc prefix 는 모델 태그로 추론(arctic-embed→query:/무접두어, e5→query:/passage:).
model_version=ollama:{model}. endpoint=models.embedding.endpoint ?? models.llm.endpoint.
wiremock 테스트 3종(L2 정규화/dim mismatch/empty no-op) + 단위 5.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
e5 하드코딩(HF_MODEL/SUPPORTED_MODEL/mean/query:+passage:) → 모델 레지스트리
EmbedModelSpec{name,hf_repo,pooling,query_prefix,doc_prefix,dim,version_tag}.
e5(mean, query:/passage:) + arctic(CLS, query:/무접두어). pooling 모델별 분기
(mean=attention-mask-weighted / CLS=hidden[:,0,:]), tokenize/forward/L2 공유.
arctic pooling=CLS 는 HF 1_Pooling/config.json(pooling_mode_cls_token:true) 확인.
model_version 은 arctic 일 때 +arctic-cls 태그(embedding_version cascade 트리거);
e5 는 fastembed-e5 호환(NUMA 드롭인) 위해 plain config.version 유지.

correctness 게이트: tests/arctic_ollama_parity.rs (#[ignore], live Ollama) —
candle arctic vs Ollama snowflake-arctic-embed2 per-sentence 코사인>0.99.
수동 실측 cosine_min=0.999984 (recall@10 130 재현 보장).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
kebab-config: EmbeddingModelCfg.endpoint: Option<String>(serde default, ollama용,
None→models.llm.endpoint 폴백) + provider 문서에 ollama + env
KEBAB_MODELS_EMBEDDING_ENDPOINT. kebab-app embedder(): provider match 에 ollama
분기(facade 경유). workspace member += kebab-embed-ollama, app dep 추가.
version 0.25.0 → 0.26.0(minor, +Cargo.lock) — 신규 임베딩 백엔드/모델은 CLAUDE.md
§Release 의 surface 변경 트리거.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
README Configuration: provider candle/ollama + arctic 모델(candle CLS / ollama 태그)
+ endpoint + e5→arctic cascade 경고. ARCHITECTURE: 백엔드 그래프 노드(embedollama)
+ 임베딩 백엔드 결정표(채택 근거 측정 recall@10 130) + 디렉토리 트리. HANDOFF 1줄.
HOTFIXES 2026-06-03 arctic dated entry(레지스트리/pooling/prefix/cascade + 수동
cosine 0.999984 실측 결과).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
claude-reviewer-01 approved these changes 2026-06-03 05:04:41 +00:00
Dismissed
claude-reviewer-01 left a comment
Member

회차 1 — arctic 임베더(candle+ollama). 독립 검증 후 actionable 결함 0, 머지 동의(APPROVE).

독립 재현/검증

  • clippy --workspace --all-targets -j 4 -D warnings → exit 0 (리뷰어 재실행).
  • correctness 게이트 직접 재현: arctic_ollama_parity 실행 → candle arctic vs Ollama snowflake-arctic-embed2 코사인 min 0.999984(16벡터, 한/영/약어/설명형 전부 >0.99998). 측정 경로와 정확 일치 → recall@10 130 재현 보장.

핵심 로직 검토

  • kebab-embed-candle: pooling 모델별 분기 정확 — Mean(attention-mask-weighted) / Cls(hidden.narrow(1,0,1).squeeze(1) = <s> 첫 토큰). e5 mean 경로 불변, arctic CLS 신규. model_version+arctic-cls 태그로 cascade 트리거. 레지스트리(EmbedModelSpec) 추상화 깔끔.
  • kebab-embed-ollama(신규): Embedder 구현 견실 — prefix 분기(arctic query-only/e5 query·passage/unknown bare), batch 48, fail-soft 재시도 3, L2 정규화(zero-vector NaN 가드), dim mismatch 명확 에러, endpoint fallback(embedding→llm), model_version ollama:{model}. wiremock+unit 테스트 양호.
  • kebab-app embedder() ollama 분기 facade 경유, kebab-config endpoint Option+provider 문서화.

좋았던 판단

  • e5↔arctic pooling/prefix 차이를 per-model spec 으로 캡슐화해 공유 파이프라인 유지(중복 0).
  • 기본 provider=fastembed e5 불변(199 그룹 회귀 0) — arctic 순수 opt-in.
  • parity 테스트를 #[ignore](live Ollama) + 수동절차 문서화로 CI 무인환경 회피하면서 correctness 게이트 확보.
  • embedding_version cascade·LanceDB 테이블 모델명 분리로 e5/arctic 혼용 안전.

기존 e5/fastembed 회귀 0 + 위 독립 검증으로 머지 안전. 머지 후 Mac Metal 도그푸딩(recall 130 재현)만 남음. 사용자 머지 권장.

회차 1 — arctic 임베더(candle+ollama). 독립 검증 후 actionable 결함 0, 머지 동의(APPROVE). **독립 재현/검증** - `clippy --workspace --all-targets -j 4 -D warnings` → exit 0 (리뷰어 재실행). - correctness 게이트 **직접 재현**: `arctic_ollama_parity` 실행 → candle arctic vs Ollama `snowflake-arctic-embed2` 코사인 **min 0.999984**(16벡터, 한/영/약어/설명형 전부 >0.99998). 측정 경로와 정확 일치 → recall@10 130 재현 보장. **핵심 로직 검토** - `kebab-embed-candle`: pooling 모델별 분기 정확 — Mean(attention-mask-weighted) / Cls(`hidden.narrow(1,0,1).squeeze(1)` = `<s>` 첫 토큰). e5 mean 경로 불변, arctic CLS 신규. `model_version` 에 `+arctic-cls` 태그로 cascade 트리거. 레지스트리(EmbedModelSpec) 추상화 깔끔. - `kebab-embed-ollama`(신규): Embedder 구현 견실 — prefix 분기(arctic query-only/e5 query·passage/unknown bare), batch 48, fail-soft 재시도 3, L2 정규화(**zero-vector NaN 가드**), dim mismatch 명확 에러, endpoint fallback(embedding→llm), model_version `ollama:{model}`. wiremock+unit 테스트 양호. - `kebab-app` embedder() ollama 분기 facade 경유, `kebab-config` endpoint Option+provider 문서화. **좋았던 판단** - e5↔arctic pooling/prefix 차이를 per-model spec 으로 캡슐화해 공유 파이프라인 유지(중복 0). - 기본 provider=fastembed e5 불변(199 그룹 회귀 0) — arctic 순수 opt-in. - parity 테스트를 `#[ignore]`(live Ollama) + 수동절차 문서화로 CI 무인환경 회피하면서 correctness 게이트 확보. - embedding_version cascade·LanceDB 테이블 모델명 분리로 e5/arctic 혼용 안전. 기존 e5/fastembed 회귀 0 + 위 독립 검증으로 머지 안전. 머지 후 Mac Metal 도그푸딩(recall 130 재현)만 남음. 사용자 머지 권장.
altair823 added 1 commit 2026-06-03 05:11:07 +00:00
SMOKE.md 의 [models.embedding] 예시 주석이 stale: provider 목록에 ollama 누락 +
"candle 은 e5-large 만 지원"(arctic 추가로 더 이상 사실 아님) + endpoint/arctic
미기재. CLAUDE.md §"README Configuration + SMOKE config 블록 동시 갱신" 규칙대로
보완 — provider 4종, arctic 모델(candle/ollama 태그), endpoint(ollama 전용, llm
endpoint fallback), e5↔arctic cascade 주석 추가.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
claude-reviewer-01 approved these changes 2026-06-03 05:11:26 +00:00
claude-reviewer-01 left a comment
Member

회차 2 — docs(smoke) 후속 1커밋(095c9f3) 추가 리뷰. actionable 결함 0, 머지 동의 유지(APPROVE).

추가 변경: docs/SMOKE.md 의 [models.embedding] 예시 블록만 갱신(코드 변경 0). 회차 1 의 clippy/test/parity 검증 결과 유효(코드 불변).

검토: SMOKE.md 주석이 v0.26.0 과 stale 했던 것 정정 — provider 목록 ollama 추가, "candle 은 e5-large 만 지원"(arctic 추가로 거짓) 제거, arctic 모델(candle snowflake-arctic-embed-l-v2.0 / ollama snowflake-arctic-embed2)·endpoint(ollama 전용, llm fallback)·e5↔arctic cascade 주석 추가. README Configuration 섹션과 일관(CLAUDE.md "README + SMOKE config 블록 동시 갱신" 규칙 충족). smoke 기본값(fastembed e5-small)은 불변 — smoke 절차 영향 0.

문서 정합성 완결. 사용자 머지 권장.

회차 2 — docs(smoke) 후속 1커밋(095c9f3) 추가 리뷰. actionable 결함 0, 머지 동의 유지(APPROVE). 추가 변경: `docs/SMOKE.md` 의 [models.embedding] 예시 블록만 갱신(코드 변경 0). 회차 1 의 clippy/test/parity 검증 결과 유효(코드 불변). 검토: SMOKE.md 주석이 v0.26.0 과 stale 했던 것 정정 — provider 목록 ollama 추가, "candle 은 e5-large 만 지원"(arctic 추가로 거짓) 제거, arctic 모델(candle `snowflake-arctic-embed-l-v2.0` / ollama `snowflake-arctic-embed2`)·endpoint(ollama 전용, llm fallback)·e5↔arctic cascade 주석 추가. README Configuration 섹션과 일관(CLAUDE.md "README + SMOKE config 블록 동시 갱신" 규칙 충족). smoke 기본값(fastembed e5-small)은 불변 — smoke 절차 영향 0. 문서 정합성 완결. 사용자 머지 권장.
altair823 merged commit d71ed2516b into main 2026-06-03 06:27:58 +00:00
altair823 deleted branch feat/arctic-embedder 2026-06-03 06:28:00 +00:00
Sign in to join this conversation.
No Reviewers
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: altair823-org/kebab#203