フレーズからフィルターへのマッピング:製品フィルターのためのセマンティック検索
この記事では、フィルター抽出システムを支えるフレーズからフィルターへのマッピングを生成・拡張する方法について説明します。これらのマッピングは、検索クエリからの自然言語フレーズと、構造化された製品フィルターを結びつけます。
問題:自然言語からのフィルター抽出
ユーザーが「mini pc with 16gb ram」を検索した場合、以下の抽出が必要です:
-
フォームファクター: Mini PC
-
メインメモリ: 16
しかし、ユーザーは同じ意図をさまざまな方法で表現します:
-
"16gb ram mini pc"
-
"mini computer 16 gb memory"
-
"small pc 16gb"
-
"compact desktop with 16 gigs"
これらのフレーズのバリエーションすべてを正しいフィルター値にマッピングするシステムが必要です。
2段階のプロセス
フレーズマッピングの生成は2段階で行います:
このハイブリッドアプローチは、ルールベースの精度とセマンティックな柔軟性を組み合わせています。
Step 3a: 基本フレーズ生成
特徴メタデータ
各製品特徴は、特徴シーケンス内にメタデータを持ちます:
-
見出し: カテゴリ名(例:プロセッサー特徴の「Processing」)
-
単位: 測定単位(例:メモリの「GB」、周波数の「GHz」)
このメタデータがフレーズ生成をガイドします。
順列ベースの生成
各特徴値について、以下の要素のすべての順列を生成します:
-
見出し: "processor"
-
特徴キー: "series"
-
値: "i5"
-
単位: (seriesにはなし)
これにより以下が生成されます:
-
"processor series i5"
-
"series processor i5"
-
"i5 processor series"
-
"i5 series processor"
-
"processor i5"
-
"series i5"
-
"i5"
すべての順列を生成することで、単語の順序に関係なくクエリにマッチさせます。
値 + 単位の組み合わせ
単位を持つ特徴(メモリ、ストレージ、周波数)については、スペースありとなしの両方のバリアントを生成します:
-
"16 gb" (スペースあり)
-
"16gb" (スペースなし)
これらは他の構成要素と組み合わされます:
-
"16gb ram"
-
"ram 16gb"
-
"processor 16gb"
ポート接尾辞ルール
接続性特徴(USB、HDMI、DisplayPort)については、ポート接尾辞を追加します:
-
"usb port"
-
"usb ports"
-
"2 usb ports"
-
"hdmi port"
これにより、「mini pc with 2 hdmi ports」のようなクエリにマッチします。
特徴固有のルール
各特徴タイプにはカスタムのフレーズ生成ルールがあります:
プロセッサー シリーズ (i3, i5, N-series):
-
コアプロセッサーの指定はバリエーションを生成:メーカー名、コアブランド、組み合わせ形式
-
N-seriesプロセッサー(N100など)は同様のパターン組み合わせを作成
-
それぞれが「processor」を含む複数の順列を生成
メインメモリ:
-
数値はスペースありとなしのGBバリアントを生成("16gb"、"16 gb")
-
自動的に「ram」と「memory」の修飾語を追加("16gb memory"、"16 gb ram")
SSDストレージ:
-
数値はGBバリアントを生成("512gb"、"512 gb")
-
値が1024以上の場合、自動的にTBバリアントを生成(例:1024GB → 1TB)
-
自動的に「ssd」と「storage」の修飾語を追加("512gb ssd"、"512 gb storage")
フォームファクター:
-
Mini PC → スペースなし形式を含む複数のバリアント
-
All-in-One → "all in one"、"aio"、省略形
-
Thin Client → スペースあり/なしのバリアント
-
Industrial PC → 省略形と完全形
世代:
- 数値の世代値は以下になる: "12th gen"、"12th generation"、"gen 12"
コア数:
-
2 → "dual core"
-
4 → "quad core"
-
6 → "hexa core"
-
8 → "octa core"
-
すべてが「[n] core processor」バリアントを生成
イーサネット:
-
"1000" → ["gigabit ethernet"、"gbe"、"1gbps"]
-
"2500" → ["2.5gbe"、"2.5 gigabit"、"2.5gbps"]
オペレーティングシステム:
-
"Windows 11" → ["windows"、"windows 11"、"win 11"]
-
"Ubuntu" → ["linux"、"ubuntu"]
-
"FreeDOS" → ["freedos"、"no os"、"without os"]
単独値のためのホワイトリスト
誤ったマッチを防ぐため、特定の特徴のみが単独値マッチングを許可します:
-
シリーズ: "i3"、"i5"、"N100"(ただし単一文字は除く)
-
プロセッサーモデル: "N100"、"1335U"
-
オペレーティングシステム: "Windows"、"Linux"、"Ubuntu"
-
世代: "12th"、"13th"、"14th"
-
プロセッサーブランド: "Intel"、"ARM"
例えば、「2 hdmi ports」というクエリの場合、「2」が「2 cores」にマッチすべきではありません。長さチェックにより、単一文字や非常に短い曖昧な値が単独でマッチするのを防ぎます。イーサネットやポートのように明示的な単位構成要素を持つ特徴は、単位で修飾された場合にのみ単独の組み合わせを生成します。
衝突防止
メモリとストレージの値は重複します(両方とも64、128、256などを持ちます)。Step 4では、曖昧さを解消するために値範囲ルールを適用します:
-
≤ 64 GB: メインメモリ (RAM)
-
≥ 128 GB: SSDストレージ
-
65-127 GB 範囲: スキップ(曖昧)
明示的な修飾語("ram"/"memory" または "ssd"/"storage")を持つフレーズはこのルールを上書きし、任意の値にマッチできます。
さらに、多くの無関係なフィルターにマッチする曖昧な一般用語は、後処理による衝突解決の際に除外されます:「connectivity」、「audio」、「display」、「processor」、「physical」などの用語は、複数のファセットで過度の曖昧さを生み出します。
Step 4: セマンティック拡張
N-gram抽出
実際の検索クエリから頻出フレーズを抽出します。単一単語(「mini」のような1-gram)から長いシーケンス(「mini pc with 16gb ram ssd」のような最大6-gram)までを含みます。少なくとも3回出現するフレーズのみが保持されます。このフィルタリングアプローチはノイズを減らしながら、本物のユーザー言語パターンを保持します。
フィルター検索テキスト生成
各フィルター値について、検索テキストを生成します:
メインメモリ: 16:
-
"16gb ram memory"
-
"16 main memory"
-
"main memory 16"
SSDストレージ: 512:
-
"512gb storage ssd"
-
"512 ssd storage"
-
"ssd storage 512"
これらの検索テキストは、埋め込み空間におけるフィルターを表現します。
埋め込みとマッチング
クエリフレーズとフィルター検索テキストの両方を埋め込みに変換し、それらの間のコサイン類似度を計算します。設定された閾値を超える類似度スコアを持つフレーズが、そのフィルターのマッピングに追加されます。
手動シードフレーズ
拡張前に高信頼度の手動シードを注入します:
"Series:i5": [
"i5",
"core i5",
"intel i5",
"intel core i5",
"i5 processor",
"cpu i5",
]
これらのシードは、各フィルターに対して正しいことが分かっているコアフレーズを表します。これらを最大類似度スコアで含めることで、拡張アルゴリズムが同様の意味を持つ関連フレーズを見つけるよう導きます。これらのシードは常に類似度1.0を持ち、拡張をガイドします。
インクリメンタル埋め込み
フレーズとフィルター検索テキストの両方の埋め込みをキャッシュします。新しいクエリが到着したら:
- 既存の埋め込みをロード
- 新しいフレーズのみを埋め込み
- キャッシュに追加
これにより、変更されていないデータの再埋め込みを回避します。詳細は埋め込み戦略を参照してください。
衝突解決
類似度マッチングが完了した後、メモリとストレージフィルター間の衝突を解決します:
数値ベースの曖昧さ解消:
-
数値を含む曖昧なフレーズの場合:値が ≤ 64 ならメモリのみ保持、> 64 ならストレージのみ保持
-
これにより、「16gb」がSSDストレージフィルターにマッチしたり、「512gb」がメモリフィルターにマッチしたりするのを防ぎます
明示的な修飾語によるルールの上書き:
-
「ram」、「memory」、「cpu」、「processor」キーワードを含むフレーズ → メモリのみ
-
「ssd」、「storage」、「disk」、「nvme」、「drive」キーワードを含むフレーズ → ストレージのみ
-
例: "processor 8gb" は数値ですが、メモリにマッピング
曖昧な用語:
- 複数の無関係なフィルターにマッチする「connectivity」、「audio」、「display」などのフレーズを削除
出力形式
最終的なマッピングは、類似度(高い順)、次に長さ(短い順)でソートされます:
{
"Main Memory:16": [
{"phrase": "16gb ram", "similarity": 1.0},
# ... (実装の詳細は省略)
フィルター抽出との統合
これらのマッピングは、フィルター抽出アルゴリズムを支えます:
- クエリ到着: "mini pc with 16gb ram"
- フレーズ抽出: ["mini pc"、"16gb ram"、"mini"、"pc"、"16gb"、"ram"]
- マッピングを使用してフレーズをフィルターにマッチ
- フィルター返却:
{"Form Factor": ["Mini PC"]、"Main Memory": ["16"]}
詳細はフィルター抽出アルゴリズムを参照してください。
ストレージと配布
フレーズマッピングはJSONファイルとして永続化され、システム全体で使用されます:
-
基本マッピングファイル: Step 3aで生成、ルールベースのフレーズを含む
-
拡張マッピングファイル: Step 4で生成、セマンティック拡張結果を含む
拡張マッピングは以下で消費されます:
-
クエリページ生成: クエリテキストからフィルターを抽出
-
検索サービス: リアルタイムフィルター抽出API
-
製品マッチング: 抽出されたフィルターで製品をフィルタリング
パフォーマンス特性
基本生成 (Step 3a):
-
処理時間はフィルター値の数に比例してスケール
-
大量の基本フレーズバリアントを生成
-
生成中のメモリ使用量は中程度
セマンティック拡張 (Step 4):
-
処理時間はクエリ量と埋め込みサイズに比例してスケール
-
出力には基本生成よりも大幅に多くのフレーズが含まれる
-
埋め込みストレージによりメモリ要件が増加
拡張は類似度計算によりCPUバウンドです。NumPyとBLASアクセラレーションを使用すると、行列演算が大幅に高速化されます。
SEOパイプラインとの統合
フレーズマッピング生成は、SEOパイプラインのStep 3a と Step 4です:
- Step 0: ソースデータの埋め込み - 製品、部品、記事
- Step 1: クエリ取得 - GSC、Google Ads、ライブ、Algolia
- Step 2: クエリ結合 - すべてのソースをマージ
- Step 3a: 基本フレーズマッピング生成 ← ここ
- Step 3b: クエリ埋め込み - ベクトルに変換
- Step 4: フレーズマッピング拡張 ← ここ
- Step 5: クエリクラスタリング - ページへのグループ化
- Step 6: 製品マッチング - クエリと製品のマッチング
- Step 7: クエリページ構築 - HTML生成
- Step 8: 関連検索生成 - 関連クエリの発見
- Step 11: Valkeyへの移行 - 検索サービスへのロード
完全なフローについてはSEOパイプライン概要を参照してください。
なぜ2段階なのか?
基本生成 (Step 3a) は以下を提供します:
-
精度: ルールベースのフレーズは期待通りのものに正確にマッチ
-
カバレッジ: 順列によりすべての単語順序がカバーされる
-
制御: 特徴固有のルールがドメイン知識を処理
セマンティック拡張 (Step 4) は以下を提供します:
-
柔軟性: 予期していなかったフレーズを発見
-
実際のユーザー言語: 実際の検索クエリから学習
-
同義語: 同等のフレーズを発見(「16gb」に対する「16 gigs」)
両者を組み合わせることで、精度と再現率のバランスを取ります。
参考文献
技術的概念
モデルドキュメント
-
all-mpnet-base-v2 - Hugging Face
-
Sentence Transformers - 公式ドキュメント
関連記事
- 埋め込み戦略 - 埋め