Formato e estrutura dos dados de entrada

Para criar um novo índice ou atualizar um índice existente, forneça vetores à pesquisa vetorial no formato e na estrutura descritos nas secções seguintes.

Pré-requisitos

Armazene os seus dados de entrada num contentor do Cloud Storage no seu Google Cloud projeto.

Os ficheiros de dados de entrada devem ser organizados da seguinte forma:

  • Cada lote de ficheiros de dados de entrada deve estar num único diretório do Cloud Storage.
  • Os ficheiros de dados devem ser colocados diretamente em batch_root e ter os seguintes sufixos: .csv, .json e .avro.
  • Existe um limite de 5000 objetos (ficheiros) no diretório raiz do lote.
  • Cada ficheiro de dados é interpretado como um conjunto de registos. O formato do registo é determinado pelo sufixo do nome do ficheiro e esses requisitos de formato são descritos. Consulte os Formatos de ficheiros de dados.
  • Cada registo deve ter um id, um vetor de caraterísticas e os seus campos opcionais suportados pelo Vertex AI Feature Store, como restrições e aglomeração.
  • Pode estar presente um subdiretório com o nome delete. Cada ficheiro diretamente em batch_root/delete é considerado um ficheiro de texto de id registos com um id em cada linha.
  • Todos os outros subdiretórios não são permitidos.
  • A transcodificação de ficheiros comprimidos com gzip não é suportada como dados de entrada.

Tratamento de dados de entrada

  • Todos os registos de todos os ficheiros de dados, incluindo os que se encontram em delete, consistem num único lote de entrada.
  • A ordem relativa dos registos num ficheiro de dados não é importante.
  • Um único ID só deve aparecer uma vez num lote. Se existir um duplicado com o mesmo ID, é apresentado como uma contagem de vetores.
  • Um ID não pode aparecer num ficheiro de dados normal e num ficheiro de dados de eliminação.
  • Todos os IDs de um ficheiro de dados na secção de eliminação fazem com que sejam removidos da próxima versão do índice.
  • Os registos de ficheiros de dados normais são incluídos na versão seguinte, substituindo um valor numa versão de índice mais antiga.

Seguem-se exemplos de incorporações densas, esparsas e híbridas:

  • Incorporações densas:

    {"id": "1", "embedding": [1,1,1]}
    {"id": "2", "embedding": [2,2,2]}
    
  • Incorporações esparsas:

    {"id": "3", "sparse_embedding": {"values": [0.1, 0.2], "dimensions": [1, 4]}}
    {"id": "4", "sparse_embedding": {"values": [-0.4, 0.2, -1.3], "dimensions": [10, 20, 20]}}
    
  • Incorporações híbridas:

    {"id": "5", "embedding": [5, 5, -5], "sparse_embedding": {"values": [0.1], "dimensions": [500]}}
    {"id": "6", "embedding": [6, 7, -8.1], "sparse_embedding": {"values": [0.1, -0.2], "dimensions": [40, 901]}}
    

Segue-se um exemplo de uma organização de ficheiros de dados de entrada válida:

batch_root/
  feature_file_1.csv
  feature_file_2.csv
  delete/
    delete_file.txt

Os ficheiros feature_file_1.csv e feature_file_2.csv contêm registos no formato CSV. O ficheiro delete_file.txt contém uma lista de IDs de registos a eliminar da próxima versão do índice.

Formatos de ficheiros de dados

