Consultar o banco de dados usando linguagem natural

Esta página descreve uma prévia disponível com o AlloyDB Omni que permite testar consultas no seu banco de dados usando linguagem natural.

Visão geral

Você pode usar o AlloyDB Omni para conferir um conjunto de recursos experimentais que permitem que seu aplicativo baseado em banco de dados execute consultas de linguagem natural dos usuários do aplicativo com mais segurança, como "Onde está meu pacote?" ou "Quem é o maior ganhador em cada departamento?". O AlloyDB Omni traduz a entrada de linguagem natural em uma consulta SQL específica do seu banco de dados, restringindo os resultados apenas ao que o usuário do seu aplicativo tem permissão para visualizar.

Os benefícios e riscos das consultas em linguagem natural

Modelos de linguagem grandes, como o Gemini Pro, podem permitir que seu aplicativo execute consultas de banco de dados com base em consultas de linguagem natural criadas pelos usuários finais do aplicativo. Por exemplo, um modelo com acesso ao esquema de banco de dados do aplicativo pode receber a entrada do usuário final desta forma:

What are the cheapest direct flights from Boston to Denver in July?

E converta em uma consulta SQL assim:

SELECT flight.id, flight.price, carrier.name, [...]
FROM [...]
WHERE [...]
ORDER BY flight.price ASC 
LIMIT 10

As consultas em linguagem natural podem oferecer ao seu aplicativo uma ferramenta poderosa para atender aos usuários. No entanto, essa tecnologia também apresenta riscos de segurança claros que você precisa considerar antes de permitir que os usuários finais executem consultas arbitrárias nas tabelas do banco de dados. Mesmo que você tenha configurado o aplicativo para se conectar ao banco de dados como um usuário de banco de dados de acesso limitado e somente leitura, um aplicativo que convida consultas em linguagem natural pode estar vulnerável a:

  • Usuários mal-intencionados podem enviar ataques de injeção de comandos, tentando manipular o modelo subjacente para revelar todos os dados a que o aplicativo tem acesso.
  • O modelo pode gerar consultas SQL com escopo mais amplo do que o adequado, revelando dados sensíveis em resposta a consultas de usuários mesmo bem-intencionadas.

Limpar consultas com visualizações seguras parametrizadas

Para ajudar a reduzir os riscos descritos na seção anterior, o Google desenvolveu visualizações seguras parametrizadas, um recurso experimental que você pode testar usando as técnicas descritas nesta página.

As visualizações seguras parametrizadas permitem definir explicitamente as tabelas e colunas de onde as consultas de linguagem natural podem extrair dados e adicionar outras restrições ao intervalo de linhas disponível para um usuário individual do aplicativo. Essas restrições permitem controlar com precisão os dados que os usuários do seu aplicativo podem acessar por meio de consultas em linguagem natural, não importa como os usuários formulem essas consultas.

Se você ativar essa prévia, terá acesso a extensões experimentais desenvolvidas pelo Google chamadas alloydb_ai_nl e parameterized_views.

A extensão parameterized_views oferece os seguintes recursos:

  • Visualizações seguras parametrizadas, uma variante das visualizações SQL para restringir o intervalo de dados que uma consulta pode acessar.
  • A função execute_parameterized_views(), que permite consultar suas visualizações seguras com parâmetros.

A extensão alloydb_ai_nl oferece o seguinte recurso:

  • A função google_get_sql_current_schema(), que converte consultas em linguagem natural em consultas SQL de tabelas e visualizações no seu esquema atual.

As seções a seguir descrevem como usar esses recursos e demonstram como eles podem funcionar juntos.

Antes de começar

Instale a versão 15.5.1 ou mais recente do AlloyDB Omni, incluindo a integração do modelo de IA. Para mais informações, consulte Instalar o AlloyDB Omni com o AlloyDB para PostgreSQL AI.

