milvus-logo
LFAI
Casa
  • Guida per l'utente

Ricerca per raggruppamento

Una ricerca di raggruppamento consente a Milvus di raggruppare i risultati della ricerca in base ai valori di un campo specifico per aggregare i dati a un livello superiore. Ad esempio, è possibile utilizzare una ricerca RNA di base per trovare libri simili a quello in questione, ma è possibile utilizzare una ricerca di raggruppamento per trovare le categorie di libri che possono riguardare gli argomenti trattati in quel libro. Questo argomento descrive come utilizzare la ricerca per raggruppamento e le considerazioni principali.

Panoramica

Quando le entità nei risultati della ricerca condividono lo stesso valore in un campo scalare, ciò indica che sono simili in un particolare attributo, il che può avere un impatto negativo sui risultati della ricerca.

Si supponga che una collezione contenga più documenti (indicati da docId). Per conservare il maggior numero possibile di informazioni semantiche durante la conversione dei documenti in vettori, ogni documento viene suddiviso in paragrafi (o chunks) più piccoli e gestibili e memorizzato come entità separate. Anche se il documento è diviso in sezioni più piccole, gli utenti sono spesso interessati a identificare i documenti più rilevanti per le loro esigenze.

ANN Search Ricerca ANN

Quando si esegue una ricerca approssimativa dei vicini (ANN) su una raccolta di questo tipo, i risultati della ricerca possono includere diversi paragrafi dello stesso documento, facendo potenzialmente trascurare altri documenti, che potrebbero non essere in linea con il caso d'uso previsto.

Grouping Search Raggruppamento della ricerca

Per migliorare la varietà dei risultati della ricerca, è possibile aggiungere il parametro group_by_field nella richiesta di ricerca per attivare la ricerca per gruppi. Come mostrato nel diagramma, è possibile impostare group_by_field su docId. Quando riceve questa richiesta, Milvus.

  • Esegue una ricerca ANN basata sul vettore di query fornito per trovare tutte le entità più simili alla query.

  • Raggruppa i risultati della ricerca in base a group_by_field, ad esempio docId.

  • Restituisce i primi risultati per ogni gruppo, come definito dal parametro limit, con l'entità più simile di ogni gruppo.

Per impostazione predefinita, la ricerca per gruppi restituisce solo un'entità per gruppo. Se si desidera aumentare il numero di risultati da restituire per gruppo, è possibile controllarlo con i parametri group_size e strict_group_size.

Questa sezione fornisce un esempio di codice per dimostrare l'uso della ricerca per gruppi. L'esempio seguente presuppone che l'insieme includa i campi id, vector, chunk e docId.

[
        {"id": 0, "vector": [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592], "chunk": "pink_8682", "docId": 1},
        {"id": 1, "vector": [0.19886812562848388, 0.06023560599112088, 0.6976963061752597, 0.2614474506242501, 0.838729485096104], "chunk": "red_7025", "docId": 5},
        {"id": 2, "vector": [0.43742130801983836, -0.5597502546264526, 0.6457887650909682, 0.7894058910881185, 0.20785793220625592], "chunk": "orange_6781", "docId": 2},
        {"id": 3, "vector": [0.3172005263489739, 0.9719044792798428, -0.36981146090600725, -0.4860894583077995, 0.95791889146345], "chunk": "pink_9298", "docId": 3},
        {"id": 4, "vector": [0.4452349528804562, -0.8757026943054742, 0.8220779437047674, 0.46406290649483184, 0.30337481143159106], "chunk": "red_4794", "docId": 3},
        {"id": 5, "vector": [0.985825131989184, -0.8144651566660419, 0.6299267002202009, 0.1206906911183383, -0.1446277761879955], "chunk": "yellow_4222", "docId": 4},
        {"id": 6, "vector": [0.8371977790571115, -0.015764369584852833, -0.31062937026679327, -0.562666951622192, -0.8984947637863987], "chunk": "red_9392", "docId": 1},
        {"id": 7, "vector": [-0.33445148015177995, -0.2567135004164067, 0.8987539745369246, 0.9402995886420709, 0.5378064918413052], "chunk": "grey_8510", "docId": 2},
        {"id": 8, "vector": [0.39524717779832685, 0.4000257286739164, -0.5890507376891594, -0.8650502298996872, -0.6140360785406336], "chunk": "white_9381", "docId": 5},
        {"id": 9, "vector": [0.5718280481994695, 0.24070317428066512, -0.3737913482606834, -0.06726932177492717, -0.6980531615588608], "chunk": "purple_4976", "docId": 3},
]


