milvus-logo
LFAI
Home
  • Benutzerhandbuch

Einzelvektor-Suche

Nachdem Sie Ihre Daten eingefügt haben, besteht der nächste Schritt darin, eine Ähnlichkeitssuche in Ihrer Sammlung in Milvus durchzuführen.

Milvus ermöglicht Ihnen die Durchführung von zwei Arten von Suchen, je nach Anzahl der Vektorfelder in Ihrer Sammlung:

  • Einzelvektor-Suche: Wenn Ihre Sammlung nur ein Vektorfeld hat, verwenden Sie die search() Methode, um die ähnlichsten Entitäten zu finden. Diese Methode vergleicht Ihren Abfragevektor mit den vorhandenen Vektoren in Ihrer Sammlung und gibt die IDs der engsten Übereinstimmungen zusammen mit den Abständen zwischen ihnen zurück. Optional kann sie auch die Vektorwerte und Metadaten der Ergebnisse zurückgeben.
  • Hybride Suche: Für Sammlungen mit zwei oder mehr Vektorfeldern, verwenden Sie die hybrid_search() Methode. Diese Methode führt mehrere ANN-Suchanfragen (Approximate Nearest Neighbor) durch und kombiniert die Ergebnisse, um die relevantesten Übereinstimmungen nach einem Reranking zurückzugeben.

Diese Anleitung konzentriert sich auf die Durchführung einer Einzelvektorsuche in Milvus. Einzelheiten zur Hybrid-Suche finden Sie unter Hybrid-Suche.

Überblick

Es gibt eine Vielzahl von Suchtypen, die unterschiedlichen Anforderungen gerecht werden:

  • Einfache Suche: Umfasst die Einzelvektorsuche, die Massenvektorsuche, die Partitionssuche und die Suche mit bestimmten Ausgabefeldern.

  • Gefilterte Suche: Wendet Filterkriterien an, die auf skalaren Feldern basieren, um die Suchergebnisse zu verfeinern.

  • Bereichssuche: Findet Vektoren innerhalb eines bestimmten Abstandsbereichs vom Abfragevektor.

  • Gruppierungssuche: Gruppiert Suchergebnisse auf der Grundlage eines bestimmten Feldes, um die Vielfalt der Ergebnisse zu gewährleisten.

Vorbereitungen

Das folgende Codeschnipsel verwendet den bestehenden Code weiter, um eine Verbindung zu Milvus herzustellen und eine Sammlung schnell einzurichten.

from pymilvus import MilvusClient
import random

# 1. Set up a Milvus client
client = MilvusClient(
    uri="http://localhost:19530"
)

# 2. Create a collection
client.create_collection(
    collection_name="quick_setup",
    dimension=5,
    metric_type="IP"
)

# 3. Insert randomly generated vectors 
colors = ["green", "blue", "yellow", "red", "black", "white", "purple", "pink", "orange", "brown", "grey"]
data = []

for i in range(1000):
    current_color = random.choice(colors)
    data.append({
        "id": i,
        "vector": [ random.uniform(-1, 1) for _ in range(5) ],
        "color": current_color,
        "color_tag": f"{current_color}_{str(random.randint(1000, 9999))}"
    })

res = client.insert(
    collection_name="quick_setup",
    data=data
)

print(res)

# Output
#
# {
#     "insert_count": 1000,
#     "ids": [
#         0,
#         1,
#         2,
#         3,
#         4,
#         5,
#         6,
#         7,
#         8,
#         9,
#         "(990 more items hidden)"
#     ]
# }

# 6.1 Create partitions 
client.create_partition(
    collection_name="quick_setup",
    partition_name="red"
)

client.create_partition(
    collection_name="quick_setup",
    partition_name="blue"
)

# 6.1 Insert data into partitions
red_data = [ {"id": i, "vector": [ random.uniform(-1, 1) for _ in range(5) ], "color": "red", "color_tag": f"red_{str(random.randint(1000, 9999))}" } for i in range(500) ]
blue_data = [ {"id": i, "vector": [ random.uniform(-1, 1) for _ in range(5) ], "color": "blue", "color_tag": f"blue_{str(random.randint(1000, 9999))}" } for i in range(500) ]

res = client.insert(
    collection_name="quick_setup",
    data=red_data,
    partition_name="red"
)

print(res)

# Output
#
# {
#     "insert_count": 500,
#     "ids": [
#         0,
#         1,
#         2,
#         3,
#         4,
#         5,
#         6,
#         7,
#         8,
#         9,
#         "(490 more items hidden)"
#     ]
# }

res = client.insert(
    collection_name="quick_setup",
    data=blue_data,
    partition_name="blue"
)

print(res)

# Output
#
# {
#     "insert_count": 500,
#     "ids": [
#         0,
#         1,
#         2,
#         3,
#         4,
#         5,
#         6,
#         7,
#         8,
#         9,
#         "(490 more items hidden)"
#     ]
# }
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Random;

import com.alibaba.fastjson.JSONObject;

import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.service.collection.request.CreateCollectionReq;
import io.milvus.v2.service.collection.request.GetLoadStateReq;
import io.milvus.v2.service.vector.request.InsertReq;
import io.milvus.v2.service.vector.response.InsertResp; 

String CLUSTER_ENDPOINT = "http://localhost:19530";

// 1. Connect to Milvus server
ConnectConfig connectConfig = ConnectConfig.builder()
    .uri(CLUSTER_ENDPOINT)
    .build();

MilvusClientV2 client = new MilvusClientV2(connectConfig);  

// 2. Create a collection in quick setup mode
CreateCollectionReq quickSetupReq = CreateCollectionReq.builder()
    .collectionName("quick_setup")
    .dimension(5)
    .metricType("IP")
    .build();

client.createCollection(quickSetupReq);

GetLoadStateReq loadStateReq = GetLoadStateReq.builder()
    .collectionName("quick_setup")
    .build();

boolean state = client.getLoadState(loadStateReq);

System.out.println(state);

// Output:
// true

// 3. Insert randomly generated vectors into the collection
List<String> colors = Arrays.asList("green", "blue", "yellow", "red", "black", "white", "purple", "pink", "orange", "brown", "grey");
List<JSONObject> data = new ArrayList<>();

for (int i=0; i<1000; i++) {
    Random rand = new Random();
    String current_color = colors.get(rand.nextInt(colors.size()-1));
    JSONObject row = new JSONObject();
    row.put("id", Long.valueOf(i));
    row.put("vector", Arrays.asList(rand.nextFloat(), rand.nextFloat(), rand.nextFloat(), rand.nextFloat(), rand.nextFloat()));
    row.put("color_tag", current_color + "_" + String.valueOf(rand.nextInt(8999) + 1000));
    data.add(row);
}

InsertReq insertReq = InsertReq.builder()
    .collectionName("quick_setup")
    .data(data)
    .build();

