🚀 Try Zilliz Cloud, the fully managed Milvus, for free—experience 10x faster performance! Try Now>>

Búsqueda híbrida

La búsqueda híbrida es un método de búsqueda que realiza varias búsquedas RNA simultáneamente, reordena varios conjuntos de resultados de estas búsquedas RNA y, en última instancia, devuelve un único conjunto de resultados. El uso de la búsqueda híbrida puede mejorar la precisión de la búsqueda. Zilliz permite realizar búsquedas híbridas en una colección con varios campos vectoriales.

La búsqueda híbrida se utiliza con mayor frecuencia en escenarios que incluyen búsquedas de vectores dispersos y densos y búsquedas multimodales. Esta guía mostrará cómo realizar una Búsqueda Híbrida en Zilliz con un ejemplo específico.

Escenarios

La búsqueda híbrida es adecuada para los dos escenarios siguientes.

Diferentes tipos de vectores pueden representar información diferente, y el uso de varios modelos de incrustación puede representar de forma más exhaustiva diferentes características y aspectos de los datos. Por ejemplo, el uso de distintos modelos de incrustación para la misma frase puede generar un vector denso que represente el significado semántico y un vector disperso que represente la frecuencia de palabras en la frase.

  • Vectores dispersos: Los vectores dispersos se caracterizan por su elevada dimensionalidad y la presencia de pocos valores distintos de cero. Esta estructura los hace especialmente adecuados para las aplicaciones tradicionales de recuperación de información. En la mayoría de los casos, el número de dimensiones utilizadas en los vectores dispersos corresponde a diferentes tokens de una o varias lenguas. A cada dimensión se le asigna un valor que indica la importancia relativa de ese token dentro del documento. Esta disposición resulta ventajosa para las tareas de comparación de textos.

  • Vectores densos: Los vectores densos son incrustaciones derivadas de redes neuronales. Cuando se disponen en una matriz ordenada, estos vectores capturan la esencia semántica del texto de entrada. Los vectores densos no se limitan al tratamiento de textos, sino que también se utilizan mucho en visión por ordenador para representar la semántica de los datos visuales. Estos vectores densos, normalmente generados por modelos de incrustación de texto, se caracterizan porque la mayoría o todos los elementos son distintos de cero. Así, los vectores densos son especialmente eficaces para las aplicaciones de búsqueda semántica, ya que pueden devolver los resultados más similares basándose en la distancia vectorial, incluso en ausencia de coincidencias textuales exactas. Esta capacidad permite obtener resultados de búsqueda más matizados y sensibles al contexto, a menudo captando relaciones entre conceptos que podrían pasar desapercibidas con enfoques basados en palabras clave.

Para más información, consulte Vector disperso y Vector denso.

La búsqueda multimodal se refiere a la búsqueda por similitud de datos no estructurados en múltiples modalidades (como imágenes, vídeos, audio, texto, etc.). Por ejemplo, una persona puede representarse utilizando varias modalidades de datos, como huellas dactilares, huellas vocales y rasgos faciales. La búsqueda híbrida permite realizar varias búsquedas simultáneamente. Por ejemplo, la búsqueda de una persona con huellas dactilares y vocales similares.

Flujo de trabajo

El flujo de trabajo principal para realizar una búsqueda híbrida es el siguiente.

  1. Generar vectores densos mediante modelos de incrustación como BERT y Transformers.

  2. Generar vectores dispersos mediante modelos de incrustación como BM25, BGE-M3, SPLADE, etc.

  3. Crear una colección en Zilliz y definir el esquema de la colección que incluya campos vectoriales densos y dispersos.

  4. Inserte los vectores dispersos-densos en la colección creada en el paso anterior.

  5. Realice una búsqueda híbrida: La búsqueda RNA en vectores densos devolverá un conjunto de los K resultados más similares, y la coincidencia de texto en vectores dispersos también devolverá un conjunto de los K resultados más similares.

  6. Normalización: Normalice las puntuaciones de los dos conjuntos de resultados top-K, convirtiendo las puntuaciones a un rango entre [0,1].

  7. Elegir una estrategia de reordenación adecuada para combinar y reordenar los dos conjuntos de resultados top-K y, en última instancia, obtener un conjunto final de resultados top-K.