Configurar o banco de dados para visualizações seguras parametrizadas

  1. Conecte-se ao cluster do AlloyDB Omni usando psql.

  2. Edite o conteúdo de /var/alloydb/config/postgresql.conf para que o valor da diretiva shared_preload_libraries inclua alloydb_ai_nl e parameterized_views. A diretiva editada vai ficar mais ou menos assim:

    shared_preload_libraries='g_stats,google_job_scheduler,google_insights,pg_stat_statements,google_db_advisor,google_columnar_engine,alloydb_ai_nl,parameterized_views'
    
  3. Interromper o AlloyDB Omni.

  4. Iniciar o AlloyDB Omni.

  5. Ative as extensões alloydb_ai_nl e parameterized_views:

    CREATE EXTENSION google_ml_integration;
    ALTER SYSTEM SET google_ml_integration.enable_model_support=on;
    ALTER SYSTEM SET alloydb_ai_nl.enabled=on;
    ALTER SYSTEM SET parameterized_views.enabled=on;
    SELECT pg_reload_conf();
    CREATE EXTENSION alloydb_ai_nl CASCADE;
    CREATE EXTENSION parameterized_views;
    
  6. Registre um novo modelo de linguagem com base na API Gemini Pro com o gerenciamento de endpoint do modelo:

    CALL google_ml.create_model(
        model_id => 'MODEL_ID',
        model_request_url => 'https://us-central1-aiplatform.googleapis.com/v1/projects/PROJECT_ID/locations/us-central1/publishers/google/models/gemini-pro:streamGenerateContent',
        model_provider => 'google',
        model_auth_type => 'alloydb_service_agent_iam');
    

    Substitua:

  7. Crie um novo usuário de banco de dados. Não conceda permissões ou papéis a ele ainda. Uma etapa subsequente neste procedimento concede ao usuário as permissões necessárias.

Visualizações seguras parametrizadas

Uma visualização segura parametrizada funciona de maneira muito semelhante a uma visualização segura do PostgreSQL: uma instrução SELECT armazenada, basicamente. As visualizações seguras parametrizadas também permitem que você exija que um ou mais valores de parâmetro nomeados sejam transmitidos para a visualização ao fazer consultas, de forma semelhante às variáveis de vinculação com consultas de banco de dados comuns.

Por exemplo, imagine executar um aplicativo cujo banco de dados rastreia remessas de itens para clientes. Um usuário fez login no aplicativo com o ID dos tipos 12345 na consulta Where is my package?. Usando visualizações seguras parametrizadas, você pode garantir que os requisitos a seguir se apliquem à forma como o AlloyDB para PostgreSQL executa essa consulta:

  • A consulta só pode ler as colunas do banco de dados que você listou explicitamente nas visualizações seguras parametrizadas do banco de dados. Nesse caso, podem ser determinadas colunas nas tabelas items, users e shipments.
  • A consulta só pode ler as linhas do banco de dados associadas ao usuário que fez a consulta. Nesse caso, talvez seja necessário que as linhas retornadas tenham uma relação de dados com a linha da tabela users cujo valor da coluna id é 12345.

Criar uma visualização segura com parâmetros

Para criar uma visualização segura parametrizada, use o comando DDL CREATE VIEW do PostgreSQL com os seguintes atributos:

  • Crie a visualização com a opção security_barrier.
  • Para restringir os usuários do aplicativo a ver apenas as linhas que podem acessar, adicione os parâmetros necessários usando a sintaxe $@PARAMETER_NAME na cláusula WHERE. Um caso comum é verificar o valor de uma coluna usando WHERE COLUMN = $@PARAMETER_NAME.

O exemplo a seguir de visualização segura parametrizada permite o acesso a três colunas de uma tabela chamada users e limita os resultados apenas às linhas em que users.id corresponde a um parâmetro obrigatório:

CREATE VIEW user_psv WITH (security_barrier) AS 
SELECT 
  username,
  full_name,
  birthday
FROM 
  users
WHERE 
  users.id = $@user_id; 

As instruções SELECT no núcleo das visualizações seguras parametrizadas podem ser tão complexas quanto as instruções permitidas pelas visualizações normais do PostgreSQL.

Depois de criar uma visualização, conceda ao usuário criado anteriormente permissão para executar consultas SELECT na visualização:

GRANT SELECT ON VIEW_NAME TO NL_DB_USER;

Substitua:

  • VIEW_NAME: o nome da visualização que você criou na etapa anterior.
  • NL_DB_USER: o nome do usuário do banco de dados que você designou para executar consultas em linguagem natural.

Consultar uma visualização segura parametrizada

Apesar da semelhança com as visualizações comuns do PostgreSQL, não é possível consultar visualizações seguras parametrizadas diretamente. Em vez disso, use a função execute_parameterized_query() fornecida pela extensão parameterized_views. A função tem a seguinte sintaxe:

SELECT * FROM
parameterized_views.execute_parameterized_query(
    query => SQL_QUERY
    param_names => ARRAY [PARAMETER_NAMES],
    param_values => ARRAY [PARAMETER_VALUES]
)

