milvus-logo
LFAI
Home
  • Benutzerhandbuch

Hybride Suche

Die hybride Suche bezieht sich auf eine Suchmethode, die mehrere ANN-Suchen gleichzeitig durchführt, mehrere Ergebnissätze aus diesen ANN-Suchen neu ordnet und schließlich einen einzigen Ergebnissatz liefert. Die Verwendung von Hybrid Search kann die Suchgenauigkeit verbessern. Zilliz unterstützt die Durchführung von Hybrid Search in einer Sammlung mit mehreren Vektorfeldern.

Die hybride Suche wird am häufigsten in Szenarien mit spärlichen und dichten Vektorsuchen und multimodalen Suchen verwendet. In diesem Leitfaden wird anhand eines konkreten Beispiels gezeigt, wie eine Hybrid-Suche in Zilliz durchgeführt werden kann.

Szenarien

Die hybride Suche eignet sich für die folgenden beiden Szenarien.

Verschiedene Arten von Vektoren können unterschiedliche Informationen repräsentieren, und die Verwendung verschiedener Einbettungsmodelle kann verschiedene Merkmale und Aspekte der Daten umfassender darstellen. Zum Beispiel kann die Verwendung verschiedener Einbettungsmodelle für denselben Satz einen dichten Vektor zur Darstellung der semantischen Bedeutung und einen spärlichen Vektor zur Darstellung der Worthäufigkeit im Satz erzeugen.

  • Spärliche Vektoren: Spärliche Vektoren zeichnen sich durch ihre hohe Vektordimensionalität und das Vorhandensein von wenigen Nicht-Null-Werten aus. Aufgrund dieser Struktur eignen sie sich besonders gut für traditionelle Information Retrieval-Anwendungen. In den meisten Fällen entspricht die Anzahl der Dimensionen, die in spärlichen Vektoren verwendet werden, den verschiedenen Token in einer oder mehreren Sprachen. Jeder Dimension wird ein Wert zugewiesen, der die relative Bedeutung dieses Tokens innerhalb des Dokuments angibt. Dieses Layout erweist sich als vorteilhaft für Aufgaben, die einen Textabgleich beinhalten.

  • Dichte Vektoren: Dichte Vektoren sind von neuronalen Netzen abgeleitete Einbettungen. Wenn sie in einem geordneten Array angeordnet sind, erfassen diese Vektoren das semantische Wesen des Eingabetextes. Dichte Vektoren sind nicht auf die Textverarbeitung beschränkt; sie werden auch häufig in der Computer Vision verwendet, um die Semantik von visuellen Daten darzustellen. Diese dichten Vektoren, die in der Regel durch Modelle zur Texteinbettung erzeugt werden, zeichnen sich dadurch aus, dass die meisten oder alle Elemente ungleich Null sind. Daher eignen sich dichte Vektoren besonders gut für semantische Suchanwendungen, da sie auf der Grundlage der Vektordistanz die ähnlichsten Ergebnisse liefern können, selbst wenn es keine exakten Textübereinstimmungen gibt. Diese Fähigkeit ermöglicht nuanciertere und kontextbezogene Suchergebnisse, die oft Beziehungen zwischen Konzepten erfassen, die bei schlagwortbasierten Ansätzen übersehen werden könnten.

Weitere Einzelheiten finden Sie unter Sparse Vector und Dense Vector.

Multimodale Suche bezieht sich auf die Ähnlichkeitssuche von unstrukturierten Daten über mehrere Modalitäten hinweg (wie Bilder, Videos, Audio, Text usw.). Eine Person kann beispielsweise durch verschiedene Modalitäten von Daten wie Fingerabdrücke, Stimmabdrücke und Gesichtsmerkmale dargestellt werden. Die hybride Suche unterstützt mehrere Suchvorgänge gleichzeitig. Zum Beispiel die Suche nach einer Person mit ähnlichen Fingerabdrücken und Stimmabdrücken.

Arbeitsablauf

