Manticore Search自6.3.0版本以来支持向量搜索!让我们深入了解它——它是什么,它带来了什么好处,以及如何通过将其集成到 GitHub问题搜索演示 的示例中来使用它。
全文搜索与向量搜索
全文搜索 很有用,因为它通过查找关键字的精确匹配来实现高效搜索。然而,它主要依赖于关键字,这有时会造成限制。相比之下,语义搜索使用向量相似性和机器学习来理解您搜索背后的含义,并找到与您所寻找的内容相似的文档。这种方法通常会带来更好的结果,并允许以更自然和放松的方式进行搜索。
我们很高兴在Manticore Search中引入这一强大功能,作为 Columnar库 的一部分实现。让我们探索如何开始使用它。
开始使用向量搜索和Manticore
向量搜索的简要介绍:要执行向量搜索,文本必须转换为向量,通常是浮点数的有序列表。您对查询也做同样的处理。然后,将您的查询向量与文档的向量进行比较,并按接近度对它们进行排序。阅读我们关于 旧版和现代数据库中的向量搜索 的其他文章。
我们将很快讨论如何将文本转换为向量,但首先,让我们探索如何在Manticore Search中处理向量。
安装
自6.3.0版本以来,Manticore中已提供向量搜索功能。确保Manticore与 Columnar库 一起安装。如果您需要安装帮助,请查看 文档 。
创建表
首先,我们需要创建一个实时表,该表将包含我们的模式声明。这包括一个用于存储向量的字段,使我们能够使用指定的语法查询它们。让我们创建一个简单的表。该表应具有配置选项的float_vector类型字段。
create table test ( title text, image_vector float_vector knn_type='hnsw' knn_dims='4' hnsw_similarity='l2' );
您可以在 这里 阅读详细文档。
插入数据
一旦表设置完成,我们需要用一些数据填充它,然后才能从中检索任何信息。
insert into test values ( 1, 'yellow bag', (0.653448,0.192478,0.017971,0.339821) ), ( 2, 'white bag', (-0.148894,0.748278,0.091892,-0.095406) );
Manticore Search支持SQL,使其对熟悉SQL数据库的用户友好。然而,如果您更喜欢使用普通的HTTP请求,也可以!以下是如何使用HTTP执行之前的SQL操作:
POST /insert
{
"index":"test_vec",
"id":1,
"doc": { "title" : "yellow bag", "image_vector" : [0.653448,0.192478,0.017971,0.339821] }
}
POST /insert
{
"index":"test_vec",
"id":2,
"doc": { "title" : "white bag", "image_vector" : [-0.148894,0.748278,0.091892,-0.095406] }
}
查询数据
最后一步是使用我们预先计算的请求向量查询结果,类似于使用AI模型准备的文档向量。我们将在文章的下一部分中更详细地解释这个过程。现在,这里是如何使用我们准备好的向量从表中查询数据的示例:
mysql> select id, knn_dist() from test where knn ( image_vector, 5, (0.286569,-0.031816,0.066684,0.032926), 2000 );
您将得到这个:
+------+------------+
| id | knn_dist() |
+------+------------+
| 1 | 0.28146550 |
| 2 | 0.81527930 |
+------+------------+
2 rows in set (0.00 sec)
也就是说,2个文档按其向量与查询向量的接近度排序。
Manticore向量搜索在支持的客户端中
Manticore Search为各种语言提供客户端,所有客户端都支持使用向量搜索进行数据查询。例如,以下是如何使用 PHP客户端 执行此操作:
<?php
use Manticoresearch\Client;
use Manticoresearch\Search;
use Manticoresearch\Query\KnnQuery;
// Create the Client first
$params = [
'host' => '127.0.0.1',
'port' => 9308,
];
$client = new Client($params);
// Create Search object and set index to query
$search = new Search($client);
$search->setIndex('test');
// Query now
$results = $search->knn('image_vector', [0.286569,-0.031816,0.066684,0.032926], 5);
简单吧?如果您想了解更多选项,可以查看 PHP客户端文档 。
如何将文本转换为向量?
现在让我们讨论如何从文本获取向量。
“嵌入”是表示文本并捕捉其语义含义的向量。目前,Manticore Search不会自动创建嵌入。然而,我们正在努力添加此功能,并在GitHub上有一个开放的 票据 。在此功能可用之前,您需要在外部准备嵌入。因此,我们需要一种将文本转换为浮点数列表的方法,以便存储并稍后使用向量搜索进行查询。
您可以使用各种解决方案将文本转换为嵌入。我们推荐使用 Hugging Face的句子变换器 ,其中包括 预训练模型 ,可以将文本转换为高维向量。这些模型有效地捕捉文本之间的语义相似性。
使用句子变换器将文本转换为向量的过程包括以下步骤:
- 加载预训练模型:首先从Hugging Face库加载所需的句子变换器模型。这些模型在大量文本数据上进行训练,能够有效理解单词和句子之间的语义关系。
- 对文本进行分词和编码:使用模型将文本分解为标记(单词或子词),并将这些标记转换为数值表示。
- 计算向量表示:模型计算文本的向量表示。这些向量通常是高维的(例如,768维),并在数值上表示文本的语义含义。
- 将向量存储在数据库中:一旦您拥有向量表示,将它们与相应的文本一起存储在Manticore中。
- 查询:要查找与查询相似的文本,请使用相同的模型将查询文本转换为向量。使用Manticore向量搜索在数据库中找到最近的向量(及其相关文本)。
GitHub演示中的语义搜索
在之前的 文章 中,我们构建了一个演示,展示了 Manticore Search 在实际应用中的使用: GitHub 问题搜索 。它运行良好,并且已经提供了比 GitHub 原生搜索更好的效果。随着 Manticore Search 的最新更新,包括向量搜索,我们认为将语义搜索功能添加到我们的演示中会很有趣。让我们探索一下它是如何实现的。
尽管大多数生成嵌入的库都是用 Python 编写的,但我们在演示中使用的是 PHP。为了将向量搜索集成到我们的演示应用程序中,我们有两个选择:
- 一个 API 服务器(可以使用 Python,但可能会更慢)
- 一个 PHP 扩展,我们选择实现这个。
在快速直接创建文本嵌入的方法时,我们发现了一些有用的工具,使我们能够实现我们的目标。因此,我们创建了一个 易于使用的 PHP 扩展 ,可以生成文本嵌入。这个扩展允许您从 HuggingFace 的 Sentence Transformers 中选择任何模型。它是基于 CandleML 框架构建的,该框架是用 Rust 编写的,并且是著名的 HuggingFace 生态系统的一部分。PHP 扩展本身也是使用 php-ext-rs 库用 Rust 编写的。这种方法确保了扩展运行快速,同时仍然易于开发。
连接所有不同部分是具有挑战性的,但结果是,我们有了 这个扩展 ,可以轻松地在 PHP 代码中将文本直接转换为向量,从而显著简化了过程。
<?php
use Manticore\\Ext\\Model;
// One from <https://huggingface.co/sentence-transformers>
$model = Model::create("sentence-transformers/all-MiniLM-L12-v2");
var_dump($model->predict("Hello world"));
最大的优势是该模型在生成嵌入方面非常快速,并且只需要加载一次。所有后续调用仅在几毫秒内执行,为 PHP 提供了良好的性能,并为演示项目提供了足够的速度。因此,我们决定继续采用这种方法。您可以在 GitHub 上查看和使用我们的扩展 。
具有挑战性的部分已经完成;接下来,我们需要将其集成到 演示项目 中,尽量减少代码更改。
集成到现有代码中
为了集成 向量搜索 功能,我们在头部添加了一个小开关,允许用户更改搜索模式。默认情况下,我们使用 关键词搜索(也称为“全文搜索”)。它看起来像这样:

