跳到主要内容

混合搜索

混合搜索指同时进行多个 ANN 搜索、对这些 ANN 搜索的多组结果进行重排序,并最终返回单一结果集的搜索方法。使用混合搜索可以提高搜索准确性。Milvus 支持在具有多个向量 field 的 collection 上进行混合搜索。

混合搜索最常用于稀疏-稠密向量搜索和多模态搜索等场景。本指南将通过具体示例演示如何在 Milvus 中进行混合搜索。

场景

混合搜索适用于以下两种场景:

稀疏-稠密向量搜索

不同类型的向量可以表示不同的信息,使用各种嵌入模型可以更全面地表示数据的不同特征和方面。例如,对同一句话使用不同的嵌入模型可以生成稠密向量来表示语义含义,以及稀疏向量来表示句子中的词频。

  • 稀疏向量: 稀疏向量的特点是向量维度高且非零值较少。这种结构使它们特别适合传统信息检索应用。在大多数情况下,稀疏向量使用的维度数量对应于一种或多种语言中的不同 token。每个维度都被分配一个值,该值表示该 token 在文档中的相对重要性。这种布局证明对涉及关键字匹配的任务是有利的。

  • 稠密向量: 稠密向量是从神经网络派生的嵌入。当排列在有序数组中时,这些向量捕获输入文本的语义本质。请注意,稠密向量不限于文本处理;它们也广泛用于计算机视觉中以表示视觉数据的语义。这些稠密向量通常由文本嵌入模型生成,其特点是大多数或所有元素都是非零的。因此,稠密向量对语义搜索应用特别有效,因为即使在没有精确关键字匹配的情况下,它们也可以根据向量距离返回最相似的结果。这种能力允许更细致和上下文感知的搜索结果,通常捕获基于关键字的方法可能错过的概念之间的关系。

有关更多详细信息,请参阅稀疏向量稠密向量

多模态搜索

多模态搜索指跨多种模态(如图像、视频、音频、文本等)的非结构化数据相似性搜索。例如,一个人可以使用各种模态的数据来表示,如指纹、声纹和面部特征。混合搜索支持同时进行多种搜索。例如,使用相似指纹和声纹搜索一个人。

工作流程

进行混合搜索的主要工作流程如下:

  1. 通过嵌入模型如 BERTTransformers 生成稠密向量。

  2. 通过嵌入模型如 BM25BGE-M3SPLADE 等生成稀疏向量。

  3. 在 Milvus 中创建 collection 并定义包含稠密和稀疏向量 field 的 collection schema。

  4. 将稀疏-稠密向量插入到上一步中创建的 collection 中。

  5. 进行混合搜索:稠密向量上的 ANN 搜索将返回一组 top-K 最相似结果,稀疏向量上的文本匹配也将返回一组 top-K 结果。

  6. 归一化:对两组 top-K 结果的分数进行归一化,将分数转换为 [0,1] 之间的范围。

  7. 选择适当的重排序策略来合并和重排序两组 top-K 结果,并最终返回最终的 top-K 结果集。

Hybrid Search

示例

本节将使用具体示例说明如何对稀疏-稠密向量进行混合搜索以提高文本搜索的准确性。

创建具有多个向量 field 的 collection

创建 collection 的过程包括三个部分:定义 collection schema、配置 index 参数和创建 collection。

定义 Schema

在此示例中,需要在 collection schema 中定义多个向量 field。目前,默认情况下每个 collection 最多可以包含 4 个向量 field。但您也可以根据需要修改 proxy.maxVectorFieldNum 的值,在 collection 中包含最多 10 个向量 field。

以下示例定义了一个 collection schema,其中 densesparse 是两个向量 field:

  • id:此 field 用作存储文本 ID 的主键。此 field 的数据类型是 INT64。

  • text:此 field 用于存储文本内容。此 field 的数据类型是 VARCHAR,最大长度为 1000 个字符。

  • dense:此 field 用于存储文本的稠密向量。此 field 的数据类型是 FLOAT_VECTOR,向量维度为 768。

  • sparse:此 field 用于存储文本的稀疏向量。此 field 的数据类型是 SPARSE_FLOAT_VECTOR。

# Create a collection in customized setup mode
from pymilvus import (
MilvusClient, DataType
)

client = MilvusClient(
uri="http://localhost:19530",
token="root:Milvus"
)

