milvus-logo
LFAI
Casa
  • Guida per l'utente

Ricerca ibrida

La ricerca ibrida si riferisce a un metodo di ricerca che conduce simultaneamente più ricerche di RNA, rielabora più serie di risultati da queste ricerche di RNA e alla fine restituisce una singola serie di risultati. L'uso della ricerca ibrida può migliorare l'accuratezza della ricerca. Zilliz supporta l'esecuzione di una ricerca ibrida su una collezione con più campi vettoriali.

La ricerca ibrida è più comunemente utilizzata in scenari che includono ricerche vettoriali rade e dense e ricerche multimodali. Questa guida illustra come condurre una ricerca ibrida in Zilliz con un esempio specifico.

Scenari

La ricerca ibrida è adatta ai due scenari seguenti.

Diversi tipi di vettori possono rappresentare informazioni diverse e l'uso di vari modelli di incorporazione può rappresentare in modo più completo diverse caratteristiche e aspetti dei dati. Ad esempio, l'uso di diversi modelli di incorporamento per la stessa frase può generare un vettore denso per rappresentare il significato semantico e un vettore rado per rappresentare la frequenza delle parole nella frase.

  • Vettori sparsi: I vettori sparsi sono caratterizzati da un'elevata dimensionalità del vettore e dalla presenza di pochi valori non nulli. Questa struttura li rende particolarmente adatti alle applicazioni tradizionali di information retrieval. Nella maggior parte dei casi, il numero di dimensioni utilizzate nei vettori sparsi corrisponde a diversi token in una o più lingue. A ogni dimensione viene assegnato un valore che indica l'importanza relativa di quel token all'interno del documento. Questa disposizione si rivela vantaggiosa per i compiti che prevedono la corrispondenza del testo.

  • Vettori densi: I vettori densi sono incorporazioni derivate dalle reti neurali. Disposti in un array ordinato, questi vettori catturano l'essenza semantica del testo in ingresso. Si noti che i vettori densi non sono limitati all'elaborazione del testo; sono anche ampiamente utilizzati nella computer vision per rappresentare la semantica dei dati visivi. Questi vettori densi, di solito generati da modelli di incorporazione del testo, sono caratterizzati dalla maggior parte o da tutti gli elementi non nulli. Pertanto, i vettori densi sono particolarmente efficaci per le applicazioni di ricerca semantica, in quanto possono restituire i risultati più simili in base alla distanza vettoriale anche in assenza di corrispondenze testuali esatte. Questa capacità consente di ottenere risultati di ricerca più sfumati e consapevoli del contesto, spesso cogliendo relazioni tra concetti che potrebbero sfuggire agli approcci basati sulle parole chiave.

Per maggiori dettagli, consultare Sparse Vector e Dense Vector.

La ricerca multimodale si riferisce alla ricerca di similarità di dati non strutturati attraverso più modalità (come immagini, video, audio, testo, ecc.). Ad esempio, una persona può essere rappresentata utilizzando diverse modalità di dati, come le impronte digitali, le impronte vocali e i tratti del viso. La ricerca ibrida supporta più ricerche simultanee. Ad esempio, la ricerca di una persona con impronte digitali e impronte vocali simili.

Flusso di lavoro

Il flusso di lavoro principale per condurre una ricerca ibrida è il seguente.

  1. Generare vettori densi attraverso modelli di embedding come BERT e Transformers.

  2. Generare vettori radi attraverso modelli di embedding come BM25, BGE-M3, SPLADE, ecc.

  3. Creare una collezione in Zilliz e definire lo schema della collezione che include campi vettoriali densi e radi.

  4. Inserire i vettori sparsi-densi nella collezione appena creata nel passaggio precedente.

  5. Eseguire una ricerca ibrida: La ricerca ANN sui vettori densi restituirà un insieme di risultati top-K più simili, mentre la corrispondenza testuale sui vettori radi restituirà anch'essa un insieme di risultati top-K.

  6. Normalizzazione: Normalizzare i punteggi delle due serie di risultati top-K, convertendo i punteggi in un intervallo compreso tra [0,1].

  7. Scegliere una strategia di reranking appropriata per unire e rerankare i due insiemi di risultati top-K e restituire infine un insieme finale di risultati top-K.

Hybrid Search Workflow Flusso di lavoro della ricerca ibrida

Esempi

Questa sezione utilizzerà un esempio specifico per illustrare come condurre una ricerca ibrida su vettori sparsi e densi per migliorare l'accuratezza delle ricerche di testo.

Creare una raccolta con più campi vettoriali

Il processo di creazione di una raccolta comprende tre parti: definizione dello schema della raccolta, configurazione dei parametri dell'indice e creazione della raccolta.

Definire lo schema

In questo esempio, è necessario definire più campi vettoriali nello schema della collezione. Attualmente, ogni collezione può includere fino a 4 campi vettoriali per impostazione predefinita. Ma è possibile modificare il valore di proxy.maxVectorFieldNum per includere fino a 10 campi vettoriali in una collezione, se necessario.

