# xz-rerank
检索结果重排序引擎,支持本地多信号融合排序与远程 Rerank API 适配。
## 概述
RAG 系统中,检索阶段返回的候选项通常只按向量相似度或 BM25 分数排序,单一信号容易漏掉语义相关但表达不同的内容。xz-rerank 通过**多信号融合**对候选结果重新打分排序,显著提升 Top-K 命中率。
## 特性
- **5 种内置打分信号**: 关键词重叠 (Jaccard)、向量相似度、元数据匹配、内容质量启发式、时间近因性
- **可自定义信号**: 实现 `SignalPlugin` trait 即可接入自己的打分逻辑
- **多阶段重排序**: 粗排(本地快速过滤)→ 精排(远程 API 精确打分)流水线
- **远程 Rerank API**: 开箱支持 Cohere (`rerank-english-v3.0`) 和 Jina (`jina-reranker-v2-base-multilingual`)
- **结果缓存**: LRU 内存缓存,避免重复计算
- **分数分解**: 支持逐信号查看打分明细,方便调优
- **通道感知**: 可按检索通道(语义搜索、关键词搜索等)配置不同的近因性衰减策略
- **权重归一化**: 自动校验权重和为 1.0,支持归一化
## 快速开始
```toml
# Cargo.toml
[dependencies]
xz-rerank = { version = "0.1", features = ["cohere", "jina"] }
```
## 使用示例
### 本地信号重排序
`LocalSignalReranker` 是核心本地引擎,默认集成 5 种信号,开箱即用:
```rust
use std::collections::HashMap;
use xz_rerank::*;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let reranker = LocalSignalReranker::default();
let candidates = vec![
RerankCandidate {
id: "doc1".into(),
content: "Rust is a systems programming language with zero-cost abstractions.".into(),
metadata: HashMap::from([("source".into(), "docs".into())]),
retrieval_score: Some(0.85),
channel: Some("semantic".into()),
created_at: Some(now_ms() - 3_600_000),
embedding: None,
},
// ... 更多候选项
];
let result = reranker
.rerank("systems programming language", candidates, &RerankConfig {
top_k: 5,
include_score_breakdown: true,
..Default::default()
})
.await?;
println!("Result ({}ms):", result.latency_ms);
for hit in &result.hits {
println!(" [{:.4}] {}", hit.score, hit.candidate.content);
if let Some(bd) = &hit.score_breakdown {
for s in &bd.signals {
println!(" {}: raw={:.4} weight={:.2} contrib={:.4}", s.name, s.raw_score, s.weight, s.contribution);
}
}
}
Ok(())
}
```
### 多阶段重排序
先用本地信号从大量候选中快速粗排,再将 Top-N 送入远程 API 精排:
```rust
use xz_rerank::*;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// 粗排: 本地信号快速过滤 (500 -> 50)
let coarse = LocalSignalReranker::default();
// 精排: Cohere Rerank API
let fine = CohereReranker::new("your-cohere-key")?;
// 两阶段流水线: 粗排保留 top 50 后交给精排
let multi_stage = MultiStageReranker::new(coarse, fine, 50);
let result = multi_stage
.rerank("Rust programming", candidates, &RerankConfig::default())
.await?;
println!("Multi-stage result ({}ms):", result.latency_ms);
Ok(())
}
```
### 远程 Rerank API
启用对应 feature 后,可直接使用 `CohereReranker` 或 `JinaReranker`:
```rust
// Cohere (feature = "cohere")
let reranker = CohereReranker::new("cohere-api-key")?
.with_model("rerank-multilingual-v3.0");
// Jina (feature = "jina")
let reranker = JinaReranker::new("jina-api-key")?
.with_model("jina-reranker-v2-base-multilingual");
```
## 信号系统
| KeywordOverlapSignal | `keyword_overlap` | 0.30 | 查询-文档 Jaccard 关键词重叠度 |
| VectorSimilaritySignal | `vector_similarity` | 0.25 | 余弦相似度(需要 `embedding` 字段) |
| MetadataMatchSignal | `metadata_match` | 0.20 | 元数据键值对匹配度 |
| ContentQualitySignal | `content_quality` | 0.10 | 内容长度、标点等启发式质量分 |
| RecencySignal | `recency` | 0.15 | 时间近因性(线性/指数/无衰减) |
权重可通过 `SignalWeights` 自定义,支持归一化。通过 `LocalSignalReranker::with_signal()` 可以注入自定义 `SignalPlugin`。
## 结果缓存
```rust
use xz_rerank::*;
use std::time::Duration;
let cache = MemoryRerankCache::new(1000); // 最多缓存 1000 条
cache.set("query", &["doc1","doc2"], &result, Duration::from_secs(300)).await;
let cached = cache.get("query", &["doc1","doc2"]).await;
```
## Feature Flags
| (default) | 本地信号重排序 + Mock |
| `cohere` | Cohere Rerank API 适配 |
| `jina` | Jina Reranker API 适配 |
## 许可证
MIT OR Apache-2.0