混合检索先用 RRF 融合
一、推荐的首版链路
当前内容
├─ embedding → pgvector Top 50
└─ 标题/摘要/标签/正文前段 → pg_trgm Top 50
↓
RRF 融合 → 最终 Top 5
↓
关系落库
二、为什么是 RRF
score = 1/(k + vectorRank) + 1/(k + lexicalRank)
- 不比较两路不可比的原始分数,因此不需要校准 cosine 与文本相似度的区间。
- 确定性强,方便测试和复现。
- 只在单路出现的内容也能参与,只是排名更低。
- 无额外模型调用和成本,适合异步 workflow。
三、两个具体坑
- 中文分词:
to_tsvector('simple')对连续中文不是可靠的关键词基线(等于整句一刀)。改用pg_trgm(Neon PG15 已支持);Neon 的pg_search已弃用,不要新接。 - trigram 的输入长度:词法侧只索引有限长度的字段(标题 + 摘要 + 标签 + 正文前段),不要拿两篇完整长文直接做 trigram 比较。
四、什么时候才加重排
RRF 之后可选接 cross-encoder reranker:它同时读「当前内容 + 候选内容」,比向量距离更能区分主题相同但观点无关 / 用词相似但语义不同。代价是每个 Run 多一次模型或 rerank API 调用。做法是先 RRF 到 Top 20,再重排取 Top 5。
五、不要第一版就引框架
已有 AiRun、版本控制、Workflow Port、关系落库时,LangChain / LlamaIndex / 额外检索服务只会再包一层。
→ 参见 Agent编排层薄自建优先于重型框架
相关
- 检索要按难度迭代
- 关键词检索的三个打分缺陷
- RAG是流程不是组件
- 检索是一条分层链 —— 本条是该链的融合/排序层