はじめに
メタデータは、Pineconeの強力で柔軟な機能であり、データオブジェクトのベクトル表現に追加のコンテキストを提供します。インデックス内のベクトルにキーと値のペアのメタデータを添付することで、ベクトル検索をより正確に特定のユースケースに合わせることができます。この記事では、Pineconeにおけるメタデータの実装やサポートされている型、検索クエリの改善における有用性、挿入、クエリ、削除などのデータ管理タスクにおける役割など、メタデータのさまざまな側面について説明します。
メタデータを使用したフィルタリング
Pineconeにおけるメタデータの主な目的は、特定の属性や条件に基づいてベクトル検索を制限することです。この機能は、インデックスへのクエリ時にフィルタ式を指定することで実現されます。メタデータフィルタは、指定したフィルタに一致するもっとも近い隣接結果の正確な数を取得するのに非常に効果的です。
メタデータフィルタを使用する主な利点の一つは、ほとんどの場合、検索のレイテンシーがフィルタなしの検索よりも低いことです。この高速化は正確性や関連性に影響を与えず、Pineconeにおけるベクトル検索の精度を向上させる効果的なツールとなります。
サポートされるメタデータの型
Pineconeでは、インデックス内の各ベクトルにメタデータペイロードを関連付けることができます。このペイロードは、キーと値のペアからなるJSONオブジェクトで、キーは文字列で、値は次のいずれかの型です。
- 文字列
- 数値(整数または浮動小数点数であり、64ビット浮動小数点数に変換されます)
- ブール値(true、false)
- 文字列のリスト
有効なメタデータペイロードの例
以下は、Pineconeで有効なメタデータペイロードの例です。
{
  "genre": "action",
  "year": 2020,
  "length_hrs": 1.5
}
映画に関連するメタデータの例です。各キーと値のペアは、映画の異なる属性を表しています。
{
  "color": "blue",
  "fit": "straight",
  "price": 29.99,
  "is_jeans": true
}
衣料品に関連するメタデータの例です。キーと値のペアは、アイテムの色、フィット感、価格、タイプを説明しています。
サポートされるメタデータサイズ
Pineconeは、1つのベクトルあたりのメタデータを40kbまでサポートしています。この制限により、効率的な検索とデータの取得パフォーマンスを維持しながら、詳細なメタデータに十分なスペースを提供することができます。
メタデータクエリ言語
Pineconeのメタデータクエリ言語では、ANDやORなどの論理演算子を使用してメタデータフィルタを組み合わせることができます。以下は使用可能な演算子の一部です。
- $eq:等しい(数値、文字列、ブール値に適用)
- $ne:等しくない(数値、文字列、ブール値に適用)
- $gt:より大きい(数値に適用)
- $gte:以上(数値に適用)
- $lt:未満(数値に適用)
- $lte:以下(数値に適用)
- $in:配列内に含まれる(文字列または数値に適用)
- $nin:配列内に含まれない(文字列または数値に適用)
Pineconeでは、メタデータの値またはメタデータフィルタとして文字列の配列を使用することができます。この柔軟性により、より複雑なフィルタリング式を作成し、さまざまなデータシナリオに対応することができます。
例えば、次のようなメタデータペイロードを持つベクトルを考えてみます。
{ "genre": ["comedy", "documentary"] }
以下は、上記のベクトルに一致するフィルタを持つクエリの例です。
{"genre":"comedy"}
{"genre": {"$in":["documentary","action"]}}
{"$and": [{"genre": "comedy"}, {"genre":"documentary"}]}
逆に、次のフィルタを持つクエリはベクトルに一致しません。
{ "$and": [{ "genre": "comedy" }, { "genre": "drama" }] }
インデックスへのメタデータの挿入
ベクトルを挿入する際に、メタデータをアップサートリクエストに含めることができます。
以下は、Pythonクライアントを使用して映画を表す関連メタデータを持つベクトルをPineconeインデックスに挿入する例です。
import pinecone
pinecone.init(api_key="your-api-key", environment="us-west1-gcp")
index = pinecone.Index("example-index")
index.upsert([
    ("A", [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1], {"genre": "comedy", "year": 2020}),
    ("B", [0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2], {"genre": "documentary", "year": 2019}),
    ("C", [0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3], {"genre": "comedy", "year": 2019}),
    ("D", [0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4], {"genre": "drama"}),
    ("E", [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5], {"genre": "drama"})
])
メタデータフィルタを使用したインデックスのクエリ
ベクトルにメタデータが添付されている場合、クエリにメタデータフィルタ式を含めることで、検索を絞り込むことができます。これにより、フィルタに一致するベクトルのみを検索の対象とすることができます。
例えば、前の章で作成した映画インデックスから、2019年のドキュメンタリー映画を検索することができます。次の例では、include_metadataフラグを使用してレスポンスにベクトルのメタデータを含めています。
index.query(
    vector=[0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1],
    filter={
        "genre": {"$eq": "documentary"},
        "year": 2019
    },
    top_k=1,
    include_metadata=True
)
{'matches': [{'id': 'B',
              'metadata': {'genre': 'documentary', 'year': 2019.0},
              'score': 0.0800000429,
              'values': []}],
 'namespace': ''}
パフォーマンス上の理由から、top_k > 1000の場合はベクトルデータとメタデータを返さないように推奨されています。top_kが1000を超えるクエリには、include_metadata=Trueまたはinclude_data=Trueを含めないようにしてください。
メタデータフィルタによるベクトルの削除
メタデータフィルタ式を削除操作に渡すことで、メタデータの値に基づいて削除するベクトルを指定することができます。この機能により、メタデータフィルタ式に一致する全てのベクトルを効率的に削除することができます。
以下は、ジャンルが「documentary」であり、年が2019年の全てのベクトルをインデックスから削除する例です。
index.delete(
    filter={
        "genre": {"$eq": "documentary"},
        "year": 2019
    }
)
参考