メインコンテンツまでスキップ
バージョン: User Guides (Cloud)

フレーズマッチ
Public Preview

フレーズマッチを使用すると、クエリ用語を正確なフレーズとして含むドキュメントを検索できます。デフォルトでは、単語は同じ順序で互いに直接隣接して表示される必要があります。たとえば、「robotics machine learning」のクエリは、「robotics」「machine」、および**「learning」の単語が間に他の単語なしで連続して表示される「…typical robotics machine learning models…」**のようなテキストに一致します。

ただし、実際のシナリオでは、厳密なフレーズマッチは柔軟性に欠けることがあります。「…machine learning models widely adopted in robotics…」のようなテキストに一致させたい場合があります。ここでは同じキーワードが存在しますが、並び順が同じでも隣接していないか、元の順序とは異なります。これを処理するために、フレーズマッチはスロップパラメータをサポートしており、フレックス性を導入します。スロップ値は、フレーズ内の語間で許容される位置シフトの数を定義します。たとえば、スロップが1の場合、「machine learning」のクエリは「...machine deep learning...」のようなテキストに一致し、元の語間に1つの単語(「deep」)が含まれます。

概要

Tantivy検索エンジンライブラリによって駆動されるフレーズマッチは、ドキュメント内の単語の位置情報を分析することによって機能します。以下の図はそのプロセスを示しています:

AFrdwVT8ChT11ibs9lpcuN7onZc

  1. ドキュメントのトークン化:ドキュメントをZilliz Cloudに挿入すると、テキストはアナライザーを使用してトークン(個別の単語または用語)に分割され、各トークンの位置情報が記録されます。たとえば、doc_1は**["machine" (pos=0), "learning" (pos=1), "boosts" (pos=2), "efficiency" (pos=3)]**にトークン化されます。アナライザーの詳細については、アナライザーの概要を参照してください。

  2. 逆インデックスの作成:Zilliz Cloudは逆インデックスを構築し、各トークンをそれが出現するドキュメントとそのドキュメント内のトークン位置にマッピングします。

  3. フレーズマッチング:フレーズクエリが実行されると、Zilliz Cloudは逆インデックスで各トークンを検索し、正しい順序で近接して表示されているかどうかを判断するためにその位置をチェックします。スロップパラメータは、一致するトークン間で許容される最大位置数を制御します:

    • スロップ = 0 は、トークンが正確な順序で直ちに隣接している必要があることを意味します(つまり、間に余分な単語がありません)。

      • 例では、doc_1"machine"pos=0、**"learning"**が pos=1)のみが正確に一致します。
    • スロップ = 2 は、一致するトークン間に最大2つの位置の柔軟性または並べ替えを許可します。

      • これにより、逆順("learning machine")またはトークン間に小さなギャップがある場合が可能になります。

      • 結果として、doc_1doc_2"learning"pos=0"machine"pos=1)、および doc_3"learning"pos=1、**"machine"**が pos=2)がすべて一致します。

フレーズマッチの有効化

フレーズマッチはZilliz Cloudの文字列データ型であるVARCHARフィールドで動作します。

フレーズマッチを有効にするには、enable_analyzerおよびenable_matchパラメータの両方をTrueに設定してコレクションスキーマを構成します。この構成により、テキストがトークン化され、位置情報を含む逆インデックスが作成され、効率的なフレーズ検索が可能になります。

スキーマフィールドの定義

特定のVARCHARフィールドでフレーズマッチを有効にするには、フィールドスキーマを定義する際にenable_analyzerおよびenable_matchの両方をTrueに設定します。

from pymilvus import MilvusClient, DataType

# MilvusClientをセットアップ
CLUSTER_ENDPOINT = "YOUR_CLUSTER_ENDPOINT"
TOKEN = "YOUR_CLUSTER_TOKEN"

client = MilvusClient(
uri=CLUSTER_ENDPOINT,
token=TOKEN
)

# 新しいコレクションのスキーマを作成
schema = client.create_schema(enable_dynamic_field=False)

# 主キーフィールドを追加
schema.add_field(
field_name="id",
datatype=DataType.INT64,
is_primary=True,
auto_id=True
)

