レコメンデーションをフィルタリングする

構造化データを使用しているレコメンデーション アプリがある場合は、ドキュメント フィールドを使用してレコメンデーション結果をフィルタできます。このページでは、ドキュメント フィールドを使用して、特定のドキュメントセットにレコメンデーションをフィルタする方法について説明します。 このページの例はメディア レコメンデーション用ですが、ここで説明する原則は汎用レコメンデーションでも同じです。メディア レコメンデーション機能の詳細については、メディア向け Vertex AI Search の概要をご覧ください。

レコメンデーションとデータストアの更新をフィルタする

データストアが更新された後、モデルが再トレーニングされるまで最大 8 時間ほどかかります。これは、モデルがドキュメント メタデータの現在の値と、フィルタ可能として構成されているフィールドを知る必要があるためです。 ドキュメントの変更とスキーマの変更が反映されるまで待つ必要があります。レコメンデーションの場合(検索とは異なり)、フィルタリングはリアルタイムで行われません。

フィルタと多様化の設定(メディア レコメンデーションのみ)

フィルタに加えて、アプリの多様化設定も、メディア レコメンデーション レスポンスで返される結果に影響します。 フィルタと多様化の効果が組み合わされます。多様化が最初に行われ、次にフィルタリングが行われます。

ルールベースの多様性とカテゴリベースの属性フィルタリングを組み合わせると、空の出力になることが多いです。これは、多様性が高いと、アプリがカテゴリごとに 1 つの結果しか返せなくなるためです。

たとえば、トイ ストーリーに基づいて映画をおすすめするとします。ルールベースの多様性レベルを高に設定します。多様性レベルが高いため、多くの映画がおすすめとして表示される場合でも、子供向け映画のカテゴリでは 1 本の映画(WALL·E など)のみが返されます。子供向け映画のフィルタを適用すると、おすすめとして返される映画は WALL·E のみになります。

多様性の一般的な情報については、メディア レコメンデーションの多様化をご覧ください。

始める前に

レコメンデーション アプリとデータストアが作成されていることを確認します。詳細については、メディアアプリを作成するまたは汎用レコメンデーション データストアを作成するをご覧ください。

ドキュメントの例

以下のメディア ドキュメントの例をご確認ください。このページを読む際にこれらのサンプル ドキュメントを参照できます。

{"id":"1","schemaId":"default_schema","structData":{"title":"Toy Story (1995)","categories":["Adventure","Animation","Children","Comedy","Fantasy"],"uri":"http://mytestdomain.movie/content/1","available_time":"2023-01-01T00:00:00Z","media_type":"movie"}}
{"id":"88125","schemaId":"default_schema","structData":{"title":"Harry Potter and the Deathly Hallows: Part 2 (2011)","categories":["Action","Adventure","Drama","Fantasy","Mystery","IMAX"],"uri":"http://mytestdomain.movie/content/88125","available_time":"2023-01-01T00:00:00Z","media_type":"movie"}}
{"id":"2857","schemaId":"default_schema","structData":{"title":"Yellow Submarine (1968)","categories":["Adventure","Animation","Comedy","Fantasy","Musical"],"uri":"http://mytestdomain.movie/content/2857","available_time":"2023-01-01T00:00:00Z","media_type":"movie"}}
{"id":"60069","schemaId":"default_schema","structData":{"title":"WALL·E (2008)","categories":["Adventure","Animation","Children","Romance","Sci-Fi"],"uri":"http://mytestdomain.movie/content/60069","available_time":"2023-01-01T00:00:00Z","media_type":"movie"}}

フィルタ式

フィルタ式を使用して、レコメンデーション フィルタを定義します。

フィルタ式の構文

次のExtended Backus-Naur form は、レコメンデーション フィルタの定義に使用できるフィルタ式の構文をまとめたものです。

  # A single expression or multiple expressions that are joined by "AND" or "OR".
  filter = expression, { " AND " | "OR", expression };
  # An expression can be prefixed with "-" or "NOT" to express a negation.
  expression = [ "-" | "NOT " ],
    # A parenthesized expression
    | "(", expression, ")"
    # A simple expression applying to a textual field.
    # Function "ANY" returns true if the field contains any of the literals.
    textual_field, ":", "ANY", "(", literal, { ",", literal }, ")"
    # OR filter by "available"
    available, ":", "true",
  # A literal is any double-quoted string. You must escape backslash (\) and
  # quote (") characters.
  literal = double-quoted string;
  textual_field = see the tables below;