# Create schema
schema = MilvusClient.create_schema(
auto_id=False,
enable_dynamic_field=True,
)
# Add fields to schema
schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True)
schema.add_field(field_name="text", datatype=DataType.VARCHAR, max_length=1000)
schema.add_field(field_name="sparse", datatype=DataType.SPARSE_FLOAT_VECTOR)
schema.add_field(field_name="dense", datatype=DataType.FLOAT_VECTOR, dim=5)
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.common.DataType;
import io.milvus.v2.service.collection.request.AddFieldReq;
import io.milvus.v2.service.collection.request.CreateCollectionReq;

MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("http://localhost:19530")
.token("root:Milvus")
.build());

CreateCollectionReq.CollectionSchema schema = client.createSchema();
schema.addField(AddFieldReq.builder()
.fieldName("id")
.dataType(DataType.Int64)
.isPrimaryKey(true)
.autoID(false)
.build());

schema.addField(AddFieldReq.builder()
.fieldName("text")
.dataType(DataType.VarChar)
.maxLength(1000)
.build());

schema.addField(AddFieldReq.builder()
.fieldName("dense")
.dataType(DataType.FloatVector)
.dimension(5)
.build());

schema.addField(AddFieldReq.builder()
.fieldName("sparse")
.dataType(DataType.SparseFloatVector)
.build());
import (
"context"
"fmt"

"github.com/milvus-io/milvus/client/v2/column"
"github.com/milvus-io/milvus/client/v2/entity"
"github.com/milvus-io/milvus/client/v2/index"
"github.com/milvus-io/milvus/client/v2/milvusclient"
)

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

milvusAddr := "localhost:19530"
client, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: milvusAddr,
})
if err != nil {
fmt.Println(err.Error())
// handle error
}
defer client.Close(ctx)

schema := entity.NewSchema().WithDynamicFieldEnabled(true)
schema.WithField(entity.NewField().
WithName("id").
WithDataType(entity.FieldTypeInt64).
WithIsPrimaryKey(true),
).WithField(entity.NewField().
WithName("text").
WithDataType(entity.FieldTypeVarChar).
WithMaxLength(1000),
).WithField(entity.NewField().
WithName("sparse").
WithDataType(entity.FieldTypeSparseVector),
).WithField(entity.NewField().
WithName("dense").
WithDataType(entity.FieldTypeFloatVector).
WithDim(5),
)
import { MilvusClient, DataType } from "@zilliz/milvus2-sdk-node";

const address = "http://localhost:19530";
const token = "root:Milvus";
const client = new MilvusClient({address, token});

// Create a collection in customized setup mode
// Define fields
const fields = [
{
name: "id",
data_type: DataType.Int64,
is_primary_key: true,
auto_id: false
},
{
name: "text",
data_type: DataType.VarChar,
max_length: 1000
},
{
name: "sparse",
data_type: DataType.SPARSE_FLOAT_VECTOR
},
{
name: "dense",
data_type: DataType.FloatVector,
dim: 5
}
]
export schema='{
"autoId": false,
"enabledDynamicField": true,
"fields": [
{
"fieldName": "id",
"dataType": "Int64",
"isPrimary": true
},
{
"fieldName": "text",
"dataType": "VarChar",
"elementTypeParams": {
"max_length": 1000
}
},
{
"fieldName": "sparse",
"dataType": "SparseFloatVector"
},
{
"fieldName": "dense",
"dataType": "FloatVector",
"elementTypeParams": {
"dim": "5"
}
}
]
}'

在稀疏向量搜索期间,您可以利用全文搜索功能简化生成稀疏嵌入向量的过程。有关更多详细信息,请参阅 全文搜索

Create index

创建索引

After defining the collection schema, it is necessary to set up the vector indexes and the similarity metrics. In this example, an index of the AUTOINDEX type is created for both the dense vector field dense, and the sparse vector field sparse. You can use other index types as you see fit. To learn about the types of indexes supported, see available index types. 定义 collection schema 后,需要设置向量索引和相似性度量。在此示例中,为密集向量 field dense 和稀疏向量 field sparse 都创建了 AUTOINDEX 类型的索引。您可以根据需要使用其他索引类型。要了解支持的索引类型,请参阅 可用索引类型

from pymilvus import MilvusClient

# Prepare index parameters
index_params = client.prepare_index_params()

# Add indexes
index_params.add_index(
field_name="dense",
index_name="dense_index",
index_type="AUTOINDEX",
metric_type="IP"
)

