Criar aplicativos de IA generativa usando a IA do AlloyDB

Esta seção descreve como invocar previsões e consultar e indexar embeddings usando a extensão pgvector. Essas funções de IA com tecnologia de machine learning estão disponíveis no AlloyDB AI, um conjunto de recursos do AlloyDB para PostgreSQL que permite aplicar o poder semântico e preditivo dos modelos de machine learning (ML) aos seus dados.

Saiba mais sobre o AlloyDB AI em https://cloud.google.com//alloydb/docs/ai.

Invocar previsões

Para integrar a Vertex AI ao AlloyDB Omni e executar previsões em modelos armazenados na Vertex AI, siga estas etapas.

Antes de começar

  1. Ative as previsões on-line da Vertex AI no GDC.
  2. Crie um secret do Kubernetes com base na chave da conta de serviço baixada nas etapas anteriores executando o seguinte comando: Crie o secret do Kubernetes no mesmo namespace que o recurso DBCluster.

    kubectl create secret generic SECRET_NAME \
    --from-file=PATH_TO_SERVICE_ACCOUNT_KEY/private-key.json \
    -n NAMESPACE

    Substitua:

    • SECRET_NAME: o nome do secret usado ao criar um manifesto DBCluster para permitir que o AlloyDB Omni acesse os recursos da IA do Distributed Cloud. Por exemplo, vertex-ai-key-alloydb.

    • PATH_TO_SERVICE_ACCOUNT_KEY: o caminho para o local onde você baixou a chave da conta de serviço do private-key.json.

    • NAMESPACE: o namespace do cluster de banco de dados.

  3. Instale o operador do AlloyDB Omni seguindo as etapas listadas em Escolher um tipo de mecanismo de banco de dados e criar um cluster de banco de dados.

  4. Crie um cluster de banco de dados com o AlloyDB AI e defina vertexAIKeyRef como o Secret do Kubernetes criado nas etapas anteriores no campo googleMLExtension do manifesto DBCluster.

    apiVersion: v1
    kind: Secret
    metadata:
      name: db-pw-DBCLUSTER_NAME
      namespace: USER_PROJECT
    type: Opaque
    data:
      DBCLUSTER_NAME: "BASE64_PASSWORD"
    ---
    apiVersion: DBENGINE_NAME.dbadmin.gdc.goog/v1
    kind: DBCluster
    metadata:
      name: DBCLUSTER_NAME
      namespace: USER_PROJECT
    spec:
      primarySpec:
        adminUser:
          passwordRef:
            name: db-pw-DBCLUSTER_NAME
        features:
          googleMLExtension:
            config:
              vertexAIKeyRef: SECRET_NAME
        version: "DB_VERSION"
        resources:
          memory: DB_MEMORY
          cpu: DB_CPU
          disks:
          - name: DataDisk
            size: DB_DATA_DISK
    

    Substitua as seguintes variáveis:

    • DBCLUSTER_NAME: o nome do cluster de banco de dados.
    • USER_PROJECT: o nome do projeto do usuário em que o cluster de banco de dados será criado.
    • BASE64_PASSWORD: a codificação base64 da senha do administrador do banco de dados.
    • DBENGINE_NAME: o nome do mecanismo de banco de dados. Defina como alloydbomni.
    • DB_VERSION: a versão do mecanismo de banco de dados.
    • DB_MEMORY: a quantidade de memória alocada para o cluster de banco de dados, por exemplo, 5Gi.
    • DB_CPU: a quantidade de CPUs alocadas para o cluster de banco de dados, por exemplo, 2.
    • DB_DATA_DISK: a quantidade de espaço alocado para o cluster de banco de dados, por exemplo, 10 Gi.

    Aplique o manifesto.

    kubectl apply -f DB_CLUSTER_YAML

    Substitua:

    • DB_CLUSTER_YAML: o nome do arquivo de manifesto do cluster de banco de dados. Por exemplo, alloydb-omni-db-cluster.yaml.
  5. Instale a extensão google_ml_integration.

    CREATE EXTENSION google_ml_integration CASCADE;
    

Invocar uma previsão

