Générer des requêtes SQL à l'aide de questions en langage naturel

Cette page explique comment configurer et générer des instructions SQL à l'aide du langage naturel AlloyDB/AI. Le langage naturel vous permet de créer des applications d'IA générative destinées aux utilisateurs à l'aide du langage naturel pour interroger des bases de données.

Pour activer l'extension alloydb_ai_nl, qui est l'API AlloyDB pour PostgreSQL de prise en charge du langage naturel, vous devez suivre les étapes générales suivantes :

  1. Installez l'extension alloydb_ai_nl.
  2. Définissez une configuration en langage naturel pour votre application.
  3. Enregistrez un schéma.
  4. Ajoutez du contexte.
  5. Ajoutez des modèles de requête.
  6. Définissez les types de concepts et créez un index de valeurs.
  7. Générez des instructions SQL à l'aide d'une interface en langage naturel.

Avant de commencer

  • Demandez l'accès au langage naturel AlloyDB/AI et attendez de recevoir la confirmation d'activation avant de suivre les instructions de cette page.
  • Découvrez comment vous connecter à la base de données AlloyDB et exécuter des commandes PostgreSQL. Pour en savoir plus, consultez la présentation des connexions.
  • Remplissez la base de données avec les données et le schéma auxquels l'utilisateur final souhaite accéder.

Créer un cluster et activer l'intégration à Vertex AI

  1. Créez un cluster et une instance AlloyDB. Vous utilisez l'instance AlloyDB pour créer la base de données et le schéma de l'application.
  2. Activez l'intégration à Vertex AI. Pour en savoir plus, consultez Intégrer à Vertex AI.

Rôles requis

Pour installer l'extension alloydb_ai_nl et accorder l'accès à d'autres utilisateurs, vous devez disposer du rôle IAM (Identity and Access Management) suivant dans le projet Google Cloud que vous utilisez :

Pour en savoir plus, consultez Gérer les utilisateurs PostgreSQL avec l'authentification intégrée.

Préparer votre environnement

Pour préparer la génération de requêtes en langage naturel, vous devez installer l'extension requise, créer une configuration et enregistrer un schéma.

Installer l'extension alloydb_nl_ai

L'extension alloydb_ai_nl utilise l'extension google_ml_integration, qui interagit avec les grands modèles de langage (LLM), y compris les modèles Gemini sur Vertex AI.

Pour installer l'extension alloydb_ai_nl, connectez-vous à la base de données et exécutez la commande suivante :

CREATE EXTENSION alloydb_ai_nl cascade;

Créer une configuration en langage naturel et enregistrer un schéma

Le langage naturel AlloyDB AI utilise nl_config pour associer des applications à certains schémas, modèles de requête et points de terminaison de modèle. nl_config est une configuration qui associe une application à des schémas, des modèles et d'autres contextes. Une grande application peut également utiliser différentes configurations pour différentes parties de l'application, à condition que vous spécifiiez la bonne configuration lorsqu'une question est envoyée à partir de cette partie de l'application. Vous pouvez enregistrer un schéma entier ou des objets de schéma spécifiques, comme des tables, des vues et des colonnes.

  1. Pour créer une configuration en langage naturel, utilisez l'exemple suivant :

    SELECT
      alloydb_ai_nl.g_create_configuration(
        'my_app_config'        -- configuration_id
      );
    

    gemini-2.0-flash:generateContent est le point de terminaison du modèle.

  2. Pour enregistrer un schéma pour une configuration spécifique, utilisez l'exemple suivant :

    SELECT
      alloydb_ai_nl.g_manage_configuration(
        operation => 'register_schema',
        configuration_id_in => 'my_app_config',
        schema_names_in => '{my_schema}'
      );
    

Ajouter le contexte

Le contexte inclut tout type d'informations que vous pouvez utiliser pour répondre à une question d'utilisateur final. Le contexte inclut la structure et les relations du schéma, les résumés et les descriptions des colonnes, les valeurs des colonnes et leur sémantique, ainsi que les règles ou les instructions de logique métier spécifiques à l'application ou au domaine.

Ajouter un contexte général pour les règles spécifiques aux applications

Les éléments de contexte général incluent les règles spécifiques à l'application, les instructions de logique métier ou toute terminologie spécifique à l'application et au domaine qui n'est pas liée à un objet de schéma spécifique.

