Weighted Ranker
Weighted Ranker は、複数の検索パスからの結果をインテリジェントに結合し、それぞれの重要度に応じて優先順位を付けます。熟練したシェフが複数の食材のバランスをとって完璧な料理を作るように、Weighted Ranker は異なる検索結果のバランスをとって、最も関連性の高い結合された結果を提供します。このアプローチは、特定のフィールドが最終的なランキングに他のフィールドよりも大きく貢献すべきである、複数のベクトルフィールドまたはモダリティにわたって検索する場合に理想的です。
Weighted Ranker を使用するタイミング
Weighted Ranker は、複数のベクトル検索パスからの結果を結合する必要があるハイブリッド検索シナリオ向けに特別に設計されています。特に以下の状況で効果的です。
ユースケース | 例 | Weighted Ranker がうまく機能する理由 |
|---|---|---|
Eコマース検索 | 画像類似性とテキスト記述を組み合わせた製品検索 | 小売業者がファッションアイテムの視覚的類似性を優先し、技術製品のテキスト記述を強調することを可能にする |
メディアコンテンツ検索 | 視覚的特徴と音声トランスクリプトの両方を使用したビデオ検索 | クエリの意図に基づいて、視覚的コンテンツと音声対話の重要性のバランスをとる |
ドキュメント検索 | 異なるセクションに複数の埋め込みを持つエンタープライズドキュメント検索 | タイトルと要約の埋め込みにより高い重みを与え、全文の埋め込みも考慮する |
ハイブリッド検索アプリケーションで、複数の検索パスを結合し、それらの相対的な重要度を制御する必要がある場合、Weighted Ranker は理想的な選択肢です。
Weighted Ranker のメカニズム
WeightedRanker 戦略の主なワークフローは次のとおりです。
-
検索スコアを収集: 各ベクトル検索パスからの結果とスコア (score_1, score_2) を収集します。
-
スコアの正規化: 各検索では異なる類似度メトリックを使用する可能性があり、結果としてスコアの分布が異なります。たとえば、内積 (IP) を類似度タイプとして使用すると、スコアは [−∞,+∞] の範囲になる可能性がありますが、ユークリッド距離 (L2) を使用すると、スコアは [0,+∞] の範囲になります。異なる検索からのスコア範囲は異なり、直接比較できないため、各検索パスからのスコアを正規化する必要があります。通常、
arctan関数を適用して、スコアを [0, 1] の範囲に変換します (score_1_normalized, score_2_normalized)。1 に近いスコアは、より高い類似度を示します。 -
重みの割り当て: 異なるベクトルフィールドに割り当てられた重要度に基づいて、正規化されたスコア (score_1_normalized, score_2_normalized) に重み (wi) が割り当てられます。各パスの重みは [0,1] の範囲である必要があります。結果として得られる重み付けされたスコアは score_1_weighted と score_2_weighted です。
-
スコアのマージ: 重み付けされたスコア (score_1_weighted, score_2_weighted) は、最終的なスコアセット (score_final) を生成するために、高い順にランク付けされます。