后端的更改并不困难。我们添加了对上述文本到向量转换扩展的调用。这就是 代码块 的样子:
// Add vector search embeddings if we have a query
if ($search_query) {
if ($search !== 'keyword-search') {
$embeddings = result(TextEmbeddings::get($query));
$filters['embeddings'] = $embeddings;
}
if ($search === 'vector-search') {
$filters['vector_search_only'] = true;
}
}
混合搜索,结合了语义搜索和关键词搜索,可以通过多种方式实现。在这种情况下,我们只是向向量搜索结果添加了一个全文过滤器。您可以在 这里 查看更新的代码。它的样子如下:
protected static function getSearch(string $table, string $query, array $filters): Search {
$client = static::client();
$Index = $client->index($table);
$vector_search_only = $filters['vector_search_only'] ?? false;
$query = $vector_search_only ? '' : $query;
$Query = new BoolQuery();
if (isset($filters['embeddings'])) {
$Query = new KnnQuery('embeddings', $filters['embeddings'], 1000);
}
if ($query) {
$QueryString = new QueryString($query);
$Query->must($QueryString);
}
return $Index->search($Query);
}
正如我们所看到的,将语义搜索集成到演示中是直接的。接下来,让我们看看我们在 向量搜索 中取得了什么。
比较我们在演示中获得的语义搜索结果
让我们看看并比较一些使用默认 关键词搜索与语义搜索 的简单结果,在我们的 演示页面 中。
例如,进行 关键词搜索 "improve performance" 可能会得到这样的结果:

看起来合理且公平。但它只是在寻找原始短语的精确匹配。让我们看看并将其与 语义搜索 进行比较:

看起来有些灵活,尽管不完美。然而,我们也可以问一个问题,比如 How to improve performance of Manticore Search? 并获得额外的相关结果。

在这里,您可以看到,得益于 向量搜索 和其背后的机器学习模型,系统能够准确理解我们在寻找什么,并提供相关结果。然而,如果您尝试在关键词模式下进行相同的搜索,您将不会得到任何结果。
结论
我们对 Manticore 的新功能感到兴奋!现在,借助向量搜索和一些外部工具的帮助,设置语义搜索变得简单。语义搜索是一种更好地理解查询的智能方式。它不仅仅是寻找确切的单词,而是理解人们提问背后的含义。这意味着它可以找到更相关的答案,特别是对于复杂或详细的问题。
通过使搜索更像自然对话,语义搜索缩小了我们谈话方式与数据组织方式之间的差距。它提供了精确且有用的结果,完全符合某人的需求,使得使用 Manticore 进行搜索变得更好。
我们现在正在努力将自动嵌入功能引入 Manticore。这将允许自动将文本转换为向量,使一切变得更简单、更快速。请关注我们在 GitHub 上的进展 。随着这些改进,使用 Manticore 的搜索变得越来越好!