Hybrid Search Workflow Flujo de trabajo de búsqueda híbrida

Ejemplos

Esta sección utilizará un ejemplo específico para ilustrar cómo realizar una búsqueda híbrida en vectores poco densos para mejorar la precisión de las búsquedas de texto.

Crear una colección con varios campos vectoriales

El proceso de creación de una colección incluye tres partes: definir el esquema de la colección, configurar los parámetros del índice y crear la colección.

Definir el esquema

En este ejemplo, es necesario definir varios campos vectoriales en el esquema de la colección. Actualmente, cada colección puede incluir hasta 4 campos vectoriales por defecto. Pero también se puede modificar el valor de proxy.maxVectorFieldNum para incluir hasta 10 campos vectoriales en una colección según sea necesario.

El siguiente ejemplo define un esquema de colección, donde dense y sparse son los dos campos vectoriales.

  • id: Este campo sirve como clave primaria para almacenar los ID de texto. El tipo de datos de este campo es INT64.

  • text: Este campo se utiliza para almacenar contenido textual. El tipo de datos de este campo es VARCHAR, con una longitud máxima de 1000 caracteres.

  • dense: Este campo se utiliza para almacenar los vectores densos de los textos. El tipo de datos de este campo es FLOAT_VECTOR, con una dimensión vectorial de 768.

  • sparse: Este campo se utiliza para almacenar los vectores dispersos de los textos. El tipo de datos de este campo es 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(768)
        .build());

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

// WIP

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: 768
    }
]

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": "768"
                }
            }
        ]
    }'

Durante las búsquedas de vectores dispersos, puede simplificar el proceso de generación de vectores dispersos de incrustación aprovechando las funciones de búsqueda de texto completo. Para obtener más información, consulte Búsqueda de texto completo.

Crear índice

Tras definir el esquema de la colección, es necesario configurar los índices vectoriales y las métricas de similitud. En este ejemplo, se crea un índice IVF_FLAT para el campo vectorial denso dense, y un SPARSE_INVERTED_INDEX para el campo vectorial disperso sparse. Para saber más sobre los tipos de índices soportados, consulta Index Explained.

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="IVF_FLAT",
    metric_type="IP",
    params={"nlist": 128},
)

index_params.add_index(
    field_name="sparse",
    index_name="sparse_index",
    index_type="SPARSE_INVERTED_INDEX",  # 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<>();
denseParams.put("nlist", 128);
IndexParam indexParamForDenseField = IndexParam.builder()
        .fieldName("dense")
        .indexName("dense_index")
        .indexType(IndexParam.IndexType.IVF_FLAT)
        .metricType(IndexParam.MetricType.IP)
        .extraParams(denseParams)
        .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.SPARSE_INVERTED_INDEX)
        .metricType(IndexParam.MetricType.IP)
        .extraParams(sparseParams)
        .build();

List<IndexParam> indexParams = new ArrayList<>();
indexParams.add(indexParamForDenseField);
indexParams.add(indexParamForSparseField);

const index_params = [{
    field_name: "dense",
    index_type: "IVF_FLAT",
    metric_type: "IP"
},{
    field_name: "sparse",
    index_type: "SPARSE_INVERTED_INDEX",
    metric_type: "IP"
}]

export indexParams='[
        {
            "fieldName": "dense",
            "metricType": "IP",
            "indexName": "dense_index",
            "indexType":"IVF_FLAT",
            "params":{"nlist":128}
        },
        {
            "fieldName": "sparse",
            "metricType": "IP",
            "indexName": "sparse_index",
            "indexType": "SPARSE_INVERTED_INDEX"
        }
    ]'

Crear colección

