Filtrare le corrispondenze vettoriali

In Vector Search, puoi limitare le ricerche di corrispondenza vettoriale a un sottoinsieme dell'indice utilizzando le regole booleane. I predicati booleani indicano a Vector Search quali vettori nell'indice ignorare. In questa pagina scoprirai come funzionano i filtri, vedrai esempi e modi per eseguire query efficienti sui tuoi dati in base alla somiglianza vettoriale.

Con la ricerca vettoriale puoi limitare i risultati in base a limitazioni categoriche e numeriche. L'aggiunta di limitazioni o il "filtro" dei risultati dell'indice sono utili per diversi motivi, come i seguenti esempi:

  • Maggiore pertinenza dei risultati: la ricerca vettoriale è un potente strumento per trovare elementi semanticamente simili. I filtri possono essere utilizzati per rimuovere risultati non pertinenti dai risultati di ricerca, ad esempio elementi che non sono nella lingua, nella categoria, nel prezzo o nell'intervallo di date corretto.

  • Numero ridotto di risultati: la ricerca vettoriale può restituire un gran numero di risultati, in particolare per set di dati di grandi dimensioni. I filtri possono essere utilizzati per ridurre il numero di risultati a un numero più gestibile, restituendo al contempo i risultati più pertinenti.

  • Risultati segmentati: i filtri possono essere utilizzati per personalizzare i risultati di ricerca in base alle esigenze e alle preferenze individuali dell'utente. Ad esempio, un utente potrebbe volere filtrare i risultati in modo da includere solo gli articoli che ha valutato molto bene in passato o che rientrano in una fascia di prezzo specifica.

Attributi vettore

In una ricerca di somiglianza vettoriale in un database di vettori, ogni vettore è descritto da zero o più attributi. Questi attributi sono noti come token per le limitazioni dei token e valori per le limitazioni numeriche. Queste limitazioni possono essere applicate da ciascuna delle diverse categorie di attributi, note anche come namespaces.

Nell'esempio di applicazione seguente, i vettori sono contrassegnati con un color, un price e un shape:

  • color, price e shape sono namespaces.
  • red e blue sono token dello spazio dei nomi color.
  • square e circle sono token dello spazio dei nomi shape.
  • 100 e 50 sono valori dello spazio dei nomi price.

Specifica gli attributi del vettore

  • Per specificare un "cerchio rosso": {color: red}, {shape: circle}.
  • Per specificare un "quadrato rosso o blu": {color: red, blue}, {shape: square}.
  • Per specificare un oggetto senza colore, ometti lo spazio dei nomi "color" nel campo restricts.
  • Per specificare limitazioni numeriche per un oggetto, prendi nota dello spazio dei nomi e del valore nel campo appropriato per il tipo. Il valore intero deve essere specificato in value_int, il valore float deve essere specificato in value_float e il valore doppio deve essere specificato in value_double. Per un determinato spazio dei nomi deve essere utilizzato un solo tipo di numero.

Per informazioni sullo schema utilizzato per specificare questi dati, consulta Specificare gli spazi dei nomi e i token nei dati di input.

Query

  • Le query esprimono un operatore logico AND tra gli spazi dei nomi e un operatore logico OR all'interno di ogni spazio dei nomi. Una query che specifica {color: red, blue}, {shape: square, circle}, corrisponde a tutti i punti del database che soddisfano (red || blue) && (square || circle).
  • Una query che specifica {color: red} corrisponde a tutti gli oggetti red di qualsiasi tipo, senza limitazioni per shape.
  • Le limitazioni numeriche nelle query richiedono namespace, uno dei valori numerici tra value_int, value_float e value_double e l'operatore op.
  • L'operatore op è uno tra LESS, LESS_EQUAL, EQUAL, GREATER_EQUAL e GREATER. Ad esempio, se viene utilizzato l'operatore LESS_EQUAL, i punti dati sono idonei se il loro valore è minore o uguale al valore utilizzato nella query.

I seguenti esempi di codice identificano gli attributi vettore nell'applicazione di esempio:

[
  {
    "namespace": "price",
    "value_int": 20,
    "op": "LESS"
  },
  {
    "namespace": "length",
    "value_float": 0.3,
    "op": "GREATER_EQUAL"
  },
  {
    "namespace": "width",
    "value_double": 0.5,
    "op": "EQUAL"
  }
]

