C.W.K.
Stream
Lesson 01 of 05 · published

BM25 안 죽었어 — 벡터와 페어링

~22 min · hybrid, bm25, keyword

Level 0Scout
0 XP0/41 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

순수 벡터 검색이 일부 query 를 지는 이유

임베딩은 의미에는 강한데 토큰 에는 평범. 'ERR_CONNECTION_REFUSED' 라는 정확한 에러 코드 들어있는 청크를 그 개념을 paraphrase 한 청크보다 reliably 위에 ranking 못 함. 제품 이름, SKU, 버전 번호, 희귀 기술 용어는 표면 형태에 살아 — BM25 (1994년 vintage probabilistic 키워드 scorer) 가 빌드된 자리.

BM25 가 실제로 하는 것

각 query term 마다 BM25 가 문서를 term frequency (occurrence 많을수록 높음), inverse document frequency (희귀 term 이 더 카운트), length normalization 으로 score. 결과는 정확 매칭 사랑 + verbosity 처벌 + 의미 무시하는 ranking. 벡터 검색의 정반대 failure mode.

가장 싼 하이브리드

  1. 벡터 검색 → top-N candidate.
  2. BM25 → top-N candidate.
  3. id 머지, union 추출, fusion score 또는 cross-encoder 로 re-rank.

두 retriever, 한 머지 step. 그것만으로 vector-only retrieval 을 factoid query 에서 10–20% 자주 이김.

Code

rank-bm25 로 BM25 (순수 Python)·python
from rank_bm25 import BM25Okapi

corpus = [doc.lower().split() for doc in documents]
bm25 = BM25Okapi(corpus)

def bm25_search(query: str, k: int = 10):
    scores = bm25.get_scores(query.lower().split())
    top = scores.argsort()[::-1][:k]
    return [(int(i), float(scores[i])) for i in top]
Postgres 의 하이브리드 (pgvector + tsvector)·sql
-- full-text 컬럼 한 번 추가
ALTER TABLE chunks ADD COLUMN tsv tsvector
    GENERATED ALWAYS AS (to_tsvector('english', text)) STORED;
CREATE INDEX chunks_tsv_idx ON chunks USING gin(tsv);

-- 하이브리드 query: 두 ranking union 후 re-rank
WITH vec AS (
    SELECT id, 1 - (embedding <=> $1) AS vscore
    FROM   chunks
    ORDER BY embedding <=> $1
    LIMIT 50
),
bm AS (
    SELECT id, ts_rank_cd(tsv, plainto_tsquery('english', $2)) AS bscore
    FROM   chunks
    WHERE  tsv @@ plainto_tsquery('english', $2)
    ORDER BY bscore DESC
    LIMIT 50
)
SELECT  c.id,
        COALESCE(vec.vscore, 0) AS vscore,
        COALESCE(bm.bscore,  0) AS bscore,
        c.text
FROM    chunks c
LEFT JOIN vec ON vec.id = c.id
LEFT JOIN bm  ON bm.id  = c.id
WHERE   vec.id IS NOT NULL OR bm.id IS NOT NULL;

External links

Exercise

같은 1000개 문서로 vector-only retriever + BM25 retriever 빌드. query 20개 실행. 각 query 마다 둘의 top-5 + union 노트. relevance 수동 마킹. vector-only vs union 의 hit rate 비교 — 그 delta 가 본인 하이브리드 budget.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.