K-近邻向量搜索

Manticore Search 支持将由机器学习模型生成的嵌入向量添加到每个文档中,然后对它们进行最近邻搜索。这使您能够构建诸如相似性搜索、推荐、语义搜索和基于自然语言处理算法的相关性排序等功能,还包括图像、视频和声音搜索。

什么是嵌入向量?

嵌入向量是一种表示数据(如文本、图像或声音)的方法,将其表示为高维空间中的向量。这些向量被设计成使它们之间的距离反映所代表数据的相似性。该过程通常采用诸如词嵌入(例如 Word2Vec、BERT)用于文本,或神经网络用于图像的算法。向量空间的高维特性,每个向量包含多个分量,允许表示项目之间复杂且细微的关系。它们的相似性通过这些向量之间的距离来衡量,通常使用欧几里得距离或余弦相似度等方法。

Manticore Search 使用 HNSW 库实现 k-近邻(KNN)向量搜索。此功能是 Manticore Columnar Library 的一部分。

配置用于 KNN 搜索的表

要运行 KNN 搜索,您必须先配置表。浮点向量和 KNN 搜索仅支持实时表(不支持普通表)。表需要至少有一个 float_vector 属性,作为数据向量。您需要指定以下属性:

  • knn_type:必填设置;目前仅支持 hnsw

  • knn_dims:必填设置,指定被索引向量的维度。

  • hnsw_similarity:必填设置,指定 HNSW 索引使用的距离函数。可接受的值有:

    • L2 - 平方 L2 距离
    • IP - 内积
    • COSINE - 余弦相似度

    注意: 使用 COSINE 相似度时,向量在插入时会自动归一化。这意味着存储的向量值可能与原始输入值不同,因为它们会被转换为单位向量(数学长度/模为 1.0 的向量),以实现高效的余弦相似度计算。此归一化保持向量的方向,同时标准化其长度。

  • hnsw_m:可选设置,定义图中最大出边连接数。默认值为 16。

  • hnsw_ef_construction:可选设置,定义构建时的时间/准确性权衡。

‹›
  • SQL
  • Config
📋
create table test ( title text, image_vector float_vector knn_type='hnsw' knn_dims='4' hnsw_similarity='l2' );
‹›
Response
Query OK, 0 rows affected (0.01 sec)

插入向量数据

自动嵌入(推荐)

处理向量数据最简单的方法是使用自动嵌入。使用此功能,您创建一个带有 MODEL_NAMEFROM 参数的表,然后只需插入文本数据——Manticore 会自动为您生成嵌入向量。

创建带自动嵌入的表

创建自动嵌入表时,指定:

  • MODEL_NAME:要使用的嵌入模型
  • FROM:用于生成嵌入的字段(为空表示所有文本/字符串字段)

支持的嵌入模型:

  • Sentence Transformers:任何合适的基于 BERT 的 Hugging Face 模型(例如 sentence-transformers/all-MiniLM-L6-v2)——无需 API 密钥。Manticore 在创建表时下载模型。
  • OpenAI:OpenAI 嵌入模型,如 openai/text-embedding-ada-002 - 需要 API_KEY='<OPENAI_API_KEY>' 参数
  • Voyage:Voyage AI 嵌入模型 - 需要 API_KEY='<VOYAGE_API_KEY>' 参数
  • Jina:Jina AI 嵌入模型 - 需要 API_KEY='<JINA_API_KEY>' 参数

有关设置 float_vector 属性的更多信息,请参见这里

‹›
  • SQL
SQL
📋

使用 sentence-transformers(无需 API 密钥)

CREATE TABLE products (
    title TEXT, 
    description TEXT,
    embedding_vector FLOAT_VECTOR KNN_TYPE='hnsw' HNSW_SIMILARITY='l2' 
    MODEL_NAME='sentence-transformers/all-MiniLM-L6-v2' FROM='title'
);

使用 OpenAI(需要 API_KEY 参数)

CREATE TABLE products_openai (
    title TEXT,
    description TEXT, 
    embedding_vector FLOAT_VECTOR KNN_TYPE='hnsw' HNSW_SIMILARITY='l2'
    MODEL_NAME='openai/text-embedding-ada-002' FROM='title,description' API_KEY='...'
);

使用所有文本字段生成嵌入(FROM 为空)

CREATE TABLE products_all (
    title TEXT,
    description TEXT,
    embedding_vector FLOAT_VECTOR KNN_TYPE='hnsw' HNSW_SIMILARITY='l2'
    MODEL_NAME='sentence-transformers/all-MiniLM-L6-v2' FROM=''
);
使用自动嵌入插入数据

