混合检索先用 RRF 融合

**向量召回与词法召回的原始分数不可比,首版应该用 RRF(Reciprocal Rank Fusion)按「排名」融合,而不是校准分数。中文语料不要用 `to_tsvector('simple')` 做词法召回——它没有中文分词,改用 `pg_trgm`。重排器(cross-encoder)留成可选端口,不要第一版就上。**

一、推荐的首版链路

当前内容
├─ embedding → pgvector Top 50
└─ 标题/摘要/标签/正文前段 → pg_trgm Top 50
                          ↓
                  RRF 融合 → 最终 Top 5
                          ↓
                    关系落库

二、为什么是 RRF

score = 1/(k + vectorRank) + 1/(k + lexicalRank)

  • 不比较两路不可比的原始分数,因此不需要校准 cosine 与文本相似度的区间。
  • 确定性强,方便测试和复现。
  • 只在单路出现的内容也能参与,只是排名更低。
  • 无额外模型调用和成本,适合异步 workflow。

三、两个具体坑

  1. 中文分词:to_tsvector('simple') 对连续中文不是可靠的关键词基线(等于整句一刀)。改用 pg_trgm(Neon PG15 已支持);Neon 的 pg_search 已弃用,不要新接。
  2. trigram 的输入长度:词法侧只索引有限长度的字段(标题 + 摘要 + 标签 + 正文前段),不要拿两篇完整长文直接做 trigram 比较。

四、什么时候才加重排

RRF 之后可选接 cross-encoder reranker:它同时读「当前内容 + 候选内容」,比向量距离更能区分主题相同但观点无关 / 用词相似但语义不同。代价是每个 Run 多一次模型或 rerank API 调用。做法是先 RRF 到 Top 20,再重排取 Top 5。

五、不要第一版就引框架

已有 AiRun、版本控制、Workflow Port、关系落库时,LangChain / LlamaIndex / 额外检索服务只会再包一层。 → 参见 Agent编排层薄自建优先于重型框架

相关