Pour ajouter un contexte général aux règles spécifiques à une application et à la terminologie spécifique à une application ou à un domaine, procédez comme suit :

  1. Pour ajouter un élément de contexte général à la configuration spécifiée, utilisez l'exemple suivant :

    SELECT
      alloydb_ai_nl.g_manage_configuration(
        'add_general_context',
        'my_app_config',
        general_context_in => '{"If the user asks for a good seat, assume that means a window or aisle seat."}'
      );
    

    L'instruction précédente aide le langage naturel AlloyDB/AI à fournir des réponses de meilleure qualité aux questions en langage naturel des utilisateurs.

  2. Pour afficher les contextes généraux de la configuration spécifiée, exécutez l'instruction suivante :

    SELECT alloydb_ai_nl.list_general_context(nl_config TEXT);
    

Générer et examiner le contexte du schéma

Le contexte de schéma décrit les objets de schéma, y compris les tables, les vues, les vues matérialisées et les colonnes. Ce contexte est stocké en tant que COMMENT de chaque objet de schéma.

  1. Pour générer des contextes pour les objets de schéma, appelez les API suivantes. Pour obtenir des résultats optimaux, assurez-vous que les tables de la base de données contiennent des données représentatives.

    -- For all schema objects (tables, views, materialized views and columns)
    -- within the scope of a provided nl_config.
    SELECT
      alloydb_ai_nl.generate_schema_context(
        'my_app_config' -- nl_config
      );
    
  2. Examinez les contextes de schéma générés en exécutant l'instruction suivante :

    SELECT schema_object, object_context
    FROM alloydb_ai_nl.generated_schema_context_view;
    

    Les contextes de schéma générés sont stockés dans la vue précédente.

  3. Facultatif : Pour mettre à jour les contextes de schéma générés, exécutez l'instruction suivante :

    SELECT
      alloydb_ai_nl.update_generated_relation_context(
        'my_schema.my_table',
        'This table contains archival records, if you need latest records use records_new table.'
      );
    
    SELECT
      alloydb_ai_nl.update_generated_column_context(
        'my_schema.my_table.column1',
        'The seat_class column takes single letters like "E" for economy, "P" for premium economy, "B" for business and "F" for First.'
      );
    
  4. Appliquez le contexte. Lorsque vous appliquez le contexte, il prend effet immédiatement et est supprimé de generated_schema_context_view. Exécutez la commande suivante :

    -- For all schema objects (tables, views, materialized views and columns)
    -- within the scope of nl_config.
    SELECT
      alloydb_ai_nl.apply_generated_schema_context(
        'my_app_config' --nl_config
      );
    
  5. Facultatif : vérifiez le contexte généré. L'API suivante vous permet de vérifier les contextes de schéma, qui sont utilisés lorsque vous générez des instructions SQL :

    -- For table, view or materialized view.
    SELECT
      alloydb_ai_nl.get_relation_context(
        'my_schema.my_table'
      );
    
    -- For column.
    SELECT
      alloydb_ai_nl.get_column_context(
        'my_schema.my_table.column1'
      );
    
  6. Facultatif : pour définir manuellement le contexte du schéma, exécutez l'instruction suivante :

    -- For table, view or materialized view.
    SELECT
      alloydb_ai_nl.set_relation_context(
        'my_schema.my_table',
        'One-to-many mapping from product to categories'
      );
    
    -- For column.
    SELECT
      alloydb_ai_nl.set_column_context(
        'my_schema.my_table.column1',
        'This column provides additional tagged info for the product in  Json format, e.g., additional color or size information of the product - tags: { "color": "red", "size": "XL"}'
      );
    

Créer des modèles de requêtes

Pour améliorer la qualité des applications d'IA générative conçues avec des LLM, vous pouvez ajouter des modèles. Un modèle de requête est un ensemble organisé de questions représentatives ou courantes en langage naturel, avec les requêtes SQL correspondantes, ainsi que des explications pour fournir une justification déclarative de la génération du langage naturel vers SQL (NL2SQL). Les modèles sont principalement destinés à être spécifiés par l'application, mais ils peuvent également être générés automatiquement par l'extension alloydb_ai_nl en fonction des requêtes SQL fréquemment utilisées. Chaque modèle doit être associé à un nl_config.