InsertResp insertResp = client.insert(insertReq);

System.out.println(JSONObject.toJSON(insertResp));

// Output:
// {"insertCnt": 1000}

// 6.1. Create a partition
CreatePartitionReq partitionReq = CreatePartitionReq.builder()
    .collectionName("quick_setup")
    .partitionName("red")
    .build();

client.createPartition(partitionReq);

partitionReq = CreatePartitionReq.builder()
    .collectionName("quick_setup")
    .partitionName("blue")
    .build();

client.createPartition(partitionReq);

// 6.2 Insert data into the partition
data = new ArrayList<>();

for (int i=1000; i<1500; i++) {
    Random rand = new Random();
    String current_color = "red";
    JSONObject row = new JSONObject();
    row.put("id", Long.valueOf(i));
    row.put("vector", Arrays.asList(rand.nextFloat(), rand.nextFloat(), rand.nextFloat(), rand.nextFloat(), rand.nextFloat()));
    row.put("color", current_color);
    row.put("color_tag", current_color + "_" + String.valueOf(rand.nextInt(8999) + 1000));
    data.add(row);
}     

insertReq = InsertReq.builder()
    .collectionName("quick_setup")
    .data(data)
    .partitionName("red")
    .build();

insertResp = client.insert(insertReq);

System.out.println(JSONObject.toJSON(insertResp));

// Output:
// {"insertCnt": 500}

data = new ArrayList<>();

for (int i=1500; i<2000; i++) {
    Random rand = new Random();
    String current_color = "blue";
    JSONObject row = new JSONObject();
    row.put("id", Long.valueOf(i));
    row.put("vector", Arrays.asList(rand.nextFloat(), rand.nextFloat(), rand.nextFloat(), rand.nextFloat(), rand.nextFloat()));
    row.put("color", current_color);
    row.put("color_tag", current_color + "_" + String.valueOf(rand.nextInt(8999) + 1000));
    data.add(row);
}

insertReq = InsertReq.builder()
    .collectionName("quick_setup")
    .data(data)
    .partitionName("blue")
    .build();

insertResp = client.insert(insertReq);

System.out.println(JSONObject.toJSON(insertResp));

// Output:
// {"insertCnt": 500}
const { MilvusClient, DataType, sleep } = require("@zilliz/milvus2-sdk-node")

const address = "http://localhost:19530"

// 1. Set up a Milvus Client
client = new MilvusClient({address});

// 2. Create a collection in quick setup mode
await client.createCollection({
    collection_name: "quick_setup",
    dimension: 5,
    metric_type: "IP"
});  

// 3. Insert randomly generated vectors
const colors = ["green", "blue", "yellow", "red", "black", "white", "purple", "pink", "orange", "brown", "grey"]
data = []

for (let i = 0; i < 1000; i++) {
    current_color = colors[Math.floor(Math.random() * colors.length)]
    data.push({
        id: i,
        vector: [Math.random(), Math.random(), Math.random(), Math.random(), Math.random()],
        color: current_color,
        color_tag: `${current_color}_${Math.floor(Math.random() * 8999) + 1000}`
    })
}

var res = await client.insert({
    collection_name: "quick_setup",
    data: data
})

console.log(res.insert_cnt)

// Output
// 
// 1000
// 

await client.createPartition({
    collection_name: "quick_setup",
    partition_name: "red"
})

await client.createPartition({
    collection_name: "quick_setup",
    partition_name: "blue"
})

// 6.1 Insert data into partitions
var red_data = []
var blue_data = []

for (let i = 1000; i < 1500; i++) {
    red_data.push({
        id: i,
        vector: [Math.random(), Math.random(), Math.random(), Math.random(), Math.random()],
        color: "red",
        color_tag: `red_${Math.floor(Math.random() * 8999) + 1000}`
    })
}

for (let i = 1500; i < 2000; i++) {
    blue_data.push({
        id: i,
        vector: [Math.random(), Math.random(), Math.random(), Math.random(), Math.random()],
        color: "blue",
        color_tag: `blue_${Math.floor(Math.random() * 8999) + 1000}`
    })
}

res = await client.insert({
    collection_name: "quick_setup",
    data: red_data,
    partition_name: "red"
})

console.log(res.insert_cnt)

// Output
// 
// 500
// 

res = await client.insert({
    collection_name: "quick_setup",
    data: blue_data,
    partition_name: "blue"
})

console.log(res.insert_cnt)

// Output
// 
// 500
// 

Wenn Sie eine search Anfrage senden, können Sie einen oder mehrere Vektorwerte angeben, die Ihre Abfrageeinbettungen darstellen, sowie einen limit Wert, der die Anzahl der zurückzugebenden Ergebnisse angibt.

Abhängig von Ihren Daten und Ihrem Abfragevektor erhalten Sie möglicherweise weniger als limit Ergebnisse. Dies geschieht, wenn limit größer ist als die Anzahl der möglichen übereinstimmenden Vektoren für Ihre Abfrage.

Die Ein-Vektor-Suche ist die einfachste Form der search Operationen in Milvus und dient dazu, die ähnlichsten Vektoren zu einem bestimmten Abfragevektor zu finden.

Um eine Einzelvektorsuche durchzuführen, geben Sie den Namen der Zielsammlung, den Abfragevektor und die gewünschte Anzahl von Ergebnissen an (limit). Dieser Vorgang gibt eine Ergebnismenge zurück, die die ähnlichsten Vektoren, ihre IDs und Abstände zum Abfragevektor enthält.

Hier ein Beispiel für die Suche nach den Top 5 Entitäten, die dem Abfragevektor am ähnlichsten sind:

# Single vector search
res = client.search(
    collection_name="quick_setup", # Replace with the actual name of your collection
    # Replace with your query vector
    data=[[0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]],
    limit=5, # Max. number of search results to return
    search_params={"metric_type": "IP", "params": {}} # Search parameters
)

# Convert the output to a formatted JSON string
result = json.dumps(res, indent=4)
print(result)
// 4. Single vector search
List<List<Float>> query_vectors = Arrays.asList(Arrays.asList(0.3580376395471989f, -0.6023495712049978f, 0.18414012509913835f, -0.26286205330961354f, 0.9029438446296592f));

SearchReq searchReq = SearchReq.builder()
    .collectionName("quick_setup")
    .data(query_vectors)
    .topK(3) // The number of results to return
    .build();

SearchResp searchResp = client.search(searchReq);

System.out.println(JSONObject.toJSON(searchResp));
// 4. Single vector search
var query_vector = [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592],

res = await client.search({
    collection_name: "quick_setup",
    data: [query_vector],
    limit: 3, // The number of results to return
})