Lista bloccata

Per abilitare scenari più avanzati, Google supporta una forma di negazione nota come token della lista negativa. Quando una query inserisce un token nella lista negativa, le corrispondenze vengono escluse per tutti i punti dati che contengono il token inserito nella lista negativa. Se uno spazio dei nomi della query contiene solo token inseriti nella lista negativa, tutti i punti non inseriti esplicitamente nella lista negativa corrispondono, esattamente come uno spazio dei nomi vuoto corrisponde a tutti i punti.

I punti dati possono anche inserire un token nella lista negativa, escludendo le corrispondenze con qualsiasi query che specifica quel token.

Ad esempio, definisci i seguenti punti dati con i token specificati:

A: {}                  // empty set matches everything
B: {red}               // only a 'red' token
C: {blue}              // only a 'blue' token
D: {orange}            // only an 'orange' token
E: {red, blue}         // multiple tokens
F: {red, !blue}        // deny the 'blue' token
G: {red, blue, !blue}  // An unlikely edge-case
H: {!blue}             // deny-only (similar to empty-set)

Il sistema si comporta nel seguente modo:

  • Gli spazi dei nomi delle query vuoti sono caratteri jolly corrispondenti a tutti. Ad esempio, D:{} corrisponde a DB:{color:red}.
  • Gli spazi dei nomi dei punti dati vuoti non sono caratteri jolly corrispondenti a tutti. Ad esempio, D:{color:red} non corrisponde a DB:{}.

    Query e punti di database.

Specifica gli spazi dei nomi e i token o i valori nei dati di input

Per informazioni su come strutturare i dati di input in generale, consulta Formato e struttura dei dati di input.

Le seguenti schede mostrano come specificare gli spazi dei nomi e i token associati a ogni vettore di input.

JSON

  • Per ogni record del vettore, aggiungi un campo denominato restricts per contenere un array di oggetti, ciascuno dei quali è uno spazio dei nomi.

    • Ogni oggetto deve avere un campo denominato namespace. Questo campo è lo spazio dei nomi TokenNamespace.namespace.
    • Il valore del campo allow, se presente, è un array di stringhe. Questo array di stringhe è l'elenco TokenNamespace.string_tokens.
    • Il valore del campo deny, se presente, è un array di stringhe. Questo array di stringhe è l'elenco TokenNamespace.string_denylist_tokens.

Di seguito sono riportati due record di esempio in formato JSON:

[
  {
    "id": "42",
    "embedding": [
      0.5,
      1
    ],
    "restricts": [
      {
        "namespace": "class",
        "allow": [
          "cat",
          "pet"
        ]
      },
      {
        "namespace": "category",
        "allow": [
          "feline"
        ]
      }
    ]
  },
  {
    "id": "43",
    "embedding": [
      0.6,
      1
    ],
    "sparse_embedding": {
      "values": [
        0.1,
        0.2
      ],
      "dimensions": [
        1,
        4
      ]
    },
    "restricts": [
      {
        "namespace": "class",
        "allow": [
          "dog",
          "pet"
        ]
      },
      {
        "namespace": "category",
        "allow": [
          "canine"
        ]
      }
    ]
  }
]
  • Per ogni record del vettore, aggiungi un campo denominato numeric_restricts per contenere un array di oggetti, ciascuno dei quali è una limitazione numerica.

    • Ogni oggetto deve avere un campo denominato namespace. Questo campo è lo spazio dei nomi NumericRestrictNamespace.namespace.
    • Ogni oggetto deve avere uno dei valori value_int, value_float e value_double.
    • Ogni oggetto non deve avere un campo denominato op. Questo campo è solo per le query.

Di seguito sono riportati due record di esempio in formato JSON:

[
  {
    "id": "42",
    "embedding": [
      0.5,
      1
    ],
    "numeric_restricts": [
      {
        "namespace": "size",
        "value_int": 3
      },
      {
        "namespace": "ratio",
        "value_float": 0.1
      }
    ]
  },
  {
    "id": "43",
    "embedding": [
      0.6,
      1
    ],
    "sparse_embedding": {
      "values": [
        0.1,
        0.2
      ],
      "numeric_restricts": [
        {
          "namespace": "weight",
          "value_double": 0.3
        }
      ]
    }
  }
]