Substitua:

  • SQL_QUERY: uma consulta SQL cuja cláusula FROM se refere a uma ou mais visualizações seguras parametrizadas.
  • PARAMETER_NAMES: uma lista de nomes de parâmetros a serem transmitidos como strings.
  • PARAMETER_VALUES: uma lista de valores de parâmetro a serem transmitidos. Essa lista precisa ter o mesmo tamanho que a lista param_names. A ordem dos valores corresponde à ordem dos nomes.

A função retorna uma tabela de objetos JSON. Cada linha na tabela é equivalente ao valor row_to_json() da linha de resultado da consulta original.

No uso normal, o valor do argumento query não é gerado pelo seu próprio código, mas por um modelo de IA integrado ao banco de dados do AlloyDB para PostgreSQL.

O exemplo a seguir mostra como consultar uma visualização segura parametrizada no Python e mostrar os resultados. Ele se baseia na visualização de exemplo user_psv da seção anterior:

# Assume a get_user_id() function that returns the ID of the current
# application user.
app_user_id = get_user_id()

pool = await asyncpg.create_pool(
    host=INSTANCE_IP
    user=NL_DB_USER
    password=NL_DB_PASSWORD
    database=DB_NAME
)

table_name = "user_psv"

query = f"""
    SELECT 
      full_name,
      birthday
    FROM 
      {table_name} 
"""
params = {
    "user_id": app_user_id
}

param_query = f"""
SELECT * FROM parameterized_views.execute_parameterized_query(
  query => '{query}',
  param_names => $1,
  param_values => $2
);
"""

sql_results = await pool.execute(
    param_query, 
    params.keys(), 
    params.values()
)

for row in sql_results:
    print(json.loads(row))

Executar uma consulta em linguagem natural

A execução de uma consulta em linguagem natural usando visualizações seguras parametrizadas é um processo de duas etapas:

  1. Como usuário do banco de dados com acesso SELECT apenas às visualizações seguras parametrizadas adequadas, converta a consulta de linguagem natural em SQL usando um modelo de linguagem grande.
  2. Use a função execute_parameterized_query() para processar o SQL, vinculando-o a valores de parâmetro adequados à sessão de usuário atual.

As seções a seguir descrevem essas etapas em mais detalhes.

Converter linguagem natural em SQL

Para traduzir a entrada de linguagem natural em SQL, use a função google_get_sql_current_schema() incluída na prévia da tecnologia de visualizações seguras parametrizadas:

SELECT alloydb_ai_nl.google_get_sql_current_schema(
  sql_text => 'NL_TEXT',
  model_id => 'MODEL_ID',
  prompt_text => 'HINT_TEXT'
);

Substitua:

  • NL_TEXT: o texto em linguagem natural a ser transformado em uma consulta SQL.
  • MODEL_ID: o ID do modelo registrado no catálogo de modelos ao configurar o banco de dados para visualizações seguras parametrizadas.
  • HINT_TEXT: informações adicionais sobre o esquema do banco de dados, expressas em linguagem natural. Isso permite que você dê ao modelo outras dicas sobre aspectos importantes do esquema que ele não extrai apenas analisando as estruturas de tabela, coluna e relacionamento. Por exemplo: When joining flights and seats, be sure to join on flights.id = seats.flight_id.

A saída da função é uma string que contém uma consulta SQL.

Executar o SQL convertido usando parâmetros

Depois de converter a consulta de linguagem natural em SQL, você pode chamar execute_parameterized_views(), conforme descrito anteriormente nesta página, transmitindo todos os parâmetros necessários para as visualizações seguras parametrizadas.

A função funciona se você transmitir mais parâmetros do que precisa com uma determinada consulta. Assim, ela pode ser chamada com todos os parâmetros usados por todas as visualizações seguras parametrizadas para as quais o aplicativo tem valores. A função gera uma exceção se tentar executar uma consulta que exige um parâmetro não definido.

Exemplo de execução de uma consulta em linguagem natural

Esta seção demonstra um fluxo completo da entrada de linguagem natural para o conjunto de resultados SQL. Os exemplos de código mostram as consultas e funções SQL subjacentes que um aplicativo executa.

