Files
connectai/scripts/compact_brain_index.mjs
T
koriweb 67927b1d4e 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>
2026-06-11 19:02:56 +09:00

41 lines
1.5 KiB
JavaScript

/**
* 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`);