自6.3.0版本起,Manticore Search支持向量搜索!让我们深入了解它——它是什么,它带来了哪些优势,以及如何通过将其集成到 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' );
您可以在此处阅读详细文档 here 。
插入数据
一旦表设置完成,我们需要在从中检索信息之前用一些数据填充它。
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的sentence transformers ,其中包括 预训练模型 ,这些模型可以将文本转换为高维向量。这些模型有效地捕获文本之间的语义相似性。
使用sentence transformers将文本转换为向量的过程包括以下步骤:
- 加载预训练模型:首先从Hugging Face仓库加载所需的sentence transformer模型。这些模型在大量文本数据上进行训练,可以有效地掌握单词和句子之间的语义关系。
- 分词和编码文本:使用模型将文本拆分为标记(单词或子词),并将这些标记转换为数值表示。
- 计算向量表示:模型计算文本的向量表示。这些向量通常是高维的(例如,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 进行搜索正在变得越来越好!