Der Hauptarbeitsablauf für die Durchführung einer hybriden Suche sieht wie folgt aus.

  1. Erzeugen von dichten Vektoren durch Einbettungsmodelle wie BERT und Transformers.

  2. Generierung von spärlichen Vektoren durch Einbettungsmodelle wie BM25, BGE-M3, SPLADE, etc.

  3. Erstellen Sie eine Sammlung in Zilliz und definieren Sie das Sammlungsschema, das sowohl dichte als auch spärliche Vektorfelder enthält.

  4. Fügen Sie spärlich-dichte Vektoren in die im vorherigen Schritt erstellte Sammlung ein.

  5. Führen Sie eine hybride Suche durch: Die ANN-Suche auf dichten Vektoren liefert eine Reihe von Top-K-Ergebnissen, die am ähnlichsten sind, und der Textabgleich auf spärlichen Vektoren liefert ebenfalls eine Reihe von Top-K-Ergebnissen.

  6. Normalisierung: Normalisieren Sie die Punktzahlen der beiden Sätze von Top-K-Ergebnissen, indem Sie die Punktzahlen in einen Bereich zwischen [0,1] umwandeln.

  7. Wählen Sie eine geeignete Reranking-Strategie, um die beiden Gruppen von Top-K-Ergebnissen zusammenzuführen und neu zu ordnen und schließlich eine endgültige Gruppe von Top-K-Ergebnissen zu erhalten.

Hybrid Search Workflow Hybrider Such-Workflow

Beispiele

In diesem Abschnitt wird anhand eines konkreten Beispiels gezeigt, wie eine hybride Suche auf spärlich dichten Vektoren durchgeführt werden kann, um die Genauigkeit der Textsuche zu verbessern.

Erstellen einer Sammlung mit mehreren Vektorfeldern

Der Prozess der Erstellung einer Sammlung umfasst drei Teile: Definieren des Schemas der Sammlung, Konfigurieren der Indexparameter und Erstellen der Sammlung.

Definieren des Schemas

In diesem Beispiel müssen mehrere Vektorfelder im Schema der Sammlung definiert werden. Derzeit kann jede Sammlung standardmäßig bis zu 4 Vektorfelder enthalten. Sie können aber auch den Wert von proxy.maxVectorFieldNum ändern, um bei Bedarf bis zu 10 Vektorfelder in eine Sammlung aufzunehmen.

Das folgende Beispiel definiert ein Auflistungsschema, wobei dense und sparse die beiden Vektorfelder sind.

  • id: Dieses Feld dient als Primärschlüssel für die Speicherung von Text-IDs. Der Datentyp dieses Feldes ist INT64.

  • text: Dieses Feld dient zur Speicherung von Textinhalten. Der Datentyp dieses Feldes ist VARCHAR, mit einer maximalen Länge von 1000 Zeichen.

  • dense: In diesem Feld werden die dichten Vektoren der Texte gespeichert. Der Datentyp dieses Feldes ist FLOAT_VECTOR, mit einer Vektordimension von 768.

  • sparse: In diesem Feld werden die spärlichen Vektoren der Texte gespeichert. Der Datentyp dieses Feldes ist 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"
                }
            }
        ]
    }'

Bei der Suche nach Sparse Vectors können Sie den Prozess der Erzeugung von Sparse Embedding Vectors vereinfachen, indem Sie die Funktionen der Volltextsuche nutzen. Weitere Einzelheiten finden Sie unter Volltextsuche.

Index erstellen

Nach der Definition des Sammelschemas müssen die Vektorindizes und die Ähnlichkeitsmetriken eingerichtet werden. In diesem Beispiel wird ein IVF_FLAT-Index für das dichte Vektorfeld dense und ein SPARSE_INVERTED_INDEX für das spärliche Vektorfeld sparse erstellt. Weitere Informationen zu den unterstützten Indextypen finden Sie unter Index erklärt.

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

Sammlung erstellen

Erstellen Sie eine Sammlung mit dem Namen demo mit dem Sammlungsschema und den Indizes, die in den beiden vorherigen Schritten konfiguriert wurden.

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

Daten einfügen

Fügen Sie die sparse-denses Vektoren in die Sammlung demo ein.

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

Mehrere AnnSearchRequest-Instanzen erstellen