# フレーズマッチ用に設定されたVARCHARフィールドを追加
schema.add_field(
field_name="text", # フィールド名
datatype=DataType.VARCHAR, # フィールドデータ型をVARCHAR(文字列)に設定
max_length=1000, # 最大文字列長
enable_analyzer=True, # 必須。テキスト分析を有効にします
enable_match=True, # 必須。フレーズマッチング用の逆インデックス作成を有効にします
# 任意:特定の言語でフレーズマッチングを改善するためにカスタムアナライザーを使用します。
# analyzer_params = {"type": "english"} # 例:英語アナライザー;コメントを解除してカスタムアナライザーを適用
)

# 埋め込み用のベクトルフィールドを追加
schema.add_field(
field_name="embeddings",
datatype=DataType.FLOAT_VECTOR,
dim=5
)

デフォルトでは、Zilliz Cloudは標準 アナライザーを使用します。これは、空白と句読点でテキストをトークン化し、テキストを小文字に変換します。

テキストデータが特定の言語または形式の場合は、analyzer_paramsパラメータを使用してカスタムアナライザーを構成できます(例:{ "type": "english" }または{ "type": "jieba" })。

詳細はアナライザーの概要を参照してください。

コレクションの作成

必要なフィールドが定義されたら、以下のコードを使用してコレクションを作成します:

# コレクションを作成
COLLECTION_NAME = "tech_articles" # コレクションに名前を付ける

if client.has_collection(COLLECTION_NAME):
client.drop_collection(COLLECTION_NAME)

client.create_collection(
collection_name=COLLECTION_NAME,
schema=schema
)

コレクションが作成された後、フレーズマッチの使用の前に以下の必要な手順を確実に実行してください:

  • エンティティをコレクションに挿入します。

  • 各ベクトルフィールドにインデックスを作成します。

  • コレクションをメモリにロードします。

サンプルコードを表示
# "machine learning"フレーズを含むサンプルデータを挿入
sample_data = [
{
"text": "Machine learning is a subset of artificial intelligence that focuses on algorithms.",
"embeddings": [0.1, 0.2, 0.3, 0.4, 0.5]
},
{
"text": "Deep learning machine algorithms require large datasets for training.",
"embeddings": [0.2, 0.3, 0.4, 0.5, 0.6]
},
{
"text": "The machine learning model showed excellent performance on the test set.",
"embeddings": [0.3, 0.4, 0.5, 0.6, 0.7]
},
{
"text": "Natural language processing and machine learning go hand in hand.",
"embeddings": [0.4, 0.5, 0.6, 0.7, 0.8]
},
{
"text": "This article discusses various learning machine techniques and applications.",
"embeddings": [0.5, 0.6, 0.7, 0.8, 0.9]
}
]

# データを挿入
client.insert(
collection_name=COLLECTION_NAME,
data=sample_data
)

# ベクトルフィールドにインデックスを作成し、コレクションをロード
index_params = client.prepare_index_params()
index_params.add_index(
field_name="embeddings",
index_type="AUTOINDEX",
index_name="embeddings_index",
metric_type="COSINE"
)

client.create_index(collection_name=COLLECTION_NAME, index_params=index_params)

client.load_collection(collection_name=COLLECTION_NAME)

フレーズマッチの使用

コレクションスキーマでVARCHARフィールドのマッチを有効にすると、PHRASE_MATCH式を使用してフレーズマッチを実行できます。

📘ノート

PHRASE_MATCH式は大文字小文字を区別しません。PHRASE_MATCHまたはphrase_matchを使用できます。

PHRASE_MATCH式の構文

PHRASE_MATCH式を使用して、検索時のフィールド、フレーズ、およびオプショナルな柔軟性(スロップ)を指定します。構文は以下の通りです:

PHRASE_MATCH(field_name, phrase, slop)
  • field_name フレーズマッチを実行するVARCHARフィールドの名前。

  • phrase 検索する正確なフレーズ。

  • slop(オプショナル) 一致するトークン間に許容される最大位置数を指定する整数。

    • 0(デフォルト):正確なフレーズのみに一致します。例:**"machine learning"のフィルターは"machine learning"に正確に一致しますが、"machine boosts learning"または"learning machine"**には一致しません。

    • 1:余分な用語または位置の微小なシフトなどの軽微な変動を許可します。例:"machine learning"のフィルターは"machine boosts learning""machine""learning"の間に1つのトークン)には一致しますが、"learning machine"(用語が逆)には一致しません。

    • 2:逆順の用語順序または間に最大2つのトークンがある場合など、より柔軟性を許可します。例:"machine learning"のフィルターは"learning machine"(用語が逆)または**"machine quickly boosts learning""machine""learning"**の間に2つのトークン)に一致します。