フィルタ式の制限

レコメンデーションのフィルタ式には、次の制限が適用されます。

  • AND 演算子と OR 演算子をかっこに埋め込む深さには制限があります。 フィルタの論理式は連言標準形(CNF)にする必要があります。サポートされる論理式で最も複雑なものは、OR 演算子のみを含む AND 句の連結リストです(例: (... OR ... OR ...) AND (... OR ...) AND (... OR ...))。
  • 式は NOT キーワードまたは - で否定できます。これは、1 つの引数を持つ ANY() 式でのみ機能します。
  • available 制限は最上位にする必要があります。OR 句または否定(NOT)の一部として使用することはできません。使用できるのは available: true のみです。
  • 最上位の AND 句の用語の最大数は 20 です。
  • OR 句には、ANY() 式に含める引数を最大 100 個まで指定できます。OR 句に複数の ANY() 式がある場合、その引数はすべてこの上限にカウントされます。たとえば、categories: ANY("drama", "comedy") OR categories: ANY("adventure") には 3 つの引数があります。

フィルタ式の例

次の表に、有効なフィルタ式と無効なフィルタ式の例を示します。無効な例が無効である理由も示します。

有効
language_code: ANY("en", "fr")
NOT language_code: ANY("en")
NOT language_code: ANY("en", "fr") × 複数の引数を使用して ANY() を否定します。
language_code: ANY("en", "fr") OR categories: ANY("drama")
(language_code: ANY("en") OR language_code: ANY("fr")) AND categories: ANY("drama")
(language_code: ANY("en") AND language_code: ANY("fr")) OR categories: ANY("drama") × 連言標準形ではありません。
(language_code: ANY("en")) AND (available: true)
(language_code: ANY("en")) OR (available: true) × OR 式の available を他の条件と結合します。

次のフィルタ式は、ドラマまたはアクションのカテゴリに属し、英語ではなく、利用可能なドキュメントをフィルタします。

categories: ANY("drama", "action") AND NOT language_code: ANY("en") AND available: true

フィルタリングの上限

フィルタリング可能なドキュメント フィールドごと、モデルごとにメモリが消費されます。次の上限は、サービス提供のパフォーマンスに対する悪影響を防ぐのに役立ちます。

  • スキーマ内で最大 10 個のカスタム フィールドをフィルタ可能に設定できます。

    アプリのトレーニング中に 10 個を超えるカスタム フィールドが見つかった場合は、10 個のみが使用されます。

  • スキーマには、最大 100,000,000 個のフィルタ可能なフィールド値を含めることができます。

    スキーマ内のドキュメント数にフィルタ可能なフィールドの数を掛けることで、スキーマ内のフィルタ可能なフィールド値の合計数を見積もることができます。これらの上限を超えると、以下が発生します。

    • フィルタ可能として追加のフィールドを設定することはできません。
    • アプリのトレーニングが失敗します。

レコメンデーションをフィルタリングする

