From 0b740ebd49a93bb101160496bb48a47c23d972da Mon Sep 17 00:00:00 2001 From: Lance Martin <122662504+rlancemartin@users.noreply.github.com> Date: Wed, 24 Jan 2024 09:03:17 -0800 Subject: [PATCH] Update SQL agent toolkit docs (#16409) --- .../integrations/toolkits/sql_database.ipynb | 734 ++++++++++-------- 1 file changed, 405 insertions(+), 329 deletions(-) diff --git a/docs/docs/integrations/toolkits/sql_database.ipynb b/docs/docs/integrations/toolkits/sql_database.ipynb index e5bc16cd95..68cdd0d6a6 100644 --- a/docs/docs/integrations/toolkits/sql_database.ipynb +++ b/docs/docs/integrations/toolkits/sql_database.ipynb @@ -8,105 +8,293 @@ "# SQL Database\n", "\n", "This notebook showcases an agent designed to interact with a `SQL` databases. \n", - "The agent builds off of [SQLDatabaseChain](https://python.langchain.com/docs/use_cases/tabular/sqlite) and is designed to answer more general questions about a database, as well as recover from errors.\n", "\n", - "Note that, as this agent is in active development, all answers might not be correct. Additionally, it is not guaranteed that the agent won't perform DML statements on your database given certain questions. Be careful running it on sensitive data!\n", + "The agent builds from [SQLDatabaseChain](https://python.langchain.com/docs/use_cases/tabular/sqlite). \n", "\n", - "This uses the example `Chinook` database. To set it up follow the instructions on https://database.guide/2-sample-databases-sqlite/, placing the .db file in a notebooks folder at the root of this repository." + "It is designed to answer more general questions about a database, as well as recover from errors.\n", + "\n", + "Note that, as this agent is in active development, all answers might not be correct. \n", + "\n", + "Additionally, it is not guaranteed that the agent won't perform DML statements on your database given certain questions. \n", + "\n", + "Be careful running it on sensitive data!|\n", + "\n", + "This uses the example `Chinook` database. \n", + "\n", + "To set it up follow [these instructions](https://database.guide/2-sample-databases-sqlite/) and place the .db file in a notebooks folder at the root of this repository." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "39ee5811-7f7d-47a9-941a-83dcf4b74239", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[33mWARNING: There was an error checking the latest version of pip.\u001b[0m\u001b[33m\n", + "\u001b[0mNote: you may need to restart the kernel to use updated packages.\n" + ] + } + ], + "source": [ + "%pip install --upgrade --quiet langchain langchain-community langchain-experimental" ] }, { "cell_type": "markdown", - "id": "ec927ac6-9b2a-4e8a-9a6e-3e429191875c", - "metadata": { - "tags": [] - }, + "id": "804533b1-2f16-497b-821b-c82d67fcf7b6", + "metadata": {}, "source": [ - "## Initialization" + "## Initialize our database" ] }, { "cell_type": "code", "execution_count": 1, - "id": "53422913-967b-4f2a-8022-00269c1be1b1", - "metadata": { - "tags": [] - }, + "id": "42bd5a41-672a-4a53-b70a-2f0c0555758c", + "metadata": {}, "outputs": [], "source": [ - "from langchain.agents import create_sql_agent\n", - "from langchain.agents.agent_types import AgentType\n", "from langchain.sql_database import SQLDatabase\n", - "from langchain_community.agent_toolkits import SQLDatabaseToolkit\n", - "from langchain_openai import OpenAI" + "\n", + "db = SQLDatabase.from_uri(\"sqlite:///Chinook.db\")" ] }, { - "cell_type": "code", - "execution_count": 2, - "id": "65ec5bb3", + "cell_type": "markdown", + "id": "fabfc8b0-2354-4f4d-b334-cd8ae3a12b0a", "metadata": {}, - "outputs": [], "source": [ - "db = SQLDatabase.from_uri(\"sqlite:///../../../../../notebooks/Chinook.db\")\n", - "toolkit = SQLDatabaseToolkit(db=db, llm=OpenAI(temperature=0))" + "## Quickstart\n", + "\n", + "Following the [SQL use case docs](https://python.langchain.com/docs/use_cases/sql/agents), we can use the `create_sql_agent` helper." ] }, { - "cell_type": "markdown", - "id": "f74d1792", + "cell_type": "code", + "execution_count": 5, + "id": "c0504b5c-72a8-4407-9056-944615f1d480", "metadata": {}, + "outputs": [], "source": [ - "## Using `ZERO_SHOT_REACT_DESCRIPTION`\n", + "from langchain_community.agent_toolkits import create_sql_agent\n", + "from langchain_openai import ChatOpenAI\n", "\n", - "This shows how to initialize the agent using the ZERO_SHOT_REACT_DESCRIPTION agent type." + "llm = ChatOpenAI(model=\"gpt-3.5-turbo\", temperature=0)\n", + "agent_executor = create_sql_agent(llm, db=db, agent_type=\"openai-tools\", verbose=True)" ] }, { "cell_type": "code", - "execution_count": 2, - "id": "090f3699-79c6-4ce1-ab96-a94f0121fd64", + "execution_count": 5, + "id": "75f2f603-6004-4363-a781-a6e352124ffa", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n", + "\u001b[32;1m\u001b[1;3m\n", + "Invoking: `sql_db_list_tables` with `{}`\n", + "\n", + "\n", + "\u001b[0m\u001b[38;5;200m\u001b[1;3mAlbum, Artist, Customer, Employee, Genre, Invoice, InvoiceLine, MediaType, Playlist, PlaylistTrack, Track\u001b[0m\u001b[32;1m\u001b[1;3m\n", + "Invoking: `sql_db_schema` with `Invoice,Customer`\n", + "\n", + "\n", + "\u001b[0m\u001b[33;1m\u001b[1;3m\n", + "CREATE TABLE \"Customer\" (\n", + "\t\"CustomerId\" INTEGER NOT NULL, \n", + "\t\"FirstName\" NVARCHAR(40) NOT NULL, \n", + "\t\"LastName\" NVARCHAR(20) NOT NULL, \n", + "\t\"Company\" NVARCHAR(80), \n", + "\t\"Address\" NVARCHAR(70), \n", + "\t\"City\" NVARCHAR(40), \n", + "\t\"State\" NVARCHAR(40), \n", + "\t\"Country\" NVARCHAR(40), \n", + "\t\"PostalCode\" NVARCHAR(10), \n", + "\t\"Phone\" NVARCHAR(24), \n", + "\t\"Fax\" NVARCHAR(24), \n", + "\t\"Email\" NVARCHAR(60) NOT NULL, \n", + "\t\"SupportRepId\" INTEGER, \n", + "\tPRIMARY KEY (\"CustomerId\"), \n", + "\tFOREIGN KEY(\"SupportRepId\") REFERENCES \"Employee\" (\"EmployeeId\")\n", + ")\n", + "\n", + "/*\n", + "3 rows from Customer table:\n", + "CustomerId\tFirstName\tLastName\tCompany\tAddress\tCity\tState\tCountry\tPostalCode\tPhone\tFax\tEmail\tSupportRepId\n", + "1\tLuís\tGonçalves\tEmbraer - Empresa Brasileira de Aeronáutica S.A.\tAv. Brigadeiro Faria Lima, 2170\tSão José dos Campos\tSP\tBrazil\t12227-000\t+55 (12) 3923-5555\t+55 (12) 3923-5566\tluisg@embraer.com.br\t3\n", + "2\tLeonie\tKöhler\tNone\tTheodor-Heuss-Straße 34\tStuttgart\tNone\tGermany\t70174\t+49 0711 2842222\tNone\tleonekohler@surfeu.de\t5\n", + "3\tFrançois\tTremblay\tNone\t1498 rue Bélanger\tMontréal\tQC\tCanada\tH2G 1A7\t+1 (514) 721-4711\tNone\tftremblay@gmail.com\t3\n", + "*/\n", + "\n", + "\n", + "CREATE TABLE \"Invoice\" (\n", + "\t\"InvoiceId\" INTEGER NOT NULL, \n", + "\t\"CustomerId\" INTEGER NOT NULL, \n", + "\t\"InvoiceDate\" DATETIME NOT NULL, \n", + "\t\"BillingAddress\" NVARCHAR(70), \n", + "\t\"BillingCity\" NVARCHAR(40), \n", + "\t\"BillingState\" NVARCHAR(40), \n", + "\t\"BillingCountry\" NVARCHAR(40), \n", + "\t\"BillingPostalCode\" NVARCHAR(10), \n", + "\t\"Total\" NUMERIC(10, 2) NOT NULL, \n", + "\tPRIMARY KEY (\"InvoiceId\"), \n", + "\tFOREIGN KEY(\"CustomerId\") REFERENCES \"Customer\" (\"CustomerId\")\n", + ")\n", + "\n", + "/*\n", + "3 rows from Invoice table:\n", + "InvoiceId\tCustomerId\tInvoiceDate\tBillingAddress\tBillingCity\tBillingState\tBillingCountry\tBillingPostalCode\tTotal\n", + "1\t2\t2009-01-01 00:00:00\tTheodor-Heuss-Straße 34\tStuttgart\tNone\tGermany\t70174\t1.98\n", + "2\t4\t2009-01-02 00:00:00\tUllevålsveien 14\tOslo\tNone\tNorway\t0171\t3.96\n", + "3\t8\t2009-01-03 00:00:00\tGrétrystraat 63\tBrussels\tNone\tBelgium\t1000\t5.94\n", + "*/\u001b[0m\u001b[32;1m\u001b[1;3m\n", + "Invoking: `sql_db_query` with `SELECT c.Country, SUM(i.Total) AS TotalSales FROM Invoice i JOIN Customer c ON i.CustomerId = c.CustomerId GROUP BY c.Country ORDER BY TotalSales DESC LIMIT 10;`\n", + "responded: To list the total sales per country, I can query the \"Invoice\" and \"Customer\" tables. I will join these tables on the \"CustomerId\" column and group the results by the \"BillingCountry\" column. Then, I will calculate the sum of the \"Total\" column to get the total sales per country. Finally, I will order the results in descending order of the total sales.\n", + "\n", + "Here is the SQL query:\n", + "\n", + "```sql\n", + "SELECT c.Country, SUM(i.Total) AS TotalSales\n", + "FROM Invoice i\n", + "JOIN Customer c ON i.CustomerId = c.CustomerId\n", + "GROUP BY c.Country\n", + "ORDER BY TotalSales DESC\n", + "LIMIT 10;\n", + "```\n", + "\n", + "Now, I will execute this query to get the total sales per country.\n", + "\n", + "\u001b[0m\u001b[36;1m\u001b[1;3m[('USA', 523.0600000000003), ('Canada', 303.9599999999999), ('France', 195.09999999999994), ('Brazil', 190.09999999999997), ('Germany', 156.48), ('United Kingdom', 112.85999999999999), ('Czech Republic', 90.24000000000001), ('Portugal', 77.23999999999998), ('India', 75.25999999999999), ('Chile', 46.62)]\u001b[0m\u001b[32;1m\u001b[1;3mThe total sales per country are as follows:\n", + "\n", + "1. USA: $523.06\n", + "2. Canada: $303.96\n", + "3. France: $195.10\n", + "4. Brazil: $190.10\n", + "5. Germany: $156.48\n", + "6. United Kingdom: $112.86\n", + "7. Czech Republic: $90.24\n", + "8. Portugal: $77.24\n", + "9. India: $75.26\n", + "10. Chile: $46.62\n", + "\n", + "To answer the second question, the country whose customers spent the most is the USA, with a total sales of $523.06.\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n" + ] + }, + { + "data": { + "text/plain": [ + "{'input': \"List the total sales per country. Which country's customers spent the most?\",\n", + " 'output': 'The total sales per country are as follows:\\n\\n1. USA: $523.06\\n2. Canada: $303.96\\n3. France: $195.10\\n4. Brazil: $190.10\\n5. Germany: $156.48\\n6. United Kingdom: $112.86\\n7. Czech Republic: $90.24\\n8. Portugal: $77.24\\n9. India: $75.26\\n10. Chile: $46.62\\n\\nTo answer the second question, the country whose customers spent the most is the USA, with a total sales of $523.06.'}" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "agent_executor.invoke(\n", + " \"List the total sales per country. Which country's customers spent the most?\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "ec927ac6-9b2a-4e8a-9a6e-3e429191875c", "metadata": { "tags": [] }, + "source": [ + "## Toolkit\n", + "\n", + "We can look at what runs under the hood with the `create_sql_agent` helper above.\n", + "\n", + "We can also highlight how the toolkit is used with the agent specifically." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "056ddd8a-9835-41ef-84a3-6b680c22248d", + "metadata": {}, "outputs": [], "source": [ - "agent_executor = create_sql_agent(\n", - " llm=OpenAI(temperature=0),\n", - " toolkit=toolkit,\n", - " verbose=True,\n", - " agent_type=AgentType.ZERO_SHOT_REACT_DESCRIPTION,\n", - ")" + "from langchain_community.agent_toolkits import SQLDatabaseToolkit\n", + "from langchain_openai import ChatOpenAI\n", + "\n", + "toolkit = SQLDatabaseToolkit(db=db, llm=ChatOpenAI(temperature=0))\n", + "context = toolkit.get_context()\n", + "tools = toolkit.get_tools()" ] }, { "cell_type": "markdown", - "id": "971cc455", + "id": "08a653b1-02f2-45f3-b357-acff5a6b3869", "metadata": {}, "source": [ - "## Using OpenAI Functions\n", - "\n", - "This shows how to initialize the agent using the OPENAI_FUNCTIONS agent type. Note that this is an alternative to the above." + "### Use SQLDatabaseToolkit within an Agent\n" ] }, { "cell_type": "code", "execution_count": 3, - "id": "6426a27d", + "id": "3f673e63-49bf-4112-b74f-d7baa91ed81f", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain_community.agent_toolkits.sql.prompt import SQL_FUNCTIONS_SUFFIX\n", + "from langchain_core.messages import AIMessage, SystemMessage\n", + "from langchain_core.prompts.chat import (\n", + " ChatPromptTemplate,\n", + " HumanMessagePromptTemplate,\n", + " MessagesPlaceholder,\n", + ")\n", + "\n", + "messages = [\n", + " HumanMessagePromptTemplate.from_template(\"{input}\"),\n", + " AIMessage(content=SQL_FUNCTIONS_SUFFIX),\n", + " MessagesPlaceholder(variable_name=\"agent_scratchpad\"),\n", + "]\n", + "\n", + "prompt = ChatPromptTemplate.from_messages(messages)\n", + "prompt = prompt.partial(**context)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "83f57336-1757-4a54-bf79-591c0a97e6a4", "metadata": {}, "outputs": [], "source": [ - "# agent_executor = create_sql_agent(\n", - "# llm=ChatOpenAI(temperature=0, model=\"gpt-3.5-turbo-0613\"),\n", - "# toolkit=toolkit,\n", - "# verbose=True,\n", - "# agent_type=AgentType.OPENAI_FUNCTIONS\n", - "# )\n" + "from langchain.agents import create_openai_tools_agent\n", + "from langchain.agents.agent import AgentExecutor\n", + "\n", + "llm = ChatOpenAI(model=\"gpt-3.5-turbo\", temperature=0)\n", + "\n", + "agent = create_openai_tools_agent(llm, tools, prompt)\n", + "\n", + "agent_executor = AgentExecutor(\n", + " agent=agent,\n", + " tools=toolkit.get_tools(),\n", + " verbose=True,\n", + ")" ] }, { "cell_type": "markdown", - "id": "54c01168", + "id": "f77805fb-c05e-408c-9b69-6d2a774c208e", "metadata": {}, "source": [ "## Disclaimer ⚠️\n", @@ -120,34 +308,20 @@ " JOIN \"public\".\"user_permissions\" ON \"public\".\"users\".id = \"public\".\"user_permissions\".user_id\n", " JOIN \"public\".\"projects\" ON \"public\".\"users\".id = \"public\".\"projects\".user_id\n", " JOIN \"public\".\"events\" ON \"public\".\"projects\".id = \"public\".\"events\".project_id;\n", - "```" - ] - }, - { - "cell_type": "markdown", - "id": "5a4a9455", - "metadata": {}, - "source": [ + "```\n", + "\n", "For a transactional SQL database, if one of the table above contains millions of rows, the query might cause trouble to other applications using the same database.\n", "\n", - "Most datawarehouse oriented databases support user-level quota, for limiting resource usage." - ] - }, - { - "cell_type": "markdown", - "id": "36ae48c7-cb08-4fef-977e-c7d4b96a464b", - "metadata": {}, - "source": [ + "Most datawarehouse oriented databases support user-level quota, for limiting resource usage.\n", + "\n", "## Example: describing a table" ] }, { "cell_type": "code", - "execution_count": 4, - "id": "ff70e83d-5ad0-4fc7-bb96-27d82ac166d7", - "metadata": { - "tags": [] - }, + "execution_count": 8, + "id": "f740fbef-d635-4121-856d-33593ae6bfc0", + "metadata": {}, "outputs": [ { "name": "stdout", @@ -155,54 +329,40 @@ "text": [ "\n", "\n", - "\u001b[1m> Entering new chain...\u001b[0m\n", + "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n", "\u001b[32;1m\u001b[1;3m\n", - "Invoking: `list_tables_sql_db` with `{}`\n", + "Invoking: `sql_db_list_tables` with ``\n", "\n", "\n", - "\u001b[0m\u001b[38;5;200m\u001b[1;3mAlbum, Artist, Track, PlaylistTrack, InvoiceLine, sales_table, Playlist, Genre, Employee, Customer, Invoice, MediaType\u001b[0m\u001b[32;1m\u001b[1;3m\n", - "Invoking: `schema_sql_db` with `PlaylistTrack`\n", + "\u001b[0m\u001b[38;5;200m\u001b[1;3mAlbum, Artist, Customer, Employee, Genre, Invoice, InvoiceLine, MediaType, Playlist, PlaylistTrack, Track\u001b[0m\u001b[32;1m\u001b[1;3m\n", + "Invoking: `sql_db_schema` with `Playlist`\n", "\n", "\n", "\u001b[0m\u001b[33;1m\u001b[1;3m\n", - "CREATE TABLE \"PlaylistTrack\" (\n", + "CREATE TABLE \"Playlist\" (\n", "\t\"PlaylistId\" INTEGER NOT NULL, \n", - "\t\"TrackId\" INTEGER NOT NULL, \n", - "\tPRIMARY KEY (\"PlaylistId\", \"TrackId\"), \n", - "\tFOREIGN KEY(\"TrackId\") REFERENCES \"Track\" (\"TrackId\"), \n", - "\tFOREIGN KEY(\"PlaylistId\") REFERENCES \"Playlist\" (\"PlaylistId\")\n", + "\t\"Name\" NVARCHAR(120), \n", + "\tPRIMARY KEY (\"PlaylistId\")\n", ")\n", "\n", "/*\n", - "3 rows from PlaylistTrack table:\n", - "PlaylistId\tTrackId\n", - "1\t3402\n", - "1\t3389\n", - "1\t3390\n", - "*/\u001b[0m\u001b[32;1m\u001b[1;3mThe `PlaylistTrack` table has two columns: `PlaylistId` and `TrackId`. It is a junction table that represents the relationship between playlists and tracks. \n", - "\n", - "Here is the schema of the `PlaylistTrack` table:\n", - "\n", - "```\n", - "CREATE TABLE \"PlaylistTrack\" (\n", - "\t\"PlaylistId\" INTEGER NOT NULL, \n", - "\t\"TrackId\" INTEGER NOT NULL, \n", - "\tPRIMARY KEY (\"PlaylistId\", \"TrackId\"), \n", - "\tFOREIGN KEY(\"TrackId\") REFERENCES \"Track\" (\"TrackId\"), \n", - "\tFOREIGN KEY(\"PlaylistId\") REFERENCES \"Playlist\" (\"PlaylistId\")\n", - ")\n", - "```\n", + "3 rows from Playlist table:\n", + "PlaylistId\tName\n", + "1\tMusic\n", + "2\tMovies\n", + "3\tTV Shows\n", + "*/\u001b[0m\u001b[32;1m\u001b[1;3mThe schema of the \"Playlist\" table is as follows:\n", "\n", - "Here are three sample rows from the `PlaylistTrack` table:\n", + "- PlaylistId: INTEGER (Primary Key)\n", + "- Name: NVARCHAR(120)\n", "\n", - "```\n", - "PlaylistId TrackId\n", - "1 3402\n", - "1 3389\n", - "1 3390\n", - "```\n", + "Here are three sample rows from the \"Playlist\" table:\n", "\n", - "Please let me know if there is anything else I can help you with.\u001b[0m\n", + "| PlaylistId | Name |\n", + "|------------|-----------|\n", + "| 1 | Music |\n", + "| 2 | Movies |\n", + "| 3 | TV Shows |\u001b[0m\n", "\n", "\u001b[1m> Finished chain.\u001b[0m\n" ] @@ -210,16 +370,17 @@ { "data": { "text/plain": [ - "'The `PlaylistTrack` table has two columns: `PlaylistId` and `TrackId`. It is a junction table that represents the relationship between playlists and tracks. \\n\\nHere is the schema of the `PlaylistTrack` table:\\n\\n```\\nCREATE TABLE \"PlaylistTrack\" (\\n\\t\"PlaylistId\" INTEGER NOT NULL, \\n\\t\"TrackId\" INTEGER NOT NULL, \\n\\tPRIMARY KEY (\"PlaylistId\", \"TrackId\"), \\n\\tFOREIGN KEY(\"TrackId\") REFERENCES \"Track\" (\"TrackId\"), \\n\\tFOREIGN KEY(\"PlaylistId\") REFERENCES \"Playlist\" (\"PlaylistId\")\\n)\\n```\\n\\nHere are three sample rows from the `PlaylistTrack` table:\\n\\n```\\nPlaylistId TrackId\\n1 3402\\n1 3389\\n1 3390\\n```\\n\\nPlease let me know if there is anything else I can help you with.'" + "{'input': 'Describe the schema of the playlist table',\n", + " 'output': 'The schema of the \"Playlist\" table is as follows:\\n\\n- PlaylistId: INTEGER (Primary Key)\\n- Name: NVARCHAR(120)\\n\\nHere are three sample rows from the \"Playlist\" table:\\n\\n| PlaylistId | Name |\\n|------------|-----------|\\n| 1 | Music |\\n| 2 | Movies |\\n| 3 | TV Shows |'}" ] }, - "execution_count": 4, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "agent_executor.run(\"Describe the playlisttrack table\")" + "agent_executor.invoke({\"input\": \"Describe the schema of the playlist table\"})" ] }, { @@ -229,16 +390,14 @@ "source": [ "## Example: describing a table, recovering from an error\n", "\n", - "In this example, the agent tries to search for a table that doesn't exist, but finds the next best result" + "In this example, the agent tries to search for a table, `playlists`, that doesn't exist, but finds the next best result" ] }, { "cell_type": "code", - "execution_count": 15, - "id": "bea76658-a65b-47e2-b294-6d52c5556246", - "metadata": { - "tags": [] - }, + "execution_count": 10, + "id": "d78ddb6e-f499-4e90-9604-fe22a9c3592e", + "metadata": {}, "outputs": [ { "name": "stdout", @@ -247,36 +406,39 @@ "\n", "\n", "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n", - "\u001b[32;1m\u001b[1;3mAction: list_tables_sql_db\n", - "Action Input: \"\"\u001b[0m\n", - "Observation: \u001b[38;5;200m\u001b[1;3mGenre, PlaylistTrack, MediaType, Invoice, InvoiceLine, Track, Playlist, Customer, Album, Employee, Artist\u001b[0m\n", - "Thought:\u001b[32;1m\u001b[1;3m I should look at the schema of the PlaylistSong table\n", - "Action: schema_sql_db\n", - "Action Input: \"PlaylistSong\"\u001b[0m\n", - "Observation: \u001b[33;1m\u001b[1;3mError: table_names {'PlaylistSong'} not found in database\u001b[0m\n", - "Thought:\u001b[32;1m\u001b[1;3m I should check the spelling of the table\n", - "Action: list_tables_sql_db\n", - "Action Input: \"\"\u001b[0m\n", - "Observation: \u001b[38;5;200m\u001b[1;3mGenre, PlaylistTrack, MediaType, Invoice, InvoiceLine, Track, Playlist, Customer, Album, Employee, Artist\u001b[0m\n", - "Thought:\u001b[32;1m\u001b[1;3m The table is called PlaylistTrack\n", - "Action: schema_sql_db\n", - "Action Input: \"PlaylistTrack\"\u001b[0m\n", - "Observation: \u001b[33;1m\u001b[1;3m\n", - "CREATE TABLE \"PlaylistTrack\" (\n", + "\u001b[32;1m\u001b[1;3m\n", + "Invoking: `sql_db_list_tables` with ``\n", + "\n", + "\n", + "\u001b[0m\u001b[38;5;200m\u001b[1;3mAlbum, Artist, Customer, Employee, Genre, Invoice, InvoiceLine, MediaType, Playlist, PlaylistTrack, Track\u001b[0m\u001b[32;1m\u001b[1;3m\n", + "Invoking: `sql_db_schema` with `Playlist`\n", + "\n", + "\n", + "\u001b[0m\u001b[33;1m\u001b[1;3m\n", + "CREATE TABLE \"Playlist\" (\n", "\t\"PlaylistId\" INTEGER NOT NULL, \n", - "\t\"TrackId\" INTEGER NOT NULL, \n", - "\tPRIMARY KEY (\"PlaylistId\", \"TrackId\"), \n", - "\tFOREIGN KEY(\"TrackId\") REFERENCES \"Track\" (\"TrackId\"), \n", - "\tFOREIGN KEY(\"PlaylistId\") REFERENCES \"Playlist\" (\"PlaylistId\")\n", + "\t\"Name\" NVARCHAR(120), \n", + "\tPRIMARY KEY (\"PlaylistId\")\n", ")\n", "\n", - "SELECT * FROM 'PlaylistTrack' LIMIT 3;\n", - "PlaylistId TrackId\n", - "1 3402\n", - "1 3389\n", - "1 3390\u001b[0m\n", - "Thought:\u001b[32;1m\u001b[1;3m I now know the final answer\n", - "Final Answer: The PlaylistTrack table contains two columns, PlaylistId and TrackId, which are both integers and are used to link Playlist and Track tables.\u001b[0m\n", + "/*\n", + "3 rows from Playlist table:\n", + "PlaylistId\tName\n", + "1\tMusic\n", + "2\tMovies\n", + "3\tTV Shows\n", + "*/\u001b[0m\u001b[32;1m\u001b[1;3mThe \"Playlists\" table has the following schema:\n", + "\n", + "- PlaylistId: INTEGER (Primary Key)\n", + "- Name: NVARCHAR(120)\n", + "\n", + "Here are three sample rows from the \"Playlists\" table:\n", + "\n", + "| PlaylistId | Name |\n", + "|------------|-----------|\n", + "| 1 | Music |\n", + "| 2 | Movies |\n", + "| 3 | TV Shows |\u001b[0m\n", "\n", "\u001b[1m> Finished chain.\u001b[0m\n" ] @@ -284,16 +446,17 @@ { "data": { "text/plain": [ - "'The PlaylistTrack table contains two columns, PlaylistId and TrackId, which are both integers and are used to link Playlist and Track tables.'" + "{'input': 'Describe the playlists table',\n", + " 'output': 'The \"Playlists\" table has the following schema:\\n\\n- PlaylistId: INTEGER (Primary Key)\\n- Name: NVARCHAR(120)\\n\\nHere are three sample rows from the \"Playlists\" table:\\n\\n| PlaylistId | Name |\\n|------------|-----------|\\n| 1 | Music |\\n| 2 | Movies |\\n| 3 | TV Shows |'}" ] }, - "execution_count": 15, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "agent_executor.run(\"Describe the playlistsong table\")" + "agent_executor.invoke({\"input\": \"Describe the playlists table\"})" ] }, { @@ -306,11 +469,9 @@ }, { "cell_type": "code", - "execution_count": 8, - "id": "17bea710-4a23-4de0-b48e-21d57be48293", - "metadata": { - "tags": [] - }, + "execution_count": 11, + "id": "5457af9a-037d-4dba-9316-0abfe841f114", + "metadata": {}, "outputs": [ { "name": "stdout", @@ -319,13 +480,15 @@ "\n", "\n", "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n", - "\u001b[32;1m\u001b[1;3mAction: list_tables_sql_db\n", - "Action Input: \"\"\u001b[0m\n", - "Observation: \u001b[38;5;200m\u001b[1;3mInvoice, MediaType, Artist, InvoiceLine, Genre, Playlist, Employee, Album, PlaylistTrack, Track, Customer\u001b[0m\n", - "Thought:\u001b[32;1m\u001b[1;3m I should look at the schema of the relevant tables to see what columns I can use.\n", - "Action: schema_sql_db\n", - "Action Input: \"Invoice, Customer\"\u001b[0m\n", - "Observation: \u001b[33;1m\u001b[1;3m\n", + "\u001b[32;1m\u001b[1;3m\n", + "Invoking: `sql_db_list_tables` with ``\n", + "\n", + "\n", + "\u001b[0m\u001b[38;5;200m\u001b[1;3mAlbum, Artist, Customer, Employee, Genre, Invoice, InvoiceLine, MediaType, Playlist, PlaylistTrack, Track\u001b[0m\u001b[32;1m\u001b[1;3m\n", + "Invoking: `sql_db_schema` with `Invoice, Customer`\n", + "\n", + "\n", + "\u001b[0m\u001b[33;1m\u001b[1;3m\n", "CREATE TABLE \"Customer\" (\n", "\t\"CustomerId\" INTEGER NOT NULL, \n", "\t\"FirstName\" NVARCHAR(40) NOT NULL, \n", @@ -344,11 +507,13 @@ "\tFOREIGN KEY(\"SupportRepId\") REFERENCES \"Employee\" (\"EmployeeId\")\n", ")\n", "\n", - "SELECT * FROM 'Customer' LIMIT 3;\n", - "CustomerId FirstName LastName Company Address City State Country PostalCode Phone Fax Email SupportRepId\n", - "1 Luís Gonçalves Embraer - Empresa Brasileira de Aeronáutica S.A. Av. Brigadeiro Faria Lima, 2170 São José dos Campos SP Brazil 12227-000 +55 (12) 3923-5555 +55 (12) 3923-5566 luisg@embraer.com.br 3\n", - "2 Leonie Köhler None Theodor-Heuss-Straße 34 Stuttgart None Germany 70174 +49 0711 2842222 None leonekohler@surfeu.de 5\n", - "3 François Tremblay None 1498 rue Bélanger Montréal QC Canada H2G 1A7 +1 (514) 721-4711 None ftremblay@gmail.com 3\n", + "/*\n", + "3 rows from Customer table:\n", + "CustomerId\tFirstName\tLastName\tCompany\tAddress\tCity\tState\tCountry\tPostalCode\tPhone\tFax\tEmail\tSupportRepId\n", + "1\tLuís\tGonçalves\tEmbraer - Empresa Brasileira de Aeronáutica S.A.\tAv. Brigadeiro Faria Lima, 2170\tSão José dos Campos\tSP\tBrazil\t12227-000\t+55 (12) 3923-5555\t+55 (12) 3923-5566\tluisg@embraer.com.br\t3\n", + "2\tLeonie\tKöhler\tNone\tTheodor-Heuss-Straße 34\tStuttgart\tNone\tGermany\t70174\t+49 0711 2842222\tNone\tleonekohler@surfeu.de\t5\n", + "3\tFrançois\tTremblay\tNone\t1498 rue Bélanger\tMontréal\tQC\tCanada\tH2G 1A7\t+1 (514) 721-4711\tNone\tftremblay@gmail.com\t3\n", + "*/\n", "\n", "\n", "CREATE TABLE \"Invoice\" (\n", @@ -365,98 +530,30 @@ "\tFOREIGN KEY(\"CustomerId\") REFERENCES \"Customer\" (\"CustomerId\")\n", ")\n", "\n", - "SELECT * FROM 'Invoice' LIMIT 3;\n", - "InvoiceId CustomerId InvoiceDate BillingAddress BillingCity BillingState BillingCountry BillingPostalCode Total\n", - "1 2 2009-01-01 00:00:00 Theodor-Heuss-Straße 34 Stuttgart None Germany 70174 1.98\n", - "2 4 2009-01-02 00:00:00 Ullevålsveien 14 Oslo None Norway 0171 3.96\n", - "3 8 2009-01-03 00:00:00 Grétrystraat 63 Brussels None Belgium 1000 5.94\u001b[0m\n", - "Thought:\u001b[32;1m\u001b[1;3m I should query the Invoice and Customer tables to get the total sales per country.\n", - "Action: query_sql_db\n", - "Action Input: SELECT c.Country, SUM(i.Total) AS TotalSales FROM Invoice i INNER JOIN Customer c ON i.CustomerId = c.CustomerId GROUP BY c.Country ORDER BY TotalSales DESC LIMIT 10\u001b[0m\n", - "Observation: \u001b[36;1m\u001b[1;3m[('USA', 523.0600000000003), ('Canada', 303.9599999999999), ('France', 195.09999999999994), ('Brazil', 190.09999999999997), ('Germany', 156.48), ('United Kingdom', 112.85999999999999), ('Czech Republic', 90.24000000000001), ('Portugal', 77.23999999999998), ('India', 75.25999999999999), ('Chile', 46.62)]\u001b[0m\n", - "Thought:\u001b[32;1m\u001b[1;3m I now know the final answer\n", - "Final Answer: The customers from the USA spent the most, with a total of $523.06.\u001b[0m\n", - "\n", - "\u001b[1m> Finished chain.\u001b[0m\n" - ] - }, - { - "data": { - "text/plain": [ - "'The customers from the USA spent the most, with a total of $523.06.'" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "agent_executor.run(\n", - " \"List the total sales per country. Which country's customers spent the most?\"\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "474dddda-c067-4eeb-98b1-e763ee78b18c", - "metadata": { - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\n", - "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n", - "\u001b[32;1m\u001b[1;3mAction: list_tables_sql_db\n", - "Action Input: \"\"\u001b[0m\n", - "Observation: \u001b[38;5;200m\u001b[1;3mInvoice, MediaType, Artist, InvoiceLine, Genre, Playlist, Employee, Album, PlaylistTrack, Track, Customer\u001b[0m\n", - "Thought:\u001b[32;1m\u001b[1;3m I should look at the schema of the Playlist and PlaylistTrack tables to see what columns I can use.\n", - "Action: schema_sql_db\n", - "Action Input: \"Playlist, PlaylistTrack\"\u001b[0m\n", - "Observation: \u001b[33;1m\u001b[1;3m\n", - "CREATE TABLE \"Playlist\" (\n", - "\t\"PlaylistId\" INTEGER NOT NULL, \n", - "\t\"Name\" NVARCHAR(120), \n", - "\tPRIMARY KEY (\"PlaylistId\")\n", - ")\n", - "\n", - "SELECT * FROM 'Playlist' LIMIT 3;\n", - "PlaylistId Name\n", - "1 Music\n", - "2 Movies\n", - "3 TV Shows\n", + "/*\n", + "3 rows from Invoice table:\n", + "InvoiceId\tCustomerId\tInvoiceDate\tBillingAddress\tBillingCity\tBillingState\tBillingCountry\tBillingPostalCode\tTotal\n", + "1\t2\t2009-01-01 00:00:00\tTheodor-Heuss-Straße 34\tStuttgart\tNone\tGermany\t70174\t1.98\n", + "2\t4\t2009-01-02 00:00:00\tUllevålsveien 14\tOslo\tNone\tNorway\t0171\t3.96\n", + "3\t8\t2009-01-03 00:00:00\tGrétrystraat 63\tBrussels\tNone\tBelgium\t1000\t5.94\n", + "*/\u001b[0m\u001b[32;1m\u001b[1;3m\n", + "Invoking: `sql_db_query` with `SELECT c.Country, SUM(i.Total) AS TotalSales FROM Customer c JOIN Invoice i ON c.CustomerId = i.CustomerId GROUP BY c.Country ORDER BY TotalSales DESC LIMIT 1;`\n", + "responded: Based on the schema of the `Customer` and `Invoice` tables, we can join these two tables on the `CustomerId` column to get the total sales per customer. Then, we can group the results by the `Country` column to get the total sales per country. Finally, we can sort the results in descending order of total sales and select the country with the highest total sales.\n", + "\n", + "Here is the SQL query to achieve this:\n", + "\n", + "```sql\n", + "SELECT c.Country, SUM(i.Total) AS TotalSales\n", + "FROM Customer c\n", + "JOIN Invoice i ON c.CustomerId = i.CustomerId\n", + "GROUP BY c.Country\n", + "ORDER BY TotalSales DESC\n", + "LIMIT 1;\n", + "```\n", "\n", + "Let me execute this query to find out which country's customers spent the most.\n", "\n", - "CREATE TABLE \"PlaylistTrack\" (\n", - "\t\"PlaylistId\" INTEGER NOT NULL, \n", - "\t\"TrackId\" INTEGER NOT NULL, \n", - "\tPRIMARY KEY (\"PlaylistId\", \"TrackId\"), \n", - "\tFOREIGN KEY(\"TrackId\") REFERENCES \"Track\" (\"TrackId\"), \n", - "\tFOREIGN KEY(\"PlaylistId\") REFERENCES \"Playlist\" (\"PlaylistId\")\n", - ")\n", - "\n", - "SELECT * FROM 'PlaylistTrack' LIMIT 3;\n", - "PlaylistId TrackId\n", - "1 3402\n", - "1 3389\n", - "1 3390\u001b[0m\n", - "Thought:\u001b[32;1m\u001b[1;3m I can use a SELECT statement to get the total number of tracks in each playlist.\n", - "Action: query_checker_sql_db\n", - "Action Input: SELECT Playlist.Name, COUNT(PlaylistTrack.TrackId) AS TotalTracks FROM Playlist INNER JOIN PlaylistTrack ON Playlist.PlaylistId = PlaylistTrack.PlaylistId GROUP BY Playlist.Name\u001b[0m\n", - "Observation: \u001b[31;1m\u001b[1;3m\n", - "\n", - "SELECT Playlist.Name, COUNT(PlaylistTrack.TrackId) AS TotalTracks FROM Playlist INNER JOIN PlaylistTrack ON Playlist.PlaylistId = PlaylistTrack.PlaylistId GROUP BY Playlist.Name\u001b[0m\n", - "Thought:\u001b[32;1m\u001b[1;3m The query looks correct, I can now execute it.\n", - "Action: query_sql_db\n", - "Action Input: SELECT Playlist.Name, COUNT(PlaylistTrack.TrackId) AS TotalTracks FROM Playlist INNER JOIN PlaylistTrack ON Playlist.PlaylistId = PlaylistTrack.PlaylistId GROUP BY Playlist.Name LIMIT 10\u001b[0m\n", - "Observation: \u001b[36;1m\u001b[1;3m[('90’s Music', 1477), ('Brazilian Music', 39), ('Classical', 75), ('Classical 101 - Deep Cuts', 25), ('Classical 101 - Next Steps', 25), ('Classical 101 - The Basics', 25), ('Grunge', 15), ('Heavy Metal Classic', 26), ('Music', 6580), ('Music Videos', 1)]\u001b[0m\n", - "Thought:\u001b[32;1m\u001b[1;3m I now know the final answer.\n", - "Final Answer: The total number of tracks in each playlist are: '90’s Music' (1477), 'Brazilian Music' (39), 'Classical' (75), 'Classical 101 - Deep Cuts' (25), 'Classical 101 - Next Steps' (25), 'Classical 101 - The Basics' (25), 'Grunge' (15), 'Heavy Metal Classic' (26), 'Music' (6580), 'Music Videos' (1).\u001b[0m\n", + "\u001b[0m\u001b[36;1m\u001b[1;3m[('USA', 523.0600000000003)]\u001b[0m\u001b[32;1m\u001b[1;3mThe country whose customers spent the most is the USA, with a total sales amount of $523.06.\u001b[0m\n", "\n", "\u001b[1m> Finished chain.\u001b[0m\n" ] @@ -464,17 +561,20 @@ { "data": { "text/plain": [ - "\"The total number of tracks in each playlist are: '90’s Music' (1477), 'Brazilian Music' (39), 'Classical' (75), 'Classical 101 - Deep Cuts' (25), 'Classical 101 - Next Steps' (25), 'Classical 101 - The Basics' (25), 'Grunge' (15), 'Heavy Metal Classic' (26), 'Music' (6580), 'Music Videos' (1).\"" + "{'input': \"List the total sales per country. Which country's customers spent the most?\",\n", + " 'output': 'The country whose customers spent the most is the USA, with a total sales amount of $523.06.'}" ] }, - "execution_count": 7, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "agent_executor.run(\n", - " \"Show the total number of tracks in each playlist. The Playlist name should be included in the result.\"\n", + "agent_executor.invoke(\n", + " {\n", + " \"input\": \"List the total sales per country. Which country's customers spent the most?\"\n", + " }\n", ")" ] }, @@ -490,11 +590,9 @@ }, { "cell_type": "code", - "execution_count": 16, - "id": "9fe4901e-f9e1-4022-b6bc-80e2b2d6a3a4", - "metadata": { - "tags": [] - }, + "execution_count": 30, + "id": "4d8d8933-c1e5-4ba9-8143-1059606c4adb", + "metadata": {}, "outputs": [ { "name": "stdout", @@ -503,49 +601,15 @@ "\n", "\n", "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n", - "\u001b[32;1m\u001b[1;3mAction: list_tables_sql_db\n", - "Action Input: \"\"\u001b[0m\n", - "Observation: \u001b[38;5;200m\u001b[1;3mMediaType, Track, Invoice, Album, Playlist, Customer, Employee, InvoiceLine, PlaylistTrack, Genre, Artist\u001b[0m\n", - "Thought:\u001b[32;1m\u001b[1;3m I should look at the schema of the Artist, InvoiceLine, and Track tables to see what columns I can use.\n", - "Action: schema_sql_db\n", - "Action Input: \"Artist, InvoiceLine, Track\"\u001b[0m\n", - "Observation: \u001b[33;1m\u001b[1;3m\n", - "CREATE TABLE \"Artist\" (\n", - "\t\"ArtistId\" INTEGER NOT NULL, \n", - "\t\"Name\" NVARCHAR(120), \n", - "\tPRIMARY KEY (\"ArtistId\")\n", - ")\n", + "\u001b[32;1m\u001b[1;3m\n", + "Invoking: `sql_db_list_tables` with ``\n", "\n", - "SELECT * FROM 'Artist' LIMIT 3;\n", - "ArtistId Name\n", - "1 AC/DC\n", - "2 Accept\n", - "3 Aerosmith\n", "\n", - "\n", - "CREATE TABLE \"Track\" (\n", - "\t\"TrackId\" INTEGER NOT NULL, \n", - "\t\"Name\" NVARCHAR(200) NOT NULL, \n", - "\t\"AlbumId\" INTEGER, \n", - "\t\"MediaTypeId\" INTEGER NOT NULL, \n", - "\t\"GenreId\" INTEGER, \n", - "\t\"Composer\" NVARCHAR(220), \n", - "\t\"Milliseconds\" INTEGER NOT NULL, \n", - "\t\"Bytes\" INTEGER, \n", - "\t\"UnitPrice\" NUMERIC(10, 2) NOT NULL, \n", - "\tPRIMARY KEY (\"TrackId\"), \n", - "\tFOREIGN KEY(\"MediaTypeId\") REFERENCES \"MediaType\" (\"MediaTypeId\"), \n", - "\tFOREIGN KEY(\"GenreId\") REFERENCES \"Genre\" (\"GenreId\"), \n", - "\tFOREIGN KEY(\"AlbumId\") REFERENCES \"Album\" (\"AlbumId\")\n", - ")\n", - "\n", - "SELECT * FROM 'Track' LIMIT 3;\n", - "TrackId Name AlbumId MediaTypeId GenreId Composer Milliseconds Bytes UnitPrice\n", - "1 For Those About To Rock (We Salute You) 1 1 1 Angus Young, Malcolm Young, Brian Johnson 343719 11170334 0.99\n", - "2 Balls to the Wall 2 2 1 None 342562 5510424 0.99\n", - "3 Fast As a Shark 3 2 1 F. Baltes, S. Kaufman, U. Dirkscneider & W. Hoffman 230619 3990994 0.99\n", + "\u001b[0m\u001b[38;5;200m\u001b[1;3mAlbum, Artist, Customer, Employee, Genre, Invoice, InvoiceLine, MediaType, Playlist, PlaylistTrack, Track\u001b[0m\u001b[32;1m\u001b[1;3m\n", + "Invoking: `sql_db_schema` with `InvoiceLine`\n", "\n", "\n", + "\u001b[0m\u001b[33;1m\u001b[1;3m\n", "CREATE TABLE \"InvoiceLine\" (\n", "\t\"InvoiceLineId\" INTEGER NOT NULL, \n", "\t\"InvoiceId\" INTEGER NOT NULL, \n", @@ -557,35 +621,38 @@ "\tFOREIGN KEY(\"InvoiceId\") REFERENCES \"Invoice\" (\"InvoiceId\")\n", ")\n", "\n", - "SELECT * FROM 'InvoiceLine' LIMIT 3;\n", - "InvoiceLineId InvoiceId TrackId UnitPrice Quantity\n", - "1 1 2 0.99 1\n", - "2 1 4 0.99 1\n", - "3 2 6 0.99 1\u001b[0m\n", - "Thought:\u001b[32;1m\u001b[1;3m I should query the database to get the top 3 best selling artists.\n", - "Action: query_sql_db\n", - "Action Input: SELECT Artist.Name, SUM(InvoiceLine.Quantity) AS TotalQuantity FROM Artist INNER JOIN Track ON Artist.ArtistId = Track.ArtistId INNER JOIN InvoiceLine ON Track.TrackId = InvoiceLine.TrackId GROUP BY Artist.Name ORDER BY TotalQuantity DESC LIMIT 3\u001b[0m\n", - "Observation: \u001b[36;1m\u001b[1;3mError: (sqlite3.OperationalError) no such column: Track.ArtistId\n", - "[SQL: SELECT Artist.Name, SUM(InvoiceLine.Quantity) AS TotalQuantity FROM Artist INNER JOIN Track ON Artist.ArtistId = Track.ArtistId INNER JOIN InvoiceLine ON Track.TrackId = InvoiceLine.TrackId GROUP BY Artist.Name ORDER BY TotalQuantity DESC LIMIT 3]\n", - "(Background on this error at: https://sqlalche.me/e/14/e3q8)\u001b[0m\n", - "Thought:\u001b[32;1m\u001b[1;3m I should double check my query before executing it.\n", - "Action: query_checker_sql_db\n", - "Action Input: SELECT Artist.Name, SUM(InvoiceLine.Quantity) AS TotalQuantity FROM Artist INNER JOIN Track ON Artist.ArtistId = Track.ArtistId INNER JOIN InvoiceLine ON Track.TrackId = InvoiceLine.TrackId GROUP BY Artist.Name ORDER BY TotalQuantity DESC LIMIT 3\u001b[0m\n", - "Observation: \u001b[31;1m\u001b[1;3m\n", - "\n", - "SELECT Artist.Name, SUM(InvoiceLine.Quantity) AS TotalQuantity \n", - "FROM Artist \n", - "INNER JOIN Track ON Artist.ArtistId = Track.ArtistId \n", - "INNER JOIN InvoiceLine ON Track.TrackId = InvoiceLine.TrackId \n", - "GROUP BY Artist.Name \n", - "ORDER BY TotalQuantity DESC \n", - "LIMIT 3;\u001b[0m\n", - "Thought:\u001b[32;1m\u001b[1;3m I now know the final answer.\n", - "Action: query_sql_db\n", - "Action Input: SELECT Artist.Name, SUM(InvoiceLine.Quantity) AS TotalQuantity FROM Artist INNER JOIN Album ON Artist.ArtistId = Album.ArtistId INNER JOIN Track ON Album.AlbumId = Track.AlbumId INNER JOIN InvoiceLine ON Track.TrackId = InvoiceLine.TrackId GROUP BY Artist.Name ORDER BY TotalQuantity DESC LIMIT 3\u001b[0m\n", - "Observation: \u001b[36;1m\u001b[1;3m[('Iron Maiden', 140), ('U2', 107), ('Metallica', 91)]\u001b[0m\n", - "Thought:\u001b[32;1m\u001b[1;3m I now know the final answer.\n", - "Final Answer: The top 3 best selling artists are Iron Maiden, U2, and Metallica.\u001b[0m\n", + "/*\n", + "3 rows from InvoiceLine table:\n", + "InvoiceLineId\tInvoiceId\tTrackId\tUnitPrice\tQuantity\n", + "1\t1\t2\t0.99\t1\n", + "2\t1\t4\t0.99\t1\n", + "3\t2\t6\t0.99\t1\n", + "*/\u001b[0m\u001b[32;1m\u001b[1;3m\n", + "Invoking: `sql_db_schema` with `Artist`\n", + "\n", + "\n", + "\u001b[0m\u001b[33;1m\u001b[1;3m\n", + "CREATE TABLE \"Artist\" (\n", + "\t\"ArtistId\" INTEGER NOT NULL, \n", + "\t\"Name\" NVARCHAR(120), \n", + "\tPRIMARY KEY (\"ArtistId\")\n", + ")\n", + "\n", + "/*\n", + "3 rows from Artist table:\n", + "ArtistId\tName\n", + "1\tAC/DC\n", + "2\tAccept\n", + "3\tAerosmith\n", + "*/\u001b[0m\u001b[32;1m\u001b[1;3m\n", + "Invoking: `sql_db_query` with `SELECT Artist.Name, SUM(InvoiceLine.Quantity) AS TotalQuantity FROM Artist JOIN Album ON Artist.ArtistId = Album.ArtistId JOIN Track ON Album.AlbumId = Track.AlbumId JOIN InvoiceLine ON Track.TrackId = InvoiceLine.TrackId GROUP BY Artist.Name ORDER BY TotalQuantity DESC LIMIT 3`\n", + "\n", + "\n", + "\u001b[0m\u001b[36;1m\u001b[1;3m[('Iron Maiden', 140), ('U2', 107), ('Metallica', 91)]\u001b[0m\u001b[32;1m\u001b[1;3mThe top 3 best selling artists are:\n", + "\n", + "1. Iron Maiden - 140 total quantity sold\n", + "2. U2 - 107 total quantity sold\n", + "3. Metallica - 91 total quantity sold\u001b[0m\n", "\n", "\u001b[1m> Finished chain.\u001b[0m\n" ] @@ -593,17 +660,26 @@ { "data": { "text/plain": [ - "'The top 3 best selling artists are Iron Maiden, U2, and Metallica.'" + "{'input': 'Who are the top 3 best selling artists?',\n", + " 'output': 'The top 3 best selling artists are:\\n\\n1. Iron Maiden - 140 total quantity sold\\n2. U2 - 107 total quantity sold\\n3. Metallica - 91 total quantity sold'}" ] }, - "execution_count": 16, + "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "agent_executor.run(\"Who are the top 3 best selling artists?\")" + "agent_executor.invoke({\"input\": \"Who are the top 3 best selling artists?\"})" ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0ca6724d-89ee-49eb-8cdb-5cf66d242a83", + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -622,7 +698,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.12" + "version": "3.9.16" } }, "nbformat": 4,