🚀 Coba Zilliz Cloud, Milvus yang sepenuhnya terkelola, secara gratis—rasakan performa 10x lebih cepat! Coba Sekarang>>

milvus-logo
LFAI
Beranda
  • Panduan Pengguna
  • Home
  • Docs
  • Panduan Pengguna

  • Cari & Beri Peringkat Ulang

  • Pencarian Pengelompokan

Pencarian Pengelompokan

Pencarian pengelompokan memungkinkan Milvus mengelompokkan hasil pencarian berdasarkan nilai dalam bidang tertentu untuk mengumpulkan data pada tingkat yang lebih tinggi. Sebagai contoh, Anda dapat menggunakan pencarian ANN dasar untuk menemukan buku yang mirip dengan buku yang sedang dicari, tetapi Anda dapat menggunakan pencarian pengelompokan untuk menemukan kategori buku yang mungkin melibatkan topik-topik yang dibahas dalam buku tersebut. Topik ini menjelaskan cara menggunakan Pencarian Pengelompokan bersama dengan pertimbangan-pertimbangan utama.

Ikhtisar

Ketika entitas dalam hasil pencarian memiliki nilai yang sama dalam bidang skalar, hal ini mengindikasikan bahwa entitas tersebut memiliki kemiripan dalam atribut tertentu, yang dapat berdampak negatif pada hasil pencarian.

Anggaplah sebuah koleksi menyimpan beberapa dokumen (dilambangkan dengan docId). Untuk mempertahankan informasi semantik sebanyak mungkin saat mengubah dokumen menjadi vektor, setiap dokumen dipecah menjadi paragraf yang lebih kecil dan mudah diatur (atau potongan) dan disimpan sebagai entitas terpisah. Meskipun dokumen dibagi menjadi beberapa bagian yang lebih kecil, pengguna sering kali masih tertarik untuk mengidentifikasi dokumen mana yang paling relevan dengan kebutuhan mereka.

ANN Search Pencarian ANN

Ketika melakukan pencarian Approximate Nearest Neighbor (ANN) pada koleksi seperti itu, hasil pencarian dapat mencakup beberapa paragraf dari dokumen yang sama, sehingga berpotensi menyebabkan dokumen lain terlewatkan, yang mungkin tidak sesuai dengan kasus penggunaan yang diinginkan.

Grouping Search Mengelompokkan Pencarian

Untuk meningkatkan keragaman hasil pencarian, Anda dapat menambahkan parameter group_by_field dalam permintaan pencarian untuk mengaktifkan Pencarian Pengelompokan. Seperti yang ditunjukkan pada diagram, Anda dapat mengatur group_by_field ke docId. Setelah menerima permintaan ini, Milvus akan.

  • Melakukan pencarian ANN berdasarkan vektor kueri yang disediakan untuk menemukan semua entitas yang paling mirip dengan kueri.

  • Mengelompokkan hasil pencarian berdasarkan group_by_field yang ditentukan, seperti docId.

  • Mengembalikan hasil teratas untuk setiap kelompok, seperti yang ditentukan oleh parameter limit, dengan entitas yang paling mirip dari setiap kelompok.

Secara default, Pencarian Pengelompokan hanya mengembalikan satu entitas per grup. Jika Anda ingin menambah jumlah hasil yang dikembalikan per grup, Anda dapat mengontrolnya dengan parameter group_size dan strict_group_size.

Bagian ini memberikan contoh kode untuk mendemonstrasikan penggunaan Pencarian Pengelompokan. Contoh berikut ini mengasumsikan koleksi mencakup bidang untuk id, vector, chunk, dan 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},
]


Dalam permintaan pencarian, setel group_by_field dan output_fields ke docId. Milvus akan mengelompokkan hasil berdasarkan bidang yang ditentukan dan mengembalikan entitas yang paling mirip dari setiap kelompok, termasuk nilai docId untuk setiap entitas yang dikembalikan.

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

Pada permintaan di atas, limit=3 menunjukkan bahwa sistem akan mengembalikan hasil pencarian dari tiga kelompok, dengan masing-masing kelompok berisi satu entitas yang paling mirip dengan vektor kueri.

Mengonfigurasi ukuran grup

Secara default, Pencarian Pengelompokan hanya mengembalikan satu entitas per grup. Jika Anda menginginkan beberapa hasil per grup, sesuaikan parameter group_size dan 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"]
}'

Dalam contoh di atas.

  • group_size: Menentukan jumlah entitas yang diinginkan untuk dikembalikan per grup. Sebagai contoh, pengaturan group_size=2 berarti setiap grup (atau setiap docId) idealnya mengembalikan dua paragraf (atau potongan) yang paling mirip. Jika group_size tidak disetel, sistem secara default mengembalikan satu hasil per grup.

  • strict_group_size: Parameter boolean ini mengontrol apakah sistem harus secara ketat memberlakukan hitungan yang ditetapkan oleh group_size. Ketika strict_group_size=True, sistem akan berusaha memasukkan jumlah entitas yang tepat yang ditentukan oleh group_size dalam setiap grup (misalnya, dua paragraf), kecuali jika tidak ada cukup data dalam grup tersebut. Secara default (strict_group_size=False), sistem akan memprioritaskan untuk memenuhi jumlah grup yang ditentukan oleh parameter limit, daripada memastikan setiap grup berisi entitas group_size. Pendekatan ini umumnya lebih efisien dalam kasus-kasus di mana distribusi data tidak merata.

Untuk detail parameter tambahan, lihat search().

Pertimbangan

  • Pengindeksan: Fitur pengelompokan ini hanya berfungsi untuk koleksi yang diindeks dengan jenis indeks berikut: FLAT, IVF_FLAT, IVF_SQ8, HNSW, HNSW_PQ, HNSW_PRQ, HNSW_SQ, DISKANN, SPARSE_INVERTED_INDEX.

  • Jumlah kelompok: Parameter limit mengontrol jumlah grup dari mana hasil pencarian dikembalikan, dan bukan jumlah spesifik entitas dalam setiap grup. Menetapkan limit yang sesuai membantu mengontrol keragaman pencarian dan kinerja kueri. Mengurangi limit dapat mengurangi biaya komputasi jika data terdistribusi secara padat atau kinerja menjadi perhatian.

  • Entitas per grup: Parameter group_size mengontrol jumlah entitas yang dikembalikan per grup. Menyesuaikan group_size berdasarkan kasus penggunaan Anda dapat meningkatkan kekayaan hasil pencarian. Namun, jika data tidak terdistribusi secara merata, beberapa grup mungkin mengembalikan lebih sedikit entitas daripada yang ditentukan oleh group_size, terutama dalam skenario data terbatas.

  • Ukuran kelompok yang ketat: Ketika strict_group_size=True, sistem akan berusaha mengembalikan jumlah entitas yang ditentukan (group_size) untuk setiap grup, kecuali jika tidak ada cukup data dalam grup tersebut. Pengaturan ini memastikan jumlah entitas yang konsisten per grup, tetapi dapat menyebabkan penurunan kinerja dengan distribusi data yang tidak merata atau sumber daya yang terbatas. Jika jumlah entitas yang ketat tidak diperlukan, pengaturan strict_group_size=False dapat meningkatkan kecepatan kueri.

Coba Milvus yang Dikelola secara Gratis

Zilliz Cloud bebas masalah, didukung oleh Milvus dan 10x lebih cepat.

Mulai
Umpan balik

Apakah halaman ini bermanfaat?