Nella richiesta di ricerca, impostare sia group_by_field che output_fields su docId. Milvus raggrupperà i risultati in base al campo specificato e restituirà l'entità più simile di ogni gruppo, includendo il valore di docId per ogni entità restituita.

from pymilvus import MilvusClient

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

query_vectors = [
    [0.14529211512077012, 0.9147257273453546, 0.7965055218724449, 0.7009258593102812, 0.5605206522382088]]

# Group search results
res = client.search(
    collection_name="group_search_collection",
    data=query_vectors,
    limit=3,
    group_by_field="docId",
    output_fields=["docId"]
)

# Retrieve the values in the `docId` column
doc_ids = [result['entity']['docId'] for result in res[0]]

import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.service.vector.request.SearchReq
import io.milvus.v2.service.vector.request.data.FloatVec;
import io.milvus.v2.service.vector.response.SearchResp

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

FloatVec queryVector = new FloatVec(new float[]{0.14529211512077012f, 0.9147257273453546f, 0.7965055218724449f, 0.7009258593102812f, 0.5605206522382088f});
SearchReq searchReq = SearchReq.builder()
        .collectionName("group_search_collection")
        .data(Collections.singletonList(queryVector))
        .topK(3)
        .groupByFieldName("docId")
        .outputFields(Collections.singletonList("docId"))
        .build();

SearchResp searchResp = client.search(searchReq);

List<List<SearchResp.SearchResult>> searchResults = searchResp.getSearchResults();
for (List<SearchResp.SearchResult> results : searchResults) {
    System.out.println("TopK results:");
    for (SearchResp.SearchResult result : results) {
        System.out.println(result);
    }
}

// Output
// TopK results:
// SearchResp.SearchResult(entity={docId=5}, score=0.74767184, id=1)
// SearchResp.SearchResult(entity={docId=2}, score=0.6254269, id=7)
// SearchResp.SearchResult(entity={docId=3}, score=0.3611898, id=3)

// nolint
func ExampleClient_Search_grouping() {
    ctx, cancel := context.WithCancel(context.Background())
    defer cancel()

    milvusAddr := "127.0.0.1:19530"
    token := "root:Milvus"

    cli, err := client.New(ctx, &client.ClientConfig{
        Address: milvusAddr,
        APIKey:  token,
    })
    if err != nil {
        log.Fatal("failed to connect to milvus server: ", err.Error())
    }

    defer cli.Close(ctx)

    queryVector := []float32{0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592}

    resultSets, err := cli.Search(ctx, client.NewSearchOption(
        "my_collection", // collectionName
        3,               // limit
        []entity.Vector{entity.FloatVector(queryVector)},
    ).WithGroupByField("docId"))
    if err != nil {
        log.Fatal("failed to perform basic ANN search collection: ", err.Error())
    }

    for _, resultSet := range resultSets {
        log.Println("IDs: ", resultSet.IDs)
        log.Println("Scores: ", resultSet.Scores)
    }
    // Output:
    // IDs:
    // Scores:
}

import { MilvusClient, DataType } from "@zilliz/milvus2-sdk-node";

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

var query_vector = [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]

res = await client.search({
    collection_name: "my_collection",
    data: [query_vector],
    limit: 3,
    // highlight-start
    group_by_field: "docId"
    // highlight-end
})

// Retrieve the values in the `docId` column
var docIds = res.results.map(result => result.entity.docId)

export CLUSTER_ENDPOINT="http://localhost:19530"
export TOKEN="root:Milvus"

curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/search" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
    "collectionName": "group_search_collection",
    "data": [
        [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]
    ],
    "annsField": "vector",
    "limit": 3,
    "groupingField": "docId",
    "outputFields": ["docId"]
}'

Nella richiesta qui sopra, limit=3 indica che il sistema restituirà i risultati della ricerca da tre gruppi, con ogni gruppo contenente la singola entità più simile al vettore della query.

Configurare la dimensione dei gruppi

Per impostazione predefinita, la ricerca per gruppi restituisce solo un'entità per gruppo. Se si desidera ottenere più risultati per gruppo, regolare i parametri group_size e strict_group_size.

# Group search results

res = client.search(
    collection_name="group_search_collection", 
    data=query_vectors, # Query vector
    limit=5, # Top K results to return
    group_by_field="docId", # Group by docId
    group_size=2, # Return 2 entities per group
    strict_group_size=True, # Ensure each group has 2 entities
    output_fields=["docId"]
)