index_params.add_index(
field_name="sparse",
index_name="sparse_index",
index_type="AUTOINDEX", # Index type for sparse vectors
metric_type="IP", # Currently, only IP (Inner Product) is supported for sparse vectors
params={"drop_ratio_build": 0.2}, # The ratio of small vector values to be dropped during indexing
)
import io.milvus.v2.common.IndexParam;
import java.util.*;

Map<String, Object> denseParams = new HashMap<>();

IndexParam indexParamForDenseField = IndexParam.builder()
.fieldName("dense")
.indexName("dense_index")
.indexType(IndexParam.IndexType.AUTOINDEX)
.metricType(IndexParam.MetricType.IP)
.build();

Map<String, Object> sparseParams = new HashMap<>();
sparseParams.put("drop_ratio_build", 0.2);
IndexParam indexParamForSparseField = IndexParam.builder()
.fieldName("sparse")
.indexName("sparse_index")
.indexType(IndexParam.IndexType.AUTOINDEX)
.metricType(IndexParam.MetricType.IP)
.extraParams(sparseParams)
.build();

List<IndexParam> indexParams = new ArrayList<>();
indexParams.add(indexParamForDenseField);
indexParams.add(indexParamForSparseField);
indexOption1 := milvusclient.NewCreateIndexOption("my_collection", "sparse",
index.NewSparseInvertedIndex(entity.IP, 0.2))
indexOption2 := milvusclient.NewCreateIndexOption("my_collection", "dense",
index.NewAutoIndex(index.MetricType(entity.IP)))
const index_params = [{
field_name: "dense",
index_type: "AUTOINDEX",
metric_type: "IP"
},{
field_name: "sparse",
index_type: "AUTOINDEX",
metric_type: "IP"
}]
export indexParams='[
{
"fieldName": "dense",
"metricType": "IP",
"indexName": "dense_index",
"indexType":"AUTOINDEX"
},
{
"fieldName": "sparse",
"metricType": "IP",
"indexName": "sparse_index",
"indexType": "AUTOINDEX"
}
]'

Create collection

使用在前面两个步骤中配置的 collection schema 和索引创建名为 demo 的 collection。

from pymilvus import MilvusClient

client.create_collection(
collection_name="my_collection",
schema=schema,
index_params=index_params
)
CreateCollectionReq createCollectionReq = CreateCollectionReq.builder()
.collectionName("my_collection")
.collectionSchema(schema)
.indexParams(indexParams)
.build();
client.createCollection(createCollectionReq);
err = client.CreateCollection(ctx,
milvusclient.NewCreateCollectionOption("my_collection", schema).
WithIndexOptions(indexOption1, indexOption2))
if err != nil {
fmt.Println(err.Error())
// handle error
}
res = await client.createCollection({
collection_name: "my_collection",
fields: fields,
index_params: index_params,
})
export CLUSTER_ENDPOINT="http://localhost:19530"
export TOKEN="root:Milvus"

curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/create" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d "{
\"collectionName\": \"my_collection\",
\"schema\": $schema,
\"indexParams\": $indexParams
}"

Insert data

Insert the sparse-dense vectors into the the collection demo.

插入数据

将稀疏-密集向量插入到 collection demo 中。

from pymilvus import MilvusClient

data=[
{"id": 0, "text": "Artificial intelligence was founded as an academic discipline in 1956.", "sparse":{9637: 0.30856525997853057, 4399: 0.19771651149001523, ...}, "dense": [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, ...]},
{"id": 1, "text": "Alan Turing was the first person to conduct substantial research in AI.", "sparse":{6959: 0.31025067641541815, 1729: 0.8265339135915016, ...}, "dense": [0.19886812562848388, 0.06023560599112088, 0.6976963061752597, ...]},
{"id": 2, "text": "Born in Maida Vale, London, Turing was raised in southern England.", "sparse":{1220: 0.15303302147479103, 7335: 0.9436728846033107, ...}, "dense": [0.43742130801983836, -0.5597502546264526, 0.6457887650909682, ...]}]

res = client.insert(
collection_name="my_collection",
data=data
)

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import io.milvus.v2.service.vector.request.InsertReq;

Gson gson = new Gson();
JsonObject row1 = new JsonObject();
row1.addProperty("id", 1);
row1.addProperty("text", "Artificial intelligence was founded as an academic discipline in 1956.");
row1.add("dense", gson.toJsonTree(dense1));
row1.add("sparse", gson.toJsonTree(sparse1));