JSON

  • Codifique o ficheiro JSON através de UTF-8.
  • Cada linha do ficheiro JSON é interpretada como um objeto JSON separado.
  • Cada registo tem de conter um campo id para especificar o ID do vetor.
  • Cada registo tem de conter, pelo menos, um dos seguintes elementos: embedding ou sparse_embedding.
  • O campo embedding é uma matriz de números de vírgula flutuante que representa o vetor de caraterísticas, em que N é a dimensão do vetor de caraterísticas que foi configurada quando o índice foi criado.N Este campo só pode ser usado para incorporações densas.
    • O atributo configs.dimensions, especificado no momento da criação do índice, tem de ter o mesmo comprimento que embeddings. configs.dimensions aplica-se apenas a embedding e não a sparse_embedding.
  • O campo sparse_embedding é um objeto com os campos values e dimensions. O campo values é uma lista de números de vírgula flutuante que representa o vetor de caraterísticas e o campo dimensions é uma lista de números inteiros que representa a dimensão na qual o valor correspondente se encontra. Por exemplo, uma incorporação esparsa que se assemelha a [0,0.1,0,0,0.2] pode ser representada como "sparse_embedding": {"values": [0.1, 0.2], "dimensions": [1,4]}. Este campo só pode ser usado para incorporações esparsas.
    • O comprimento de sparse_embedding.values tem de ser igual ao comprimento de sparse_embedding.dimensions. Não têm de ter o mesmo comprimento que configs.dimensions, que é especificado no momento da criação do índice e não se aplica a sparse_embedding.
  • Pode incluir um campo restricts opcional que especifica uma matriz de objetos TokenNamespace em restrições. Para cada objeto:
    • Especifique um campo namespace que seja o TokenNamespace.namespace.
    • Um campo allow opcional pode ser definido como uma matriz de strings que é a lista de TokenNamespace.string_tokens.
    • Um campo deny opcional pode ser definido como uma matriz de strings que é a lista de TokenNamespace.string_blacklist_tokens.
    • O valor do campo crowding_tag, se estiver presente, tem de ser uma string.
  • Pode incluir um campo numeric_restricts opcional que especifica uma matriz de NumericRestrictNamespace. Para cada objeto:
    • Especifique um campo namespace que seja o NumericRestrictNamespace.namespace.
    • Um dos campos de valor value_int, value_float e value_double.
    • Não pode ter um campo com o nome op. Este campo destina-se apenas a consultas.

Avro

  • Use um ficheiro Avro válido.
  • Para representar um ponto de dados apenas esparso, forneça uma incorporação esparsa no campo sparse_embedding e introduza uma lista vazia no campo embedding.
  • Crie registos em conformidade com 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

  • Formato: ID,N feature vector values,Any number of dimension:value sparse values,name=value lists
  • Codifique o ficheiro CSV com UTF-8.
  • Cada linha do CSV tem de conter exatamente um registo.
  • O primeiro valor em cada linha tem de ser o ID do vetor, que tem de ser uma string UTF-8 válida.
  • Após o ID, tem de especificar, pelo menos, uma incorporação densa ou uma incorporação esparsa.
  • Para uma incorporação densa, os próximos valores N representam o vetor de caraterísticas, em que N é a dimensão do vetor de caraterísticas que foi configurada quando o índice foi criado.
  • Para uma incorporação esparsa, pode especificar qualquer número de dimension:value, em que value é analisado como um número de vírgula flutuante e dimension é analisado como um long.
  • Para uma incorporação híbrida que tenha incorporações densas e esparsas, as incorporações densas têm de ser especificadas antes das incorporações esparsas.
  • Os valores dos vetores de caraterísticas têm de ser literais de ponto flutuante, conforme definido na especificação da linguagem Java.
  • Os valores adicionais podem estar no formato name=value.
  • O nome crowding_tag é interpretado como a etiqueta de aglomeração e só pode aparecer uma vez no registo.
  • Todos os outros pares name=value são interpretados como restrições de espaço de nomes de 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"]
    }
    
  • Se o valor começar por !, o resto da string é interpretado como um valor excluído.

    Por exemplo, color=!red representa este TokenNamespace:

    {
      "namespace": "color"
      "string_blacklist_tokens": ["red"]
    }
    
  • Os pares #name=numericValue com o sufixo do tipo de número são interpretados como 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
    }
    
  • O exemplo seguinte é 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 congestionamento test, lista de autorizações de tokens de color: red, blue, lista de exclusões de tokens de color: purple e restrição numérica de ratio com 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
    

O que se segue?