Crea una colección llamada demo con el esquema de colección y los índices configurados en los dos pasos anteriores.

from pymilvus import MilvusClient

client.create_collection(
    collection_name="hybrid_search_collection",
    schema=schema,
    index_params=index_params
)

CreateCollectionReq createCollectionReq = CreateCollectionReq.builder()
        .collectionName("hybrid_search_collection")
        .collectionSchema(schema)
        .indexParams(indexParams)
        .build();
client.createCollection(createCollectionReq);

res = await client.createCollection({
    collection_name: "hybrid_search_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\": \"hybrid_search_collection\",
    \"schema\": $schema,
    \"indexParams\": $indexParams
}"

Insertar datos

Inserta los vectores dispersos-densos en la colección 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="hybrid_search_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("hybrid_search_collection")
        .data(data)
        .build();

InsertResp insertResp = client.insert(insertReq);

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: "hybrid_search_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": "hybrid_search_collection"
}'

Crear múltiples instancias AnnSearchRequest

La Búsqueda Híbrida se implementa creando múltiples AnnSearchRequest en la función hybrid_search(), donde cada AnnSearchRequest representa una petición de búsqueda ANN básica para un campo vectorial específico. Por lo tanto, antes de realizar una Búsqueda Híbrida, es necesario crear un AnnSearchRequest para cada campo vectorial.

En la búsqueda híbrida, cada AnnSearchRequest sólo admite un vector de consulta.

Supongamos que el texto de consulta "¿Quién inició la investigación sobre IA?" ya se ha convertido en vectores dispersos y densos. En base a esto, se crean dos peticiones de búsqueda AnnSearchRequest para los campos vectoriales sparse y dense respectivamente, como se muestra en el siguiente ejemplo.

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

const search_param_1 = {
    "data": query_vector, 
    "anns_field": "dense", 
    "param": {
        "metric_type": "IP", // 参数值需要与 Collection Schema 中定义的保持一致
        "params": {"nprobe": 10}
    },
    "limit": 2 // AnnSearchRequest 返还的搜索结果数量
}

const search_param_2 = {
    "data": query_sparse_vector, 
    "anns_field": "sparse", 
    "param": {
        "metric_type": "IP", // 参数值需要与 Collection Schema 中定义的保持一致
        "params": {"drop_ratio_build": 0.2}
    },
    "limit": 2 // AnnSearchRequest 返还的搜索结果数量
}

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
    }
 ]'

Dado que el parámetro limit se establece en 2, cada AnnSearchRequest devuelve 2 resultados de búsqueda. En este ejemplo, se crean 2 AnnSearchRequest, por lo que se devolverá un total de 4 resultados de búsqueda.

Configurar una estrategia de reordenación

Para combinar y jerarquizar los dos conjuntos de resultados de búsqueda de RNA, es necesario seleccionar una estrategia de jerarquización adecuada. Zilliz admite dos tipos de estrategia de reordenación: WeightedRanker y RRFRanker. A la hora de elegir una estrategia de reordenación, hay que tener en cuenta si se hace hincapié en una o varias búsquedas básicas de RNA en los campos vectoriales.

  • WeightedRanker: Esta estrategia se recomienda si necesita que los resultados hagan hincapié en un campo vectorial concreto. El WeightedRanker permite asignar pesos más altos a determinados campos vectoriales, enfatizándolos más. Por ejemplo, en las búsquedas multimodales, las descripciones textuales de una imagen podrían considerarse más importantes que los colores de esta imagen.

  • RRFRanker (Reciprocal Rank Fusion Ranker): Esta estrategia se recomienda cuando no hay un énfasis específico. El RRF puede equilibrar eficazmente la importancia de cada campo vectorial.

Para más detalles sobre los mecanismos de estas dos estrategias de reordenación, consulte Reordenación.

