Filtre correspondências vetoriais

Na pesquisa vetorial, pode restringir as pesquisas de correspondência vetorial a um subconjunto do índice através de regras booleanas. Os predicados booleanos indicam à pesquisa vetorial que vetores no índice ignorar. Nesta página, vai saber como funciona a filtragem, ver exemplos e formas de consultar os seus dados de forma eficiente com base na semelhança vetorial.

Com a pesquisa vetorial, pode restringir os resultados por restrições categóricas e numéricas. Adicionar restrições ou "filtrar" os resultados do índice é útil por vários motivos, como nos exemplos seguintes:

  • Relevância dos resultados melhorada: a pesquisa vetorial é uma ferramenta poderosa para encontrar itens semanticamente semelhantes. A filtragem pode ser usada para remover resultados irrelevantes dos resultados da pesquisa, como itens que não estão no idioma, na categoria, no preço ou no intervalo de datas corretos.

  • Número reduzido de resultados: a pesquisa vetorial pode devolver um grande número de resultados, especialmente para grandes conjuntos de dados. A filtragem pode ser usada para reduzir o número de resultados a um número mais gerível, ao mesmo tempo que devolve os resultados mais relevantes.

  • Resultados segmentados: a filtragem pode ser usada para personalizar os resultados da pesquisa de acordo com as necessidades e as preferências individuais do utilizador. Por exemplo, um utilizador pode querer filtrar os resultados para incluir apenas os artigos que classificou com uma pontuação elevada no passado ou que se enquadram numa gama de preços específica.

Atributos de vetores

Numa pesquisa de similaridade vetorial numa base de dados de vetores, cada vetor é descrito por zero ou mais atributos. Estes atributos são conhecidos como tokens para restrições de tokens e valores para restrições numéricas. Estas restrições podem aplicar-se a cada uma das várias categorias de atributos, também conhecidas como namespaces.

Na aplicação de exemplo seguinte, os vetores são etiquetados com um color, um price e um shape:

  • color, price e shape são espaços de nomes.
  • red e blue são tokens do espaço de nomes color.
  • square e circle são tokens do espaço de nomes shape.
  • 100 e 50 são valores do espaço de nomes price.

Especifique os atributos de vetores

  • Para especificar um "círculo vermelho": {color: red}, {shape: circle}.
  • Para especificar um "quadrado vermelho ou azul": {color: red, blue}, {shape: square}.
  • Para especificar um objeto sem cor, omita o espaço de nomes "color" no campo restricts.
  • Para especificar restrições numéricas para um objeto, tome nota do espaço de nomes e do valor no campo adequado para o tipo. O valor int deve ser especificado em value_int, o valor float deve ser especificado em value_float e o valor double deve ser especificado em value_double. Deve ser usado apenas um tipo de número para um determinado espaço de nomes.

Para obter informações sobre o esquema usado para especificar estes dados, consulte o artigo Especifique espaços de nomes e tokens nos dados de entrada.

Consultas

  • As consultas expressam um operador lógico AND em todos os espaços de nomes e um operador lógico OR em cada espaço de nomes. Uma consulta que especifica {color: red, blue}, {shape: square, circle} corresponde a todos os pontos da base de dados que satisfazem (red || blue) && (square || circle).
  • Uma consulta que especifica {color: red} corresponde a todos os objetos red de qualquer tipo, sem restrições em shape.
  • As restrições numéricas nas consultas requerem namespace, um dos valores numéricos de value_int, value_float e value_double, e o operador op.
  • O operador op é um dos seguintes: LESS, LESS_EQUAL, EQUAL, GREATER_EQUAL e GREATER. Por exemplo, se for usado o operador LESS_EQUAL, os pontos de dados são elegíveis se o respetivo valor for inferior ou igual ao valor usado na consulta.

Os seguintes exemplos de código identificam atributos de vetor na aplicação de exemplo:

