Cómo consultar tu base de datos con lenguaje natural

En esta página, se describe una versión preliminar disponible con AlloyDB Omni que te permite experimentar con la consulta de tu base de datos con lenguaje natural.

Descripción general

Puedes usar AlloyDB Omni para obtener una vista previa de un conjunto de funciones experimentales que permiten que tu aplicación basada en la base de datos ejecute consultas en lenguaje natural de forma más segura desde los usuarios de tu aplicación, como "¿Dónde está mi paquete?" o "¿Quién es el que más gana en cada departamento?". AlloyDB Omni traduce la entrada de lenguaje natural en una consulta en SQL específica de tu base de datos, lo que restringe los resultados solo a lo que el usuario de tu aplicación puede ver.

La potencia y los riesgos de las consultas de lenguaje natural

Los modelos de lenguaje grandes, como Gemini Pro, pueden permitir que tu aplicación ejecute consultas a la base de datos basadas en consultas de lenguaje natural que crean los usuarios finales de tu aplicación. Por ejemplo, un modelo con acceso al esquema de la base de datos de tu aplicación puede aceptar entradas del usuario final de la siguiente manera:

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

Y transfórmala en una consulta en SQL como esta:

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

Las consultas en lenguaje natural pueden proporcionarle a tu aplicación una herramienta potente para servir a tus usuarios. Sin embargo, esta tecnología también conlleva riesgos de seguridad claros que debes tener en cuenta antes de permitir que los usuarios finales ejecuten consultas arbitrarias en las tablas de tu base de datos. Incluso si configuraste tu aplicación para que se conecte a tu base de datos como un usuario de base de datos de solo lectura con acceso limitado, una aplicación que invite a consultas en lenguaje natural puede ser vulnerable a lo siguiente:

  • Los usuarios maliciosos pueden enviar ataques de inserción de instrucciones para intentar manipular el modelo subyacente y revelar todos los datos a los que tiene acceso la aplicación.
  • El modelo en sí podría generar consultas de SQL más amplias de lo que es apropiado, lo que revelaría datos sensibles en respuesta incluso a consultas de usuarios bien intencionadas.

Cómo limpiar consultas con vistas seguras parametrizadas

Para ayudar a mitigar los riesgos descritos en la sección anterior, Google desarrolló vistas seguras parametrizadas, una función experimental que puedes obtener como versión preliminar con las técnicas que se describen en esta página.

Las vistas seguras parametrizadas te permiten definir de forma explícita las tablas y columnas de las que las consultas de lenguaje natural pueden extraer datos y agregar restricciones adicionales al rango de filas disponibles para un usuario de la aplicación individual. Estas restricciones te permiten controlar de forma estricta los datos que los usuarios de tu aplicación pueden ver a través de búsquedas en lenguaje natural, sin importar cómo formulen estas búsquedas.

Si habilitas esta vista previa, obtendrás acceso a extensiones experimentales desarrolladas por Google llamadas alloydb_ai_nl y parameterized_views.

La extensión parameterized_views proporciona las siguientes funciones:

  • Vistas seguras parametrizadas, una variante de las vistas de SQL para restringir el rango de datos a los que puede acceder una consulta
  • La función execute_parameterized_views(), que te permite consultar tus vistas seguras parametrizadas

La extensión alloydb_ai_nl proporciona la siguiente función:

  • La función google_get_sql_current_schema(), que convierte las consultas de lenguaje natural en consultas de SQL de tablas y vistas en tu esquema actual.

En las siguientes secciones, se describe cómo usar estas funciones y se muestra cómo pueden funcionar en conjunto.

Antes de comenzar

Instala AlloyDB Omni versión 15.5.1 o una posterior, incluida la integración de modelos de IA. Para obtener más información, consulta Cómo instalar AlloyDB Omni con la IA de AlloyDB para PostgreSQL.