Die hybride Suche wird durch die Erstellung mehrerer AnnSearchRequest in der Funktion hybrid_search() implementiert, wobei jede AnnSearchRequest eine grundlegende ANN-Suchanfrage für ein bestimmtes Vektorfeld darstellt. Daher muss vor der Durchführung einer Hybrid Search für jedes Vektorfeld eine AnnSearchRequest erstellt werden.

Bei der hybriden Suche unterstützt jedes AnnSearchRequest nur einen Abfragevektor.

Angenommen, der Abfragetext "Wer begann mit der KI-Forschung?" wurde bereits in sparse und dense Vektoren umgewandelt. Auf dieser Grundlage werden zwei AnnSearchRequest Suchanfragen für die Vektorfelder sparse und dense erstellt, wie im folgenden Beispiel gezeigt.

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

Da der Parameter limit auf 2 gesetzt ist, liefert jede AnnSearchRequest 2 Suchergebnisse. In diesem Beispiel werden 2 AnnSearchRequest erstellt, daher werden insgesamt 4 Suchergebnisse zurückgegeben.

Konfigurieren Sie eine Ranglistenstrategie

Um die beiden Gruppen von ANN-Suchergebnissen zusammenzuführen und neu zu ordnen, ist es notwendig, eine geeignete Rangordnungsstrategie zu wählen. Zilliz unterstützt zwei Arten von Reranking-Strategien: WeightedRanker und RRFRanker. Bei der Wahl der Reranking-Strategie muss unter anderem berücksichtigt werden, ob eine oder mehrere ANN-Basissuchen auf den Vektorfeldern einen Schwerpunkt bilden.

  • WeightedRanker: Diese Strategie wird empfohlen, wenn die Ergebnisse ein bestimmtes Vektorfeld betonen sollen. Mit dem WeightedRanker können Sie bestimmten Vektorfeldern eine höhere Gewichtung zuweisen und sie damit stärker hervorheben. Bei einer multimodalen Suche könnten beispielsweise Textbeschreibungen eines Bildes als wichtiger angesehen werden als die Farben dieses Bildes.

  • RRFRanker (Reciprocal Rank Fusion Ranker): Diese Strategie wird empfohlen, wenn es keine besondere Gewichtung gibt. Der RRF kann die Bedeutung der einzelnen Vektorfelder effektiv ausgleichen.

Weitere Einzelheiten zu den Mechanismen dieser beiden Reranking-Strategien finden Sie unter Reranking.

Die folgenden zwei Beispiele zeigen, wie die Reranking-Strategien WeightedRanker und RRFRanker verwendet werden können.

  1. Beispiel 1: Verwendung von WeightedRanker

    Wenn Sie die WeightedRanker-Strategie verwenden, müssen Sie Gewichtungswerte in die Funktion WeightedRanker eingeben. Die Anzahl der ANN-Basissuchen in einer Hybrid Search entspricht der Anzahl der einzugebenden Werte. Die Eingabewerte sollten im Bereich [0,1] liegen, wobei Werte, die näher an 1 liegen, eine größere Wichtigkeit anzeigen.

    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. Beispiel 2: Verwendung von RRFRanker

    Wenn Sie die RRFRanker-Strategie verwenden, müssen Sie den Parameterwert k in den RRFRanker eingeben. Der Standardwert von k ist 60. Mit diesem Parameter wird festgelegt, wie die Ränge aus verschiedenen ANN-Suchen kombiniert werden, um die Wichtigkeit über alle Suchen hinweg auszugleichen und zu mischen.

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

Bevor eine hybride Suche durchgeführt wird, muss die Sammlung in den Speicher geladen werden. Wenn die Vektorfelder in der Sammlung keinen Index haben oder nicht geladen sind, tritt beim Aufruf der Methode Hybrid Search ein Fehler auf.

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

Es folgt die Ausgabe.

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

Da limit=2 in der Hybrid Search angegeben ist, wird Zilliz die vier Suchergebnisse aus Schritt 3 neu ordnen und schließlich nur die zwei ähnlichsten Suchergebnisse zurückgeben.

Übersetzt vonDeepL

Try Managed Milvus for Free

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

Get Started
Feedback

War diese Seite hilfreich?