Para este fluxo de exemplo, suponha o seguinte sobre seu aplicativo:

  • Seu aplicativo baseado em banco de dados rastreia os envios de produtos para os clientes.
  • Você registrou um modelo baseado no Gemini Pro chamado my-gemini-model no catálogo de modelos.
  • Você definiu uma visualização segura parametrizada no banco de dados chamada shipment_view.
    • A visualização seleciona dados de várias tabelas relevantes para envios a clientes.
    • A visualização exige um parâmetro user_id, cujo valor é o ID de um usuário final do aplicativo.
  1. Um usuário final cujo ID do usuário do aplicativo é 12345 digita "Onde está meu pacote?" no seu aplicativo da Web.
  2. Seu aplicativo chama google_get_sql_current_schema() para traduzir a entrada em SQL:

    SELECT alloydb_ai_nl.google_get_sql_current_schema(
      sql_text => 'Where is my package?'
      model_id => 'my-gemini-model'
    );
    

    Essa chamada retorna uma string contendo uma única consulta SQL SELECT. A consulta é limitada apenas às visualizações seguras parametrizadas visíveis ao usuário do banco de dados que você criou para trabalhar com visualizações seguras parametrizadas.

    O SQL gerado por Where is my package? pode ser semelhante a este:

    SELECT current_location, ship_date, ship_eta FROM shipment_view;
    

    Como shipment_view é uma visualização segura parametrizada e não uma visualização PostgreSQL comum, seu aplicativo precisa usar execute_parameterized_views() para executar com segurança a consulta com o parâmetro user_id necessário, conforme mostrado na próxima etapa.

  3. Seu aplicativo transmite o SQL para execute_parameterized_views(), com os parâmetros que restringem a saída. No nosso exemplo, esse é o ID do usuário final do aplicativo que forneceu a entrada:

    SELECT * FROM
    parameterized_views.execute_parameterized_views(
        query => 'SELECT current_location, ship_date, ship_eta FROM shipment_view',
        param_names => ['user_id'],
        param_values => ['12345']
    );
    
    

    A saída é um conjunto de resultados SQL, expresso como dados JSON.

  4. O aplicativo processa os dados JSON conforme necessário.

Design de banco de dados para processamento de linguagem natural

A função google_get_sql_current_schema() fornecida com essa visualização de tecnologia serve principalmente para demonstrar a funcionalidade de visualizações seguras parametrizadas, oferecendo a você uma oportunidade antecipada de experimentar essa tecnologia em desenvolvimento. Como em qualquer visualização, não aplique essa função a um aplicativo em produção.

Com isso em mente, você pode aplicar os conselhos desta seção para melhorar a qualidade da saída de google_get_sql_current_schema() durante a experimentação com ela.

Projete seu esquema para compreensão humana

Em geral, dê nomes e comentários claros o suficiente para que um desenvolvedor humano típico possa inferir a finalidade das tabelas, colunas e relações. Essa clareza pode ajudar um modelo de linguagem grande a gerar consultas SQL mais precisas com base no seu esquema.

Usar nomes descritivos

Dê preferência a nomes descritivos para tabelas, colunas e relacionamentos. Evite abreviações ou siglas. Por exemplo, o modelo funciona melhor com uma tabela chamada users do que com uma chamada u.

Se não for possível renomear estruturas de dados existentes, forneça dicas ao modelo usando o argumento prompt_text ao chamar google_get_sql_current_schema().

Usar tipos de dados específicos

O modelo pode fazer inferências melhores sobre seus dados se você usar tipos de dados mais específicos com suas colunas. Por exemplo, se você usa uma coluna exclusivamente para armazenar valores verdadeiros ou falsos, use um tipo de dados boolean com true e false em vez de um integer com 1 e 0.

Reverter com cuidado após ativar a visualização

Se você tiver ativado a visualização da tecnologia de visualizações seguras parametrizadas no seu banco de dados, mas decidir reverter o AlloyDB Omni para uma versão anterior à 15.5.0, será necessário realizar algumas etapas de limpeza manual antes de fazer o downgrade.

Se você não seguir essas etapas, qualquer tentativa de consultar, modificar ou excluir uma visualização segura parametrizada vai resultar em um erro SQL. Isso inclui consultas no catálogo de visualizações do seu banco de dados que incluiriam visualizações seguras parametrizadas nos resultados, como SELECT * FROM pg_views.

Para remover completamente essa tecnologia de teste do seu banco de dados antes de uma reversão do AlloyDB Omni, siga estas etapas:

  1. Em psql, use o comando DROP VIEW para excluir todas as visualizações seguras parametrizadas no seu banco de dados.

  2. Em psql, use o comando DROP EXTENSION para desativar as extensões alloydb_ai_nl e parameterized_views no seu banco de dados.

  3. No arquivo postgresql.conf, remova a referência a alloydb_ai_nl e parameterized_views da diretiva shared_preload_libraries.

Para mais informações sobre como reverter a instalação do AlloyDB Omni, consulte Reverter um upgrade.