Configura tu base de datos para vistas seguras parametrizadas

  1. Conéctate a tu clúster de AlloyDB Omni con psql.

  2. Edita el contenido de /var/alloydb/config/postgresql.conf para que el valor de la directiva shared_preload_libraries incluya alloydb_ai_nl y parameterized_views. La directiva editada debería ser similar a la siguiente:

    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. Detén AlloyDB Omni.

  4. Inicia AlloyDB Omni.

  5. Habilita las extensiones alloydb_ai_nl y 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. Registra un nuevo modelo de lenguaje basado en la API de Gemini Pro con la administración de extremos de modelos:

    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');
    

    Reemplaza lo siguiente:

  7. Crea un usuario de base de datos nuevo. Aún no le otorgues ningún permiso ni rol. Un paso posterior de este procedimiento le otorga al usuario los permisos que requiere.

Vistas seguras parametrizadas

Una vista segura parametrizada funciona de manera muy similar a una vista segura de PostgreSQL normal: es una sentencia SELECT almacenada, en esencia. Además, las vistas seguras parametrizadas te permiten exigir uno o más valores de parámetros nombrados que se pasan a la vista cuando la consultas, algo similar a las variables de vinculación con consultas de bases de datos ordinarias.

Por ejemplo, imagina que ejecutas una aplicación cuya base de datos realiza un seguimiento de los envíos de artículos a los clientes. Un usuario accedió a esta aplicación con el ID de tipos 12345 en la consulta Where is my package?. Con las vistas seguras parametrizadas, puedes asegurarte de que se apliquen los siguientes requisitos a la forma en que AlloyDB para PostgreSQL ejecuta esta consulta:

  • La consulta solo puede leer las columnas de la base de datos que enumeraste de forma explícita en las vistas seguras parametrizadas de tu base de datos. En este caso, podrían ser ciertas columnas de tus tablas items, users y shipments.
  • La consulta solo puede leer las filas de la base de datos asociadas con el usuario que realizó la consulta. En este caso, es posible que las filas que se devuelven tengan una relación de datos con la fila de la tabla users cuyo valor de la columna id sea 12345.

Crea una vista segura parametrizada

Para crear una vista segura parametrizada, usa el comando DDL CREATE VIEW de PostgreSQL con los siguientes atributos:

  • Crea la vista con la opción security_barrier.
  • Para restringir a los usuarios de la aplicación a ver solo las filas que tienen permitido ver, agrega los parámetros obligatorios con la sintaxis $@PARAMETER_NAME en la cláusula WHERE. Un caso común es verificar el valor de una columna con WHERE COLUMN = $@PARAMETER_NAME.

En el siguiente ejemplo, la vista segura parametrizada permite el acceso a tres columnas de una tabla llamada users y limita los resultados solo a las filas en las que users.id coincide con un parámetro obligatorio:

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

Las instrucciones SELECT en el centro de las vistas seguras parametrizadas pueden ser tan complejas como las instrucciones permitidas por las vistas ordinarias de PostgreSQL.

Después de crear una vista, debes otorgarle al usuario que creaste antes permiso para ejecutar consultas SELECT en la vista:

GRANT SELECT ON VIEW_NAME TO NL_DB_USER;

Reemplaza lo siguiente:

  • VIEW_NAME: Es el nombre de la vista que creaste en el paso anterior.
  • NL_DB_USER: Es el nombre del usuario de la base de datos que designaste para ejecutar consultas de lenguaje natural.

Cómo consultar una vista segura parametrizada

A pesar de su similitud con las vistas normales de PostgreSQL, no puedes consultar las vistas seguras parametrizadas directamente. En su lugar, usa la función execute_parameterized_query() que proporciona la extensión parameterized_views. La función tiene la siguiente sintaxis:

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

Reemplaza lo siguiente:

  • SQL_QUERY: Es una consulta en SQL cuya cláusula FROM hace referencia a una o más vistas seguras parametrizadas.
  • PARAMETER_NAMES: Es una lista de nombres de parámetros que se pasarán como cadenas.
  • PARAMETER_VALUES: Es una lista de valores de parámetros que se pasarán. Esta lista debe tener el mismo tamaño que la lista param_names. El orden de los valores coincide con el orden de los nombres.