JsonObject row2 = new JsonObject();
row2.addProperty("id", 2);
row2.addProperty("text", "Alan Turing was the first person to conduct substantial research in AI.");
row2.add("dense", gson.toJsonTree(dense2));
row2.add("sparse", gson.toJsonTree(sparse2));

JsonObject row3 = new JsonObject();
row3.addProperty("id", 3);
row3.addProperty("text", "Born in Maida Vale, London, Turing was raised in southern England.");
row3.add("dense", gson.toJsonTree(dense3));
row3.add("sparse", gson.toJsonTree(sparse3));

List<JsonObject> data = Arrays.asList(row1, row2, row3);
InsertReq insertReq = InsertReq.builder()
.collectionName("my_collection")
.data(data)
.build();

InsertResp insertResp = client.insert(insertReq);
v := make([]entity.SparseEmbedding, 0, 3)
sparseVector1, _ := entity.NewSliceSparseEmbedding([]uint32{9637, 4399, 3573}, []float32{0.30856525997853057, 0.19771651149001523, 0.1576378135})
v = append(v, sparseVector1)
sparseVector2, _ := entity.NewSliceSparseEmbedding([]uint32{6959, 1729, 5263}, []float32{0.31025067641541815, 0.8265339135915016, 0.68647322132})
v = append(v, sparseVector2)
sparseVector3, _ := entity.NewSliceSparseEmbedding([]uint32{1220, 7335}, []float32{0.15303302147479103, 0.9436728846033107})
v = append(v, sparseVector3)
sparseColumn := column.NewColumnSparseVectors("sparse", v)

_, err = client.Insert(ctx, milvusclient.NewColumnBasedInsertOption("my_collection").
WithInt64Column("id", []int64{0, 1, 2}).
WithVarcharColumn("text", []string{
"Artificial intelligence was founded as an academic discipline in 1956.",
"Alan Turing was the first person to conduct substantial research in AI.",
"Born in Maida Vale, London, Turing was raised in southern England.",
}).
WithFloatVectorColumn("dense", 5, [][]float32{
{0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592},
{0.19886812562848388, 0.06023560599112088, 0.6976963061752597, 0.2614474506242501, 0.838729485096104},
{0.43742130801983836, -0.5597502546264526, 0.6457887650909682, 0.7894058910881185, 0.20785793220625592},
}).
WithColumns(sparseColumn))
if err != nil {
fmt.Println(err.Error())
// handle err
}
const { MilvusClient, DataType } = require("@zilliz/milvus2-sdk-node")

var data = [
{id: 0, text: "Artificial intelligence was founded as an academic discipline in 1956.", sparse:[9637: 0.30856525997853057, 4399: 0.19771651149001523, ...] , dense: [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]},
{id: 1, text: "Alan Turing was the first person to conduct substantial research in AI.", sparse:[6959: 0.31025067641541815, 1729: 0.8265339135915016, ...] , dense: [0.19886812562848388, 0.06023560599112088, 0.6976963061752597, 0.2614474506242501, 0.838729485096104]},
{id: 2, text: "Born in Maida Vale, London, Turing was raised in southern England." , sparse:[1220: 0.15303302147479103, 7335: 0.9436728846033107, ...] , dense: [0.43742130801983836, -0.5597502546264526, 0.6457887650909682, 0.7894058910881185, 0.20785793220625592]}
]

var res = await client.insert({
collection_name: "my_collection",
data: data,
})
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/insert" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"data": [
{"id": 0, "text": "Artificial intelligence was founded as an academic discipline in 1956.", "sparse":{"9637": 0.30856525997853057, "4399": 0.19771651149001523}, "dense": [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, ...]},
{"id": 1, "text": "Alan Turing was the first person to conduct substantial research in AI.", "sparse":{"6959": 0.31025067641541815, "1729": 0.8265339135915016}, "dense": [0.19886812562848388, 0.06023560599112088, 0.6976963061752597, ...]},
{"id": 2, "text": "Born in Maida Vale, London, Turing was raised in southern England.", "sparse":{"1220": 0.15303302147479103, "7335": 0.9436728846033107}, "dense": [0.43742130801983836, -0.5597502546264526, 0.6457887650909682, ...]}
],
"collectionName": "my_collection"
}'

Create multiple AnnSearchRequest instances

创建多个 AnnSearchRequest 实例

