Files
sundynix-agentix/sundynix-mcp-go/internal/rag/fuse.go
T
Blizzard 85a5c2c1e7 feat(rag): 混合检索融合 — Milvus 向量 + Bleve 全文 + RRF + DashScope rerank
检索从向量单路升级为混合:向量(Milvus) + 全文(Bleve BM25) → RRF 融合 →
可选 rerank(DashScope gte-rerank)。

- rag/bleve.go: Bleve 全文索引(内存,随 ingest 写入;kb 过滤);ingest 同步写 Milvus+Bleve
- rag/fuse.go: RRF(Reciprocal Rank Fusion, k=60, 按文本去重)融合多路排序
- rag/rerank.go: DashScope gte-rerank 客户端(可选,env 配置,失败降级 RRF)
- rag/rag.go: Search 改混合(向量+全文→RRF→可选rerank→topK);main 读 RERANK_* env
- 验证: 全模块 build✓ + e2e PASS; live——入库写双索引;查'NATS'→全文精确命中#1+向量
  →RRF NATS 排首(向量=4 全文=1);接 DashScope gte-rerank(百炼 key 有权限)→relevance
  score 0.19 真重排;retriever 节点端到端→DeepSeek 答 Milvus
- 边界: Neo4j 图路(GraphRAG,需实体抽取)推迟;Bleve 内存索引重启重建;rerank 走 env
  (TODO 同 embedding 搬控制面 kind=rerank)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 09:53:37 +08:00

27 lines
758 B
Go

package rag
import "sort"
// rrfK 是 RRF 的平滑常数(业界常用 60)。
const rrfK = 60.0
// rrf 用 Reciprocal Rank Fusion 融合多路检索的排序列表,按文本去重。
// 每路对一个文档的贡献 = 1/(k + 该路中的名次);累加后重排。
func rrf(lists [][]Hit, topK int) []Hit {
score := map[string]float64{}
for _, list := range lists {
for rank, h := range list {
score[h.Text] += 1.0 / (rrfK + float64(rank+1))
}
}
fused := make([]Hit, 0, len(score))
for text, s := range score {
fused = append(fused, Hit{Text: text, Score: float32(s)})
}
sort.Slice(fused, func(i, j int) bool { return fused[i].Score > fused[j].Score })
if topK > 0 && len(fused) > topK {
fused = fused[:topK]
}
return fused
}