Avro

I record Avro utilizzano lo schema seguente:

{
  "type": "record",
  "name": "FeatureVector",
  "fields": [
    {
      "name": "id",
      "type": "string"
    },
    {
      "name": "embedding",
      "type": {
        "type": "array",
        "items": "float"
      }
    },
    {
      "name": "sparse_embedding",
      "type": [
        "null",
        {
          "type": "record",
          "name": "sparse_embedding",
          "fields": [
            {
              "name": "values",
              "type": {
                "type": "array",
                "items": "float"
              }
            },
            {
              "name": "dimensions",
              "type": {
                "type": "array",
                "items": "long"
              }
            }
          ]
        }
      ]
    },
    {
      "name": "restricts",
      "type": [
        "null",
        {
          "type": "array",
          "items": {
            "type": "record",
            "name": "Restrict",
            "fields": [
              {
                "name": "namespace",
                "type": "string"
              },
              {
                "name": "allow",
                "type": [
                  "null",
                  {
                    "type": "array",
                    "items": "string"
                  }
                ]
              },
              {
                "name": "deny",
                "type": [
                  "null",
                  {
                    "type": "array",
                    "items": "string"
                  }
                ]
              }
            ]
          }
        }
      ]
    },
    {
      "name": "numeric_restricts",
      "type": [
        "null",
        {
          "type": "array",
          "items": {
            "name": "NumericRestrict",
            "type": "record",
            "fields": [
              {
                "name": "namespace",
                "type": "string"
              },
              {
                "name": "value_int",
                "type": [ "null", "int" ],
                "default": null
              },
              {
                "name": "value_float",
                "type": [ "null", "float" ],
                "default": null
              },
              {
                "name": "value_double",
                "type": [ "null", "double" ],
                "default": null
              }
            ]
          }
        }
      ],
      "default": null
    },
    {
      "name": "crowding_tag",
      "type": [
        "null",
        "string"
      ]
    }
  ]
}

CSV

  • Limitazioni token

    • Per ogni record del vettore, aggiungi coppie di formati name=value separate da virgole per specificare le limitazioni dello spazio dei nomi dei token. Lo stesso nome può essere ripetuto se sono presenti più valori in uno spazio dei nomi.

      Ad esempio, color=red,color=blue rappresenta questo TokenNamespace:

      {
        "namespace": "color"
        "string_tokens": ["red", "blue"]
      }
      
    • Per ogni record del vettore, aggiungi coppie di formatiname=!value separate da virgole per specificare il valore escluso per le limitazioni dello spazio dei nomi dei token.

      Ad esempio, color=!red rappresenta questo TokenNamespace:

      {
        "namespace": "color"
        "string_blacklist_tokens": ["red"]
      }
      
  • Limitazioni numeriche

    • Per ogni record del vettore, aggiungi coppie di formato separate da virgola#name=numericValue con suffisso di tipo numerico per specificare le limitazioni dello spazio dei nomi numerici.

      Il suffisso del tipo di numero è i per int, f per float e d per double. Lo stesso nome non deve essere ripetuto, in quanto deve essere associato un singolo valore per spazio dei nomi.

      Ad esempio, #size=3i rappresenta questo NumericRestrictNamespace:

      {
        "namespace": "size"
        "value_int": 3
      }
      

      #ratio=0.1f rappresenta questo NumericRestrictNamespace:

      {
        "namespace": "ratio"
        "value_float": 0.1
      }
      

      #weight=0.3d rappresenta questo NumericRestriction:

      {
        "namespace": "weight"
        "value_double": 0.3
      }
      
    • Ecco un esempio di punto dati con id: "6", embedding: [7, -8.1], sparse_embedding: {values: [0.1, -0.2, 0.5], dimensions: [40, 901, 1111]}}, tag di affollamento test, lista consentita di token color: red, blue, lista vietata di token color: purple e limitazione numerica ratio con numero decimale 0.1:

      6,7,-8.1,40:0.1,901:-0.2,1111:0.5,crowding_tag=test,color=red,color=blue,color=!purple,
      ratio=0.1f
      

Passaggi successivi