以下の内容はhttps://product.10x.co.jp/entry/2025/04/14/080000より取得しました。


LLMを活用した商品検索タグ自動生成とRecall改善の取り組み(BigQuery × Gemini)

はじめに

こんにちは、10Xで検索推薦の機能・基盤の開発運用を担当している安達(id:kotaroooo0)です。 10Xでは小売チェーン向けECプラットフォームStailerにおいて、商品検索機能ではElasticsearchを利用しており、主にテキストマッチングによって検索を実現しています。

今回、LLMを活用して商品検索タグ(以下、タグ)を自動生成し、検索対象に加えることでRecallを改善しました。 本記事では、その取り組みの背景、具体的な施策、設計、評価、そして得られた成果についてご紹介します。

課題:情報不足による検索ヒット率の低さ

Stailerでは、商品データに含まれるテキスト情報が限定的であるために、ユーザーが検索しても意図する商品がヒットしないケースがありました。

例えば、ユーザーが「メイク落とし」と検索しても、商品名やカテゴリ名、商品説明文に「メイク落とし」という文言が含まれていないクレンジングオイルの商品はヒットしませんでした。 特に商品説明文自体が存在しない商品も多く、全体的に検索に利用できるテキスト情報が不足している状況でした。

この問題に対しては、小売事業者様が管理画面から手動で商品に検索キーワード(同義語や関連語)を紐付ける機能を提供していました。 しかし、対象となる商品数が膨大であることや、キーワード選定・入力の手間から、この機能は十分に活用されているとは言えず、手動運用によるカバーには限界がありました。

また、10X内部でもElasticsearchに類義語辞書を登録することで継続的にRecall向上に取り組んでいますが、こちらも手動でのメンテナンスが必要であり網羅性には限界がありました。

施策:LLMによる検索タグの自動生成と活用

これらの課題に対し、商品名とカテゴリ情報をインプットとして、LLMにタグを自動生成させるアプローチを採用しました。 生成したタグをElasticsearchの商品データに追加し、検索対象とすることで、ユーザーが入力するであろう多様な検索キーワードに対応し、Recallの向上を目指しました。

なぜタグ生成か?

ベクトル検索やシノニムの自動生成など他のアプローチも検討しましたが、まずは既存のテキスト検索の仕組みを大きく変更せず、低コストかつ迅速にRecallを改善する手段として、LLMによるタグ生成が有効と判断しました。

また、ネットスーパーの検索特性として、ユーザーは欲しい商品が比較的明確であり、商品名やカテゴリ名を表す短いキーワード(例: 「牛乳」, 「パン」, 「シャンプー」)での検索が多い傾向があります。 このような検索行動に対しては、関連キーワードをタグとして補強するアプローチが効果的ではないかと考えました。

設計

タグ生成からElasticsearchへの反映までの処理フローは、以下のようになっています。

タグ生成と紐付けの概要図

このフローは、大きく以下の2つの独立したプロセスで構成されています。

  • タグ生成パイプライン
    • 日次で実行
    • LLMを使ってJANコードごとにタグを生成し、その結果をFirestoreに保存する役割
  • Elasticsearchへのインデキシング
    • 差分更新であり在庫情報が更新されるタイミング(1日1回以上)で実行
    • 更新された在庫情報と、対応するJANコードのタグをマージし、Elasticsearchのインデックスを更新する役割

それぞれの実行タイミングが異なるため、生成されたタグが実際に検索結果に反映されるまでに最大1日のタイムラグが発生する構成となっています。

JANコード単位での生成と管理

Stailerは複数の小売事業者様がそれぞれ複数の店舗を運営しており、同じ商品(同一JANコード)でも在庫を持つ店舗ごとに個別のElasticsearchドキュメントが存在します。 全てのドキュメントに対してLLMでタグ生成を行うと、APIコストと処理時間が膨大になります。

そこで、JANコード単位でタグを生成・管理し、Elasticsearchへのインデックス時にJANコードをキーとして各ドキュメントにタグ情報を付与する方式を採用しました。 これにより、LLMのAPIコール数を商品数(JANコード数)に抑えることができました。

タグデータの更新について

更新頻度:バッチ更新 vs リアルタイム更新

No Option Pros Cons
1 バッチ更新 既存のMLパイプライン基盤を利用でき実装がシンプル 新商品が登録されてからタグが付与されるまでにタイムラグが発生する(最大1日)
2 リアルタイム更新 新商品登録後、即座にタグが付与される イベントドリブンな新しいアーキテクチャの構築・運用コストが必要

結論: バッチ更新を採用。タグは検索体験を補強するものであり、必須データではありません。 新商品へのタグ付与遅延による影響は限定的と判断し、実装・運用のシンプルさを優先しました。

