Filtrare le corrispondenze vettoriali

In Vector Search, puoi limitare le ricerche di corrispondenze vettoriali a un sottoinsieme dell'indice utilizzando regole booleane. I predicati booleani indicano a Vector Search quali vettori nell'indice ignorare. In questa pagina scoprirai come funziona il filtro, vedrai esempi e modi per eseguire query sui dati in modo efficiente in base alla somiglianza dei vettori.

Con Vector Search puoi limitare i risultati in base a restrizioni numeriche e di categoria. L'aggiunta di restrizioni o il "filtraggio" dei risultati dell'indice è utile per diversi motivi, come i seguenti esempi:

  • Maggiore pertinenza dei risultati: Vector Search è un potente strumento per trovare elementi semanticamente simili. Il filtro può essere utilizzato per rimuovere i risultati non pertinenti dai risultati di ricerca, ad esempio gli elementi che non sono nella lingua, nella categoria, nel prezzo o nell'intervallo di date corretti.

  • Numero ridotto di risultati: Vector Search può restituire un numero elevato di risultati, soprattutto per i set di dati di grandi dimensioni. Il filtro può essere utilizzato per ridurre il numero di risultati a un numero più gestibile, restituendo comunque i risultati più pertinenti.

  • Risultati segmentati: il filtro può essere utilizzato per personalizzare i risultati di ricerca in base alle esigenze e alle preferenze individuali dell'utente. Ad esempio, un utente potrebbe voler filtrare i risultati in modo da includere solo gli elementi che ha valutato positivamente in passato o che rientrano in una fascia di prezzo specifica.

Attributi dei vettori

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

Nella seguente applicazione di esempio, i vettori sono taggati con un color, un price e una shape:

  • color, price e shape sono spazi dei nomi.
  • 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.

Specificare gli attributi dei vettori

  • 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 le restrizioni 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 in value_float e il valore double 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 spazi dei nomi e 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 restrizioni su shape.
  • Le restrizioni numeriche nelle query richiedono namespace, uno dei valori numerici di 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 è inferiore o uguale al valore utilizzato nella query.

I seguenti esempi di codice identificano gli attributi dei vettori 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 consentire scenari più avanzati, Google supporta una forma di negazione nota come token della lista bloccata. Quando una query inserisce un token nella lista bloccata, le corrispondenze vengono escluse per qualsiasi punto dati che abbia il token nella lista bloccata. Se uno spazio dei nomi della query contiene solo token nella lista bloccata, tutti i punti non esplicitamente nella lista bloccata corrispondono esattamente allo stesso modo in cui uno spazio dei nomi vuoto corrisponde a tutti i punti.

I punti dati possono anche inserire un token nella lista bloccata, escludendo le corrispondenze con qualsiasi query che specifichi 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 che corrispondono a tutto. Ad esempio, Q:{} corrisponde a DB:{color:red}.
  • Gli spazi dei nomi dei punti dati vuoti non sono caratteri jolly che corrispondono a tutto. Ad esempio, Q:{color:red} non corrisponde a DB:{}.

    Query e punti di database.

Specificare spazi dei nomi e token o 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, che contenga un array di oggetti, ognuno dei quali è uno spazio dei nomi.

    • Ogni oggetto deve avere un campo denominato namespace. Questo campo è TokenNamespace.namespace, lo spazio dei nomi.
    • 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, che contenga un array di oggetti, ognuno dei quali è una restrizione numerica.

    • Ogni oggetto deve avere un campo denominato namespace. Questo campo è NumericRestrictNamespace.namespace, lo spazio dei nomi.
    • Ogni oggetto deve avere uno tra value_int, value_float e value_double.
    • Ogni oggetto non deve avere un campo denominato op. Questo campo è solo per la 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

  • Restrizioni dei token

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

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

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

      Ad esempio, color=!red rappresenta questo TokenNamespace:

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

    • Per ogni record del vettore, aggiungi coppie separate da virgole nel formato #name=numericValue con il suffisso del tipo di numero per specificare le restrizioni dello spazio dei nomi numerico.

      Il suffisso del tipo di numero è i per int, f per float, e d per double. Lo stesso nome non deve essere ripetuto perché 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 questa NumericRestriction:

      {
        "namespace": "weight"
        "value_double": 0.3
      }
      
    • Di seguito è riportato un punto dati di esempio 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 bloccata di token color: purple e restrizione numerica di ratio con float 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