# Indexfox 如何基于 Manticore 构建 AI 站内搜索小组件

Indexfox 是一个 AI 搜索小组件，任何网站只需加入一个 <script> 标签即可使用：自动抓取、关键词 + 语义混合结果，以及带来源链接的直接 AI 回答。在底层，每次查询都由 Manticore Search 提供服务：使用英语词形还原的全文 MATCH、基于 HNSW 并采用 8 位量化的 KNN 向量搜索、用于合并两者的 Reciprocal Rank Fusion，以及用于输入即时建议的 CALL AUTOCOMPLETE。本文将介绍 Indexfox 如何在 Manticore 之上构建多租户 AI 站内搜索产品、他们重点依赖了哪些功能，以及为什么开源搜索引擎最终成为了合适的基础。

### 初识 Indexfox

[Indexfox](https://indexfox.ai) 是一个托管式 AI 搜索小组件，任何网站只需一个 `<script>` 标签即可安装。它的卖点很简洁：把代码片段放进你的 `<head>`，几分钟内 Indexfox 就会抓取网站、索引每个页面，并提供一个搜索框，直接回答用户问题，同时给出来源链接和常规的排序结果列表。其落地页将它概括为“能查找、能回答、能促成转化的 AI 搜索”，并在 apple.com 上运行实时演示，让访客在注册前就能体验效果。

从搜索工程角度看，Indexfox 有趣之处在于终端用户*看不到*的部分。在友好的狐狸吉祥物和两分钟完成设置的叙事背后，是一套混合搜索栈：关键词匹配、向量检索、自动补全和答案生成，全部由单个 Manticore Search 实例提供服务。本文将介绍 Indexfox 如何在底层使用 Manticore，以及为什么开源搜索引擎最终成为多租户 SaaS 的合适基础。

### 站内搜索的问题

大多数网站的搜索体验仍像是事后补上的功能。Indexfox 落地页从一个熟悉的场景切入：相当一部分用户在一次搜索失败后就会离开网站，而在内容密集型或商品密集型网站上，这次流失的会话往往就意味着一次流失的转化。传统全文引擎会漏掉用自然语言表达的查询；纯语义搜索会漏掉精确术语和商品代码；同时运行两套引擎则意味着要维护两个索引的一致性，并承担两倍的运维面。

Indexfox 需要一个引擎，能够在同一次查询中运行全文搜索和向量搜索，不必为每个租户单独启动基础设施就能隔离不同客户的数据，并且在爬虫持续刷新客户内容时承受不断重建索引的压力，同时成本还要允许一个小团队支撑数百个网站。

### 为什么选择 Manticore Search

Indexfox 选择 Manticore Search 有三个具体原因。

首先，Manticore 是一个单一的开源引擎，同时把全文索引*和* KNN 向量索引作为一等能力提供。不需要部署第二个数据存储，不需要胶水代码来保持向量存储和关键词存储一致，客户规模增长时也没有许可方面的顾虑。同一种类 SQL 方言即可处理这两个领域。

其次，Manticore 让按租户隔离变得成本很低。Indexfox 将每个客户网站建模为自己的一组表：一个用于页面，一个用于内容片段，一个用于句子，并按需创建和删除。平台上新增一个网站，在存储层面只是一个 `CREATE TABLE` 语句；客户下线则是一个 `DROP TABLE`。

第三，Manticore 运维负担很轻。后端通过 HTTP/JSON API 使用官方 `manticoresearch-ts` 客户端与其通信。实时插入会立即生效，引擎像 Postgres 一样运行在单台虚拟机上，不需要 JVM、不需要集群，也不需要额外的编排平面来照看。

### 三层语义

Indexfox 将每个抓取到的网站索引到三层表中，全部标记为 `engine='columnar'`：

- **webpage** 表：每个 URL 一行，包含标题、描述、原始 HTML、语言，以及平均后的页面级嵌入。
- **segment** 表：每个逻辑内容块一行（一个标题及其下方段落）。这个表上的 Manticore 选项承担了大部分语言处理工作：`morphology='lemmatize_en'` 用于英语词干处理，`bigram_index='all'` 用于短语匹配，`min_infix_len=2` 用于部分词召回，以及一份精心整理的 `stopwords='en'` 列表。
- **sentence** 表：每个句子一行，既用于细粒度语义召回，也作为驱动自动补全的词典。

每张表都有一个 `float_vector` 字段，并配置了 `knn_type='hnsw'`、`hnsw_similarity='cosine'` 和 `quantization='8bit'`。向量维度按网站动态变化，因为每个客户都可以选择最适合其内容和预算的嵌入模型：OpenAI 的 1536 维 `text-embedding-3-small`、Voyage 的 1024 维 `voyage-3`、Jina 的 1024 维多语言模型，或面向成本敏感型部署的 384 维本地 sentence-transformer。Manticore 都能存储它们；变化的只是 schema。

### 一次查询实际如何运行

当用户在 Indexfox 小组件中输入时，后端会并行调用 Manticore 的三项功能。

关键词路径对 segment 和 sentence 表运行 `SELECT … MATCH('…')`，当分词后的查询足够长时启用邻近度和 quorum，并由 Manticore 的 `highlight()` 函数直接标注摘要。向量路径在相同表的 HNSW 图上运行 `SELECT … WHERE knn(embedding, k, (?), { oversampling=3.0, rescore=1 })`，并按用户语言过滤。两组结果使用 **Reciprocal Rank Fusion** 合并，即标准的 `1 / (60 + rank_keyword) + 1 / (60 + rank_vector)` 公式。两条路径都排得很靠前的命中会浮到最上方，而强关键词命中和强语义命中也都能获得各自应有的关注。每条结果都会标注它来自关键词、向量还是两者兼有，因此 UI 可以提示页面出现的*原因*。

对于输入即时建议框，小组件会在 sentence 表上调用 Manticore 的 `CALL AUTOCOMPLETE`，并使用 `force_bigrams=1` 和 `expansion_len=12`，在远低于一毫秒的时间内返回感知二元词组的建议。小组件显示在结果列表上方的 AI 回答由 LLM 生成，但它引用的带来源链接的段落，正是 Manticore 返回的最高排名命中；从实际产品角度看，检索质量就是产品本身。

客户看不到这些细节。他们这一侧的集成方式，就是 Indexfox 自发布以来一直展示在落地页上的那段代码片段：

```html
<script>
(function(d, w) {
    w.IndexfoxID = 'your-website-id';
    var s = d.createElement('script');
    s.async = true;
    s.src = 'https://widget.indexfox.ai/indexfox.js';
    if (d.head) d.head.appendChild(s);
})(document, window);
</script>
```

页面里一个标签，另一端一个 Manticore 集群。

### Manticore Search 也在使用 Indexfox

[manticoresearch.com](https://manticoresearch.com) 顶部的搜索框本身就是一个 Indexfox 小组件。在本站任意页面点击搜索输入框，或按下 <kbd>⌘</kbd>+<kbd>K</kbd>，你都会得到同样的关键词 + 语义混合结果、同样的输入即时二元词组建议，以及同样带来源链接的 AI 生成回答，内容来自 Manticore 自己的博客、文档和产品页面。集成方式正是上面的 `<script>` 代码片段，放入网站的布局模板即可。Manticore 在底层驱动 Indexfox；如今 Indexfox 也驱动着 Manticore 官网的搜索。

![manticoresearch.com 上的 Indexfox](./how-indexfox-built-an-ai-site-search-widget-on-manticore/manticore-indexfox.png)

### 关键结论

Indexfox 的判断是：合适的开源搜索引擎可以用一个二进制程序取代 Postgres 加 pgvector 加 Elasticsearch 的技术栈，让小团队把精力放在爬虫质量、嵌入模型选择和答案生成上，而不是基础设施运维上。如今，无论是在 [indexfox.ai](https://indexfox.ai) 的实时演示中，还是在每个已安装它的网站上，用户在 Indexfox 小组件中敲下的每一次按键，都由 Manticore 提供服务。