Los dos ejemplos siguientes muestran cómo utilizar las estrategias de reordenación WeightedRanker y RRFRanker.

  1. Ejemplo 1: Uso de WeightedRanker

    Al utilizar la estrategia WeightedRanker, debe introducir valores de ponderación en la función WeightedRanker. El número de búsquedas básicas de RNA en una búsqueda híbrida corresponde al número de valores que hay que introducir. Los valores de entrada deben estar en el rango [0,1], con valores más cercanos a 1 indicando mayor importancia.

    from pymilvus import WeightedRanker
    
    rerank= 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));
    
    
    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]}
        }'
    
    
  2. Ejemplo 2: Uso de RRFRanker

    Cuando se utiliza la estrategia RRFRanker, es necesario introducir el valor del parámetro k en el RRFRanker. El valor predeterminado de k es 60. Este parámetro ayuda a determinar cómo se combinan los rangos de diferentes búsquedas de RNA, con el objetivo de equilibrar y mezclar la importancia entre todas las búsquedas.

    from pymilvus import RRFRanker
    
    ranker = RRFRanker(100)
    
    
    import io.milvus.v2.service.vector.request.ranker.BaseRanker;
    import io.milvus.v2.service.vector.request.ranker.RRFRanker;
    
    BaseRanker reranker = new RRFRanker(100);
    
    
    import { MilvusClient, DataType } from "@zilliz/milvus2-sdk-node";
    
    const rerank = RRFRanker("100");
    
    
    export rerank='{
            "strategy": "rrf",
            "params": { "k": 100}
        }'
    
    

Antes de realizar una búsqueda híbrida, es necesario cargar la colección en memoria. Si alguno de los campos vectoriales de la colección no tiene un índice o no está cargado, se producirá un error al llamar al método de Búsqueda Híbrida.

from pymilvus import MilvusClient

res = client.hybrid_search(
    collection_name="hybrid_search_collection",
    reqs=reqs,
    ranker=ranker,
    limit=2
)
for hits in res:
    print("TopK results:")
    for hit in hits:
        print(hit)

import io.milvus.v2.common.ConsistencyLevel;
import io.milvus.v2.service.vector.request.HybridSearchReq;
import io.milvus.v2.service.vector.response.SearchResp;

HybridSearchReq hybridSearchReq = HybridSearchReq.builder()
        .collectionName("hybrid_search_collection")
        .searchRequests(searchRequests)
        .ranker(reranker)
        .topK(2)
        .consistencyLevel(ConsistencyLevel.BOUNDED)
        .build();

SearchResp searchResp = client.hybridSearch(hybridSearchReq);

const { MilvusClient, DataType } = require("@zilliz/milvus2-sdk-node")

res = await client.loadCollection({
    collection_name: "hybrid_search_collection"
})

import { MilvusClient, RRFRanker, WeightedRanker } from '@zilliz/milvus2-sdk-node';

const search = await client.search({
  collection_name: "hybrid_search_collection",
  data: [search_param_1, search_param_2],
  limit: 2,
  rerank: RRFRanker(100)
});

curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/advanced_search" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d "{
    \"collectionName\": \"hybrid_search_collection\",
    \"search\": ${req},
    \"rerank\": {
        \"strategy\":\"rrf\",
        \"params\": {
            \"k\": 10
        }
    },
    \"limit\": 3,
    \"outputFields\": [
        \"user_id\",
        \"word_count\",
        \"book_describe\"
    ]
}"

A continuación se muestra el resultado.

["['id: 844, distance: 0.006047376897186041, entity: {}', 'id: 876, distance: 0.006422005593776703, entity: {}']"]

Dado que limit=2 se especifica en la Búsqueda Híbrida, Zilliz reordenará los cuatro resultados de búsqueda del paso 3 y finalmente devolverá sólo los 2 resultados de búsqueda más similares.

Traducido porDeepL

Try Managed Milvus for Free

Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.

Get Started
Feedback

¿Fue útil esta página?

How we use cookies

This website stores cookies on your computer. By continuing to browse or by clicking ‘Accept’, you agree to the storing of cookies on your device to enhance your site experience and for analytical purposes.