console.log(res.results)
Parameter Beschreibung
collection_name Der Name einer bestehenden Sammlung.
data Eine Liste von Vektoreinbettungen.
Milvus sucht nach den Vektoreinbettungen, die den angegebenen am ähnlichsten sind.
limit Die Gesamtzahl der zurückzugebenden Entitäten.
Sie können diesen Parameter in Kombination mit offset in param verwenden, um die Paginierung zu aktivieren.
Die Summe aus diesem Wert und offset in param sollte kleiner als 16.384 sein.
search_params Die spezifischen Parametereinstellungen für diesen Vorgang.
  • metric_type: Der metrische Typ, der für diesen Vorgang verwendet wird. Dies sollte derselbe sein, der verwendet wird, wenn Sie das oben angegebene Vektorfeld indizieren. Mögliche Werte sind L2, IP, COSINE, JACCARD, HAMMING.
  • params: Zusätzliche Parameter. Einzelheiten finden Sie unter search().
Parameter Beschreibung
collectionName Der Name einer bestehenden Sammlung.
data Eine Liste von Vektoreinbettungen.
Milvus sucht nach den Vektoreinbettungen, die den angegebenen am ähnlichsten sind.
topK Die Anzahl der Datensätze, die im Suchergebnis zurückgegeben werden sollen. Dieser Parameter verwendet dieselbe Syntax wie der Parameter limit, so dass Sie nur einen der beiden Parameter setzen sollten.
Sie können diesen Parameter in Kombination mit offset in param verwenden, um die Paginierung zu aktivieren.
Die Summe aus diesem Wert und offset in param sollte kleiner als 16.384 sein.
Parameter Beschreibung
collection_name Der Name einer bestehenden Sammlung.
data Eine Liste von Vektoreinbettungen.
Milvus sucht nach den Vektoreinbettungen, die den angegebenen am ähnlichsten sind.
limit Die Gesamtzahl der zurückzugebenden Entitäten.
Sie können diesen Parameter in Kombination mit offset in param verwenden, um die Paginierung zu aktivieren.
Die Summe aus diesem Wert und offset in param sollte kleiner als 16.384 sein.

Die Ausgabe ist ähnlich wie die folgende:

[
    [
        {
            "id": 0,
            "distance": 1.4093276262283325,
            "entity": {}
        },
        {
            "id": 4,
            "distance": 0.9902134537696838,
            "entity": {}
        },
        {
            "id": 1,
            "distance": 0.8519943356513977,
            "entity": {}
        },
        {
            "id": 5,
            "distance": 0.7972343564033508,
            "entity": {}
        },
        {
            "id": 2,
            "distance": 0.5928734540939331,
            "entity": {}
        }
    ]
]
{"searchResults": [[
    {
        "score": 1.263043,
        "fields": {
            "vector": [
                0.9533119,
                0.02538395,
                0.76714665,
                0.35481733,
                0.9845762
            ],
            "id": 740
        }
    },
    {
        "score": 1.2377806,
        "fields": {
            "vector": [
                0.7411156,
                0.08687937,
                0.8254139,
                0.08370924,
                0.99095553
            ],
            "id": 640
        }
    },
    {
        "score": 1.1869997,
        "fields": {
            "vector": [
                0.87928146,
                0.05324632,
                0.6312755,
                0.28005534,
                0.9542448
            ],
            "id": 455
        }
    }
]]}
[
  { score: 1.7463608980178833, id: '854' },
  { score: 1.744946002960205, id: '425' },
  { score: 1.7258622646331787, id: '718' }
]

Die Ausgabe zeigt die Top 5 Nachbarn, die Ihrem Abfragevektor am nächsten sind, einschließlich ihrer eindeutigen IDs und der berechneten Abstände.

Die Massenvektorsuche erweitert das Konzept der Einzelvektorsuche, indem sie die Suche nach mehreren Abfragevektoren in einer einzigen Anfrage ermöglicht. Diese Art der Suche ist ideal für Szenarien, in denen ähnliche Vektoren für eine Reihe von Abfragevektoren gefunden werden müssen, was den Zeit- und Rechenaufwand erheblich reduziert.

Bei einer Massenvektorsuche können Sie mehrere Abfragevektoren in das Feld data aufnehmen. Das System verarbeitet diese Vektoren parallel und gibt für jeden Abfragevektor einen separaten Ergebnissatz zurück, wobei jeder Satz die engsten Übereinstimmungen enthält, die in der Sammlung gefunden wurden.

Hier ist ein Beispiel für die Suche nach zwei verschiedenen Gruppen der ähnlichsten Entitäten aus zwei Abfragevektoren:

# Bulk-vector search
res = client.search(
    collection_name="quick_setup", # Replace with the actual name of your collection
    data=[
        [0.19886812562848388, 0.06023560599112088, 0.6976963061752597, 0.2614474506242501, 0.838729485096104],
        [0.3172005263489739, 0.9719044792798428, -0.36981146090600725, -0.4860894583077995, 0.95791889146345]
    ], # Replace with your query vectors
    limit=2, # Max. number of search results to return
    search_params={"metric_type": "IP", "params": {}} # Search parameters
)

result = json.dumps(res, indent=4)
print(result)
// 5. Batch vector search
query_vectors = Arrays.asList(
    Arrays.asList(0.3580376395471989f, -0.6023495712049978f, 0.18414012509913835f, -0.26286205330961354f, 0.9029438446296592f),
    Arrays.asList(0.19886812562848388f, 0.06023560599112088f, 0.6976963061752597f, 0.2614474506242501f, 0.838729485096104f)
);

searchReq = SearchReq.builder()
    .collectionName("quick_setup")
    .data(query_vectors)
    .topK(2)
    .build();

searchResp = client.search(searchReq);

System.out.println(JSONObject.toJSON(searchResp));
// 5. Batch vector search
var query_vectors = [
    [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592],
    [0.19886812562848388, 0.06023560599112088, 0.6976963061752597, 0.2614474506242501, 0.838729485096104]
]

res = await client.search({
    collection_name: "quick_setup",
    data: query_vectors,
    limit: 2,
})

console.log(res.results)

Die Ausgabe ist ähnlich wie die folgende:

[
    [
        {
            "id": 1,
            "distance": 1.3017789125442505,
            "entity": {}
        },
        {
            "id": 7,
            "distance": 1.2419954538345337,
            "entity": {}
        }
    ], # Result set 1
    [
        {
            "id": 3,
            "distance": 2.3358664512634277,
            "entity": {}
        },
        {
            "id": 8,
            "distance": 0.5642921924591064,
            "entity": {}
        }
    ] # Result set 2
]
// Two sets of vectors are returned as expected