FloatVec queryVector = new FloatVec(new float[]{0.14529211512077012f, 0.9147257273453546f, 0.7965055218724449f, 0.7009258593102812f, 0.5605206522382088f});
SearchReq searchReq = SearchReq.builder()
        .collectionName("group_search_collection")
        .data(Collections.singletonList(queryVector))
        .topK(5)
        .groupByFieldName("docId")
        .groupSize(2)
        .strictGroupSize(true)
        .outputFields(Collections.singletonList("docId"))
        .build();

SearchResp searchResp = client.search(searchReq);

List<List<SearchResp.SearchResult>> searchResults = searchResp.getSearchResults();
for (List<SearchResp.SearchResult> results : searchResults) {
    System.out.println("TopK results:");
    for (SearchResp.SearchResult result : results) {
        System.out.println(result);
    }
}

// Output
// TopK results:
// SearchResp.SearchResult(entity={docId=5}, score=0.74767184, id=1)
// SearchResp.SearchResult(entity={docId=5}, score=-0.49148706, id=8)
// SearchResp.SearchResult(entity={docId=2}, score=0.6254269, id=7)
// SearchResp.SearchResult(entity={docId=2}, score=0.38515577, id=2)
// SearchResp.SearchResult(entity={docId=3}, score=0.3611898, id=3)
// SearchResp.SearchResult(entity={docId=3}, score=0.19556211, id=4)

import { MilvusClient, DataType } from "@zilliz/milvus2-sdk-node";

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

var query_vector = [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]

res = await client.search({
    collection_name: "my_collection",
    data: [query_vector],
    limit: 3,
    group_by_field: "docId",
    // highlight-start
    group_size: 2,
    strict_group_size: true
    // highlight-end
})

// Retrieve the values in the `docId` column
var docIds = res.results.map(result => result.entity.docId)

curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/search" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
    "collectionName": "group_search_collection",
    "data": [
        [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]
    ],
    "annsField": "vector",
    "limit": 5,
    "groupingField": "docId",
    "groupSize":2,
    "strictGroupSize":true,
    "outputFields": ["docId"]
}'

Nell'esempio precedente.

  • group_size: Specifica il numero desiderato di entità da restituire per gruppo. Per esempio, impostando group_size=2 si intende che ogni gruppo (o ogni docId) dovrebbe idealmente restituire due dei paragrafi (o pezzi) più simili. Se group_size non è impostato, il sistema restituisce per default un risultato per gruppo.

  • strict_group_size: Questo parametro booleano controlla se il sistema deve applicare rigorosamente il conteggio impostato da group_size. Se strict_group_size=True, il sistema cercherà di includere il numero esatto di entità specificato da group_size in ogni gruppo (ad esempio, due paragrafi), a meno che non ci siano abbastanza dati in quel gruppo. Per impostazione predefinita (strict_group_size=False), il sistema dà la priorità al raggiungimento del numero di gruppi specificato dal parametro limit, piuttosto che assicurarsi che ogni gruppo contenga le entità di group_size. Questo approccio è generalmente più efficiente nei casi in cui la distribuzione dei dati non è uniforme.

Per ulteriori dettagli sui parametri, fare riferimento a search().

Considerazioni

  • Numero di gruppi: Il parametro limit controlla il numero di gruppi da cui vengono restituiti i risultati della ricerca, piuttosto che il numero specifico di entità all'interno di ciascun gruppo. L'impostazione di un limit appropriato aiuta a controllare la diversità della ricerca e le prestazioni della query. Ridurre limit può ridurre i costi di calcolo se i dati sono distribuiti densamente o se le prestazioni sono un problema.

  • Entità per gruppo: Il parametro group_size controlla il numero di entità restituite per gruppo. La regolazione di group_size in base al caso d'uso può aumentare la ricchezza dei risultati della ricerca. Tuttavia, se i dati sono distribuiti in modo non uniforme, alcuni gruppi potrebbero restituire un numero di entità inferiore a quello specificato da group_size, in particolare in scenari di dati limitati.

  • Dimensione rigida del gruppo: Quando si utilizza strict_group_size=True, il sistema cercherà di restituire il numero di entità specificato (group_size) per ogni gruppo, a meno che non ci siano abbastanza dati in quel gruppo. Questa impostazione garantisce un conteggio coerente delle entità per gruppo, ma può comportare un calo delle prestazioni in caso di distribuzione non uniforme dei dati o di risorse limitate. Se non è richiesto un numero rigido di entità, l'impostazione di strict_group_size=False può migliorare la velocità delle query.

Tradotto daDeepLogo

Try Managed Milvus for Free

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

Get Started
Feedback

Questa pagina è stata utile?