使用自动嵌入时,不要在 INSERT 语句中指定向量字段。嵌入向量会自动从 FROM 参数指定的文本字段生成。

‹›
  • SQL
SQL
📋

仅插入文本数据 - 嵌入自动生成

INSERT INTO products (title) VALUES 
('machine learning artificial intelligence'),
('banana fruit sweet yellow');

插入多个字段 - 如果 FROM='title,description',则两者都用于生成嵌入

INSERT INTO products_openai (title, description) VALUES
('smartphone', 'latest mobile device with advanced features'),
('laptop', 'portable computer for work and gaming');

插入空向量(文档将被排除在向量搜索之外)

INSERT INTO products (title, embedding_vector) VALUES 
('no embedding item', ());
使用自动嵌入搜索

搜索方式相同——提供查询文本,Manticore 会生成嵌入并找到相似文档:

‹›
  • SQL
  • JSON
📋
SELECT id, knn_dist() FROM products WHERE knn(embedding_vector, 3, 'machine learning');
‹›
Response
+------+------------+
| id   | knn_dist() |
+------+------------+
|    1 | 0.12345678 |
|    2 | 0.87654321 |
+------+------------+
2 rows in set (0.00 sec)

手动插入向量

或者,您可以手动插入预先计算好的向量数据,确保其维度与创建表时指定的维度匹配。您也可以插入空向量;这意味着该文档将被排除在向量搜索结果之外。

重要提示: 当使用 hnsw_similarity='cosine' 时,向量在插入时会自动归一化为单位向量(数学长度/幅度为1.0的向量)。这种归一化保持了向量的方向,同时标准化了其长度,这是高效计算余弦相似度所必需的。这意味着存储的值将与您原始输入的值不同。

‹›
  • SQL
  • JSON
📋
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) );
‹›
Response
Query OK, 2 rows affected (0.00 sec)

KNN 向量搜索

现在,您可以使用 SQL 或 JSON 格式中的 knn 子句执行 KNN 搜索。两种接口都支持相同的基本参数,确保无论选择哪种格式,都能获得一致的体验:

  • SQL: select ... from <table name> where knn ( <field>, <k>, <query vector> [,<options>] )
  • JSON:
    POST /search
    {
        "table": "<table name>",
        "knn":
        {
            "field": "<field>",
            "query": "<text or vector>",
            "k": <k>,
            "ef": <ef>,
            "rescore": <rescore>,
            "oversampling": <oversampling>
        }
    }

参数说明:

  • field:这是包含向量数据的浮点向量属性的名称。
  • k:表示返回的文档数量,是分层可导航小世界(HNSW)索引的关键参数。它指定单个 HNSW 索引应返回的文档数量。然而,最终结果中包含的文档数量可能会有所不同。例如,如果系统处理的是分割成磁盘块的实时表,每个块可能返回 k 个文档,导致总数超过指定的 k(因为累计计数为 num_chunks * k)。另一方面,如果在请求了 k 个文档后,根据特定属性过滤掉了一些文档,最终文档数可能少于 k。需要注意的是,参数 k 不适用于 ramchunks。在 ramchunks 的上下文中,检索过程不同,因此 k 参数对返回文档数量的影响不适用。
  • query:(推荐参数)搜索查询,可以是:
    • 文本字符串:如果字段配置了自动嵌入,则自动转换为嵌入向量。如果字段没有自动嵌入,将返回错误。
    • 向量数组:与 query_vector 功能相同。
  • query_vector:(遗留参数)作为数字数组的搜索向量。为向后兼容仍然支持。 注意: 在同一请求中使用 queryquery_vector 中的一个,不要同时使用。
  • ef:搜索过程中使用的动态列表大小的可选参数。ef 越大,搜索越准确但越慢。
  • rescore:启用 KNN 重新评分(默认禁用)。在 SQL 中设置为 1,在 JSON 中设置为 true 以启用重新评分。KNN 搜索完成后,使用量化向量(可能带有过采样)进行距离计算,然后用原始(全精度)向量重新计算距离并重新排序结果,以提高排名准确性。
  • oversampling:设置一个因子(浮点值),在执行 KNN 搜索时将 k 乘以该因子,导致使用量化向量检索的候选项多于所需数量。默认不应用过采样。如果启用重新评分,这些候选项可以稍后重新评估。过采样也适用于非量化向量。由于它增加了 k,影响 HNSW 索引的工作方式,可能会导致结果准确性略有变化。