フレーズマッチでのクエリ

query()メソッドを使用する場合、PHRASE_MATCHはスカラーフィルターとして機能します。指定されたフレーズ(許容されるスロップを含む)を含むドキュメントのみが返されます。

例:スロップ = 0(正確一致)

この例では、間に余分なトークンがない正確なフレーズ**"machine learning"**を含むドキュメントを返します。

# "machine learning"を正確に含むドキュメントに一致
filter = "PHRASE_MATCH(text, 'machine learning')"

result = client.query(
collection_name=COLLECTION_NAME,
filter=filter,
output_fields=["id", "text"]
)

print("クエリ結果: ", result)

# 期待される出力:
# クエリ結果: data: ["{'id': 461366973343948097, 'text': 'Machine learning is a subset of artificial intelligence that focuses on algorithms.'}", "{'id': 461366973343948099, 'text': 'The machine learning model showed excellent performance on the test set.'}", "{'id': 461366973343948100, 'text': 'Natural language processing and machine learning go hand in hand.'}"]

フレーズマッチでの検索

検索操作では、PHRASE_MATCHを使用してベクトル類似度ランキングを適用する前にドキュメントを事前フィルタリングします。この2段階アプローチは、まずテキストマッチングで候補セットを絞り込み、その後ベクトル埋め込みに基づいてそれらの候補を再ランク付けします。

例:スロップ = 1

ここでは、スロップ1を許可します。フィルターは、少しの柔軟性があるフレーズ**"learning machine"**を含むドキュメントに適用されます。

# 例: スロップ1で"learning machine"を含むドキュメントをフィルター
filter_slop1 = "PHRASE_MATCH(text, 'learning machine', 1)"

result_slop1 = client.search(
collection_name=COLLECTION_NAME,
anns_field="embeddings",
data=[[0.1, 0.2, 0.3, 0.4, 0.5]],
filter=filter_slop1,
search_params={},
limit=10,
output_fields=["id", "text"]
)

print("スロップ1の結果: ", result_slop1)

# 期待される出力:
# スロップ1の結果: data: [[{'id': 461366973343948097, 'distance': 0.9999999403953552, 'entity': {'text': 'Machine learning is a subset of artificial intelligence that focuses on algorithms.', 'id': 461366973343948097}}, {'id': 461366973343948098, 'distance': 0.9949367046356201, 'entity': {'text': 'Deep learning machine algorithms require large datasets for training.', 'id': 461366973343948098}}, {'id': 461366973343948099, 'distance': 0.9864400029182434, 'entity': {'text': 'The machine learning model showed excellent performance on the test set.', 'id': 461366973343948099}}, {'id': 461366973343948100, 'distance': 0.9782319068908691, 'entity': {'text': 'Natural language processing and machine learning go hand in hand.', 'id': 461366973343948100}}, {'id': 461366973343948101, 'distance': 0.9710607528686523, 'entity': {'text': 'This article discusses various learning machine techniques and applications.', 'id': 461366973343948101}}]]

例:スロップ = 2

この例では、スロップ2を許可しており、**"machine""learning"**の単語間で最大2つの余分なトークン(または逆の用語)が許可されていることを意味します。

# 例: スロップ2で"machine learning"を含むドキュメントをフィルター
filter_slop2 = "PHRASE_MATCH(text, 'machine learning', 2)"

result_slop2 = client.search(
collection_name=COLLECTION_NAME,
anns_field="embeddings", # ベクトルフィールド名
data=[[0.1, 0.2, 0.3, 0.4, 0.5]], # クエリベクトル
filter=filter_slop2, # フィルター式
search_params={},
limit=10, # 返される最大結果数
output_fields=["id", "text"]
)

print("スロップ2の結果: ", result_slop2)