L'esempio seguente definisce uno schema di collezione, dove dense e sparse sono i due campi vettoriali.

  • id: Questo campo serve come chiave primaria per memorizzare gli ID del testo. Il tipo di dati di questo campo è INT64.

  • text: Questo campo è utilizzato per memorizzare il contenuto testuale. Il tipo di dati di questo campo è VARCHAR, con una lunghezza massima di 1000 caratteri.

  • dense: Questo campo viene utilizzato per memorizzare i vettori densi dei testi. Il tipo di dati di questo campo è FLOAT_VECTOR, con una dimensione del vettore di 768.

  • sparse: Questo campo viene utilizzato per memorizzare i vettori sparsi dei testi. Il tipo di dati di questo campo è 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 le ricerche di vettori sparsi, è possibile semplificare il processo di generazione di vettori di incorporamento sparsi sfruttando le funzionalità di Full Text Search. Per maggiori dettagli, vedere Ricerca a testo completo.

Creare l'indice

Dopo aver definito lo schema della collezione, è necessario impostare gli indici dei vettori e le metriche di somiglianza. In questo esempio, viene creato un indice IVF_FLAT per il campo vettoriale denso dense, e uno SPARSE_INVERTED_INDEX per il campo vettoriale rado sparse. Per conoscere i tipi di indici supportati, vedere Indice spiegato.

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

Creare una collezione

Creare una collezione chiamata demo con lo schema della collezione e gli indici configurati nei due passi precedenti.

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
}"

Inserire i dati

Inserire i vettori sparsi e densi nella collezione 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"
}'

Creare istanze multiple di AnnSearchRequest

La ricerca ibrida è implementata creando più istanze AnnSearchRequest nella funzione hybrid_search(), dove ogni AnnSearchRequest rappresenta una richiesta di ricerca ANN di base per uno specifico campo vettoriale. Pertanto, prima di effettuare una ricerca ibrida, è necessario creare un AnnSearchRequest per ogni campo vettoriale.

Nella Ricerca ibrida, ogni AnnSearchRequest supporta un solo vettore di interrogazione.

Supponiamo che il testo della query "Who started AI research?" sia già stato convertito in vettori sparsi e densi. Su questa base, vengono create due richieste di ricerca AnnSearchRequest per i campi vettoriali sparse e dense rispettivamente, come mostrato nell'esempio seguente.

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

Poiché il parametro limit è impostato su 2, ogni AnnSearchRequest restituisce 2 risultati di ricerca. In questo esempio, sono stati creati 2 AnnSearchRequest, quindi verranno restituiti in totale 4 risultati di ricerca.

Configurare una strategia di reranking

Per unire e classificare i due gruppi di risultati di ricerca ANN, è necessario selezionare una strategia di reranking appropriata. Zilliz supporta due tipi di strategia di reranking: WeightedRanker e RRFRanker. Quando si sceglie una strategia di reranking, una cosa da considerare è se c'è un'enfasi per una o più ricerche RNA di base sui campi vettoriali.

  • WeightedRanker: Questa strategia è consigliata se si desidera che i risultati enfatizzino un particolare campo vettoriale. Il WeightedRanker consente di assegnare pesi maggiori a determinati campi vettoriali, enfatizzandoli maggiormente. Ad esempio, nelle ricerche multimodali, le descrizioni testuali di un'immagine potrebbero essere considerate più importanti dei colori presenti nell'immagine.

  • RRFRanker (Reciprocal Rank Fusion Ranker): Questa strategia è consigliata quando non c'è un'enfasi specifica. L'RRF può bilanciare efficacemente l'importanza di ciascun campo vettoriale.

Per maggiori dettagli sui meccanismi di queste due strategie di reranking, consultare Reranking.

I due esempi seguenti mostrano come utilizzare le strategie di reranking WeightedRanker e RRFRanker.

  1. Esempio 1: Uso del WeightedRanker

    Quando si utilizza la strategia WeightedRanker, è necessario inserire i valori dei pesi nella funzione WeightedRanker. Il numero di ricerche della RNA di base in una ricerca ibrida corrisponde al numero di valori che devono essere immessi. I valori inseriti devono essere compresi nell'intervallo [0,1], con valori più vicini a 1 che indicano una maggiore importanza.

    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. Esempio 2: Utilizzo di RRFRanker

    Quando si utilizza la strategia RRFRanker, è necessario inserire il valore del parametro k nel RRFRanker. Il valore predefinito di k è 60. Questo parametro aiuta a determinare il modo in cui vengono combinati i ranghi delle diverse ricerche di RNA, con l'obiettivo di bilanciare e fondere l'importanza di tutte le ricerche.

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

Prima di eseguire una ricerca ibrida, è necessario caricare la collezione in memoria. Se i campi vettoriali dell'insieme non hanno un indice o non sono caricati, si verificherà un errore durante la chiamata al metodo Hybrid Search.

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\"
    ]
}"

L'output è il seguente.

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

Dal momento che limit=2 è specificato nella ricerca ibrida, Zilliz esegue un rerank dei quattro risultati di ricerca del passo 3 e restituisce solo i primi due risultati più simili.

Tradotto daDeepL

Try Managed Milvus for Free

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

Get Started
Feedback

Questa pagina è stata utile?