[
  {
    "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 de negações

Para ativar cenários mais avançados, a Google suporta uma forma de negação conhecida como tokens de lista de exclusão. Quando uma consulta inclui um token numa lista de recusa, as correspondências são excluídas para qualquer ponto de dados que tenha o token na lista de recusa. Se um espaço de nomes de consulta tiver apenas tokens na lista de recusa, todos os pontos que não estejam explicitamente na lista de recusa correspondem exatamente da mesma forma que um espaço de nomes vazio corresponde a todos os pontos.

Os pontos de dados também podem recusar um token, excluindo correspondências com qualquer especificação de consulta desse token.

Por exemplo, defina os seguintes pontos de dados com os tokens especificados:

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)

O sistema funciona da seguinte forma:

  • Os espaços de nomes de consultas vazios são carateres universais de correspondência total. Por exemplo, Q:{} corresponde a DB:{color:red}.
  • Os espaços de nomes de pontos de dados vazios não são carateres universais de correspondência total. Por exemplo, Q:{color:red} não corresponde a DB:{}.

    Pontos de consulta e base de dados.

Especifique espaços de nomes e tokens ou valores nos dados de entrada

Para obter informações sobre como estruturar os dados de entrada em geral, consulte o artigo Formato e estrutura dos dados de entrada.

Os separadores seguintes mostram como especificar os espaços de nomes e os tokens associados a cada vetor de entrada.

JSON

  • Para cada registo do vetor, adicione um campo denominado restricts, para conter uma matriz de objetos, cada um dos quais é um espaço de nomes.

    • Cada objeto tem de ter um campo denominado namespace. Este campo é o TokenNamespace.namespace, espaço de nomes.
    • Se estiver presente, o valor do campo allow é uma matriz de strings. Esta matriz de strings é a lista TokenNamespace.string_tokens.
    • Se estiver presente, o valor do campo deny é uma matriz de strings. Esta matriz de strings é a lista TokenNamespace.string_denylist_tokens.

Seguem-se dois exemplos de registos no 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"
        ]
      }
    ]
  }
]
  • Para cada registo do vetor, adicione um campo denominado numeric_restricts, para conter uma matriz de objetos, cada um dos quais é uma restrição numérica.

    • Cada objeto tem de ter um campo denominado namespace. Este campo é o NumericRestrictNamespace.namespace, espaço de nomes.
    • Cada objeto tem de ter um dos seguintes elementos: value_int, value_float e value_double.
    • Cada objeto não pode ter um campo com o nome op. Este campo destina-se apenas a consultas.

Seguem-se dois exemplos de registos no 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

Os registos Avro usam o seguinte esquema:

{
  "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

  • Restrições de tokens

    • Para cada registo do vetor, adicione pares separados por vírgulas de formato name=value para especificar restrições do espaço de nomes dos tokens. O mesmo nome pode ser repetido se existirem vários valores num espaço de nomes.

      Por exemplo, color=red,color=blue representa este TokenNamespace:

      {
        "namespace": "color"
        "string_tokens": ["red", "blue"]
      }
      
    • Para cada registo do vetor, adicione pares separados por vírgulas no formato name=!value para especificar o valor excluído para restrições do espaço de nomes do token.

      Por exemplo, color=!red representa este TokenNamespace:

      {
        "namespace": "color"
        "string_blacklist_tokens": ["red"]
      }
      
  • Restrições numéricas

    • Para cada registo do vetor, adicione pares separados por vírgulas no formato #name=numericValue com o sufixo do tipo de número para especificar restrições do espaço de nomes numérico.

      O sufixo do tipo de número é i para int, f para float e d para double. O mesmo nome não deve ser repetido, uma vez que deve existir um único valor associado por espaço de nomes.

      Por exemplo, #size=3i representa este NumericRestrictNamespace:

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

      #ratio=0.1f representa o seguinte NumericRestrictNamespace:

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

      #weight=0.3d representa o seguinte NumericRestriction:

      {
        "namespace": "weight"
        "value_double": 0.3
      }
      
    • Segue-se um exemplo de um ponto de dados com id: "6", embedding: [7, -8.1], sparse_embedding: {values: [0.1, -0.2, 0.5], dimensions: [40, 901, 1111]}}, etiqueta de sobreposição de test, lista de autorizações de tokens de color: red, blue, lista de recusas de tokens de color: purple e restrição numérica de ratio com o valor flutuante 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
      

O que se segue?