feat(retrieval): 임베딩 하이브리드 검색 활성화 — 자동 감지 + 측정 기반 수정 (v2.2.222)
골든셋(24질의) 측정으로 기존 하이브리드 구현의 결함 3건을 잡고 기본 활성화. 측정 결과: recall@3 83.3%→87.5%, MRR 0.802→0.806, recall@1 회귀 없음 (α=0.5). 수정 (측정으로 검증): - 임베딩 입력을 토큰 재조합(tokens.join)→원문 슬라이스로 교체 + nomic/e5 task prefix (search_query:/search_document:). 토큰 죽 입력은 하이브리드를 전 지표 하락시켰음 (recall@1 75%→54%). @r2 리비전 키로 구벡터 자동 무효화. - 블렌드 스케일 버그: 벡터 있는 후보만 정규화돼 벡터 없는 후보의 raw 점수가 상위 독식 → 전 후보 정규화 + cosine 후보군 내 min-max 정규화. - 헤딩-only 청크도 헤딩 텍스트로 임베딩 (벡터 공백 제거). 추가: - embeddingBootstrap: 활성화 시 엔진 모델 목록에서 임베딩 모델 자동 감지 → embeddingModel 자동 설정 + "전체 색인" 버튼 알림. 다국어 모델(e5/bge-m3) 우선. 사용자가 의도적으로 비우면 재설정 안 함 (globalState 가드). - 벡터 저장 시 소수 4자리 양자화 — 캐시 360MB→~150MB (코사인 순위 영향 없음). - tests/retrievalEvalEmbedding.test.ts: env-gated 하이브리드 측정 하니스 (alpha sweep). - scripts/compact_brain_index.mjs: 기존 full-precision 캐시 1회 압축 도구. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* brain-index.json 일괄 압축 — 기존 full-precision 임베딩 벡터를 소수 4자리로 양자화.
|
||||
*
|
||||
* 양자화 저장(quantizeVector)이 들어가기 *전에* 백필된 벡터를 줄이는 1회성 도구.
|
||||
* 이후 신규 벡터는 저장 시점에 양자화되므로 다시 돌릴 일은 드물다.
|
||||
*
|
||||
* node --max-old-space-size=8192 scripts/compact_brain_index.mjs "E:/Wiki/2nd/10_Wiki/Topics/.astra/brain-index.json"
|
||||
*/
|
||||
import fs from 'fs';
|
||||
|
||||
const file = process.argv[2];
|
||||
if (!file || !fs.existsSync(file)) {
|
||||
console.error('사용법: node compact_brain_index.mjs <brain-index.json 경로>');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const before = fs.statSync(file).size;
|
||||
console.log(`읽는 중… (${(before / 1e6).toFixed(0)} MB)`);
|
||||
const idx = JSON.parse(fs.readFileSync(file, 'utf8'));
|
||||
|
||||
const q = (v) => Math.round(v * 10000) / 10000;
|
||||
let files = 0, chunks = 0;
|
||||
for (const entry of Object.values(idx.entries || {})) {
|
||||
if (Array.isArray(entry?.embedding)) {
|
||||
entry.embedding = entry.embedding.map(q);
|
||||
files++;
|
||||
}
|
||||
for (const ch of entry?.chunks || []) {
|
||||
if (Array.isArray(ch?.embedding)) {
|
||||
ch.embedding = ch.embedding.map(q);
|
||||
chunks++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const tmp = file + '.compact-tmp';
|
||||
fs.writeFileSync(tmp, JSON.stringify(idx));
|
||||
fs.renameSync(tmp, file);
|
||||
const after = fs.statSync(file).size;
|
||||
console.log(`완료: 파일벡터 ${files} · 청크벡터 ${chunks} · ${(before / 1e6).toFixed(0)} MB → ${(after / 1e6).toFixed(0)} MB`);
|
||||
Reference in New Issue
Block a user