blog-post

在 Manticore 中进行向量搜索

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;

// 首先创建客户端
$params = [
	'host' => '127.0.0.1',
	'port' => 9308,
];
$client = new Client($params);

// 创建搜索对象并设置要查询的索引
$search = new Search($client);
$search->setIndex('test');

// 现在查询
$results = $search->knn('image_vector', [0.286569,-0.031816,0.066684,0.032926], 5);

简单吧?如果您想了解更多选项,可以查看 PHP 客户端文档

如何将文本转换为向量?

现在让我们讨论如何 从文本中获取向量

“嵌入”是一个表示文本并捕捉其语义意义的向量。目前,Manticore Search 不会自动创建嵌入。然而,我们正在努力添加此功能,并在 GitHub 上有一个开放 工单 。在此功能可用之前,您需要外部准备嵌入。因此,我们需要一种方法将文本转换为浮点数列表以进行存储,并稍后使用向量搜索进行查询。

您可以使用各种解决方案将文本转换为嵌入。我们建议使用 Hugging Face 的句子转换器 ,其中包括 预训练模型 ,可以将文本转换为高维向量。这些模型有效地捕捉文本之间的语义相似性。

使用句子转换器将文本转换为向量的过程包括以下步骤:

  1. 加载预训练模型:首先从 Hugging Face 仓库加载所需的句子转换器模型。这些模型在大量文本数据上进行训练,能够有效地理解单词和句子之间的语义关系。
  2. 分词和编码文本:使用模型将文本分解为标记(单词或子词),并将这些标记转换为数值表示。
  3. 计算向量表示:模型计算文本的向量表示。这些向量通常是高维的(例如,768 维),并在数值上表示文本的语义含义。
  4. 在数据库中存储向量:一旦您拥有了向量表示,就将它们与对应的文本一起存储在 Manticore 中。
  5. 查询:要查找与查询相似的文本,请使用相同的模型将查询文本转换为向量。使用 Manticore 向量搜索来定位数据库中最近的向量(及其相关文本)。

GitHub 演示中的语义搜索

在之前的 文章 中,我们构建了一个演示,展示了在真实世界示例中使用 Manticore Search 的方式: GitHub 问题搜索 。它运行良好,并且相比 GitHub 的原生搜索已经提供了好处。随着 Manticore Search 的最新更新,包括向量搜索,我们认为将语义搜索功能添加到我们的演示中是有趣的。让我们来探讨一下它是如何实现的。

尽管大多数生成嵌入的库都是用 Python 编写的,但我们在演示中使用的是 PHP。为了将向量搜索集成到我们的演示应用程序中,我们有两个选项:

  • 一个 API 服务器(可以使用 Python,但可能会较慢)
  • 我们选择实现的 PHP 扩展。

在快速和直接创建文本嵌入的方法时,我们发现了一些有用的工具,使我们能够实现目标。因此,我们创建了一个 易于使用的 PHP 扩展 ,可以生成文本嵌入。该扩展允许您从 HuggingFace 的句子转换器中选择任何模型。它基于 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 上查看和使用我们的扩展

挑战性部分已完成;接下来,我们需要将其集成到 演示项目 中,代码更改最小。

集成到现有代码中

为了集成 向量搜索 功能,我们在头部添加了一个小开关,允许用户更改搜索模式。默认情况下,我们使用 关键字搜索(也称为“全文搜索”)。它看起来像这样:

Search type selector

后端的更改并不困难。我们添加了对上述文本到向量转换扩展的调用。这就是 代码块 的样子:

// 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;
    }
}

混合搜索,结合了语义搜索和关键字搜索,可以以多种方式实现。在这种情况下,我们仅为向量搜索结果添加了一个全文过滤器。您可以在这里查看更新后的代码 here 。代码如下:

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);
}

As we can see, integrating semantic search into the demo was straightforward. Next, let’s see what we achieve with Vector Search.

让我们看看并比较一些使用默认的关键词搜索与语义搜索所产生的简单结果,出现在我们的 演示页面 上。

例如,进行关键词搜索 "improve performance" 可能会得到这样的结果:

Results for keyword search

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

Results for semantic search

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

Results for semantic search with question

在这里,你可以看到多亏了向量搜索和其背后的机器学习模型,系统能够准确理解我们在寻找什么并提供相关结果。然而,如果你尝试在关键词模式下进行相同的搜索,你将不会得到任何结果。

Conclusion

我们对Manticore的新功能感到兴奋!现在,借助向量搜索和一些外部工具的帮助,设置语义搜索变得简单。语义搜索是一种更智能的理解查询的方法。它不仅仅是寻找确切的单词,而是理解人们提问背后的意义。这意味着它可以找到更相关的答案,尤其是对于复杂或详细的问题。

通过使搜索更类似于自然对话,语义搜索缩小了我们说话的方式与数据组织方式之间的差距。它提供了精确和有用的结果,完全符合某人所寻找的内容,使得使用Manticore的搜索体验大大改善。

我们现在正在努力将自动嵌入功能引入Manticore。这将允许将文本自动转换为向量,从而简化和加快所有过程。请关注我们在 GitHub上的进展 。随着这些改进,使用Manticore进行搜索将变得更好!

安装Manticore Search

安装Manticore Search