L'extension alloydb_ai_nl utilise un template_store pour incorporer dynamiquement des modèles SQL pertinents dans le processus de génération d'une instruction SQL permettant de répondre à la question de l'utilisateur. template_store identifie les modèles dont les intentions sont similaires à la question en langage naturel posée, identifie l'instruction SQL paramétrée correspondante et synthétise une instruction SQL en instanciant les paramètres avec les valeurs de la question en langage naturel. Toutefois, s'il n'existe pas de modèle ayant la même intention que la question posée par l'utilisateur, alloydb_ai_nl utilise tous les modèles et contextes pertinents pour composer une instruction SQL.

Pour ajouter des modèles, vous devez spécifier la question à l'aide d'un paramètre nommé intent et la requête SQL.

Pour ajouter un modèle au magasin de modèles, exécutez l'instruction suivante :

SELECT
  alloydb_ai_nl.add_template(
    nl_config => 'my_app_config',
    intent => 'How many accounts associated with loans are located in the Prague region?',
    sql => 'SELECT COUNT(T1.account_id)
            FROM bird_dev_financial.account AS T1
            INNER JOIN bird_dev_financial.loan AS T2
              ON T1.account_id = T2.account_id
            INNER JOIN bird_dev_financial.district AS T3
              ON T1.district_id = T3.district_id
            WHERE T3."A3" = ''Prague''',
    check_intent => TRUE
  );

Lorsque check_intent est défini sur TRUE, alloydb_ai_nl effectue une vérification sémantique pour confirmer que l'intention fournie correspond à l'instruction SQL transmise. Si l'intention ne correspond pas à l'instruction SQL, le modèle n'est pas ajouté.

Générer automatiquement des modèles

Une fois que vous disposez d'un ensemble de données représentatif dans vos tables, nous vous recommandons d'exécuter des requêtes SQL correspondant aux questions courantes que vos utilisateurs finaux sont susceptibles de poser. Il est important de vous assurer que les requêtes disposent de bons plans de requête et qu'elles sont performantes.

Après l'exécution des requêtes, le langage naturel AlloyDB/AI peut générer automatiquement des modèles en fonction de l'historique des requêtes. Vous pouvez appeler les API suivantes pour générer des modèles. Vous devez examiner et appliquer les modèles générés avant qu'ils ne prennent effet.

La génération automatique de modèles est basée sur les requêtes les plus fréquemment utilisées dans le journal des requêtes, google_db_advisor_workload_statements. Les requêtes sont filtrées en fonction des critères suivants :

  • Instructions SELECT
  • Exécutables : la commande EXPLAIN traite correctement la requête.
  • Aucun doublon : la requête n'a pas été utilisée précédemment pour générer des modèles.
  • Toutes les tables et vues référencées sont dans le champ d'application de nl_config.

Pour générer, examiner et appliquer automatiquement des modèles, procédez comme suit :

  1. Demandez à AlloyDB de générer des modèles en fonction de votre historique de requêtes :

    SELECT
      alloydb_ai_nl.generate_templates(
        'my_app_config',
    );
    

    Utilisez la vue fournie, alloydb_ai_nl.generated_templates_view, pour examiner le generated_templates.

    Le résultat suivant indique le nombre de modèles générés :

    -[ RECORD 1 ]------+--
    generate_templates | 1
    
  2. Examinez les modèles générés à l'aide de la vue generated_templates_view.

    SELECT *
    FROM alloydb_ai_nl.generated_templates_view;
    

    Voici un exemple de résultat renvoyé :

    -[ RECORD 1 ]----------------------------------------------------------------
    id          | 1
    config      | my_app_config
    type        | Template
    manifest    | How many clients have a birth year of a given number?
    nl          | How many clients have a birth year of 1997?
    sql         | select count(*) from public.client as T where
                 to_char(T.birth_date::timestamp, 'YYYY') = '1997';
    intent      | How many clients have a birth year of 1997?
    psql        | select count(*) from public.client as T where
                 to_char(T.birth_date::timestamp, 'YYYY') = $1;
    pintent     | How many clients have a birth year of $1?
    comment     |
    explanation |
    weight      | 1
    

    Le manifest dans le résultat renvoyé est un modèle général ou une description générale du type de question ou de l'opération qui peut être effectuée. pintent est une version paramétrée de intent. Elle généralise intent en remplaçant la valeur spécifique (1997) par un espace réservé ($1).

  3. Pour mettre à jour un modèle généré, exécutez l'exemple d'instruction suivant :

    SELECT alloydb_ai_nl.update_generated_template(
      id => 1,
      manifest => 'How many clients are born in a given year?',
      nl => 'How many clients are born in 1997?',
      intent => 'How many clients are born in 1997?',
      pintent => 'How many clients are born in $1?'
    
    );
    
  4. Appliquez les modèles. Les modèles que vous appliquez sont immédiatement ajoutés à la bibliothèque de modèles et supprimés de la vue "Examen".

    -- For all templates generated under the nl config.
    SELECT
      alloydb_ai_nl.apply_generated_templates('my_app_config');
    

Configurer la sécurité pour le langage naturel

Pour configurer la sécurité du langage naturel AlloyDB/AI, consultez Gérer la sécurité des applications de données à l'aide de vues sécurisées paramétrées.

Définir les types de concepts et l'index de valeurs

Vous définissez des types de concepts et des index de valeurs pour mieux comprendre les questions posées. Un type de concept est une catégorie ou une classe d'entités qui identifie la signification sémantique des mots et des expressions plutôt que leur forme littérale.

Par exemple, deux noms de pays peuvent être identiques même si l'un est en majuscules (USA) et l'autre en minuscules (usa). Dans ce cas, le nom du pays est le type de concept. Les noms de personnes, les noms de villes et les dates sont d'autres exemples de types de concepts.

Un index de valeurs est un index basé sur les valeurs des colonnes qui font partie de la configuration en langage naturel nl_config, en fonction des types de concepts associés à chaque colonne. Un index de valeurs permet de faire correspondre efficacement les expressions de valeurs pour la question posée et les valeurs de la base de données.

Pour définir des types de concepts et un index de valeurs, suivez les étapes ci-dessous en utilisant les exemples fournis. Les exemples associent une colonne à un type de concept, créent et actualisent un index de valeurs, et utilisent un ensemble de synonymes pour effectuer une recherche de valeurs.

  1. Pour associer une colonne à un type de concept, exécutez la requête suivante :

    SELECT
      alloydb_ai_nl.associate_concept_type(
        column_names_in => 'my_schema.country.country_name',
        concept_type_in => 'country_name',
        nl_config_id_in => 'my_app_config'
      );
    
  2. Pour créer un index de valeurs basé sur toutes les colonnes qui font partie d'une configuration en langage naturel et qui sont associées à un type de concept, exécutez l'instruction suivante :

    SELECT
      alloydb_ai_nl.create_value_index(
        nl_config_id_in => 'my_app_config'
      );
    
  3. Lorsque vous associez des types de concepts à de nouvelles colonnes, actualisez l'index des valeurs pour refléter les modifications. Utilisez l'instruction suivante :

    SELECT
      alloydb_ai_nl.refresh_value_index(
        nl_config_id_in => 'my_app_config'
      );
    
  4. Pour permettre à AlloyDB/AI en langage naturel de faire correspondre les synonymes d'une valeur, exécutez l'exemple d'instruction suivant :

    SELECT
      alloydb_ai_nl.insert_synonym_set(
        ARRAY [
          'USA',
          'US',
          'United States',
          'United States of America'
        ]
      );
    

    Bien que les données de vos tableaux puissent utiliser une valeur spécifique (par exemple, si United States est utilisé pour identifier un pays), vous pouvez définir un ensemble de synonymes contenant tous les synonymes de United States. Si l'un des synonymes apparaît dans la question en langage naturel, AlloyDB AI fait correspondre les synonymes aux valeurs de vos tables.

  5. Effectuez une recherche de valeurs pour trouver les valeurs de base de données correctes, en fonction d'un tableau d'expressions de valeurs, à l'aide de l'instruction suivante :

    SELECT
      alloydb_ai_nl.get_concept_and_value(
        value_phrases_in => ARRAY['United States'],
        nl_config_id_in  => 'my_app_config'
      );
    

    Par exemple, si un utilisateur pose une question comme "Quelle est la population des États-Unis ?" qui utilise la requête get_sql suivante, le langage naturel AlloyDB/AI utilise la fonction get_concept_and_value avec l'expression de valeur United States pour effectuer une recherche approximative par rapport aux index de valeurs. La recherche approximative est une technique de recherche qui trouve des correspondances même lorsque la requête de recherche ne correspond pas exactement aux données correspondantes.

    Le langage naturel trouve un résultat (la valeur USA) proche de la requête de recherche et l'utilise pour générer la requête SQL.

    SELECT
      alloydb_ai_nl.get_sql(
        nl_config_id    => 'my_app_config',
        nl_question     => 'What is the population of the United States?',
        additional_info => json_build_object('enrich_nl_question', TRUE)
      ) ->> 'sql';
    

    Le tableau suivant liste les types de concepts intégrés définis par le langage naturel AlloyDB/AI :

    Nom du concept Description
    generic_entity_name Une seule colonne de type chaîne peut être utilisée pour un nom d'entité générique. Exemple :
      SELECT alloydb_ai_nl.associate_concept_type('public.item.item_name', 'generic_entity_name')
      
    country_name, city_name, region_name Noms de pays, de villes et de régions. L'utilisation est exactement la même que pour le type de concept generic_entity_name.
    full_person_name Nom de la personne, composé du prénom, du nom de famille et du deuxième prénom. Vous pouvez utiliser jusqu'à trois colonnes de type chaîne pour le nom complet d'une personne. Vous pouvez ignorer n'importe quelle colonne lorsque vous associez des colonnes de nom à full_person_name. Par exemple :
      SELECT alloydb_ai_nl.associate_concept_type('public.person.last_name,public.person.first_name,public.person.middle_name','full_person_name')
      
    ssn Colonne de chaîne unique contenant un numéro de sécurité sociale. Exemple :
      SELECT alloydb_ai_nl.associate_concept_type('public.person.ssn','ssn')
     
    date Une date ou un code temporel. Exemple :
     SELECT alloydb_ai_nl.associate_concept_type('public.person.date_col','date')
     

Générer des instructions SQL à partir de saisies en langage naturel

Vous pouvez utiliser le langage naturel AlloyDB AI pour générer des instructions SQL à partir d'entrées en langage naturel. Lorsque vous exécutez l'instruction SQL générée, elle fournit les données de la base de données dont vous avez besoin pour répondre à la question en langage naturel.

  1. Pour utiliser le langage naturel afin d'obtenir des résultats à partir de votre base de données à l'aide de la fonction alloydb_ai_nl.get_sql, utilisez l'exemple suivant :

    SELECT
      alloydb_ai_nl.get_sql(
        'my_app_config', -- nl_config
        'What is the sum that client number 4''s account has following transaction 851?' -- nl question
      );
    

    Le résultat JSON suivant s'affiche :

    {
      "sql": "SELECT T3.balance FROM public.client AS T1 INNER JOIN public.account AS T2 ON T1.district_id = T2.district_id INNER JOIN public.trans AS T3 ON T2.account_id = T3.account_id WHERE T1.client_id = 4 AND T3.trans_id = 851",
      "prompt": "",
      "retries": 0,
      "error_msg": "",
      "nl_question": "What is the sum that client number 4's account has following transaction 851?"
    }
    
  2. Facultatif : Pour extraire la requête SQL générée sous forme de chaîne de texte, ajoutez ->>'sql' :

    SELECT
      alloydb_ai_nl.get_sql(
        'my_app_config', -- nl_config
        'What is the sum that client number 4''s account has following transaction 851?' -- nl question
      ) ->> 'sql';
    

    L'opérateur ->> permet d'extraire une valeur JSON sous forme de texte. La fonction alloydb_ai_nl.get_sql renvoie un objet JSON, qui est la partie de l'instruction qui récupère la valeur associée à la clé sql. Cette valeur correspond à la requête SQL générée.

Tester et affiner

Pour obtenir des requêtes autogénérées améliorées, modifiez ou ajoutez un meilleur contexte, des modèles de requêtes et des index de valeurs, puis itérez jusqu'à obtenir les résultats souhaités.

Étapes suivantes