メディア レコメンデーションをフィルタする手順は次のとおりです。

  1. データストア ID を確認します。データストア ID がすでにある場合は、次のステップに進みます。

    1. Google Cloud コンソールで [Agent Builder] ページに移動し、ナビゲーション メニューで [データストア] をクリックします。

      [データストア] ページに移動

    2. データストアの名前をクリックします。

    3. データストアの [データ] ページで、データストア ID を取得します。

  2. フィルタするドキュメント フィールドを特定します。たとえば、始める前にのドキュメントの場合は、categories フィールドをフィルタとして使用できます。

  3. categories フィールドをフィルタ可能にするには、次の操作を行います。

    1. Google Cloud コンソールで、[Agent Builder] ページに移動します。

      Agent Builder

    2. レコメンデーション アプリをクリックします。

    3. [スキーマ] タブをクリックします。このタブには、現在のフィールド設定が表示されます。

    4. [編集] をクリックします。

    5. まだ選択していない場合は、[カテゴリ] 行の [フィルタ可能] チェックボックスをオンにして、[保存] をクリックします。

    6. スキーマの編集が反映されるまで 6 時間ほど待ちます。6 時間経過したら、次のステップに進みます。

  4. レコメンデーションを取得して categories フィールドでフィルタするには、コマンドラインで次のコードを実行します。

    curl -X POST \
    -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
    -H "Content-Type: application/json; charset=utf-8" \
    -d '{
         "userEvent": {
           "eventType": "EVENT_TYPE",
           "userPseudoId": "USER_PSEUDO_ID",
           "documents": {
             "id": "DOCUMENT_ID"
           }
         },
         "params": {
           "returnDocument": true,
           "attributeFilteringSyntax": true,
           "strictFiltering": true
         },
         "filter": "FILTER"
       }' \
    "https://discoveryengine.googleapis.com/v1beta/projects/PROJECT_ID/locations/global/collections/default_collection/dataStores/DATA_STORE_ID/servingConfigs/SERVING_CONFIG_ID:recommend"
    
    • PROJECT_ID: プロジェクトの ID。
    • DATA_STORE_ID: データストアの ID。
    • DOCUMENT_ID: レコメンデーションをプレビューするドキュメントの ID。データを取り込むときにこのドキュメントに使用した ID を使用します。
    • EVENT_TYPE: ユーザー イベントのタイプ。eventType の値については、UserEventをご覧ください。
    • USER_PSEUDO_ID: ユーザーの仮名化 ID。このフィールドには HTTP Cookie を使用できます。これにより、1 つのデバイス上の訪問者を一意に識別できます。このフィールドを複数のユーザーに対して同じ ID に設定しないでください。これにより、イベント履歴が統合され、モデルの品質が低下します。このフィールドには個人を特定できる情報(PII)を含めないでください。
    • SERVING_CONFIG_ID: サービス提供構成の ID。サービス提供構成 ID はエンジン ID と同じであるため、ここではエンジン ID を使用します。
    • FILTER: フィルタ式の構文を使用して、指定されたフィールドセットでフィルタリングできるテキスト フィールド。デフォルト値は空の文字列で、フィルタが適用されないことを意味します。

    たとえば、特定のメディア プレーヤー ユーザー イベントのレコメンデーションを取得し、(1)子供向けカテゴリに含まれ、(2)現在利用可能なドキュメントのみが含まれるようにレコメンデーション結果をフィルタリングするとします。 これを行うには、呼び出しに次のステートメントを含めます。

    • "eventType": "media-play"
    • "filter": "categories: ANY(\"Children\") AND available: true"

    詳細については、recommend メソッドをご覧ください。

    クリックしてレスポンスの例を表示します。

    前述のようなレコメンデーション リクエストを実行すると、次のようなレスポンスが返されます。レスポンスには、categories 値が Children で、availability_start_time 値が現在の日付より後の 2 つのドキュメントが含まれています。

    {
    "results": [
      {
        "id":"1",
        "schemaId":"default_schema",
        "structData":{"title":"Toy Story (1995)","categories":["Adventure","Animation","Children","Comedy","Fantasy"],"uri":"http://mytestdomain.movie/content/1",
        "availability_start_time":"2023-01-01T00:00:00Z",
        "media_type":"movie"
        }
      },
      {
        "id":"60069",
        "schemaId":"default_schema",
        "structData":{"title":"WALL·E (2008)","categories":["Adventure","Animation","Children","Romance","Sci-Fi"],"uri":"http://mytestdomain.movie/content/60069",
        "availability_start_time":"2023-01-01T00:00:00Z",
        "media_type":"movie"
        }
      }
    ],
    "attributionToken": "ChMzMDk3NTQ4MzQxOTcxOTE0ODM1GglhZi10ZXN0LTEiDmFmLXRlc3QtMTE0NTE0KAAwBg",
    "debugInfo": {
      "fallbackModelInvoked": false
    }
    }