文档始终按与搜索向量的距离排序。您指定的任何额外排序条件将在此主要排序条件之后应用。要获取距离,有一个内置函数叫做 knn_dist()

‹›
  • SQL
  • JSON
📋
select id, knn_dist() from test where knn ( image_vector, 5, (0.286569,-0.031816,0.066684,0.032926), { ef=2000, oversampling=3.0, rescore=1 } );
‹›
Response
+------+------------+
| id   | knn_dist() |
+------+------------+
|    1 | 0.28146550 |
|    2 | 0.81527930 |
+------+------------+
2 rows in set (0.00 sec)

向量量化

HNSW 索引需要完全加载到内存中以执行 KNN 搜索,这可能导致显著的内存消耗。为了减少内存使用,可以应用标量量化——一种通过用有限数量的离散值表示每个分量(维度)来压缩高维向量的技术。Manticore 支持 8 位和 1 位量化,意味着每个向量分量从 32 位浮点压缩到 8 位甚至 1 位,分别减少了 4 倍或 32 倍的内存使用。这些压缩表示还允许更快的距离计算,因为可以在单个 SIMD 指令中处理更多的向量分量。虽然标量量化引入了一些近似误差,但通常是在搜索准确性和资源效率之间值得的权衡。为了获得更好的准确性,量化可以与重新评分和过采样结合使用:检索的候选项多于请求的数量,并使用原始 32 位浮点向量重新计算这些候选项的距离。

支持的量化类型包括:

  • 8bit:每个向量分量量化为 8 位。
  • 1bit:每个向量分量量化为 1 位。使用非对称量化,查询向量量化为 4 位,存储向量量化为 1 位。这种方法比简单方法提供更高的精度,但性能有所折衷。
  • 1bitsimple:每个向量分量量化为 1 位。此方法比 1bit 更快,但通常准确性较低。
‹›
  • SQL
SQL
📋
create table test ( title text, image_vector float_vector knn_type='hnsw' knn_dims='4' hnsw_similarity='l2' quantization='1bit');
‹›
Response
Query OK, 0 rows affected (0.01 sec)

通过 id 查找相似文档

注意:通过 id 查找相似文档需要 Manticore Buddy。如果无法使用,请确保已安装 Buddy。

基于特定文档的唯一ID查找相似文档是一项常见任务。例如,当用户查看某个特定项目时,Manticore Search 可以高效地识别并显示在向量空间中与其最相似的项目列表。操作方法如下:

  • SQL: select ... from <table name> where knn ( <field>, <k>, <document id> )
  • JSON:
    POST /search
    {
        "table": "<table name>",
        "knn":
        {
            "field": "<field>",
            "doc_id": <document id>,
            "k": <k>
        }
    }

参数说明:

  • field:这是包含向量数据的浮点向量属性的名称。
  • k:表示返回的文档数量,是分层可导航小世界(HNSW)索引的关键参数。它指定单个 HNSW 索引应返回的文档数量。然而,最终结果中包含的文档实际数量可能会有所不同。例如,如果系统处理的是分割成磁盘块的实时表,每个块可能返回 k 个文档,导致总数超过指定的 k(因为累计数量为 num_chunks * k)。另一方面,如果在请求了 k 个文档后,根据特定属性过滤掉了一些文档,最终文档数量可能少于 k。需要注意的是,参数 k 不适用于 ramchunks。在 ramchunks 的上下文中,检索过程不同,因此 k 参数对返回文档数量的影响不适用。
  • document id:用于 KNN 相似度搜索的文档ID。
‹›
  • SQL
  • JSON
📋
select id, knn_dist() from test where knn ( image_vector, 5, 1 );
‹›
Response
+------+------------+
| id   | knn_dist() |
+------+------------+
|    2 | 0.81527930 |
+------+------------+
1 row in set (0.00 sec)

过滤 KNN 向量搜索结果

Manticore 还支持通过全文匹配、属性过滤或两者结合,对 KNN 搜索返回的文档进行额外过滤。

‹›
  • SQL
  • JSON
📋
select id, knn_dist() from test where knn ( image_vector, 5, (0.286569,-0.031816,0.066684,0.032926) ) and match('white') and id < 10;
‹›
Response
+------+------------+
| id   | knn_dist() |
+------+------------+
|    2 | 0.81527930 |
+------+------------+
1 row in set (0.00 sec)
Last modified: September 16, 2025