Sift:本地混合搜索,无需基础设施税

发布: (2026年3月10日 GMT+8 12:33)
7 分钟阅读
原文: Dev.to

Source: Dev.to

请提供您希望翻译的完整文本内容(除代码块和 URL 之外),我将把它翻译成简体中文并保持原有的 Markdown 格式。

概述

sift 是一个本地 Rust CLI,用于文档检索。指向一个目录,提出一个问题,它会运行完整的混合搜索管道——BM25、稠密向量、融合、可选的重新排序——并返回排序后的结果。无需守护进程、后台索引器,也不依赖云服务。一个二进制文件。

它为需要在原始代码库、文档和混合格式语料库上进行可靠、可重复搜索的代理和开发者而构建,无需启动基础设施。

您可以立即在 macOS、Windows 和 Linux 上安装它

检索管道

每个查询都会经历四个阶段:

  • 扩展 – 生成查询变体,以在检索开始前扩大召回范围。
  • 检索 – 对语料库执行 BM25(关键词)、短语匹配和稠密向量检索。每种方法捕获不同的信号。
  • 融合 – 使用 Reciprocal Rank Fusion (RRF) 合并结果,在检索方法之间平衡信号,无需手动权重调优。
  • 重新排序 – 可选的本地 LLM(通过 Qwen)对融合后的候选集合进行语义消歧重新排序。

每个阶段都可以独立调优。如果只需要 BM25 的速度,可跳过向量检索阶段。想要最佳精度则运行完整流程。

Architecture

实现分为 domainadapters 两大部分:

  • Domain objects 用于建模搜索计划、候选项和评分输出。
  • Adapters 实现具体的 BM25、短语、向量和重排序后端。

共享的搜索服务在 CLI、基准测试和评估流程中执行相同的策略模型——在开发运行和 CI 评估之间没有任何变化。

Performance highlights

  • SIMD‑accelerated dot‑product 用于 CPU 密集型工作负载下的向量评分。
  • Zig‑inspired incremental cache ——一种借鉴自 Zig 构建系统的两层设计。manifest 存储跟踪文件系统元数据(inode、mtime、size),并映射到 BLAKE3 内容哈希,从而 sift 能准确知道哪些文件已更改而无需重新读取。内容可寻址的 blob 存储保存预提取的文本、预计算的 BM25 词频以及预嵌入的稠密向量——这意味着重复查询根本不触及神经网络。不同项目中相同的文件共享同一个 blob 条目。
  • Per‑query embedding reuse 跨多阶段管道的嵌入复用。
  • Mapped I/O and tight tokenization hot loops 以在大语料库上保持低延迟。

开发过程中的一个具体权衡:将嵌入的 max_length 从 48 降至 40,既恢复了延迟预算,又保持了质量高于 BM25 基线——这是证据驱动调优胜过盲目猜测的典型例子。

完整内部实现请参阅 ARCHITECTURE.md

评估

Comparative strategy run over 5,185 SciFact documents (~7.8 MB) on an AMD Ryzen Threadripper 3960X:

StrategynDCG@10MRR@10Recall@10p50 (ms)
bm250.72620.70000.80005.41
legacy‑hybrid0.78930.72501.000050.29
page‑index0.70000.66670.800016.79
page‑index‑hybrid0.57010.43671.000041.09
page‑index‑llm0.78930.72501.000041.28
page‑index‑qwen0.78930.72501.000041.18
vector0.82620.76671.000025.94

关键要点

  • BM25 在 5.41 ms p50 时是延迟受限情况下的合适默认选项,适用于关键词召回已足够的场景。
  • Vector 在 25.94 ms 时实现了最佳 nDCG@10(0.8262)和完美召回——是大多数工作负载最平衡的策略。
  • LLM 重排序(page‑index‑llm、page‑index‑qwen)在相近速度下匹配 legacy‑hybrid 的质量,验证了本地 Qwen 路径是比更重的混合流水线更实用的替代方案。
  • page‑index‑hybrid 是唯一在 nDCG 上表现不如 BM25 的策略,提醒我们增加复杂性并不总能提升质量。

缓存命中率 (100/0/100 %) 证实缓存层在所有策略中均正常工作。详细输出 (-v, -vv) 在 CLI 中直接显示缓存命中率、阶段时间以及排序元数据。

为什么这对代理很重要

对于代理而言,延迟和可靠性是必需的,而不是可有可无的特性。当搜索速度慢、上下文丢失或依赖的服务可能不可用时,工具循环会严重失效。

sift 消除了这些摩擦:检索是本地的、确定性的,并且重复成本低。无需守护进程进行健康检查。无需嵌入服务来限制速率。也不需要管理云端依赖。该二进制文件通过 Homebrew 和静态 Linux 构件提供,因而代理可以依赖固定版本而不受环境漂移的影响。

构建方式

项目在一次专注且几乎不间断的 24 小时冲刺中完成——实现、评估设计、基准测试、性能优化、打包以及发布准备全部在同一持续流程中进行。每个主要单元在标记为完成之前,都附有验收标准和可衡量的证据。

促成这种速度的因素尚未准备好详细讨论。但 sift 是第一个真正证明它在高速、真实约束下且不走捷径的案例。稍后会有更多信息。

开始使用

0 浏览
Back to Blog

相关文章

阅读更多 »