# 期待される出力:
# スロップ2の結果: data: [[{'id': 461366973343948097, 'distance': 0.9999999403953552, 'entity': {'text': 'Machine learning is a subset of artificial intelligence that focuses on algorithms.', 'id': 461366973343948097}}, {'id': 461366973343948098, 'distance': 0.9949367046356201, 'entity': {'text': 'Deep learning machine algorithms require large datasets for training.', 'id': 461366973343948098}}, {'id': 461366973343948099, 'distance': 0.9864400029182434, 'entity': {'text': 'The machine learning model showed excellent performance on the test set.', 'id': 461366973343948099}}, {'id': 461366973343948100, 'distance': 0.9782319068908691, 'entity': {'text': 'Natural language processing and machine learning go hand in hand.', 'id': 461366973343948100}}, {'id': 461366973343948101, 'distance': 0.9710607528686523, 'entity': {'text': 'This article discusses various learning machine techniques and applications.', 'id': 461366973343948101}}]]

例:スロップ = 3

この例では、スロップ3により柔軟性がさらに高まります。フィルターは、単語間に最大3つのトークン位置が許容される**"machine learning"**を検索します。

# 例: スロップ3で"machine learning"を含むドキュメントをフィルター
filter_slop3 = "PHRASE_MATCH(text, 'machine learning', 3)"

result_slop3 = client.search(
collection_name=COLLECTION_NAME,
anns_field="embeddings", # ベクトルフィールド名
data=[[0.1, 0.2, 0.3, 0.4, 0.5]], # クエリベクトル
filter=filter_slop3, # フィルター式
search_params={},
limit=10, # 返される最大結果数
output_fields=["id", "text"]
)

print("スロップ3の結果: ", result_slop3)

# 期待される出力:
# スロップ3の結果: data: [[{'id': 461366973343948097, 'distance': 0.9999999403953552, 'entity': {'text': 'Machine learning is a subset of artificial intelligence that focuses on algorithms.', 'id': 461366973343948097}}, {'id': 461366973343948098, 'distance': 0.9949367046356201, 'entity': {'text': 'Deep learning machine algorithms require large datasets for training.', 'id': 461366973343948098}}, {'id': 461366973343948099, 'distance': 0.9864400029182434, 'entity': {'text': 'The machine learning model showed excellent performance on the test set.', 'id': 461366973343948099}}, {'id': 461366973343948100, 'distance': 0.9782319068908691, 'entity': {'text': 'Natural language processing and machine learning go hand in hand.', 'id': 461366973343948100}}, {'id': 461366973343948101, 'distance': 0.9710607528686523, 'entity': {'text': 'This article discusses various learning machine techniques and applications.', 'id': 461366973343948101}}]]

考慮事項

  • フィールドのフレーズマッチを有効にすると、逆インデックスの作成がトリガーされ、ストレージリソースが消費されます。この機能を有効にする際には、テキストサイズ、一意のトークン、および使用されるアナライザーに基づいてストレージへの影響を考慮してください。

  • スキーマでアナライザーを定義すると、その設定はそのコレクションでは永久になります。異なるアナライザーがニーズにより適していると判断した場合は、既存のコレクションを削除し、目的のアナライザー構成で新しいものを作成することを検討してください。

  • フレーズマッチのパフォーマンスは、テキストがどのようにトークン化されるかに依存します。アナライザーをコレクション全体に適用する前に、run_analyzerメソッドを使用してトークン化出力を確認してください。詳細については、アナライザーの概要を参照してください。

  • filter式のエスケープルール:

    • 式内で二重引用符または単一引用符で囲まれた文字は文字列定数として解釈されます。文字列定数にエスケープ文字が含まれている場合、エスケープ文字はエスケープシーケンスで表す必要があります。たとえば、\を表すには\\、タブ\tを表すには\\t、改行を表すには\\nを使用します。

    • 文字列定数が単一引用符で囲まれている場合、定数内の単一引用符は\\'として表されなければならず、二重引用符は"または\\"のいずれかとして表すことができます。例:'It\\'s milvus'

    • 文字列定数が二重引用符で囲まれている場合、定数内の二重引用符は\\"として表されなければならず、単一引用符は'または\\'のいずれかとして表すことができます。例:"He said \\"Hi\\""