La función muestra una tabla de objetos JSON. Cada fila de la tabla es equivalente al valor row_to_json() de la fila del resultado de la consulta original.

En el uso típico, el valor del argumento query no lo genera tu propio código, sino un modelo de IA con el que integraste tu base de datos de AlloyDB para PostgreSQL.

En el siguiente ejemplo, se muestra cómo puedes consultar una vista segura parametrizada en Python y, luego, mostrar sus resultados. Se basa en la vista de ejemplo de user_psv de la sección 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))

Ejecuta una consulta en lenguaje natural

Ejecutar una consulta en lenguaje natural con vistas seguras parametrizadas es un proceso de dos pasos:

  1. Como usuario de la base de datos con solo acceso SELECT a las vistas seguras parametrizadas adecuadas, convierte la consulta de lenguaje natural a SQL con un modelo de lenguaje extenso.
  2. Usa la función execute_parameterized_query() para procesar la SQL y vincularla a los valores de parámetros adecuados para la sesión del usuario actual.

En las siguientes secciones, se describen estos pasos con más detalle.

Convierte lenguaje natural a SQL

Para traducir la entrada de lenguaje natural a SQL, usa la función google_get_sql_current_schema() que se incluye con la vista previa de la tecnología de vistas seguras parametrizadas:

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

Reemplaza lo siguiente:

  • NL_TEXT: Es el texto en lenguaje natural que se convertirá en una consulta en SQL.
  • MODEL_ID: Es el ID del modelo que registraste en el catálogo de modelos cuando configuraste tu base de datos para vistas seguras parametrizadas.
  • HINT_TEXT: Información adicional sobre el esquema de la base de datos, expresada en lenguaje natural. Esto te permite darle al modelo sugerencias adicionales sobre aspectos importantes del esquema que podría no extraer solo con el análisis de la tabla, la columna y las estructuras de relación. A continuación, se muestra un ejemplo: When joining flights and seats, be sure to join on flights.id = seats.flight_id.

El resultado de la función es una cadena que contiene una consulta en SQL.

Ejecuta el SQL convertido con parámetros

Después de convertir la consulta en lenguaje natural a SQL, puedes llamar a execute_parameterized_views() como se describió anteriormente en esta página y pasar los parámetros que puedan necesitar tus vistas seguras parametrizadas.

La función funciona si le pasas más parámetros de los que necesita con una consulta determinada, de modo que puedes llamarla con todos los parámetros que usan todas las vistas seguras parametrizadas para las que tu aplicación tiene valores. La función arroja una excepción si intenta ejecutar una consulta que requiere un parámetro no definido.

Ejemplo de ejecución de una consulta de lenguaje natural

En esta sección, se muestra un flujo completo desde la entrada de lenguaje natural hasta el conjunto de resultados de SQL. En las muestras de código, se muestran las consultas y funciones de SQL subyacentes que ejecuta una aplicación.

