我用 JavaScript 构建了一个 Offline-First 语义搜索引擎
发布: (2025年12月29日 GMT+8 14:57)
4 min read
原文: Dev.to
Source: Dev.to
介绍
搜索看似简单,实则困难。大多数 JavaScript 搜索库只停留在关键词或模糊匹配,而大多数语义搜索方案又假设需要外部 API、向量数据库或托管服务。我想要一些不同的东西:
- 完全本地运行
- 能在 Node.js 或浏览器中使用
- 理解语义,而不仅仅是文本
- 不需要额外搭建基础设施
于是我构建了 Simile Search —— 一个离线优先的语义 + 模糊搜索引擎,使用 JavaScript 实现。
核心技术
Simile 结合了多种技术,而不是依赖单一的评分方法:
- 基于 Transformer 的嵌入(通过
transformers.js)来捕获语义,这样即使没有关键词重叠,像 “phone charger” → “USB‑C cable” 这样的查询也能匹配。 - HNSW(层次化可导航小世界)索引 用于近似最近邻搜索,提供亚线性搜索时间,随着目录规模增长仍能保持可预测的性能,并实现交互式搜索的实用延迟。
- 向量量化 在降低内存占用的同时保持高相似度质量,这在 Node.js 环境下运行、嵌入大规模目录或全部放在内存中时尤为重要。
性能优化
嵌入是语义搜索中最慢的环节。Simile 通过以下方式避免重复工作:
- 为已处理过的文本缓存向量。
- 支持完整快照的保存/加载,能够瞬间恢复而无需重新嵌入。
评分融合
单纯的语义相似度并不足够。Simile 将以下因素融合在一起:
- 模糊匹配(拼写错误、部分输入)
- 精确关键词提升(提高精度)
- 归一化评分,防止某一种方法占据主导
权重可以根据你的业务领域进行调节。
结构化数据支持
不需要手动将数据扁平化,Simile 可以直接在嵌套路径上搜索,例如:
metadata.author.firstNamemetadata.tagsitems[0].name
这使得它在实际的产品目录和结构化数据场景中非常实用。
理想使用场景
Simile 最适合以下场景:
- 产品与库存目录
- 内部工具和仪表盘
- 知识库
- 自动完成 / 输入提示搜索
- 注重隐私或需要离线能力的应用
- 不想额外引入搜索基础设施的 NestJS 后端
它并不是要取代 MeiliSearch、Elastic 或大型向量数据库——而是面向那些数据规模中小、语义重要且基础设施需要保持简洁的场景。
Simile 存在的原因
我经常看到以下项目:
- 完整的搜索引擎显得大材小用。
- 为了存放索引而额外建了一个数据库。
- 模糊搜索不足以满足需求。
- 语义搜索需要的配置过于繁琐。
Simile 正是为填补这一空白而诞生的。
安装与源码
- npm:
- GitHub: