Les technologies text-to-SQL ont souvent du mal à capturer le contexte complet et la signification de la demande d'un utilisateur, ce qui entraîne des requêtes qui ne correspondent pas exactement aux prévus. Bien que les développeurs travaillent dur pour améliorer ces systèmes, il vaut la peine de se demander s'il existe une meilleure méthode.
Entrez Rag à SQL - une nouvelle approche qui combine la compréhension du langage naturel avec une puissante récupération de données pour générer des requêtes SQL précises. En mélangeant le meilleur du traitement du langage naturel et de la récupération des informations, Rag-to-SQL offre un moyen plus fiable de transformer le langage quotidien en informations significatives de votre base de données.
Dans cet article, nous explorerons comment Rag to-SQL peut transformer la façon dont nous interagissons avec les bases de données, en particulier en utilisant les services de Google Cloud tels que BigQuery et Vertex AI.
Cet article a été publié dans le cadre du Blogathon de la science des données.
L'idée principale derrière le texte aux modèles SQL de LLM était de permettre aux personnes qui ne connaissent pas SQL d'interagir avec la base de données et d'obtenir des informations en utilisant le langage naturel à la place. Le cadre SQL Text 2 existant repose principalement dans les connaissances LLM pour pouvoir convertir la requête en langage naturel en requête SQL. Cela peut conduire à une formulation erronée ou non valide des requêtes SQL. C'est là que la nouvelle approche Rag to SQL arrive à notre sauvetage qui est expliquée dans la section suivante.
Afin de surmonter les lacunes du texte à SQL, nous pouvons utiliser l'approche innovante de RAG en SQL. L'intégration des informations de domaine sur la base de données est le principal problème auquel chaque logiciel de texte à SQL est confronté. L'architecture RAG2SQL aborde cette difficulté en ajoutant des données contextuelles (métadonnées, DDL, requêtes, etc.). Ces données sont ensuite «formées» et mises à disposition pour l'utilisation.
En outre, le «Retriever» évalue et transmet le contexte le plus pertinent pour répondre à la requête utilisateur. Le résultat final est une précision considérablement améliorée.
Suivez un guide détaillé pour implémenter RAG-TO-SQL à l'aide de services Cloud Google tels que BigQuery et Vertex AI.
Afin de suivre et d'exécuter ce code, vous devrez configurer votre GCP (compte Google Cloud avec des informations de paiement). Initialement, ils offrent un essai gratuit de 300 $ pendant 90 jours, donc aucun frais ne sera engagé. Détail pour la configuration du compte: lien
Vous trouverez ci-dessous l'organigramme de code qui décrit à un niveau supérieur les différents blocs de code. Nous pouvons le référer pour suivre au fur et à mesure que nous procédons.
L'implémentation du code peut être divisée en 3 blocs majeurs:
Dans Colab Notebook, nous devons installer les bibliothèques ci-dessous nécessaires pour cette implémentation.
! pip install Langchain == 0,0,340 --quiet ! pip install chromadb == 0.4.13 --quiet ! PIP install google-cloud-bigquery [pandas] --quiet ! PIP installe Google-Cloud-AiplaTform --quiet # Importer CSV
Maintenant, nous devons déclarer certaines variables pour initialiser notre projet GCP et les ensembles de données de requête GCP. En utilisant ces variables, nous pouvons accéder aux tables en grande requête avec GCP dans notre cahier.
Vous pouvez afficher ces détails dans votre console Cloud GCP. Dans BigQuery, vous pouvez créer un ensemble de données et dans un ensemble de données, vous pouvez ajouter ou télécharger une table pour plus de détails Voir Créer un ensemble de données et créer une table.
Vertex_project = "Votre ID de projet GCP" # @param {type: "String"} Vertex_region = "us-central1" # @param {type: "String"} BigQuery_dataset = "Nom de jeu de données de Big Query" # @param {type: "String"} BigQuery_project = "Vertex Project ID" # @param {type: "String"}
Maintenant, authentifiez et connectez-vous à votre GCP Vertex AI à partir de votre ordinateur portable en utilisant le code ci-dessous dans Colab.
De Google.Colab Import Auth auth.authenticate_user () Importer Vertexai vertexai.init (project = vertex_project, location = vertex_region)
Maintenant, nous devons créer une base de données vectorielle qui contiendra le schéma de diverses tables présentes dans notre ensemble de données et nous créerons un retriever au-dessus de cette base de données vectorielle afin que nous puissions incorporer RAG dans notre flux de travail.
Connexion à Big Query en utilisant BQ Client dans Python et schéma de tables.
à partir de google.cloud import bigQuery Importer JSON #Fetching schémas de tables bq_client = bigQuery.client (project = vertex_project) bq_tables = bq_client.list_tables (dataset = f "{bigQuery_project}. {bigQuery_dataset}") schémas = [] pour bq_table dans bq_tables: t = bq_client.get_table (f "{bigQuery_project}. {bigQuery_dataset}. {bq_table.table_id}") schema_fields = [f.to_api_repr () pour f dans t.schema] schéma = f "Le schéma pour la table {bq_table.table_id} est le suivant: \ n``` {json.dumps (schema_fields, indent = 1)}}` `" " schémas.APPEND (schéma) print (f "Found {len (schémas)} tables dans le jeu de données {bigQuery_project}: {bigQuery_dataset}") # import CSV
Stockage des schémas dans la base de données vectorielle telle que Chroma DB. Nous devons créer un dossier appelé « données»
De Langchain.embeddings Import VertexaieMeddings De Langchain.VectorStores Import Chroma embeddings = vertexaiembeddings () Essayez: # Évitez les documents dupliqués vector_store.delete_collection () sauf: Imprimer ("Pas besoin de nettoyer le magasin vectoriel") vector_store = chroma.from_texts (schémas, embedding = embeddings, persist_directory = '. / data') n_docs = len (vector_store.get () ['ids']) Retriever = vector_store.as_retriever (search_kwargs = {'k': 2}) print (f "Le magasin vectoriel a {n_docs} documents")
Nous instancions les 3 modèles LLM pour les 3 chaînes différentes.
Le premier modèle est le modèle de requête qui est responsable de la génération de la requête SQL basée sur la question de l'utilisateur et le schéma de table récupéré à partir de DB vectoriel similaire à la question de l'utilisateur. Pour cela, nous utilisons «codechat-bison» modèle . Ce modèle est spécialisé dans la génération de code dans différentes langues de codage et est donc approprié pour notre cas d'utilisation.
Les 2 autres modèles sont des modèles LLM par défaut dans Chatvertexai qui est « Gemini-1.5-Flash-001 » Il s'agit du dernier modèle Gemini optimisé pour le chat et la réponse rapide.
De Langchain.chat_models importe Chatvertexai de Langchain.llms Import Vertexai query_model = chatvertexai (modèle_name = "codechat-bison", max_output_tokens = 1000) interprét_data_model = chatvertexai (max_output_tokens = 1000) agent_model = chatvertexai (max_output_tokens = 1024)
Vous trouverez ci-dessous l'invite SQL utilisée pour générer la requête SQL pour la question de l'utilisateur d'entrée.
SQL_PROMPT = "" "Vous êtes un expert SQL et BigQuery. Votre travail consiste à créer une requête pour BigQuery dans SQL. Le paragraphe suivant contient le schéma de la table utilisé pour une requête. Il est codé au format JSON. {contexte} Créez une requête SQL BigQuery pour l'entrée utilisateur suivante, en utilisant le tableau ci-dessus. Et utilisez uniquement des colonnes mentionnées dans le schéma pour la requête SQL L'utilisateur et l'agent ont fait cette conversation jusqu'à présent: {Chat_history} Suivez strictement ces restrictions: - Renvoie uniquement le code SQL. - N'ajoutez pas de backticks ni de marquage. Écrivez uniquement la requête en sortie. Rien d'autre. - Dans, utilisez toujours le chemin complet de la table, en utilisant `{project}` en tant que projet et `{ensemble de données}` en tant que jeu de données. - Transformez toujours les noms du pays en majuscules en maîtrise. Par exemple, si le pays est le Japon, vous devez utiliser le Japon dans la requête. Entrée utilisateur: {Question} Requête SQL: "" "
Nous allons maintenant définir une fonction qui récupérera les documents pertinents, c'est-à-dire des schémas pour l'entrée de la question de l'utilisateur.
De Langchain.schema.VectorStore Import VectorStoreRerever Def Get_Documents (Retriever: VectorStoreRerever, Question: Str) -> Str: # Renvoie uniquement le premier document output = "" Pour D dans Retriever.get_Relevant_Documents (question): sortie = d.page_content output = "\ n" Sortie de retour
Ensuite, nous définissons la chaîne LLM en utilisant la syntaxe du langage d'expression de Langchain. Remarque Nous définissons l'invite avec 5 variables d'espace réservé et plus tard, nous définissons une invite partielle en remplissant le projet et l'ensemble de données de variables d'espace réservé.
à partir de l'opérateur Import ItemGetter à partir de Langchain.prompts Importer PromptTemplate De Langchain.schema Import StroutputParser prompt_template = promptTemplate ( input_variables = ["contexte", "chat_history", "question", "projet", "ensemble de données"], template = sql_prompt) partial_prompt = prompt_template.partial (project = bigQuery_project, DataSet = BigQuery_Dataset) # L'entrée sera comme {"entrée": "Some_question", "Chat_history": "History"} docs = {"context": lambda x: get_documents (retriever, x ['entrée'])} Question = {"Question": ItemGetter ("Input")} chat_history = {"chat_history": itemGetter ("chat_history")} query_chain = docs | Question | Chat_history | Partial_Prompt | query_model query = query_chain | StroutputParser ()
Testons notre chaîne à l'aide du gestionnaire de rappel de Langchain qui affichera chaque étapes de l'exécution de la chaîne en détail.
De Langchain.Callbacks.Tracers Importer ConsoleCallbackHandler # Exemple x = {"entrée": "la plus haute durée de voyage où la station de départ était de Atlantic Ave & Fort Greene PL", "Chat_history": ""} print (query.invoke (x, config = {'callbacks': [consoleCallbackHandler ()]}))
Nous devons affiner la sortie de la chaîne SQL ci-dessus afin qu'elle inclue également d'autres variables dans son Outp qui sera ensuite transmise à la deuxième chaîne - Interpréter la chaîne.
De Langchain.output_Parsers Importer des réponses de la réponse, structurée De Langchain.schema.Runnable Import Runnablelambda #Refine la sortie de la chaîne pour inclure d'autres variables dans la sortie au format de dictionnaire def _dict_to_json (x: dict) -> str: Renvoie "` `\ n" JSON.Dumps (x) "\ n```" " query_response_schema = [ Réponseschema (name = "query", description = "requête SQL pour résoudre la question de l'utilisateur."), Réponseschema (name = "question", description = "Question posée par l'utilisateur."), Réponseschema (name = "context", description = "documents récupérés du magasin vectoriel.") ]] query_output_parser = StructuredOutputParser.from_response_schemas (query_response_schema) query_output_json = docs | Question | {"Query": Query} | Runnablelambda (_dict_to_json) | StroutputParser () query_output = query_output_json | query_output_parser
Essayons d'exécuter cette chaîne.
# Exemple x = {"entrée": "Donnez-moi les 2 premières stations de départ où la durée du voyage était la plus élevée?", "Chat_history": ""} output = query_output.invoke (x) # La sortie est maintenant un dictionnaire, entrée pour la prochaine chaîne
Ci-dessus, nous pouvons voir que la sortie de la chaîne raffinée est une requête SQL.
Nous devons maintenant construire la prochaine chaîne qui prendra la production de chaîne de requête SQL définie ci-dessus. Cette chaîne prendra la requête SQL de la chaîne précédente et l'exécutera dans une grande requête et ses résultats sont ensuite utilisés pour générer une réponse en utilisant une invite appropriée.
Interprét_prompt = "" "Vous êtes un expert BigQuery. Vous êtes également expert dans l'extraction des données de CSV. Le paragraphe suivant décrit le schéma du tableau utilisé pour une requête. Il est codé au format JSON. {contexte} Un utilisateur a posé cette question: {question} Pour trouver la réponse, la requête SQL suivante a été gérée à BigQuery: `` ' {requête} `` ' Le résultat de cette requête était le tableau suivant au format CSV: `` ' {résultat} `` ' Sur la base de ces résultats, fournissez une brève réponse à la question de l'utilisateur. Suivez strictement ces restrictions: - N'ajoutez aucune explication sur la façon dont la réponse est obtenue, écrivez simplement la réponse. - Extraire toute valeur liée à la réponse uniquement à partir du résultat de la requête. N'utilisez aucune autre source de données. - Écrivez simplement la réponse, omettez la question de votre réponse, c'est un chat, fournissez simplement la réponse. - Si vous ne trouvez pas la réponse dans le résultat, ne compensez aucune donnée, dites simplement "Je ne trouve pas la réponse" "" "
à partir de google.cloud import bigQuery def get_bq_csv (bq_client: bigQuery.client, requête: str) -> str: Cleaned_Query = Clean_Query (Query) df = bq_client.query (cleaned_query, location = "us"). to_dataframe () return df.to_csv (index = false) Def Clean_Query (Query: Str): query = query.replace ("` `` sql "," ") Cleaned_Query = Query.replace ("` `` "," ") Retour nettoyer_query
Nous définirons deux fonctions, on est Clean_Query - cela nettoiera la requête SQL des apostrophes et d'autres caractères inutiles et d'autres sont GET_BQ_CSV - cela exécutera la requête SQL nettoyée dans une grande requête et obtiendra la table de sortie au format CSV.
# Obtenez la sortie de la chaîne précédente query = {"Query": itemGetter ("Query")} context = {"context": itemGetter ("context")} Question = {"Question": ItemGetter ("Question")} #Cleaned_Query = {"Result": Lambda X: Clean_Query (x ["Query"])} query_result = {"result": lambda x: get_bq_csv (bq_client, x ["query"])} prompt = promptTemplate ( input_variables = ["question", "requête", "résultat", "contexte"], template = interprét_prompt) run_bq_chain = contexte | Question | Requête | Query_result | rapide run_bq_result = run_bq_chain | Interprét_data_model | StroutputParser ()
Exécutons la chaîne et le testons.
# Exemple x = {"entrée": "Donnez-moi les 2 premières stations de départ où la durée du voyage était la plus élevée?", "Chat_history": ""} final_response = run_bq_result.invoke (query_output.invoke (x)) imprimer (final_response)
Maintenant, nous allons construire la chaîne finale qui est la chaîne d'agent. Lorsqu'un utilisateur pose une question, il décide d'utiliser l'outil de requête SQL ou de y répondre directement. Fondamentalement, il envoie des requêtes utilisateur à divers outils en fonction des travaux qui doivent être terminés afin de répondre à la demande de l'utilisateur.
Nous définissons un agent_memory, une invite d'agent, une fintion d'outil.
De Langchain.Memory Import Conversation BufferwindowMemory agent_memory = ConversationBufferwindowMemory ( mémoire_key = "chat_history", k = 10, return_messages = true)
Agent_prompt = "" "Vous êtes un assistant très puissant qui peut répondre aux questions en utilisant BigQuery. Vous pouvez invoquer l'outil user_question_tool pour répondre aux questions en utilisant BigQuery. Utilisez toujours les outils pour essayer de répondre aux questions. Utilisez l'historique de chat pour le contexte. N'essayez jamais d'utiliser d'autres informations externes. Supposons que l'utilisateur peut écrire avec des fautes d'orthographe, réparez l'orthographe de l'utilisateur avant de passer la question à n'importe quel outil. Ne mentionnez pas l'outil que vous avez utilisé dans votre réponse. "" "
à partir de Langchain.tools Import Tool De Langchain.Callbacks.Tracers Importer ConsoleCallbackHandler @outil def user_question_tool (question) -> str: "" "Utile pour répondre aux questions du langage naturel des utilisateurs utilisant BigQuery." "" config = {'callbacks': [consoleCallbackHandler ()]} config = {} mémoire = agent_memory.buffer_as_str.strip () question = {"entrée": question, "chat_history": mémoire} query = query_output.invoke (question, config = config) print ("\ n \ n ****************** \ n \ n") imprimer (requête ['requête']) print ("\ n \ n ****************** \ n \ n") result = run_bq_result.invoke (query, config = config) return result.strip ()
Nous réunissons maintenant toutes les principales composantes de l'agent et initialisons l'agent.
De Langchain.agents Import AgentType, initialize_agent, agentExecutor agent_kwgards = {"System_Message": agent_prompt} agent_tools = [user_question_tool] agent_memory.clear () agent = initialize_agent ( outils = agent_tools, llm = agent_model, agent = agentType.chat_Conversational_react_description, mémoire = agent_memory, agent_kwgards = agent_kwgards, max_iterations = 5, Early_Stopping_Method = 'Generate', Verbose = true)
Permet d'exécuter l'agent maintenant.
Q = "Donnez-moi les 2 premières stations de départ où la durée du voyage était la plus élevée?" agent.invoke (q)
Question de suivi à l'agent.
Q = "Quelle est la capacité de chacun de ces noms de station?" agent.invoke (q)
L'agent a été avec précision en mesure de traiter la question complexe et de générer également des réponses correctes pour une question de suivi en fonction de l'historique du chat, puis il a utilisé un autre tableau pour obtenir des informations sur la capacité des vélos Citi.
L'approche RAG-TO-SQL représente une progression significative dans la lutte contre les limites des modèles traditionnels de texte à SQL en incorporant des données contextuelles et en tirant parti des techniques de récupération. Cette méthodologie améliore la précision de la requête en récupérant les informations de schéma pertinentes à partir de bases de données vectorielles, permettant une génération SQL plus précise. La mise en œuvre de RAG-to-SQL dans Google Cloud Services comme BigQuery et Vertex AI démontre son évolutivité et son efficacité dans les applications du monde réel. En automatisant le processus décisionnel dans la manipulation des requêtes, Rag-to-SQL ouvre de nouvelles possibilités pour que les utilisateurs non techniques interagissent de manière transparente avec les bases de données tout en maintenant une haute précision.
R. Non, mais vous pouvez obtenir une période d'essai de 90 jours avec 300 $ de crédits si vous vous inscrivez pour la première fois et que vous n'avez qu'à fournir les détails d'une carte pour l'accès. Aucun frais n'est déduit de la carte et même si vous utilisez des services qui consomment au-delà de 300 $ de crédits, Google vous demandera d'activer le compte de paiement afin que vous puissiez utiliser le service. Il n'y a donc pas de déduction automatique du montant.
Q2. Quel est le principal avantage de l'utilisation de Rag to SQL?R. Cela nous permet d'automatiser le schéma de table qui doit être alimenté au LLM si nous utilisons plusieurs tables, nous n'avons pas besoin de nourrir tous les schémas de table à la fois. Sur la base de la requête utilisateur, le schéma de table pertinent peut être récupéré à partir du chiffon. Ainsi, augmentant l'efficacité sur le texte conventionnel aux systèmes SQL.
Q3. Comment les agents peuvent-ils être utiles pour ce cas d'utilisation?A. Si nous construisons un chatbot holistique, cela pourrait nécessiter beaucoup d'autres outils en dehors de l'outil de requête SQL. Nous pouvons donc tirer parti de l'agent et lui fournir plusieurs outils tels que la recherche Web, l'outil de requête SQL à base de données, d'autres outils de chiffon ou les outils API d'appel de fonction. Cela permettra de gérer différents types de requêtes utilisateur en fonction de la tâche qui doit être accomplie pour répondre à la requête utilisateur.
Les médias présentés dans cet article ne sont pas détenus par l'analytique vidhya et sont utilisés à la discrétion de l'auteur.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!