更新方法:全件洗い替え vs 差分更新

No Option Pros Cons
1 全件洗い替え LLMモデルやプロンプト改善の恩恵を常に受けられる。常に最新の状態で上書きするため、差分管理ロジックが不要。 LLM APIコストの増大: 変更がない商品に対しても毎回APIコールが発生し、非効率。また、処理時間が長くなる。
2 差分更新 LLM APIコストの最適化: 新規商品や商品情報が更新されたもののみを対象にタグ生成を行う。また、処理時間も短くなる。 どの商品に対して再生成が必要かを判断する差分検出ロジックが必要になる

結論: 差分更新を採用。APIコスト、処理時間の抑制のため、差分検出ロジックの実装コストは許容できると判断しました。

タグ生成の品質とリスク

LLMが生成するタグの品質は100%正確ではありません。 不適切なタグが検索結果に悪影響を与えるリスクを考慮し、以下の設計にしました。

  • 手動でのタグ管理: 必要に応じて自動生成されたタグを確認し、追加・削除できる設計に。
  • フロントエンドへは非表示: 生成されたタグはあくまで検索ロジック内部で利用するものとし、商品詳細ページなどでユーザーに表示しない。
  • 検索スコアへの影響抑制: 検索結果のランキング精度を維持するため、タグの検索スコアへの重みは0に設定。これにより、タグによってヒットするようになった商品は検索結果の末尾に表示され、既存のランキングロジックへの影響を最小限に留めました。まずは「見つからない」を減らすことを最優先しました。

プロジェクトの進め方

1. PoC:タグ自動生成の実現可能性と品質検証

LLMによるタグ生成が実用に足るか、コスト・処理時間はどの程度かを見極めるため、以下の検証を行いました。

モデル、プロンプト

  • モデル候補: gemini-1.5-progemini-2.0-flash
  • 検証データ: 約1000件のJANコード(商品名、カテゴリ情報)
  • プロンプト: 商品名とカテゴリ名をインプットとし、複数のパターンを試行しました。
  • 評価:
    • 定性評価: 生成されたタグの関連性を目視で確認。
    • コスト試算: 各モデル・プロンプトでのトークン数を計測し、全商品(約15万JANコード)に適用した場合のAPIコストを試算。

今回のタスクは短いテキスト生成であり、gemini-2.0-flashで十分な品質のタグが生成でき、かつコストと処理速度の点で優位性があると判断し採用しました。 gemini-2.0-flashでは15万JANコードに対して、$6程度で想定以上に安価でした。

検証で十分な精度が期待できなければ別モデルも検証しようと思いましたが、gemini-2.0-flashがコストパフォーマンスが優れており今回は試しませんでした。

タグを生成する基盤

LLM APIを直接叩く方式も検討しましたが、既存のデータ処理基盤であるBigQueryとの親和性、運用負荷を考慮し、BigQuery MLのML.GENERATE_TEXT 関数の利用を第一候補としました。

cloud.google.com

  • 検証内容:
    • サンプルデータ(1000件)に対するSQLでのタグ生成処理の実行時間とコストを計測
    • 既存のMLパイプラインへの組み込みやすさを確認
    • 全データ(約15万JANコード)に適用した場合の処理時間を見積もり
      • 12時間程度と見積もれた。差分更新にするため、全データに対して生成するのは初回実行だけ。

結果として、BigQueryのML.GENERATE_TEXT は、既存のパイプラインへの統合も容易であると判断し、採用することにしました。

2. インデキシングの実装

タグ生成パイプライン(VertexAI Pipelinesで日次実行)

  1. 対象抽出: BigQueryで、前回の実行以降に新規追加または商品情報(商品名・カテゴリ)が更新されたJANコードを特定。
  2. タグ生成: 対象JANコードの商品名・カテゴリ情報を取得し、BigQueryのML.GENERATE_TEXTを用いてタグを生成。
  3. 結果保存: 生成されたタグを、JANコードをキーとしてFirestoreに保存。

indexing worker

  1. データ取得: Pub/Subから更新対象の在庫情報(JANコード含む)を取得。
  2. タグ取得: 対象JANコードをキーとしてFirestoreから対応するタグ情報を取得。
  3. データマージ: 在庫情報とタグ情報をマージし、Elasticsearchに投入するドキュメントを生成。
  4. インデキシング: Elasticsearchにデータをインデックス。

3. 商品検索ロジックの評価とプロンプトチューニング

生成されたタグを検索対象に含めた新しい検索ロジックを評価し、問題があればプロンプトやロジックを修正するサイクルを回しました。

評価