Weighted Ranker の例
この例では、画像とテキストを含むマルチモーダルハイブリッド検索 (topK=5) を示し、WeightedRanker 戦略が 2 つの ANN 検索の結果をどのように再ランク付けするかを説明します。
-
画像に対する ANN 検索の結果 (topK=5):
ID
スコア (画像)
101
0.92
203
0.88
150
0.85
198
0.83
175
0.8
-
テキストに対する ANN 検索の結果 (topK=5):
ID
スコア (テキスト)
198
0.91
101
0.87
110
0.85
175
0.82
250
0.78
-
WeightedRanker を使用して、画像とテキストの検索結果に重みを割り当てます。画像 ANN 検索の重みが 0.6、テキスト検索の重みが 0.4 であると仮定します。
ID
スコア (画像)
スコア (テキスト)
重み付けされたスコア
101
0.92
0.87
0.6×0.92+0.4×0.87=0.90
203
0.88
N/A
0.6×0.88+0.4×0=0.528
150
0.85
N/A
0.6×0.85+0.4×0=0.51
198
0.83
0.91
0.6×0.83+0.4×0.91=0.86
175
0.80
0.82
0.6×0.80+0.4×0.82=0.81
110
画像にない
0.85
0.6×0+0.4×0.85=0.34
250
画像にない
0.78
0.6×0+0.4×0.78=0.312
-
再ランク付け後の最終結果 (topK=5):
ランク
ID
最終スコア
1
101
0.90
2
198
0.86
3
175
0.81
4
203
0.528
5
150
0.51
Weighted Ranker の使用法
WeightedRanker 戦略を使用する場合、重み値を入力する必要があります。入力する重み値の数は、ハイブリッド検索における基本的な ANN 検索リクエストの数に対応している必要があります。入力する重み値は [0,1] の範囲である必要があり、1 に近い値ほど重要度が高いことを示します。
Weighted Ranker の作成
たとえば、ハイブリッド検索にテキスト検索と画像検索という 2 つの基本的な ANN 検索リクエストがあるとします。テキスト検索がより重要であると見なされる場合、より大きな重みを割り当てる必要があります。
- Python
- Java
- NodeJS
- Go
- cURL
from pymilvus import Function, FunctionType
rerank = Function(
name="weight",
input_field_names=[], # Must be an empty list
function_type=FunctionType.RERANK,
params={
"reranker": "weighted",
"weights": [0.1, 0.9],
"norm_score": True # Optional
}
)
import io.milvus.common.clientenum.FunctionType;
import io.milvus.v2.service.collection.request.CreateCollectionReq;
CreateCollectionReq.Function rerank = CreateCollectionReq.Function.builder()
.name("weight")
.functionType(FunctionType.RERANK)
.param("reranker", "weighted")
.param("weights", "[0.1, 0.9]")
.param("norm_score", "true")
.build();
import { FunctionType } from '@zilliz/milvus2-sdk-node';
const rerank = {
name: "weight",
input_field_names: [],
function_type: FunctionType.RERANK,
params: {
reranker: "weighted",
weights: [0.1, 0.9],
norm_score: true
}
};
// Go
# Restful
パラメータ | 必須項目 | 説明 | 値/例 |
|---|---|---|---|
| はい | この関数のユニークな識別子 |
|
| はい | 関数を適用するベクトルフィールドのリスト (Weighted Ranker の場合は空である必要があります) | [] |
| はい | 呼び出す関数のタイプ。リランキング戦略を指定するには |
|
| はい | 使用するリランキング方法を指定します。 Weighted Ranker を使用するには |
|
| はい | 各検索パスに対応する重みの配列。値は [0,1] です。 詳細については、Weighted Ranker のメカニズムを参照してください。 |
|
| いいえ | 重み付けの前に生スコアを (arctan を使用して) 正規化するかどうか。 詳細については、Weighted Ranker のメカニズムを参照してください。 |
|
ハイブリッド検索への適用
Weighted Ranker は、複数のベクトルフィールドを組み合わせるハイブリッド検索操作のために特別に設計されています。ハイブリッド検索を実行する場合、各検索パスの重みを指定する必要があります。
- Python
- Java
- NodeJS
- Go
- cURL
from pymilvus import MilvusClient, AnnSearchRequest
# Connect to Milvus server
milvus_client = MilvusClient(uri="YOUR_CLUSTER_ENDPOINT")
# Assume you have a collection setup
# Define text vector search request
text_search = AnnSearchRequest(
data=["modern dining table"],
anns_field="text_vector",
param={},
limit=10
)
# Define image vector search request
image_search = AnnSearchRequest(
data=[image_embedding], # Image embedding vector
anns_field="image_vector",
param={},
limit=10
)
# Apply Weighted Ranker to product hybrid search
# Text search has 0.8 weight, image search has 0.3 weight
hybrid_results = milvus_client.hybrid_search(
collection_name,
[text_search, image_search], # Multiple search requests
ranker=rerank, # Apply the weighted ranker
limit=10,
output_fields=["product_name", "price", "category"]
)
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.service.vector.request.AnnSearchReq;
import io.milvus.v2.service.vector.request.HybridSearchReq;
import io.milvus.v2.service.vector.response.SearchResp;
import io.milvus.v2.service.vector.request.data.EmbeddedText;
import io.milvus.v2.service.vector.request.data.FloatVec;
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("YOUR_CLUSTER_ENDPOINT")
.build());
List<AnnSearchReq> searchRequests = new ArrayList<>();
searchRequests.add(AnnSearchReq.builder()
.vectorFieldName("text_vector")
.vectors(Collections.singletonList(new EmbeddedText("\"modern dining table\"")))
.limit(10)
.build());
searchRequests.add(AnnSearchReq.builder()
.vectorFieldName("image_vector")
.vectors(Collections.singletonList(new FloatVec(imageEmbedding)))
.limit(10)
.build());
HybridSearchReq hybridSearchReq = HybridSearchReq.builder()
.collectionName(COLLECTION_NAME)
.searchRequests(searchRequests)
.ranker(ranker)
.limit(10)
.outputFields(Arrays.asList("product_name", "price", "category"))
.build();
SearchResp searchResp = client.hybridSearch(hybridSearchReq);
import { MilvusClient, FunctionType } from "@zilliz/milvus2-sdk-node";
const milvusClient = new MilvusClient({ address: "YOUR_CLUSTER_ENDPOINT" });
const text_search = {
data: ["modern dining table"],
anns_field: "text_vector",
param: {},
limit: 10,
};
const image_search = {
data: [image_embedding],
anns_field: "image_vector",
param: {},
limit: 10,
};
const search = await milvusClient.search({
collection_name: collection_name,
limit: 10,
data: [text_search, image_search],
rerank: rerank,
output_fields = ["product_name", "price", "category"],
});
// go
# restful
ハイブリッド検索の詳細については、マルチベクトルハイブリッド検索を参照してください。