Hybrid Search is implemented by creating multiple AnnSearchRequest in the hybrid_search() function, where each AnnSearchRequest represents a basic ANN search request for a specific vector field. Therefore, before conducting a Hybrid Search, it is necessary to create an AnnSearchRequest for each vector field.

By configuring the expr parameter in an AnnSearchRequest, you can set the filtering conditions for your hybrid sesarch. Please refer to Filtered Search and Filtering.

In Hybrid Search, each AnnSearchRequest supports only one query vector.

混合搜索通过在 hybrid_search() 函数中创建多个 AnnSearchRequest 来实现,其中每个 AnnSearchRequest 表示对特定向量 field 的基本 ANN 搜索请求。因此,在进行混合搜索之前,需要为每个向量 field 创建一个 AnnSearchRequest

通过在 AnnSearchRequest 中配置 expr 参数,您可以为混合搜索设置过滤条件。请参阅 过滤搜索过滤

在混合搜索中,每个 AnnSearchRequest 仅支持一个查询向量。

假设查询文本"Who started AI research?"已经转换为稀疏和稠密向量。基于此,分别为 sparsedense 向量 field 创建两个 AnnSearchRequest 搜索请求,如以下示例所示。

from pymilvus import AnnSearchRequest

query_dense_vector = [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]

search_param_1 = {
"data": [query_dense_vector],
"anns_field": "dense",
"param": {
"metric_type": "IP",
"params": {"nprobe": 10}
},
"limit": 2
}
request_1 = AnnSearchRequest(**search_param_1)

query_sparse_vector = {3573: 0.34701499565746674}, {5263: 0.2639375518635271}
search_param_2 = {
"data": [query_sparse_vector],
"anns_field": "sparse",
"param": {
"metric_type": "IP",
"params": {"drop_ratio_build": 0.2}
},
"limit": 2
}
request_2 = AnnSearchRequest(**search_param_2)

reqs = [request_1, request_2]

import io.milvus.v2.service.vector.request.AnnSearchReq;
import io.milvus.v2.service.vector.request.data.BaseVector;
import io.milvus.v2.service.vector.request.data.FloatVec;
import io.milvus.v2.service.vector.request.data.SparseFloatVec;

float[] dense = new float[]{-0.0475336798f, 0.0521207601f, 0.0904406682f, ...};
SortedMap<Long, Float> sparse = new TreeMap<Long, Float>() {{
put(3573L, 0.34701499f);
put(5263L, 0.263937551f);
...
}};

List<BaseVector> queryDenseVectors = Collections.singletonList(new FloatVec(dense));
List<BaseVector> querySparseVectors = Collections.singletonList(new SparseFloatVec(sparse));

List<AnnSearchReq> searchRequests = new ArrayList<>();
searchRequests.add(AnnSearchReq.builder()
.vectorFieldName("dense")
.vectors(queryDenseVectors)
.metricType(IndexParam.MetricType.IP)
.params("{\"nprobe\": 10}")
.topK(2)
.build());
searchRequests.add(AnnSearchReq.builder()
.vectorFieldName("sparse")
.vectors(querySparseVectors)
.metricType(IndexParam.MetricType.IP)
.params("{\"drop_ratio_build\": 0.2}")
.topK(2)
.build());
queryVector := []float32{0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592}
sparseVector, _ := entity.NewSliceSparseEmbedding([]uint32{3573, 5263}, []float32{0.34701499, 0.263937551})

request1 := milvusclient.NewAnnRequest("dense", 2, entity.FloatVector(queryVector)).
WithAnnParam(index.NewIvfAnnParam(10)).
WithSearchParam(index.MetricTypeKey, "IP")
annParam := index.NewSparseAnnParam()
annParam.WithDropRatio(0.2)
request2 := milvusclient.NewAnnRequest("sparse", 2, sparseVector).
WithAnnParam(annParam).
WithSearchParam(index.MetricTypeKey, "IP")
const search_param_1 = {
"data": query_vector,
"anns_field": "dense",
"param": {
"metric_type": "IP",
"params": {"nprobe": 10}
},
"limit": 2
}

const search_param_2 = {
"data": query_sparse_vector,
"anns_field": "sparse",
"param": {
"metric_type": "IP",
"params": {"drop_ratio_build": 0.2}
},
"limit": 2
}
export req='[
{
"data": [[0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592,....]],
"annsField": "dense",
"params": {
"params": {
"nprobe": 10
}
},
"limit": 2
},
{
"data": [{"3573": 0.34701499565746674}, {"5263": 0.2639375518635271}],
"annsField": "sparse",
"params": {
"params": {
"drop_ratio_build": 0.2
}
},
"limit": 2
}
]'