タグ追加によるRecall向上(ヒット件数増加、ゼロマッチ率減少)を期待し、評価を行いました。

  • 定性評価

    • 目的: 新ロジックで不適切な商品が検索結果に含まれていないか、意図通りに検索結果が改善されているかを確認。
    • 方法: デモ環境で、実際に様々なキーワードで検索し、新旧ロジックの結果を目視比較。
    • 主な確認キーワード:
      • 従来ゼロマッチだったキーワード
      • 検索結果数が少なかったキーワード
      • 検索ボリュームが多い主要なキーワード
  • 定量評価

    • ゼロマッチ改善率: 従来ゼロマッチだったキーワード群を新ロジックで再検索し、ヒット件数が0件でなくなる割合を計測。
    • ヒット件数変化: 主要キーワード群における平均ヒット件数の変化を計測。
    • nDCG: 既存の検索ログを用いて算出したnDCGスコアが、新ロジック導入によって悪化しないことを確認。タグによるヒットは結果の末尾に追加されるため、理論上nDCGへの悪影響はないと考えられたがガードレールとして確認。

プロンプトチューニング

デモをしていると、タグの品質にばらつきが見られ、いくつかの具体的な課題が見つかりました。 例えば、冷凍でない「うどん」に対して「冷凍うどん」という誤った温度帯を示すタグが付与されたり、商品の実態とは異なるサイズ(例: 「大容量」)やブランド名が生成されたりするケースがありました。

また、商品の「味・成分」(例: 「無添加」「グルテンフリー」)や「用途・対象」(例: 「赤ちゃん用」)に関するタグが誤って生成されることはリスクが高いと判断しました。 これらの情報が不正確だと、ユーザーに誤解を与え、購買体験や安全性を損なう恐れがあるためです。

このリスクを低減し、より安全で関連性の高いタグを生成するため、プロンプトに具体的な制約ルールを盛り込みました。 試行錯誤を経て、最終的に以下のプロンプトを作成しました。

Instacartのようなネットスーパーの商品検索精度改善を担当しています。
商品検索のRecallを向上させるために、次の商品に関連するキーワードを生成してください。
【商品情報】
商品名: {product_name}, カテゴリ名: {category_names},
【キーワード生成ルール】
1. 商品名やカテゴリ名に含まれる単語、または部分一致する単語は生成しない。
2. 次のような誤解を招く可能性のある属性を示すキーワードは生成しない。
- 温度帯: 冷凍, 冷蔵, チルド, 常温
- 味・成分: 無糖, 加糖, 低糖質, グルテンフリー, オーガニック, 無添加
- サイズ・量: 大容量, 業務用, 小分け, 一人前, ファミリーサイズ
- ブランド・地域: 北海道産, 沖縄産, 国産, 地域限定, 直輸入
- 用途・対象: 赤ちゃん用, 幼児向け, ペット用
3. 商品に関連性が高く、かつ一般的に検索される可能性のある単語を優先する。
4. 料理・用途・関連カテゴリを考慮したキーワードを生成する。
【出力ルール】
- 出力は生成されたキーワードのみで構成し、スペースなしのカンマ区切りで出力する。
- 生成するキーワードの数は、関連性が高い順に最大3つに制限する。

4. 検索ロジックの修正と本番リリース

評価とチューニングを経て、品質に問題がないと判断できた段階で、生成されたタグを検索対象フィールドに加えるロジック修正を行い、本番環境へリリースしました。

5. 本番リリース後の効果測定

今回は、開発期間やリソースの制約からABテストやインターリービングは実施せず、リリース前後の主要KPIを比較することで効果を測定しました。

結果

  • ゼロマッチレート: 15%減少
  • 平均ヒット件数 : 8%増加

ゼロマッチレートのモニタリング

おわりに

本記事では、商品情報の不足による検索Recallの低さという課題に対し、LLMを活用して検索タグを自動生成し、既存のElasticsearchベースの検索システムに組み込むことで改善を図った事例を紹介しました。 設計段階でのトレードオフの考慮や、LLM生成物の品質担保、評価方法などが、同様の課題に取り組む方々の参考になれば幸いです。

今回はLLM活用の第一歩として、まずは既存の仕組みと連携しながら検索のヒット率を改善しましたが、LLMにはお客様の買い物体験を大きく進化させる可能性があると考えています。

例えば、ネットスーパー特有の課題として、一度の買い物で多くの商品をカートに入れる手間が挙げられます。 RAGのような技術を取り入れれば、「今週の献立に必要な食材をまとめて提案し、ワンタップでカートに追加できる」といった、新しい買い物体験を提供できる可能性があります。 このようなユーザーの課題解決に繋がるLLMの活用についても、今後挑戦していきたいです。




以上の内容はhttps://product.10x.co.jp/entry/2025/04/14/080000より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14