Invoque uma previsão on-line usando um endpoint de modelo da Vertex AI executando a seguinte função SQL ml_predict_row():

  SELECT ml_predict_row('PREDICTION_ENDPOINT/PROJECT_NAMESPACE/ORGANIZATION/ZONE/DNS/DNS_SUFFIX', '{ "instances": [ INSTANCES ], "parameters":
  PARAMETERS');

Substitua:

  • PREDICTION_ENDPOINT: o nome qualificado do endpoint da Vertex AI

  • PROJECT_NAMESPACE: o namespace em que o endpoint da Vertex AI é implantado.

  • ORGANIZATION: o nome da organização em que o endpoint da Vertex AI está implantado.

  • ZONE: a zona em que o endpoint da Vertex AI está implantado

  • DNS: o DNS da sua organização

  • DNS_SUFFIX: o sufixo do objeto DNS.

  • INSTANCES: as entradas para a chamada de previsão, no formato JSON

  • PARAMETERS: os parâmetros para a chamada de previsão, no formato JSON

Consultar e indexar embeddings usando pgvector

A extensão pgvector do PostgreSQL permite usar operadores e funções específicos de vetor ao armazenar, indexar e consultar embeddings de texto no banco de dados. O AlloyDB oferece otimizações para trabalhar com pgvector, permitindo que você crie índices que podem acelerar determinadas consultas que envolvem embeddings.

Saiba mais sobre como usar o AlloyDB como um LLM e gerar e armazenar embeddings vetoriais com base em um LLM em https://cloud.google.com/alloydb/docs/ai/work-with-embeddings#index.

Criar índices e consultar vetores usando o ScaNN

Nesta seção, mostramos como usar embeddings armazenados para gerar índices e consultar embeddings. É possível criar índices ScaNN com o AlloyDB.

Antes de começar

Antes de começar a criar índices, conclua os seguintes pré-requisitos.

  • Os vetores de embedding são adicionados a uma tabela no banco de dados do AlloyDB.

  • A versão 0.5.0 ou mais recente da extensão vector, baseada em pgvector e estendida pelo Google para o AlloyDB, está instalada.

    CREATE EXTENSION IF NOT EXISTS vector;
    
  • Para gerar índices ScaNN, instale a extensão postgres_ann além da extensão vector.

    CREATE EXTENSION IF NOT EXISTS postgres_ann;
    

Criar um índice ScaNN

É possível criar um índice ScaNN para tabelas no seu banco de dados.

AlloyDB postgres_ann, uma extensão do PostgreSQL desenvolvida pelo Google que implementa um índice de vizinho mais próximo altamente eficiente com tecnologia do algoritmo ScaNN.

O índice ScaNN é um índice de quantização baseado em árvore para pesquisa aproximada de vizinho mais próximo. Ele oferece um tempo de criação de índice baixo e uma pequena pegada de memória. Além disso, ele oferece QPS rápido com base na carga de trabalho.

Índice de árvore de dois níveis ScaNN

Para aplicar um índice de árvore de dois níveis usando o algoritmo ScaNN a uma coluna que contém embeddings de vetores armazenados, execute a seguinte consulta DDL:

CREATE INDEX INDEX_NAME ON TABLE
  USING scann (EMBEDDING_COLUMN DISTANCE_FUNCTION)
  WITH (num_leaves=NUM_LEAVES_VALUE);

Substitua:

  • INDEX_NAME: o nome do índice que você quer criar. Por exemplo, my-scann-index. Os nomes de índice são compartilhados em todo o banco de dados. Verifique se cada nome de índice é exclusivo para cada tabela no banco de dados.

  • TABLE: a tabela em que o índice será adicionado.

  • EMBEDDING_COLUMN: uma coluna que armazena dados de vector.

  • DISTANCE_FUNCTION: a função de distância a ser usada com esse índice. Escolha uma destas opções:

    • Distância de L2:l2

    • Produto escalar: dot_product

    • Distância do cosseno:cosine

  • NUM_LEAVES_VALUE: o número de partições a serem aplicadas a esse índice. Definido como qualquer valor entre 1 e 1048576.

Índice de árvore de três níveis ScaNN

Para criar um índice de árvore de três níveis usando o algoritmo ScaNN em uma coluna que contém embeddings de vetores armazenados, execute a seguinte consulta DDL:

CREATE INDEX INDEX_NAME ON TABLE
  USING scann (EMBEDDING_COLUMN DISTANCE_FUNCTION)
  WITH (num_leaves=NUM_LEAVES_VALUE, max_num_levels = MAX_NUM_LEVELS);

Substitua:

  • MAX_NUM_LEVELS: o número máximo de níveis da árvore de clusterização K-means. Defina como 1(padrão) para quantização de dois níveis baseada em árvore e como 2 para quantização de três níveis baseada em árvore.

Depois de criar o índice, siga as instruções em Fazer uma consulta de vizinho mais próximo com um texto fornecido para executar consultas de pesquisa de vizinho mais próximo que usam o índice.

Os parâmetros de índice precisam ser definidos para encontrar o equilíbrio certo entre QPS e recall.

Para criar esse índice em uma coluna incorporada que usa o tipo de dados real[] em vez de vector, converta a coluna no tipo de dados vector:

CREATE INDEX INDEX_NAME ON TABLE
  USING scann (CAST(EMBEDDING_COLUMN AS vector(DIMENSIONS)) DISTANCE_FUNCTION)
  WITH (num_leaves=NUM_LEAVES_VALUE, max_num_levels = MAX_NUM_LEVELS);

Substitua DIMENSIONS pela largura dimensional da coluna de embedding.

Para conferir o progresso da indexação, use a visualização pg_stat_progress_create_index:

SELECT * FROM pg_stat_progress_create_index;

A coluna phase mostra o estado atual da criação do índice, e a fase building index: tree training desaparece depois que o índice é criado.

Executar uma consulta

Depois de armazenar e indexar embeddings no banco de dados, você pode começar a consultar usando a funcionalidade de consulta pgvector. Não é possível executar consultas de pesquisa em massa usando a extensão postgres_ann.

Para encontrar os vizinhos semânticos mais próximos de um vetor de embedding, execute a consulta de exemplo a seguir, em que você define a mesma função de distância usada durante a criação do índice.

  SELECT * FROM TABLE
    ORDER BY EMBEDDING_COLUMN DISTANCE_FUNCTION_QUERY ['EMBEDDING']
    LIMIT ROW_COUNT

Substitua:

  • TABLE: a tabela que contém o embedding a que você compara o texto.

  • INDEX_NAME: o nome do índice que você quer usar. Por exemplo, my-scann-index.

  • EMBEDDING_COLUMN: a coluna que contém os embeddings armazenados.

  • DISTANCE_FUNCTION_QUERY: a função de distância a ser usada com esta consulta. Escolha uma das seguintes opções com base na função de distância usada ao criar o índice:

    • Distância de L2:<->

    • Produto interno:<#>

    • Distância do cosseno:<=>

  • EMBEDDING: o vetor de embedding para encontrar os vizinhos semânticos armazenados mais próximos.

  • ROW_COUNT: o número de linhas que serão retornadas.

    Especifique 1 se você quiser apenas a melhor correspondência.

Você também pode usar a função embedding() para traduzir o texto em um vetor. Aplique o vetor a um dos operadores vizinho mais próximo pgvector, <-> para distância L2, e encontre as linhas do banco de dados com os embeddings mais semanticamente semelhantes. Primeiro, registre o modelo Gecko de embedding de texto para usar essa função.

Como embedding() retorna uma matriz real, é necessário transmitir explicitamente a chamada embedding() para vector para usar esses valores com operadores pgvector.

  CREATE EXTENSION google_ml_integration;
  CREATE EXTENSION IF NOT EXISTS vector;

  SELECT * FROM TABLE
    ORDER BY EMBEDDING_COLUMN::vector
    <-> embedding('MODEL_IDVERSION_TAG', 'TEXT')
    LIMIT ROW_COUNT

Substitua:

  • MODEL_ID: o ID do modelo a ser consultado.

    Se você estiver usando o Model Garden da Vertex AI, especifique textembedding-gecko@003 como o ID do modelo. Esses são os modelos baseados na nuvem que o Distributed Cloud pode usar para embeddings de texto.

  • Opcional: VERSION_TAG: a tag da versão do modelo a ser consultada. Adicione @ ao início da tag.

    Se você estiver usando um dos modelos textembedding-gecko em inglês com a Vertex AI, especifique uma das tags de versão, por exemplo, textembedding-gecko@003.

    O Google recomenda que você sempre especifique a tag de versão. Se você não especificar a tag de versão, o AlloyDB sempre usará a versão mais recente do modelo, o que pode gerar resultados inesperados.

  • TEXT: o texto a ser traduzido em um embedding vetorial.

Métricas de índice vetorial

Esta seção lista as métricas relacionadas aos índices de vetores gerados no AlloyDB. É possível conferir essas métricas usando a visualização pg_stat_ann_indexes, disponível quando você instala a extensão postgres_ann.

Métricas de usabilidade

As métricas de usabilidade incluem métricas que ajudam a entender o estado da utilização do índice com métricas como configuração do índice e número de verificações de índice.

Nome da métrica Tipo de dado Descrição
relid OID Identificador exclusivo da tabela que contém o índice vetorial.
indexrelid OID Identificador exclusivo do índice vetorial.
schemaname NAME Nome do esquema a que o índice pertence.
relname NAME Nome da tabela que contém o índice.
indexrelname NAME Nome do índice.
indextype NAME Tipo do índice. Esse valor é sempre definido como postgres_ann.
indexconfig TEXT[] Configuração, como contagem de folhas e quantizador, definida para o índice quando ele foi criado.
indexsize TEXT Tamanho do índice.
indexscan BIGINT Número de verificações de índice iniciadas no índice.

Métricas de ajuste

As métricas de ajuste oferecem insights sobre a otimização de índice atual, permitindo que você aplique recomendações para melhorar a performance das consultas.

Nome da métrica Tipo de dado Descrição
insertcount BIGINT Número de operações de inserção no índice. Essa métrica também inclui qualquer número de linhas que existia antes da criação do índice.
updatecount BIGINT Número de operações de atualização no índice. Essa métrica não considera atualizações HOT.
deletecount BIGINT Número de operações de exclusão no índice.
distribution JSONB Distribuições de vetores em todas as partições do índice.

Os seguintes campos mostram a distribuição:
  • maximum (INT8): número máximo de vetores em todas as partições.
  • minimum (INT8): número mínimo de vetores em todas as partições.
  • average (FLOAT) : número médio de vetores em todas as partições.
  • outliers (INT8[]): outliers principais em todas as partições. Esse valor mostra os 20 principais outliers.

Observação:devido às características inerentes do algoritmo de clusterização K-means, sempre haverá algum grau de variância na distribuição de vetores entre as partições, mesmo quando o índice é criado inicialmente.

Recomendação de ajuste com base nas métricas

Mutação
As métricas insertcount, updatecount e deletecount mostram juntas as mudanças ou mutações no vetor do índice.
O índice é criado com um número específico de vetores e partições. Quando operações como inserção, atualização ou exclusão são realizadas no índice de vetor, elas afetam apenas o conjunto inicial de partições em que os vetores residem. Como resultado, o número de vetores em cada partição varia com o tempo, o que pode afetar o recall, o QPS ou ambos.
Se você encontrar problemas de lentidão ou precisão, como QPS baixo ou recall ruim, nas suas consultas de pesquisa de ANN ao longo do tempo, revise essas métricas. Um número alto de mutações em relação ao número total de vetores pode indicar a necessidade de reindexação.
Distribuição
A métrica distribution mostra as distribuições de vetores em todas as partições.
Quando você cria um índice, ele é criado com um número específico de vetores e partições fixas. O processo de particionamento e a distribuição subsequente ocorrem com base nessa consideração. Se outros vetores forem adicionados, eles serão particionados entre as partições atuais, resultando em uma distribuição diferente em comparação com a distribuição quando o índice foi criado. Como a distribuição final não considera todos os vetores simultaneamente, o recall, o QPS ou ambos podem ser afetados.
Se você notar um declínio gradual na performance das suas consultas de pesquisa de rede neural artificial, como tempos de resposta mais lentos ou redução na acurácia dos resultados (medida por QPS ou recall), verifique essa métrica e faça a reindexação.