Para este flujo de ejemplo, supongamos lo siguiente sobre tu aplicación:

  • Tu aplicación basada en una base de datos realiza un seguimiento de los envíos de productos a los clientes.
  • Registraste un modelo basado en Gemini Pro llamado my-gemini-model en el catálogo de modelos.
  • Definiste una vista segura parametrizada en tu base de datos llamada shipment_view.
    • La vista selecciona datos de varias tablas relevantes para los envíos a los clientes.
    • La vista requiere un parámetro user_id, cuyo valor es el ID de un usuario final de la aplicación.
  1. Un usuario final cuyo ID de usuario de la aplicación es 12345 escribe "¿Dónde está mi paquete?" en tu aplicación web.
  2. Tu aplicación llama a google_get_sql_current_schema() para traducir la entrada a SQL:

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

    Esta llamada muestra una cadena que contiene una sola consulta SELECT de SQL. La consulta se limita solo a las vistas seguras parametrizadas que puede ver el usuario de la base de datos que creaste para trabajar con vistas seguras parametrizadas.

    El SQL generado a partir de Where is my package? podría ser similar al siguiente:

    SELECT current_location, ship_date, ship_eta FROM shipment_view;
    

    Debido a que shipment_view es una vista segura parametrizada y no una vista de PostgreSQL ordinaria, tu aplicación debe usar execute_parameterized_views() para ejecutar de forma segura la consulta con el parámetro user_id que requiere, como se muestra en el siguiente paso.

  3. Tu aplicación pasa la SQL a execute_parameterized_views(), junto con los parámetros que restringen el resultado. En nuestro ejemplo, ese es el ID del usuario final de la aplicación que proporcionó la 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']
    );
    
    

    El resultado es un conjunto de resultados de SQL, expresado como datos JSON.

  4. Tu aplicación controla los datos JSON según sea necesario.

Diseño de bases de datos para el manejo de lenguaje natural

La función google_get_sql_current_schema() proporcionada con esta vista previa de la tecnología sirve principalmente para demostrar la funcionalidad de las vistas seguras parametrizadas, lo que te brinda una oportunidad anticipada de experimentar con esta tecnología en desarrollo. Al igual que con cualquier versión preliminar, no debes aplicar esta función a una aplicación en producción.

Con eso en mente, puedes aplicar los consejos de esta sección para mejorar la calidad del resultado de google_get_sql_current_schema() durante tu experimentación con él.

Diseña tu esquema para la comprensión humana

En general, asigna nombres y comentarios a las estructuras de tu base de datos lo suficientemente claros como para permitir que un desarrollador humano típico infiera el propósito de sus tablas, columnas y relaciones. Esta claridad puede ayudar a que un modelo de lenguaje grande genere consultas SQL más precisas según tu esquema.

Usa nombres descriptivos

Usa nombres descriptivos para las tablas, las columnas y las relaciones. Evita abreviaturas o siglas. Por ejemplo, el modelo funciona mejor con una tabla llamada users que con una llamada u.

Si no es posible cambiar el nombre de las estructuras de datos existentes, proporciona sugerencias al modelo con el argumento prompt_text cuando llames a google_get_sql_current_schema().

Usa tipos de datos específicos

El modelo puede hacer mejores inferencias sobre tus datos si usas tipos de datos más específicos con tus columnas. Por ejemplo, si usas una columna exclusivamente para almacenar valores de verdadero o falso, usa un tipo de datos boolean con true y false en lugar de un integer con 1 y 0.

Revierte con precaución después de habilitar la vista previa

Si habilitaste la vista previa de la tecnología de vistas seguras parametrizadas en tu base de datos, pero luego decides revertir AlloyDB Omni a una versión anterior a la 15.5.0, debes seguir algunos pasos de limpieza manuales antes de realizar la reversión.

Si no sigues estos pasos, cualquier intento de consultar, modificar o descartar una vista segura parametrizada generará un error de SQL. Esto incluye las consultas en el catálogo de vistas de tu base de datos que, de otro modo, incluirían vistas seguras parametrizadas en sus resultados, como SELECT * FROM pg_views.

Para quitar por completo esta versión preliminar de la tecnología de tu base de datos antes de una rollback de AlloyDB Omni, sigue estos pasos:

  1. En psql, usa el comando DROP VIEW para borrar todas las vistas seguras parametrizadas de tu base de datos.

  2. En psql, usa el comando DROP EXTENSION para inhabilitar las extensiones alloydb_ai_nl y parameterized_views en tu base de datos.

  3. En tu archivo postgresql.conf, quita la referencia a alloydb_ai_nl y parameterized_views de la directiva shared_preload_libraries.

Para obtener más información sobre cómo revertir la instalación de AlloyDB Omni, consulta Cómo revertir una actualización.