feat(retrieval): 实现 Embedding/Vector/RRF/Reranker 混合检索引擎
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
"""Reranker 统一接口与轻量实现。
|
||||
|
||||
真实默认是 BGE reranker 类 Cross-Encoder,第一阶段先用词面重叠 + 原始分数加权的
|
||||
确定性精排跑通链路;后续替换实现即可。
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Protocol, runtime_checkable
|
||||
|
||||
from app.textutils import tokens
|
||||
|
||||
|
||||
@dataclass
|
||||
class RankedCandidate:
|
||||
block_id: str
|
||||
score: float
|
||||
text: str = "" # 块正文,供轻量精排计算词面重叠
|
||||
|
||||
|
||||
@runtime_checkable
|
||||
class RerankerProvider(Protocol):
|
||||
"""统一 Reranker 接口:输入候选块,输出按相关性重排后的候选块。"""
|
||||
|
||||
model_id: str
|
||||
|
||||
async def rerank(self, query: str, candidates: list[RankedCandidate]) -> list[RankedCandidate]: ...
|
||||
|
||||
|
||||
class LexicalReranker:
|
||||
"""轻量精排:query 与块正文的词面重叠度,与归一化后的原始分数加权求和。"""
|
||||
|
||||
model_id = "lexical-v1"
|
||||
|
||||
def __init__(self, lexical_weight: float = 0.5) -> None:
|
||||
self.lexical_weight = lexical_weight
|
||||
|
||||
async def rerank(self, query: str, candidates: list[RankedCandidate]) -> list[RankedCandidate]:
|
||||
if not candidates:
|
||||
return []
|
||||
|
||||
# 把原始分数(RRF 等)归一化到 [0,1],便于与重叠度同量纲加权
|
||||
scores = [c.score for c in candidates]
|
||||
lo, hi = min(scores), max(scores)
|
||||
span = (hi - lo) or 1.0
|
||||
|
||||
query_tokens = set(tokens(query))
|
||||
ranked: list[RankedCandidate] = []
|
||||
for c in candidates:
|
||||
norm = (c.score - lo) / span
|
||||
if query_tokens:
|
||||
overlap = len(query_tokens & set(tokens(c.text))) / len(query_tokens)
|
||||
else:
|
||||
overlap = 0.0
|
||||
final = self.lexical_weight * overlap + (1 - self.lexical_weight) * norm
|
||||
ranked.append(RankedCandidate(block_id=c.block_id, score=final, text=c.text))
|
||||
|
||||
ranked.sort(key=lambda c: c.score, reverse=True)
|
||||
return ranked
|
||||
Reference in New Issue
Block a user