{"searchResults": [
    [
        {
            "score": 1.263043,
            "fields": {
                "vector": [
                    0.9533119,
                    0.02538395,
                    0.76714665,
                    0.35481733,
                    0.9845762
                ],
                "id": 740
            }
        },
        {
            "score": 1.2377806,
            "fields": {
                "vector": [
                    0.7411156,
                    0.08687937,
                    0.8254139,
                    0.08370924,
                    0.99095553
                ],
                "id": 640
            }
        }
    ],
    [
        {
            "score": 1.8654699,
            "fields": {
                "vector": [
                    0.4671427,
                    0.8378432,
                    0.98844475,
                    0.82763994,
                    0.9729997
                ],
                "id": 638
            }
        },
        {
            "score": 1.8581753,
            "fields": {
                "vector": [
                    0.735541,
                    0.60140246,
                    0.86730254,
                    0.93152493,
                    0.98603314
                ],
                "id": 855
            }
        }
    ]
]}
[
  [
    { score: 2.3590476512908936, id: '854' },
    { score: 2.2896690368652344, id: '59' }
  [
    { score: 2.664059638977051, id: '59' },
    { score: 2.59483003616333, id: '854' }
  ]
]

Die Ergebnisse umfassen zwei Sätze nächster Nachbarn, einen für jeden Abfragevektor, was die Effizienz der Massenvektorsuche bei der gleichzeitigen Bearbeitung mehrerer Abfragevektoren verdeutlicht.

Die Partitionssuche grenzt den Umfang Ihrer Suche auf eine bestimmte Teilmenge oder Partition Ihrer Sammlung ein. Dies ist besonders nützlich für organisierte Datensätze, bei denen die Daten in logische oder kategorische Unterteilungen segmentiert sind, was schnellere Suchvorgänge ermöglicht, da die zu durchsuchende Datenmenge reduziert wird.

Um eine Partitionssuche durchzuführen, geben Sie einfach den Namen der Zielpartition unter partition_names in Ihrer Suchanfrage an. Dadurch wird festgelegt, dass die Operation search nur Vektoren innerhalb der angegebenen Partition berücksichtigt.

Hier ist ein Beispiel für die Suche nach Entitäten in red:

# 6.2 Search within a partition
query_vector = [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]

res = client.search(
    collection_name="quick_setup",
    data=[query_vector],
    limit=5,
    search_params={"metric_type": "IP", "params": {"level": 1}},
    partition_names=["red"]
)

print(res)
// 6.3 Search within partitions
query_vectors = Arrays.asList(Arrays.asList(0.3580376395471989f, -0.6023495712049978f, 0.18414012509913835f, -0.26286205330961354f, 0.9029438446296592f));

searchReq = SearchReq.builder()
    .collectionName("quick_setup")
    .data(query_vectors)
    .partitionNames(Arrays.asList("red"))
    .topK(5)
    .build();

searchResp = client.search(searchReq);

System.out.println(JSONObject.toJSON(searchResp));
// 6.2 Search within partitions
query_vector = [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]

res = await client.search({
    collection_name: "quick_setup",
    data: [query_vector],
    partition_names: ["red"],
    limit: 5,
})

console.log(res.results)

Die Ausgabe ist ähnlich wie die folgende:

[
    [
        {
            "id": 16,
            "distance": 0.9200337529182434,
            "entity": {}
        },
        {
            "id": 14,
            "distance": 0.4505271911621094,
            "entity": {}
        },
        {
            "id": 15,
            "distance": 0.19924677908420563,
            "entity": {}
        },
        {
            "id": 17,
            "distance": 0.0075093843042850494,
            "entity": {}
        },
        {
            "id": 13,
            "distance": -0.14609718322753906,
            "entity": {}
        }
    ]
]
{"searchResults": [
    [
        {
            "score": 1.1677284,
            "fields": {
                "vector": [
                    0.9986977,
                    0.17964739,
                    0.49086612,
                    0.23155272,
                    0.98438674
                ],
                "id": 1435
            }
        },
        {
            "score": 1.1476475,
            "fields": {
                "vector": [
                    0.6952647,
                    0.13417172,
                    0.91045254,
                    0.119336545,
                    0.9338931
                ],
                "id": 1291
            }
        },
        {
            "score": 1.0969629,
            "fields": {
                "vector": [
                    0.3363194,
                    0.028906643,
                    0.6675426,
                    0.030419827,
                    0.9735209
                ],
                "id": 1168
            }
        },
        {
            "score": 1.0741848,
            "fields": {
                "vector": [
                    0.9980543,
                    0.36063594,
                    0.66427994,
                    0.17359233,
                    0.94954175
                ],
                "id": 1164
            }
        },
        {
            "score": 1.0584627,
            "fields": {
                "vector": [
                    0.7187005,
                    0.12674773,
                    0.987718,
                    0.3110777,
                    0.86093885
                ],
                "id": 1085
            }
        }
    ],
    [
        {
            "score": 1.8030131,
            "fields": {
                "vector": [
                    0.59726167,
                    0.7054632,
                    0.9573117,
                    0.94529945,
                    0.8664103
                ],
                "id": 1203
            }
        },
        {
            "score": 1.7728865,
            "fields": {
                "vector": [
                    0.6672442,
                    0.60448086,
                    0.9325822,
                    0.80272985,
                    0.8861626
                ],
                "id": 1448
            }
        },
        {
            "score": 1.7536311,
            "fields": {
                "vector": [
                    0.59663296,
                    0.77831805,
                    0.8578314,
                    0.88818026,
                    0.9030075
                ],
                "id": 1010
            }
        },
        {
            "score": 1.7520742,
            "fields": {
                "vector": [
                    0.854198,
                    0.72294194,
                    0.9245805,
                    0.86126596,
                    0.7969224
                ],
                "id": 1219
            }
        },
        {
            "score": 1.7452049,
            "fields": {
                "vector": [
                    0.96419,
                    0.943535,
                    0.87611496,
                    0.8268136,
                    0.79786557
                ],
                "id": 1149
            }
        }
    ]
]}
[
  { score: 3.0258803367614746, id: '1201' },
  { score: 3.004319190979004, id: '1458' },
  { score: 2.880324363708496, id: '1187' },
  { score: 2.8246407508850098, id: '1347' },
  { score: 2.797295093536377, id: '1406' }
]

Suchen Sie dann nach Entitäten in blue:

res = client.search(
    collection_name="quick_setup",
    data=[query_vector],
    limit=5,
    search_params={"metric_type": "IP", "params": {"level": 1}},
    partition_names=["blue"]
)

print(res)
searchReq = SearchReq.builder()
    .collectionName("quick_setup")
    .data(query_vectors)
    .partitionNames(Arrays.asList("blue"))
    .topK(5)
    .build();

searchResp = client.search(searchReq);

System.out.println(JSONObject.toJSON(searchResp));
res = await client.search({
    collection_name: "quick_setup",
    data: [query_vector],
    partition_names: ["blue"],
    limit: 5,
})

console.log(res.results)

Die Ausgabe ist ähnlich wie die folgende:

[
    [
        {
            "id": 20,
            "distance": 2.363696813583374,
            "entity": {}
        },
        {
            "id": 26,
            "distance": 1.0665391683578491,
            "entity": {}
        },
        {
            "id": 23,
            "distance": 1.066049575805664,
            "entity": {}
        },
        {
            "id": 29,
            "distance": 0.8353596925735474,
            "entity": {}
        },
        {
            "id": 28,
            "distance": 0.7484277486801147,
            "entity": {}
        }
    ]
]
{"searchResults": [
    [
        {
            "score": 1.1628494,
            "fields": {
                "vector": [
                    0.7442872,
                    0.046407282,
                    0.71031404,
                    0.3544345,
                    0.9819991
                ],
                "id": 1992
            }
        },
        {
            "score": 1.1470042,
            "fields": {
                "vector": [
                    0.5505825,
                    0.04367262,
                    0.9985836,
                    0.18922359,
                    0.93255126
                ],
                "id": 1977
            }
        },
        {
            "score": 1.1450152,
            "fields": {
                "vector": [
                    0.89994013,
                    0.052991092,
                    0.8645576,
                    0.6406729,
                    0.95679337
                ],
                "id": 1573
            }
        },
        {
            "score": 1.1439825,
            "fields": {
                "vector": [
                    0.9253267,
                    0.15890503,
                    0.7999555,
                    0.19126713,
                    0.898583
                ],
                "id": 1552
            }
        },
        {
            "score": 1.1029172,
            "fields": {
                "vector": [
                    0.95661926,
                    0.18777144,
                    0.38115507,
                    0.14323527,
                    0.93137646
                ],
                "id": 1823
            }
        }
    ],
    [
        {
            "score": 1.8005109,
            "fields": {
                "vector": [
                    0.5953582,
                    0.7794224,
                    0.9388869,
                    0.79825854,
                    0.9197286
                ],
                "id": 1888
            }
        },
        {
            "score": 1.7714822,
            "fields": {
                "vector": [
                    0.56805456,
                    0.89422905,
                    0.88187534,
                    0.914824,
                    0.8944365
                ],
                "id": 1648
            }
        },
        {
            "score": 1.7561421,
            "fields": {
                "vector": [
                    0.83421993,
                    0.39865613,
                    0.92319834,
                    0.42695504,
                    0.96633124
                ],
                "id": 1688
            }
        },
        {
            "score": 1.7553532,
            "fields": {
                "vector": [
                    0.89994013,
                    0.052991092,
                    0.8645576,
                    0.6406729,
                    0.95679337
                ],
                "id": 1573
            }
        },
        {
            "score": 1.7543385,
            "fields": {
                "vector": [
                    0.16542226,
                    0.38248396,
                    0.9888778,
                    0.80913955,
                    0.9501492
                ],
                "id": 1544
            }
        }
    ]
]}
[
  { score: 2.8421106338500977, id: '1745' },
  { score: 2.838560104370117, id: '1782' },
  { score: 2.8134000301361084, id: '1511' },
  { score: 2.718268871307373, id: '1679' },
  { score: 2.7014894485473633, id: '1597' }
]

Die Daten in red unterscheiden sich von denen in blue. Daher werden die Suchergebnisse auf die angegebene Partition beschränkt und spiegeln die einzigartigen Merkmale und die Datenverteilung dieser Untergruppe wider.

Suche mit Ausgabefeldern

Bei der Suche mit Ausgabefeldern können Sie angeben, welche Attribute oder Felder der übereinstimmenden Vektoren in die Suchergebnisse aufgenommen werden sollen.

Sie können output_fields in einer Anfrage angeben, um Ergebnisse mit bestimmten Feldern zu erhalten.

Hier ist ein Beispiel für die Rückgabe von Ergebnissen mit color Attributwerten:

# Search with output fields
res = client.search(
    collection_name="quick_setup", # Replace with the actual name of your collection
    data=[[0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]],
    limit=5, # Max. number of search results to return
    search_params={"metric_type": "IP", "params": {}}, # Search parameters
    output_fields=["color"] # Output fields to return
)

result = json.dumps(res, indent=4)
print(result)
// 7. Search with output fields
query_vectors = Arrays.asList(Arrays.asList(0.3580376395471989f, -0.6023495712049978f, 0.18414012509913835f, -0.26286205330961354f, 0.9029438446296592f));

searchReq = SearchReq.builder()
    .collectionName("quick_setup")
    .data(query_vectors)
    .outputFields(Arrays.asList("color"))
    .topK(5)
    .build();

searchResp = client.search(searchReq);

System.out.println(JSONObject.toJSON(searchResp));
// 7. Search with output fields
query_vector = [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]

res = await client.search({
    collection_name: "quick_setup",
    data: [query_vector],
    limit: 5,
    output_fields: ["color"],
})

console.log(res.results)

Die Ausgabe ist ähnlich wie die folgende:

[
    [
        {
            "id": 0,
            "distance": 1.4093276262283325,
            "entity": {
                "color": "pink_8682"
            }
        },
        {
            "id": 16,
            "distance": 1.0159327983856201,
            "entity": {
                "color": "yellow_1496"
            }
        },
        {
            "id": 4,
            "distance": 0.9902134537696838,
            "entity": {
                "color": "red_4794"
            }
        },
        {
            "id": 14,
            "distance": 0.9803846478462219,
            "entity": {
                "color": "green_2899"
            }
        },
        {
            "id": 1,
            "distance": 0.8519943356513977,
            "entity": {
                "color": "red_7025"
            }
        }
    ]
]
{"searchResults": [
    [
        {
            "score": 1.263043,
            "fields": {}
        },
        {
            "score": 1.2377806,
            "fields": {}
        },
        {
            "score": 1.1869997,
            "fields": {}
        },
        {
            "score": 1.1748955,
            "fields": {}
        },
        {
            "score": 1.1720343,
            "fields": {}
        }
    ]
]}

[
  { score: 3.036271572113037, id: '59', color: 'orange' },
  { score: 3.0267879962921143, id: '1745', color: 'blue' },
  { score: 3.0069446563720703, id: '854', color: 'black' },
  { score: 2.984386682510376, id: '718', color: 'black' },
  { score: 2.916019916534424, id: '425', color: 'purple' }
]

Die Suchergebnisse enthalten neben den nächsten Nachbarn auch das angegebene Feld color und bieten somit einen umfangreicheren Satz an Informationen für jeden passenden Vektor.

Die gefilterte Suche wendet skalare Filter auf die Vektorsuche an und ermöglicht es Ihnen, die Suchergebnisse anhand bestimmter Kriterien zu verfeinern. Weitere Informationen zu Filterausdrücken finden Sie unter Boolesche Ausdrucksregeln und Beispiele unter Hole & Skalare Abfrage.

Verwenden Sie den like Operator

Der like Operator verbessert die Zeichenkettensuche durch die Auswertung von Mustern, einschließlich Präfixen, Infixen und Suffixen:

  • Präfixabgleich: Um Werte zu finden, die mit einem bestimmten Präfix beginnen, verwenden Sie die Syntax 'like "prefix%"'.
  • Infix-Abgleich: Um Werte zu finden, die eine bestimmte Zeichenfolge an beliebiger Stelle in der Zeichenkette enthalten, verwenden Sie die Syntax 'like "%infix%"'.
  • Suffix-Abgleich: Um Werte zu finden, die mit einem bestimmten Suffix enden, verwenden Sie die Syntax 'like "%suffix"'.

Bei der Suche nach einzelnen Zeichen dient der Unterstrich (_) als Platzhalter für ein Zeichen, z. B. 'like "y_llow"'.

Sonderzeichen in Suchzeichenketten

Wenn Sie nach einer Zeichenkette suchen wollen, die Sonderzeichen wie Unterstriche (_) oder Prozentzeichen (%) enthält, die normalerweise als Platzhalter in Suchmustern verwendet werden (_ für ein einzelnes Zeichen und % für eine beliebige Folge von Zeichen), müssen Sie diese Zeichen mit einem Escapezeichen versehen, um sie als literale Zeichen zu behandeln. Verwenden Sie einen Backslash (\), um Sonderzeichen zu entschlüsseln, und denken Sie daran, den Backslash selbst zu entschlüsseln. Ein Beispiel:

  • Um nach einem buchstäblichen Unterstrich zu suchen, verwenden Sie \\_.
  • Um nach einem wörtlichen Prozentzeichen zu suchen, verwenden Sie \\%.

Wenn Sie also nach dem Text "_version_" suchen müssen, sollte Ihre Abfrage als 'like "\\_version\\_"' formatiert werden, um sicherzustellen, dass die Unterstriche als Teil des Suchbegriffs und nicht als Platzhalter behandelt werden.

Filtern Sie Ergebnisse, deren Farbe mit einem roten Präfix versehen ist:

# Search with filter
res = client.search(
    collection_name="quick_setup", # Replace with the actual name of your collection
    data=[[0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]],
    limit=5, # Max. number of search results to return
    search_params={"metric_type": "IP", "params": {}}, # Search parameters
    output_fields=["color"], # Output fields to return
    filter='color like "red%"'
)

result = json.dumps(res, indent=4)
print(result)
// 8. Filtered search
query_vectors = Arrays.asList(Arrays.asList(0.3580376395471989f, -0.6023495712049978f, 0.18414012509913835f, -0.26286205330961354f, 0.9029438446296592f));

searchReq = SearchReq.builder()
    .collectionName("quick_setup")
    .data(query_vectors)
    .outputFields(Arrays.asList("color_tag"))
    .filter("color_tag like \"red%\"")
    .topK(5)
    .build();

searchResp = client.search(searchReq);

System.out.println(JSONObject.toJSON(searchResp));
// 8. Filtered search
// 8.1 Filter with "like" operator and prefix wildcard
query_vector = [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]

res = await client.search({
    collection_name: "quick_setup",
    data: [query_vector],
    limit: 5,
    filters: "color_tag like \"red%\"",
    output_fields: ["color_tag"]
})

console.log(res.results)

Die Ausgabe ist ähnlich wie die folgende:

[
    [
        {
            "id": 4,
            "distance": 0.9902134537696838,
            "entity": {
                "color": "red_4794"
            }
        },
        {
            "id": 1,
            "distance": 0.8519943356513977,
            "entity": {
                "color": "red_7025"
            }
        },
        {
            "id": 6,
            "distance": -0.4113418459892273,
            "entity": {
                "color": "red_9392"
            }
        }
    ]
]
{"searchResults": [
    [
        {
            "score": 1.1869997,
            "fields": {"color_tag": "red_3026"}
        },
        {
            "score": 1.1677284,
            "fields": {"color_tag": "red_9030"}
        },
        {
            "score": 1.1476475,
            "fields": {"color_tag": "red_3744"}
        },
        {
            "score": 1.0969629,
            "fields": {"color_tag": "red_4168"}
        },
        {
            "score": 1.0741848,
            "fields": {"color_tag": "red_9678"}
        }
    ]
]}
[
  { score: 2.5080761909484863, id: '1201', color_tag: 'red_8904' },
  { score: 2.491129159927368, id: '425', color_tag: 'purple_8212' },
  { score: 2.4889798164367676, id: '1458', color_tag: 'red_6891' },
  { score: 2.42964243888855, id: '724', color_tag: 'black_9885' },
  { score: 2.4004223346710205, id: '854', color_tag: 'black_5990' }
]

Filtert Ergebnisse, deren Farbe die Buchstaben ll an einer beliebigen Stelle der Zeichenkette enthält:

# Infix match on color field
res = client.search(
    collection_name="quick_setup", # Replace with the actual name of your collection
    data=[[0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]],
    limit=5, # Max. number of search results to return
    search_params={"metric_type": "IP", "params": {}}, # Search parameters
    output_fields=["color"], # Output fields to return
    filter='color like "%ll%"' # Filter on color field, infix match on "ll"
)

result = json.dumps(res, indent=4)
print(result)
// 8. Filtered search
query_vectors = Arrays.asList(Arrays.asList(0.3580376395471989f, -0.6023495712049978f, 0.18414012509913835f, -0.26286205330961354f, 0.9029438446296592f));

searchReq = SearchReq.builder()
    .collectionName("quick_setup")
    .data(query_vectors)
    .outputFields(Arrays.asList("color_tag"))
    .filter("color like \"%ll%\"")
    .topK(5)
    .build();

searchResp = client.search(searchReq);

System.out.println(JSONObject.toJSON(searchResp));
// 8. Filtered search
// 8.1 Filter with "like" operator and prefix wildcard
query_vector = [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]

res = await client.search({
    collection_name: "quick_setup",
    data: [query_vector],
    limit: 5,
    filters: "color_tag like \"%ll%\"",
    output_fields: ["color_tag"]
})

console.log(res.results)

Die Ausgabe ist ähnlich wie die folgende:

[
    [
        {
            "id": 5,
            "distance": 0.7972343564033508,
            "entity": {
                "color": "yellow_4222"
            }
        }
    ]
]
{"searchResults": [
    [
        {
            "score": 1.1869997,
            "fields": {"color_tag": "yellow_4222"}
        }
    ]
]}
[
  { score: 2.5080761909484863, id: '1201', color_tag: 'yellow_4222' }
]

Die Bereichssuche ermöglicht es Ihnen, Vektoren zu finden, die innerhalb eines bestimmten Abstandsbereichs zu Ihrem Abfragevektor liegen.

Durch Einstellen von radius und optional range_filter können Sie die Breite Ihrer Suche so anpassen, dass auch Vektoren einbezogen werden, die dem Abfragevektor einigermaßen ähnlich sind, und so eine umfassendere Übersicht über mögliche Übereinstimmungen erhalten.

  • radius: Legt die äußere Grenze des Suchraums fest. Nur Vektoren, die innerhalb dieses Abstands zum Abfragevektor liegen, werden als potenzielle Übereinstimmungen betrachtet.

  • range_filter: Während radius die äußere Grenze der Suche festlegt, kann range_filter optional verwendet werden, um eine innere Grenze zu definieren und einen Abstandsbereich zu schaffen, in den Vektoren fallen müssen, um als Treffer zu gelten.

# Conduct a range search
search_params = {
    "metric_type": "IP",
    "params": {
        "radius": 0.8, # Radius of the search circle
        "range_filter": 1.0 # Range filter to filter out vectors that are not within the search circle
    }
}

res = client.search(
    collection_name="quick_setup", # Replace with the actual name of your collection
    data=[[0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]],
    limit=3, # Max. number of search results to return
    search_params=search_params, # Search parameters
    output_fields=["color"], # Output fields to return
)

result = json.dumps(res, indent=4)
print(result)
// 9. Range search
query_vectors = Arrays.asList(Arrays.asList(0.3580376395471989f, -0.6023495712049978f, 0.18414012509913835f, -0.26286205330961354f, 0.9029438446296592f));

searchReq = SearchReq.builder()
    .collectionName("quick_setup")
    .data(query_vectors)
    .outputFields(Arrays.asList("color_tag"))
    .searchParams(Map.of("radius", 0.1, "range", 1.0))
    .topK(5)
    .build();

searchResp = client.search(searchReq);

System.out.println(JSONObject.toJSON(searchResp));
// 9. Range search
query_vector = [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]

res = await client.search({
    collection_name: "quick_setup",
    data: [query_vector],
    limit: 5,
    params: {
        radius: 0.1,
        range: 1.0
    },
    output_fields: ["color_tag"]
})

console.log(res.results)

Die Ausgabe ist ähnlich wie die folgende:

[
    [
        {
            "id": 4,
            "distance": 0.9902134537696838,
            "entity": {
                "color": "red_4794"
            }
        },
        {
            "id": 14,
            "distance": 0.9803846478462219,
            "entity": {
                "color": "green_2899"
            }
        },
        {
            "id": 1,
            "distance": 0.8519943356513977,
            "entity": {
                "color": "red_7025"
            }
        }
    ]
]
{"searchResults": [
    [
        {
            "score": 1.263043,
            "fields": {"color_tag": "green_2052"}
        },
        {
            "score": 1.2377806,
            "fields": {"color_tag": "purple_3709"}
        },
        {
            "score": 1.1869997,
            "fields": {"color_tag": "red_3026"}
        },
        {
            "score": 1.1748955,
            "fields": {"color_tag": "black_1646"}
        },
        {
            "score": 1.1720343,
            "fields": {"color_tag": "green_4853"}
        }
    ]
]}
[
  { score: 2.3387961387634277, id: '718', color_tag: 'black_7154' },
  { score: 2.3352415561676025, id: '1745', color_tag: 'blue_8741' },
  { score: 2.290485382080078, id: '1408', color_tag: 'red_2324' },
  { score: 2.285870313644409, id: '854', color_tag: 'black_5990' },
  { score: 2.2593345642089844, id: '1309', color_tag: 'red_8458' }
]

Sie werden feststellen, dass alle zurückgegebenen Entitäten einen Abstand zwischen 0,8 und 1,0 vom Abfragevektor haben.

Die Parametereinstellungen für radius und range_filter variieren je nach verwendetem metrischen Typ.

Metrischer TypCharakteristikenBereich Sucheinstellungen
L2Kleinere L2-Distanzen zeigen eine höhere Ähnlichkeit an.Um die nächstgelegenen Vektoren von den Ergebnissen auszuschließen, stellen Sie sicher, dass:
range_filter <= distance < radius
IPGrößere IP-Distanzen weisen auf eine höhere Ähnlichkeit hin.Um die nächstgelegenen Vektoren von den Ergebnissen auszuschließen, stellen Sie sicher, dass:
radius <= distance <= range_filter
COSINEEin größerer Kosinuswert deutet auf eine größere Ähnlichkeit hin.Um die engsten Vektoren von den Ergebnissen auszuschließen, stellen Sie sicher, dass:
radius < Abstand <= range_filter
JACCARDKleinere Jaccard-Distanzen weisen auf eine höhere Ähnlichkeit hin.Um die nächstgelegenen Vektoren aus den Ergebnissen auszuschließen, stellen Sie sicher, dass:
range_filter <= distance < radius
HAMMINGKleinere Hamming-Distanzen weisen auf eine höhere Ähnlichkeit hin.Um die nächstgelegenen Vektoren aus den Ergebnissen auszuschließen, stellen Sie sicher, dass:
range_filter <= distance < radius

Weitere Informationen über die Arten von Abstandsmetriken finden Sie unter Ähnlichkeitsmetriken.

In Milvus wurde die Gruppierungssuche entwickelt, um die Vollständigkeit und Genauigkeit der Suchergebnisse zu verbessern.

Stellen Sie sich ein Szenario in RAG vor, in dem eine Menge von Dokumenten in verschiedene Passagen aufgeteilt ist und jede Passage durch eine Vektoreinbettung dargestellt wird. Die Benutzer möchten die relevantesten Passagen finden, um die LLMs genau abzufragen. Die gewöhnliche Milvus-Suchfunktion kann diese Anforderung erfüllen, aber sie kann zu stark verzerrten und voreingenommenen Ergebnissen führen: Die meisten Passagen stammen aus nur wenigen Dokumenten, und die Vollständigkeit der Suchergebnisse ist sehr gering. Dies kann die Genauigkeit oder sogar die Korrektheit der vom LLM gelieferten Ergebnisse ernsthaft beeinträchtigen und die Erfahrung der LLM-Nutzer negativ beeinflussen.

Die Gruppensuche kann dieses Problem wirksam lösen. Durch Übergabe eines group_by_field und group_size können Milvus-Benutzer die Suchergebnisse in mehrere Gruppen aufteilen und sicherstellen, dass die Anzahl der Entitäten aus jeder Gruppe eine bestimmte group_size nicht überschreitet. Diese Funktion kann den Umfang und die Fairness der Suchergebnisse erheblich steigern und die Qualität der LLM-Ausgabe spürbar verbessern.

Hier ist der Beispielcode zum Gruppieren von Suchergebnissen nach Feld:

# Connect to Milvus
client = MilvusClient(uri='http://localhost:19530') # Milvus server address

# Load data into collection
client.load_collection("group_search") # Collection name

# Group search results
res = client.search(
    collection_name="group_search", # Collection name
    data=[[0.14529211512077012, 0.9147257273453546, 0.7965055218724449, 0.7009258593102812, 0.5605206522382088]], # Query vector
    search_params={
    "metric_type": "L2",
    "params": {"nprobe": 10},
    }, # Search parameters
    limit=5, # Max. number of groups to return
    group_by_field="doc_id", # Group results by document ID
    group_size=2, # returned at most 2 passages per document, the default value is 1
    group_strict_size=True, # ensure every group contains exactly 3 passages
    output_fields=["doc_id", "passage_id"]
)

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

print(doc_ids)
print(passage_ids)

Die Ausgabe ist ähnlich wie die folgende:

["doc_11", "doc_11", "doc_7", "doc_7", "doc_3", "doc_3", "doc_2", "doc_2", "doc_8", "doc_8"]
[5, 10, 11, 10, 9, 6, 5, 4, 9, 2]

In der gegebenen Ausgabe ist zu sehen, dass für jedes Dokument genau zwei Passagen gefunden werden und insgesamt 5 Dokumente die Ergebnisse ausmachen.

Zum Vergleich kommentieren wir die gruppenbezogenen Parameter aus und führen eine reguläre Suche durch:

# Connect to Milvus
client = MilvusClient(uri='http://localhost:19530') # Milvus server address

# Load data into collection
client.load_collection("group_search") # Collection name

# Search without `group_by_field`
res = client.search(
    collection_name="group_search", # Collection name
    data=query_passage_vector, # Replace with your query vector
    search_params={
    "metric_type": "L2",
    "params": {"nprobe": 10},
    }, # Search parameters
    limit=5, # Max. number of search results to return
    # group_by_field="doc_id", # Group results by document ID
    # group_size=2, 
    # group_strict_size=True,
    output_fields=["doc_id", "passage_id"]
)

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

print(doc_ids)
print(passage_ids)

Die Ausgabe ist ähnlich wie die folgende:

["doc_11", "doc_11", "doc_11", "doc_11", "doc_11"]
[1, 10, 3, 12, 9]

In der gegebenen Ausgabe ist zu beobachten, dass "doc_11" die Suchergebnisse vollständig dominiert und die qualitativ hochwertigen Absätze aus anderen Dokumenten überschattet, was eine schlechte Aufforderung an LLM sein kann.

Noch ein Hinweis: Standardmäßig gibt grouping_search sofort Ergebnisse zurück, wenn es genügend Gruppen hat, was dazu führen kann, dass die Anzahl der Ergebnisse in jeder Gruppe nicht ausreicht, um die group_size zu erfüllen. Wenn Ihnen die Anzahl der Ergebnisse für jede Gruppe wichtig ist, setzen Sie group_strict_size=True wie im obigen Code gezeigt. Dies führt dazu, dass Milvus sich bemüht, genügend Ergebnisse für jede Gruppe zu erhalten, was allerdings zu einem leichten Leistungsverlust führt.

Beschränkungen

  • Indizierung: Diese Gruppierungsfunktion funktioniert nur für Sammlungen, die mit dem HNSW-, IVF_FLAT- oder FLAT-Typ indiziert sind. Weitere Informationen finden Sie unter In-Memory-Index.

  • Vektor: Derzeit unterstützt die Gruppierungssuche kein Vektorfeld vom Typ BINARY_VECTOR. Weitere Informationen zu Datentypen finden Sie unter Unterstützte Datentypen.

  • Feld: Derzeit ist bei der Gruppierungssuche nur eine einzige Spalte möglich. Sie können nicht mehrere Feldnamen in der Konfiguration group_by_field angeben. Außerdem ist die Gruppierungssuche nicht mit den Datentypen JSON, FLOAT, DOUBLE, ARRAY oder Vektorfeldern kompatibel.

  • Auswirkungen auf die Leistung: Beachten Sie, dass die Leistung mit zunehmender Anzahl von Abfragevektoren abnimmt. Am Beispiel eines Clusters mit 2 CPU-Kernen und 8 GB Speicher steigt die Ausführungszeit für die Gruppierungssuche proportional zur Anzahl der Eingabeabfragevektoren.

  • Funktionsweise: Derzeit wird die Gruppierungssuche nicht von der Bereichssuche und den Suchitern unterstützt.

Suchparameter

Für die oben genannten Suchvorgänge, mit Ausnahme der Bereichssuche, gelten die Standardsuchparameter. Im Normalfall müssen Sie die Suchparameter nicht manuell einstellen.

# In normal cases, you do not need to set search parameters manually
# Except for range searches.
search_parameters = {
    'metric_type': 'L2',
    'params': {
        'nprobe': 10,
        'level': 1'radius': 1.0
        'range_filter': 0.8
    }
}

In der folgenden Tabelle sind alle möglichen Einstellungen für die Suchparameter aufgeführt.

Parameter NameParameter Beschreibung
metric_typeWie wird die Ähnlichkeit zwischen Vektoreinbettungen gemessen.
Mögliche Werte sind IP, L2, COSINE, JACCARD und HAMMING, und sind standardmäßig die der geladenen Indexdatei.
params.nprobeAnzahl der Einheiten, die während der Suche abgefragt werden.
Der Wert fällt in den Bereich [1, nlist[1]].
params.levelGenauigkeitsgrad der Suche.
Mögliche Werte sind 1, 2 und 3, der Standardwert ist 1. Höhere Werte liefern genauere Ergebnisse, aber eine langsamere Leistung.
params.radiusLegt die äußere Begrenzung des Suchraums fest. Nur Vektoren, die innerhalb dieses Abstands zum Abfragevektor liegen, werden als potenzielle Übereinstimmungen betrachtet.
Der Wertebereich wird durch den Parameter metric_type bestimmt. Wenn metric_type beispielsweise auf L2 eingestellt ist, ist der gültige Wertebereich [0, ∞]. Wenn metric_type auf COSINE eingestellt ist, ist der gültige Wertebereich [-1, 1]. Weitere Informationen finden Sie unter Ähnlichkeitsmetriken.
params.range_filterWährend radius die äußere Grenze der Suche festlegt, kann range_filter optional verwendet werden, um eine innere Grenze zu definieren und einen Abstandsbereich zu schaffen, in den Vektoren fallen müssen, um als übereinstimmend zu gelten.
Der Wertebereich wird durch den Parameter metric_type bestimmt. Wenn beispielsweise metric_type auf L2 gesetzt ist, ist der gültige Wertebereich [0, ∞]. Wenn metric_type auf COSINE gesetzt ist, ist der gültige Wertebereich [-1, 1]. Weitere Informationen finden Sie unter Ähnlichkeitsmetriken.

Hinweise

[1] Anzahl der Cluster-Einheiten nach der Indizierung. Bei der Indizierung einer Sammlung unterteilt Milvus die Vektordaten in mehrere Clustereinheiten, deren Anzahl von den aktuellen Indexeinstellungen abhängt.

[2] Anzahl der Entitäten, die bei einer Suche zurückgegeben werden.

Übersetzt vonDeepLogo

Try Managed Milvus for Free

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

Get Started
Feedback

War diese Seite hilfreich?