Recall Rate を調整する
Zilliz Cloud は、検索の Recall Rate とパフォーマンスのバランスを取るための検索パラメーター level を提供しています。また、現在の検索の推定 Recall Rate を取得するための別の検索パラメーター enable_recall_calculation も提供しています。これら 2 つのパラメーターを組み合わせて、ベクトル検索の Recall Rate を調整できます。
これは、基本的なベクトル検索、フィルター検索、範囲検索、グループ化検索、ハイブリッド検索、検索イテレーターを含むすべての検索に適用されます。
概要
Zilliz Cloud における Recall Rate は通常、検索によって正常に取得された関連結果の割合を指します。これは、コレクションからすべての関連項目を取得するシステムの能力を測るものです。

検索の Recall Rate を計算するには、取得された関連項目の数を、取得されるべき該当項目の総数で割ります。たとえば、100 個の関連項目のうち 90 個が検索で取得された場合、Recall Rate は 0.9 または 90% になります。
Recall Rate が高いほど通常は検索結果の精度が高くなりますが、時間がかかる場合があります。ベクトル検索の精度と効率のバランスを取るために、Recall Rate を調整することを検討してください。
検索リクエストを設定する
Recall Rate を調整可能な検索リクエストを設定するには、次のように検索パラメーター内に level パラメーターを含める必要があります。
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- CSharp
- cURL
from pymilvus import MilvusClient
client = MilvusClient(
uri="YOUR_CLUSTER_ENDPOINT",
token="YOUR_CLUSTER_TOKEN"
)
query_vector = [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]
res = client.search(
collection_name="quick_setup",
data=[query_vector],
limit=3, # The number of results to return
search_params={
"params": {
"level": 1 # The precision control
}
}
)
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;
import java.util.*;
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("YOUR_CLUSTER_ENDPOINT")
.token("YOUR_CLUSTER_TOKEN")
.build());
FloatVec queryVector = new FloatVec(new float[]{0.3580376395471989f, -0.6023495712049978f, 0.18414012509913835f, -0.26286205330961354f, 0.9029438446296592f});
Map<String, Object> searchParams = new HashMap<>();
searchParams.put("level", 1);
SearchReq searchReq = SearchReq.builder()
.collectionName("quick_setup")
.data(Collections.singletonList(queryVector))
.annsField("vector")
.topK(3)
.searchParams(searchParams)
.build();
SearchResp searchResp = client.search(searchReq);
System.out.println(searchResp.getSearchResults());
import (
"context"
"fmt"
"github.com/milvus-io/milvus/client/v3/entity"
"github.com/milvus-io/milvus/client/v3/milvusclient"
)
ctx := context.Background()
client, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: "YOUR_CLUSTER_ENDPOINT",
APIKey: "YOUR_CLUSTER_TOKEN",
})
if err != nil {
fmt.Println(err.Error())
// handle error
}
queryVector := []float32{0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592}
resultSets, err := client.Search(ctx, milvusclient.NewSearchOption(
"quick_setup", // collectionName
3, // limit
[]entity.Vector{entity.FloatVector(queryVector)},
).WithANNSField("vector").
WithSearchParam("level", "1"))
if err != nil {
fmt.Println(err.Error())
// handle error
}
for _, resultSet := range resultSets {
fmt.Println("IDs: ", resultSet.IDs.FieldData().GetScalars())
fmt.Println("Scores: ", resultSet.Scores)
}
use milvus::v2::prelude::*;
use std::collections::HashMap;
let client = ClientV2::new(
&ConnectConfig::new()
.uri("YOUR_CLUSTER_ENDPOINT")
.token("YOUR_CLUSTER_TOKEN"),
)
.await?;
let query_vector = vec![0.3580376395471989f32, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592];
let res = client
.search(
SearchRequest::builder()
.collection_name("quick_setup")
.vector_field("vector")
.vectors(SearchVectors::Float(vec![query_vector]))
.limit(3)
.extra_params(HashMap::from([("level".into(), "1".into())]))
.build()?,
)
.await?;
println!("{:?}", res.results());
#include <iostream>
#include <vector>
#include "milvus/MilvusClientV2.h"
auto client = milvus::MilvusClientV2::Create();
auto status = client->Connect(milvus::ConnectParam("YOUR_CLUSTER_ENDPOINT", "YOUR_CLUSTER_TOKEN"));
if (!status.IsOk()) {
std::cerr << "Failed to connect: " << status.Message() << std::endl;
return;
}
std::vector<float> queryVector = {
0.35803764F, -0.60234958F, 0.18414013F, -0.26286206F, 0.90294385F
};
auto searchRequest = milvus::SearchRequest()
.WithCollectionName("quick_setup")
.WithAnnsField("vector")
.WithLimit(3)
.WithExtraParams({{"level", "1"}})
.AddFloatVector(queryVector);
milvus::SearchResponse searchResponse;
status = client->Search(searchRequest, searchResponse);
if (!status.IsOk()) {
std::cerr << "Search failed: " << status.Message() << std::endl;
return;
}
for (const auto& result : searchResponse.Results().Results()) {
const auto ids = result.Ids().IntIDArray();
for (size_t i = 0; i < result.Scores().size(); ++i) {
std::cout << "id=" << ids[i] << ", score=" << result.Scores()[i] << std::endl;
}
}
import { MilvusClient } from "@zilliz/milvus2-sdk-node";
const client = new MilvusClient({ address: "YOUR_CLUSTER_ENDPOINT", token: "YOUR_CLUSTER_TOKEN" });
const queryVector = [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592];
const res = await client.search({
collection_name: "quick_setup",
data: queryVector,
limit: 3,
params: {
level: "1"
}
});
console.log(res.results);
using Milvus.Client.V2;
using Milvus.Client.V2.Requests.Dql;
using Milvus.Client.V2.Responses.Dql;
using Milvus.Client.V2.Types;
MilvusClientV2 client = new(new ConnectConfig
{
Uri = "YOUR_CLUSTER_ENDPOINT",
Username = "root",
Password = "Milvus"
});
float[] queryVector = [0.3580376395471989f, -0.6023495712049978f, 0.18414012509913835f, -0.26286205330961354f, 0.9029438446296592f];
SearchResp res = await client.SearchAsync(new SearchReq
{
CollectionName = "quick_setup",
VectorFieldName = "vector",
Vectors = [queryVector],
Limit = 3, // The number of results to return
Parameters = new SearchParameters
{
// The precision control
ExtraParameters = { ["level"] = "1" }
}
});
curl --request POST \
--url "YOUR_CLUSTER_ENDPOINT/v2/vectordb/entities/search" \
--header "Authorization: Bearer YOUR_CLUSTER_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"collectionName": "quick_setup",
"data": [
[0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]
],
"annsField": "vector",
"limit": 3,
"searchParams": {
"params": {
"level": 1
}
}
}'
level パラメーターは 1 から 10 の範囲で、デフォルトは 1 です。デフォルト値では Recall Rate は 90% になり、通常はほとんどのユースケースで十分です。
高い Recall Rate(99% 以上)が必要なシナリオでは、level パラメーターを 6 から 10 の間の整数に設定してみてください。検索効率を気にする必要がない場合は、このパラメーターを 10 に設定すると、最も精度の高い結果を得られます。
最も高いレベルの設定でもまだ不十分な場合は、Zilliz Cloud サポート にお問い合わせください。
Recall Rate を調整する
Zilliz Cloud は、調整プロセスを容易にするために、enable_recall_calculation という別の検索パラメーターも提供しています。このパラメーターを True に設定すると、Zilliz Cloud が現在の検索の Recall Rate を推定し、その推定値を検索結果と一緒に返します。
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- CSharp
- cURL
from pymilvus import MilvusClient
client = MilvusClient(
uri="YOUR_CLUSTER_ENDPOINT",
token="YOUR_CLUSTER_TOKEN"
)
query_vector = [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]
res = client.search(
collection_name="quick_setup",
data=[query_vector],
limit=3, # The number of results to return
search_params={
"params": {
"level": 6, # The precision control
"enable_recall_calculation": True # Ask for recall rate calculation
}
}
)
print(res)
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;
import java.util.*;
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("YOUR_CLUSTER_ENDPOINT")
.token("YOUR_CLUSTER_TOKEN")
.build());
FloatVec queryVector = new FloatVec(new float[]{0.3580376395471989f, -0.6023495712049978f, 0.18414012509913835f, -0.26286205330961354f, 0.9029438446296592f});
Map<String, Object> searchParams = new HashMap<>();
searchParams.put("level", 6);
searchParams.put("enable_recall_calculation", true);
SearchReq searchReq = SearchReq.builder()
.collectionName("quick_setup")
.data(Collections.singletonList(queryVector))
.annsField("vector")
.topK(3)
.searchParams(searchParams)
.build();
SearchResp searchResp = client.search(searchReq);
System.out.println(searchResp.getSearchResults());
System.out.println(searchResp.getRecalls());
import (
"context"
"fmt"
"github.com/milvus-io/milvus/client/v3/entity"
"github.com/milvus-io/milvus/client/v3/milvusclient"
)
ctx := context.Background()
client, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: "YOUR_CLUSTER_ENDPOINT",
APIKey: "YOUR_CLUSTER_TOKEN",
})
if err != nil {
fmt.Println(err.Error())
// handle error
}
queryVector := []float32{0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592}
resultSets, err := client.Search(ctx, milvusclient.NewSearchOption(
"quick_setup", // collectionName
3, // limit
[]entity.Vector{entity.FloatVector(queryVector)},
).WithANNSField("vector").
WithSearchParam("level", "6").
WithSearchParam("enable_recall_calculation", "true"))
if err != nil {
fmt.Println(err.Error())
// handle error
}
for _, resultSet := range resultSets {
fmt.Println("IDs: ", resultSet.IDs.FieldData().GetScalars())
fmt.Println("Scores: ", resultSet.Scores)
fmt.Println("Recall: ", resultSet.Recall)
}
use milvus::v2::prelude::*;
use std::collections::HashMap;
let client = ClientV2::new(
&ConnectConfig::new()
.uri("YOUR_CLUSTER_ENDPOINT")
.token("YOUR_CLUSTER_TOKEN"),
)
.await?;
let query_vector = vec![0.3580376395471989f32, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592];
let res = client
.search(
SearchRequest::builder()
.collection_name("quick_setup")
.vector_field("vector")
.vectors(SearchVectors::Float(vec![query_vector]))
.limit(3)
.extra_params(HashMap::from([
("level".into(), "6".into()),
("enable_recall_calculation".into(), "true".into()),
]))
.build()?,
)
.await?;
println!("results: {:?}", res.results());
println!("recalls: {:?}", res.results().get_recalls());
#include <iostream>
#include <vector>
#include "milvus/MilvusClientV2.h"
auto client = milvus::MilvusClientV2::Create();
auto status = client->Connect(milvus::ConnectParam("YOUR_CLUSTER_ENDPOINT", "YOUR_CLUSTER_TOKEN"));
if (!status.IsOk()) {
std::cerr << "Failed to connect: " << status.Message() << std::endl;
return;
}
std::vector<float> queryVector = {
0.35803764F, -0.60234958F, 0.18414013F, -0.26286206F, 0.90294385F
};
auto searchRequest = milvus::SearchRequest()
.WithCollectionName("quick_setup")
.WithAnnsField("vector")
.WithLimit(3)
.WithExtraParams({{"level", "6"}, {"enable_recall_calculation", "true"}})
.AddFloatVector(queryVector);
milvus::SearchResponse searchResponse;
status = client->Search(searchRequest, searchResponse);
if (!status.IsOk()) {
std::cerr << "Search failed: " << status.Message() << std::endl;
return;
}
for (const auto& result : searchResponse.Results().Results()) {
const auto ids = result.Ids().IntIDArray();
for (size_t i = 0; i < result.Scores().size(); ++i) {
std::cout << "id=" << ids[i] << ", score=" << result.Scores()[i] << std::endl;
}
}
for (const auto& recall : searchResponse.Results().Recalls()) {
std::cout << "recall=" << recall << std::endl;
}
import { MilvusClient } from "@zilliz/milvus2-sdk-node";
const client = new MilvusClient({ address: "YOUR_CLUSTER_ENDPOINT", token: "YOUR_CLUSTER_TOKEN" });
const queryVector = [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592];
const res = await client.search({
collection_name: "quick_setup",
data: queryVector,
limit: 3,
params: {
level: "6",
enable_recall_calculation: "true"
}
});
console.log(res.results);
console.log(res.recalls);
using Milvus.Client.V2;
using Milvus.Client.V2.Requests.Dql;
using Milvus.Client.V2.Responses.Dql;
using Milvus.Client.V2.Types;
MilvusClientV2 client = new(new ConnectConfig
{
Uri = "YOUR_CLUSTER_ENDPOINT",
Username = "root",
Password = "Milvus"
});
float[] queryVector = [0.3580376395471989f, -0.6023495712049978f, 0.18414012509913835f, -0.26286205330961354f, 0.9029438446296592f];
SearchResp res = await client.SearchAsync(new SearchReq
{
CollectionName = "quick_setup",
VectorFieldName = "vector",
Vectors = [queryVector],
Limit = 3, // The number of results to return
Parameters = new SearchParameters
{
ExtraParameters =
{
["level"] = "6", // The precision control
["enable_recall_calculation"] = "true" // Ask for recall rate calculation
}
}
});
curl --request POST \
--url "YOUR_CLUSTER_ENDPOINT/v2/vectordb/entities/search" \
--header "Authorization: Bearer YOUR_CLUSTER_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"collectionName": "quick_setup",
"data": [
[0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]
],
"annsField": "vector",
"limit": 3,
"searchParams": {
"params": {
"level": 6,
"enable_recall_calculation": true
}
}
}'
上記の検索リクエストを使用すると、現在の検索の推定 Recall Rate を次のように取得できます。
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- CSharp
- cURL
# data: [...], recalls: [0.98]
// searchResults: [...], recalls: [0.98]
// IDs: [...], Scores: [...], Recall: 0.98
// results: [...], recalls: [0.98]
// id=..., score=...; recall=0.98
// results: [...], recalls: [0.98]
// searchResults: [...], recalls: [0.98]
# data: [...], recalls: [0.98]
推定プロセスでは、Zilliz Cloud は次の処理を行います。
-
levelパラメーターをユーザーが定義した値に設定して検索します。 -
内部の高精度モードで別の検索を実行します。
-
2 回目の検索をグラウンドトゥルースとして使用して、Recall Rate を推定します。
enable_recall_calculation を True に設定した状態で level パラメーターの値を調整すると、複数の Recall Rate を取得できます。これらの推定値と各検索の所要時間を考慮することで、適切なレベル設定を概算できます。
enable_recall_calculation を有効にすると検索パフォーマンスに影響する可能性があるため、本番環境では推奨されません。
制限
現在、この機能は Zilliz Cloud クラスターの基本ベクトル検索、フィルター検索、範囲検索でのみ使用できます。