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

フレーズ一致

フレーズ一致を使用すると、クエリ語句を正確なフレーズとして含むドキュメントを検索できます。デフォルトでは、単語は同じ順序で隣接して出現する必要があります。たとえば、"robotics machine learning" というクエリは、"…typical robotics machine learning models…" のようなテキストに一致します。この場合、"robotics""machine"、および**"learning"** の単語は間に他の単語がない状態で連続して出現します。

しかし、現実のシナリオでは、厳密なフレーズ一致は硬すぎる場合があります。"…machine learning models widely adopted in robotics…" のようなテキストに一致させたい場合もあります。ここでは同じキーワードが存在しますが、並んでいたり元の順序で出現していたりしていません。これを処理するために、フレーズ一致は slop パラメータをサポートしており、これにより柔軟性がもたらされます。slop 値は、フレーズ内の各語間で許容される位置のシフト数を定義します。たとえば、slop が 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は逆インデックスで各トークンを検索し、それらの位置をチェックして正しい順序と近接性で出現しているかどうかを判断します。slop パラメータは、一致するトークン間で許容される最大位置数を制御します。

    • slop = 0 は、トークンが正確な順序で直ちに隣接して出現しなければならないことを意味します(つまり、間に余分な単語は存在できません)。

      • 例では、doc_1"machine"pos=0"learning"pos=1)のみが正確に一致します。
    • slop = 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_analyzerenable_match の両方のパラメータを True に設定してコレクションスキーマを構成します。この設定では、テキストをトークン化し、位置情報を含む逆インデックスを構築して、効率的なフレーズ検索を可能にします。

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

特定の VARCHAR フィールドでフレーズ一致を有効にするには、フィールドスキーマを定義する際に enable_analyzerenable_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はstandard analyzerを使用し、これは空白文字や句読点でテキストをトークン化し、小文字に変換します。

テキストデータが特定の言語や形式の場合には、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式を使用して、検索時のフィールド、フレーズ、およびオプションの柔軟性(slop)を指定します。構文は以下の通りです。

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

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

  • slop(オプション): 一致するトークンで許容される最大位置数を示す整数。

    • 0(デフォルト): 完全一致のみを検索します。例:"machine learning" というフィルターは "machine learning" にのみ一致し、"machine boosts learning""learning machine" には一致しません。

    • 1: 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 はスカラー絞り込みとして機能します。指定されたフレーズ(許容されたslop以内)を含むドキュメントのみが返されます。

例:slop = 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("Query result: ", result)

# 期待される出力:
# Query 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段階アプローチは、まずテキスト一致によって候補セットを絞り込み、それからベクトル埋め込みに基づいてそれらの候補を再ランキングします。

例:slop = 1

ここでは、slop の値を 1 に設定しています。フィルターは、フレーズ "learning machine" を少しの柔軟性で含むドキュメントに適用されます。

# 例:slop=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("Slop 1 result: ", result_slop1)

# 期待される出力:
# Slop 1 r...

例:slop = 2

この例では、slop の値を 2 に設定しています。つまり、"machine""learning" の間にある高々 2 つの余分なトークン(または逆順の語)が許容されます。

# 例:slop=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("Slop 2 result: ", result_slop2)

# 期待される出力:
# Slop 2 result: 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}}]]

例:slop = 3

この例では、slop の値を 3 に設定しています。これにより、さらに柔軟性が高まります。フィルターは、"machine learning" の間に最大 3 つのトークン位置が許容される状態で検索します。

# 例:slop=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("Slop 3 result: ", result_slop3)

# 期待される出力:
# Slop 3 result: 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\\""