Since the parameter limit is set to 2, each AnnSearchRequest returns 2 search results. In this example, 2 AnnSearchRequest are created, therefore a total of 4 search results will be returned.

Configure a reranking strategy

由于参数 limit 设置为 2,每个 AnnSearchRequest 返回 2 个搜索结果。在此示例中,创建了 2 个 AnnSearchRequest,因此总共将返回 4 个搜索结果。

Configure a reranking strategy

要合并和重排序两组 ANN 搜索结果,需要选择适当的重排序策略。Milvus 支持两种类型的重排序策略:WeightedRankerRRFRanker。在选择重排序策略时,需要考虑的一点是是否要对向量 field 上的一个或多个基本 ANN 搜索有任何强调。

  • WeightedRanker: This strategy is recommended if you require the results to emphasize a particular vector field. The WeightedRanker allows you to assign higher weights to certain vector fields, emphasizing them more. For instance, in multimodal searches, textual descriptions of an image might be considered more important than the colors in this image.

  • RRFRanker (Reciprocal Rank Fusion Ranker): This strategy is recommended when there is no specific emphasis. The RRF can effectively balance the importance of each vector field.

WeightedRanker:如果您需要结果强调特定向量 field,建议使用此策略。WeightedRanker 允许您为某些向量 field 分配更高的权重,从而更多地强调它们。例如,在多模态搜索中,图像的文本描述可能被认为比该图像中的颜色更重要。

RRFRanker(倒数排名融合排名器):当没有特定强调时,建议使用此策略。RRF 可以有效地平衡每个向量 field 的重要性。

For more details about the mechanisms of these two reranking strategies, refer to Reranking.

The following two examples demonstrate how to use the WeightedRanker and RRFRanker reranking strategies:

  1. Example 1: Using WeightedRanker

  2. 示例 1:使用 WeightedRanker

    When using the WeightedRanker strategy, you need to input weight values into the WeightedRanker function. The number of basic ANN searches in a Hybrid Search corresponds to the number of values that need to be inputted. The input values should be in the range [0,1], with values closer to 1 indicating greater importance.

    使用 WeightedRanker 策略时,您需要将权重值输入到 WeightedRanker 函数中。混合搜索中基本 ANN 搜索的数量对应于需要输入的值的数量。输入值应在 [0,1] 范围内,值越接近 1 表示重要性越大。

    from pymilvus import WeightedRanker

    ranker = WeightedRanker(0.8, 0.3)
    import io.milvus.v2.service.vector.request.ranker.BaseRanker;
    import io.milvus.v2.service.vector.request.ranker.WeightedRanker;

    BaseRanker reranker = new WeightedRanker(Arrays.asList(0.8f, 0.3f));
    reranker := milvusclient.NewWeightedReranker([]float64{0.8, 0.3})
    import { MilvusClient, DataType } from "@zilliz/milvus2-sdk-node";

    const rerank = WeightedRanker(0.8, 0.3);
    export rerank='{
    "strategy": "ws",
    "params": {"weights": [0.8,0.3]}
    }'
  3. Example 2: Using RRFRanker

  4. 示例 2:使用 RRFRanker

    When using the RRFRanker strategy, you need to input the parameter value k into the RRFRanker. The default value of k is 60. This parameter helps to determine how the ranks are combined from different ANN searches, aiming to balance and blend the importance across all searches.

    使用 RRFRanker 策略时,您需要将参数值 k 输入到 RRFRanker 中。默认值为 60。此参数有助于确定如何从不同的 ANN 搜索中合并排名,旨在平衡和混合所有搜索的重要性。

    from pymilvus import RRFRanker

    ranker = RRFRanker(60)
    import io.milvus.v2.service.vector.request.ranker.BaseRanker;
    import io.milvus.v2.service.vector.request.ranker.RRFRanker;

    BaseRanker reranker = new RRFRanker(60);
    reranker := milvusclient.NewRRFReranker(60)
    import { MilvusClient, DataType } from "@zilliz/milvus2-sdk-node";

    const rerank = RRFRanker(60);
    export rerank='{
    "strategy": "rrf",
    "params": {"k": 60}
    }'