Milvus2.6でフレーズマッチの精度が向上:フレーズレベルの全文検索精度を向上させる方法
非構造化データが爆発的に増え続け、AIモデルが賢くなり続ける中、ベクトル検索は多くのAIシステム-RAGパイプライン、AI検索、エージェント、レコメンデーション・エンジンなど-にとってデフォルトの検索レイヤーとなっている。ユーザーが入力した単語だけでなく、その背後にある意図など、意味を捉えることができるからだ。
しかし、これらのアプリケーションが本番稼動すると、チームはしばしば、意味理解が検索問題の一面に過ぎないことに気づく。多くのワークロードはまた、厳密なテキストルールに依存しています。例えば、正確な用語のマッチング、語順の保持、技術的、法的、または運用上の重要性を持つフレーズの識別などです。
Milvus 2.6は、ベクトルデータベースに直接ネイティブな全文検索を導入することで、このような分岐を取り除きます。Milvusは、コアエンジンに組み込まれたトークンとポジションインデックスにより、正確なキーワードとフレーズレベルの制約を適用しながら、クエリの意味的意図を解釈することができます。その結果、意味と構造が別々のシステムに存在するのではなく、互いに補強し合う統合された検索パイプラインとなる。
フレーズマッチは、このフルテキスト機能の重要な部分である。これは、ログパターン、エラーシグネチャ、製品名など、語順が意味を定義するあらゆるテキストを検出するために不可欠です。この投稿では、Milvusにおける Phrase Matchの仕組み、slop 、実世界のテキストに必要な柔軟性がどのように追加されるのか、そしてなぜこれらの機能により、単一のデータベース内でベクターとフルテキストのハイブリッド検索が可能になるだけでなく、実用的になるのかについて説明します。
フレーズマッチとは?
Phrase MatchはMilvusの全文検索クエリタイプの一つであり、構造に着目したクエリである。柔軟性がない場合、クエリは厳密に動作します。したがって、"robotics machine learning "のようなクエリは、この3つの単語が連続したフレーズとして出現した場合にのみマッチする。
問題は、実際のテキストがこのようにきれいに動作することはほとんどないということだ。余計な形容詞が入り込んだり、ログがフィールドを並べ替えたり、商品名が修飾語になっていたり、人間の作者はクエリーエンジンを意識して書いたりはしない。厳密なフレーズマッチは簡単に壊れてしまう。単語が挿入されたり、言い換えられたり、用語が入れ替わったりすると、ミスマッチを引き起こす可能性がある。そして、多くのAIシステム、特に本番向けのシステムでは、関連するログ行やルールを引き起こすフレーズを見逃すことは許されない。
Milvus2.6はこの摩擦をスロップというシンプルなメカニズムで解決します。スロップとは、クエリ用語間に許容されるゆとりの量を定義するものである。フレーズをもろく柔軟性のないものとして扱う代わりに、スロップによって、1語余分に許容できるか、2語許容できるか、あるいはわずかな並び替えでもマッチとしてカウントするかどうかを決めることができます。これによって、フレーズ検索は合格・不合格の二者択一のテストから、コントロールされ、調整可能な検索ツールへと移行する。
なぜこれが重要なのかを知るために、おなじみのネットワークエラー"connection reset by peer "のすべてのバリエーションをログから検索することを想像してみてほしい。実際には、ログは次のようになるでしょう:
connection reset by peer
connection fast reset by peer
connection was suddenly reset by the peer
peer reset connection by ...
peer unexpected connection reset happened
一見したところ、これらはすべて同じ根本的な事象を表している。しかし、一般的な検索方法では苦労します:
BM25は構造と格闘している。
BM25は、クエリをキーワードの袋として捉え、キーワードの出現順序を無視する。コネクション」と「ピア」がどこかに表示されている限り、BM25はドキュメントを上位にランク付けする可能性がある-たとえそのフレーズが逆であっても、実際に検索しているコンセプトと無関係であっても。
ベクトル検索は制約と格闘する。
エンベッディングは意味や意味的関係を捉えることに優れていますが、"これらの単語はこの順序で現れなければならない "というようなルールを強制することはできません。意味的に関連するメッセージを検索しても、デバッグやコンプライアンスに必要な正確な構造パターンを見逃してしまうかもしれません。
フレーズ・マッチは、この2つのアプローチのギャップを埋める。スロップを使用することで、どの程度のばらつきを許容するかを正確に指定することができる:
slop = 0- 完全一致(すべての用語が連続し、順番に現れる必要があります。)slop = 1- 余分な単語を1つ許可する(挿入される単語が1つで、一般的な自然言語のバリエーションをカバーします。)slop = 2- 複数の単語の挿入を許可する(より説明的または冗長な表現に対応します。)slop = 3- 順序の入れ替えを許可する (実際のテキストで最も難しいケースである、順序が逆であったり緩やかであったりするフレーズをサポートする)
採点アルゴリズムが「正しく」採点してくれることを期待するのではなく、アプリケーションが要求する構造的な許容範囲を明示的に宣言するのです。
Milvusのフレーズマッチの仕組み
Tantivyサーチエンジンライブラリを利用したMilvusのフレーズマッチは、位置情報を持つ転置インデックスの上に実装されています。用語が文書中に現れるかどうかだけをチェックするのではなく、用語が正しい順序で、制御可能な距離内に現れるかどうかを検証します。
下図はそのプロセスを示している:
1.文書のトークン化(位置情報付き)
Milvusに文書が挿入されると、テキストフィールドはアナライザによって処理され、アナライザはテキストをトークン(単語または用語)に分割し、文書内での各トークンの位置を記録する。例えば、doc_1 は次のようにトークン化されます:machine (pos=0), learning (pos=1), boosts (pos=2), efficiency (pos=3).
2.転置インデックスの作成
次にMilvusは転置インデックスを作成する。転置インデックスでは、文書とその内容を対応付ける代わりに、各トークンをそれが出現する文書に対応付け、各文書内でのそのトークンのすべての位置を記録します。
3.フレーズマッチング
フレーズクエリが実行されると、Milvusはまず転置インデックスを用いて全てのクエリトークンを含む文書を特定する。次に、トークンの位置を比較することにより、各候補が正しい順序で、かつ、slop の許容距離内にあることを確認します。両方の条件を満たす文書のみがマッチとして返される。
下の図は、フレーズ一致がエンドツーエンドでどのように機能するかをまとめたものです。
Milvusでフレーズ一致を有効にする方法
フレーズマッチは VARCHARMilvusにおける文字列タイプです。これを使用するには、Milvusがテキスト分析を行い、フィールドの位置情報を保存するようにコレクションスキーマを設定する必要があります。これは、enable_analyzer とenable_match の2つのパラメータを有効にすることで行います。
enable_analyzerとenable_matchの設定
特定のVARCHARフィールドのフレーズ・マッチを有効にするには、フィールド・スキーマを定義する際に両方のパラメータをTrue 。この2つのパラメータはMilvusに次のことを指示します:
テキストをトークン化(
enable_analyzerを使用)し位置オフセットによる転置インデックスの構築(
enable_match経由)。
フレーズマッチはこの2つのステップに依存しており、アナライザーはテキストをトークンに分解し、マッチインデックスはそれらのトークンが出現する場所を保存することで、効率的なフレーズやスループベースのクエリを可能にします。
以下は、text フィールドでフレーズ一致を有効にするスキーマ設定の例です:
from pymilvus import MilvusClient, DataType
schema = MilvusClient.create_schema(enable_dynamic_field=False)
schema.add_field(
field_name=“id”,
datatype=DataType.INT64,
is_primary=True,
auto_id=True
)
schema.add_field(
field_name=‘text’, # Name of the field
datatype=DataType.VARCHAR, # Field data type set as VARCHAR (string)
max_length=1000, # Maximum length of the string
enable_analyzer=True, # Enables text analysis (tokenization)
enable_match=True # Enables inverted indexing for phrase matching
)
schema.add_field(
field_name=“embeddings”,
datatype=DataType.FLOAT_VECTOR,
dim=5
)
フレーズ一致で検索:スロップが候補セットに与える影響
コレクション・スキーマでVARCHARフィールドのマッチを有効にすると、PHRASE_MATCH 式を使用してフレーズ・マッチを実行できます。
注:PHRASE_MATCH 式は大文字と小文字を区別しません。PHRASE_MATCH またはphrase_match のいずれかを使用できます。
検索操作では、Phrase Matchは一般的にベクトル類似度ランキングの前に適用されます。これはまず、明示的なテキスト制約に基づいて文書をフィルタリングし、候補セットを絞り込みます。そして残った文書をベクトル埋め込みを使って再ランク付けする。
以下の例は、slop の値の違いがこのプロセスにどのような影響を与えるかを示しています。slop パラメータを調整することで、どの文書がフレーズフィルタを通過し、ベクトルランキングの段階に進むかを直接制御できます。
次の5つのエンティティを含むtech_articles という名前のコレクションがあるとします:
| doc_id | テキスト |
|---|---|
| 1 | 機械学習が大規模データ分析の効率を高める |
| 2 | 現代のAIの進歩には機械ベースのアプローチの学習が不可欠 |
| 3 | 計算負荷を最適化するディープラーニング・マシンアーキテクチャ |
| 4 | 機械は、継続的な学習のためにモデルの性能を迅速に向上させる |
| 5 | 高度な機械アルゴリズムの学習がAIの能力を拡張する |
slop=1
ここでは、"learning machine "という語句を含む文書に対して、若干の柔軟性を持たせてフィルタを適用する。
# Example: Filter documents containing "learning machine" with slop=1
filter_slop1 = "PHRASE_MATCH(text, 'learning machine', 1)"
result_slop1 = client.search(
collection_name=“tech_articles”,
anns_field=“embeddings”,
data=[query_vector],
filter=filter_slop1,
search_params={“params”: {“nprobe”: 10}},
limit=10,
output_fields=[“id”, “text”]
)
マッチ結果
| doc_id | テキスト |
|---|---|
| 2 | 機械ベースのアプローチを学ぶことは、現代のAIの進歩に不可欠である |
| 3 | ディープラーニングマシンのアーキテクチャは計算負荷を最適化する |
| 5 | 高度な機械アルゴリズムの学習がAIの能力を拡張する |
slop=2
この例では、"machine "と "learning "の間に最大2つの余分なトークン(または逆順の用語)が許容されることを意味する、2のスロープが許容されます。
# Example: Filter documents containing "machine learning" with slop=2
filter_slop2 = "PHRASE_MATCH(text, 'machine learning', 2)"
result_slop2 = client.search(
collection_name=“tech_articles”,
anns_field=“embeddings”, # Vector field name
data=[query_vector], # Query vector
filter=filter_slop2, # Filter expression
search_params={“params”: {“nprobe”: 10}},
limit=10, # Maximum results to return
output_fields=[“id”, “text”]
)
マッチ結果
| doc_id | テキスト |
|---|---|
| 1 | 機械学習が大規模データ分析の効率を高める |
| 3 | ディープラーニングマシンのアーキテクチャが計算負荷を最適化 |
slop=3
この例では、スロープを3にすることで、さらに柔軟性が増す。このフィルターでは、単語間のトークン位置を3つまで許容して、「機械学習」を検索する。
# Example: Filter documents containing "machine learning" with slop=3
filter_slop3 = "PHRASE_MATCH(text, 'machine learning', 3)"
result_slop2 = client.search(
collection_name=“tech_articles”,
anns_field=“embeddings”, # Vector field name
data=[query_vector], # Query vector
filter=filter_slop3, # Filter expression
search_params={“params”: {“nprobe”: 10}},
limit=10, # Maximum results to return
output_fields=[“id”, “text”]
)
一致した結果
| doc_id | テキスト |
|---|---|
| 1 | 機械学習が大規模データ分析の効率を高める |
| 2 | 現代のAIの進歩には機械ベースのアプローチの学習が不可欠 |
| 3 | 計算負荷を最適化するディープラーニング・マシンアーキテクチャ |
| 5 | 高度な機械アルゴリズムの学習がAIの能力を拡張する |
クイックヒントMilvusでフレーズマッチを有効にする前に知っておくべきこと
Phrase Matchはフレーズレベルのフィルタリングをサポートしますが、有効にするにはクエリ時の設定だけではありません。本番環境で適用する前に、関連する考慮事項を知っておくと便利です。
フィールドでPhrase Matchを有効にすると、逆インデックスが作成され、ストレージ使用量が増加します。正確なコストは、テキストの長さ、一意なトークンの数、アナライザーの設定などの要因に依存する。大きなテキストフィールドやカーディナリティの高いデータを扱う場合は、このオーバーヘッドを前もって考慮する必要があります。
アナライザーの構成も重要な設計上の選択です。いったんアナライザがコレクション・スキーマで定義されると、それを変更することはできません。後で別の分析器に切り替えるには、既存のコレクションを削除し、新しいスキーマで再作成する必要があります。このため、アナライザーの選択は実験的なものではなく、長期的な決定として扱う必要がある。
フレーズ一致の動作は、テキストがどのようにトークン化されるかと密接に関係している。コレクション全体にアナライザを適用する前に、
run_analyzerメソッドを使用してトークン化の出力を検査し、期待するものと一致していることを確認することをお勧めします。このステップにより、微妙な不一致や予期しないクエリ結果を避けることができます。詳細については、Analyzer Overviewを参照してください。
結論
フレーズ一致は、単純なキーワード一致を超えるフレーズレベルと位置の制約を可能にする、コアな全文検索タイプです。トークンの順序と近接性に基づいて操作することで、用語が実際にテキストにどのように現れるかに基づいて文書をフィルタリングする、予測可能で正確な方法を提供します。
最新の検索システムでは、Phrase Matchはベクトルベースのランキングの前に適用されるのが一般的である。フレーズマッチは、まず候補集合を、必要なフレーズや構造を明示的に満たす文書に限定する。その後、ベクトル検索を使って、これらの結果を意味的関連性によってランク付けする。このパターンは、ログ解析、技術文書検索、RAGパイプラインなど、意味的類似性を考慮する前にテキスト的制約を強制しなければならないシナリオで特に効果的である。
Milvus 2.6でslop パラメータが導入されたことにより、Phrase Matchはフルテキストフィルタリングメカニズムとしての役割を維持しながら、自然言語のバリエーションに対してより寛容になりました。これにより、本番の検索ワークフローでフレーズレベルの制約を適用しやすくなりました。
👉デモスクリプトでお試しいただき、Milvus 2.6でフレーズを意識した検索がどのようにお客様のスタックにフィットするかをご確認ください。
Milvusの最新機能についてのご質問やディープダイブをご希望ですか?私たちの Discordチャンネルに参加するか、 GitHubに課題を提出してください。また、 Milvusオフィスアワーを通して、20分間の1対1のセッションを予約し、洞察、ガイダンス、質問への回答を得ることもできます。
Try Managed Milvus for Free
Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.
Get StartedLike the article? Spread the word



