├── .gitignore ├── LICENSE ├── README.md ├── assets ├── data analysis with llm agent demo.gif └── flow.png ├── chainlit.md ├── chatbot.log ├── poetry.lock ├── pyproject.toml ├── requirements.txt └── src ├── data-analysis-llm-agent ├── app.py ├── bot.py ├── chatbot.log ├── tools.py └── utils.py └── data └── movies.db /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore compiled Python files 2 | *.pyc 3 | __pycache__/ 4 | 5 | # Ignore environment-specific settings files 6 | .env 7 | 8 | # Ignore virtual environment directories 9 | venv/ 10 | env/ 11 | 12 | # Ignore chainlit configuration folder 13 | .chainlit/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Conversational AI with Function Calling for Data Analysis 2 | 3 | ## Overview 4 | 5 | The chatbot is designed to provide data analysis insights from database based on a predefined schema. It is built using Chainlit and OpenAI's GPT-3.5-turbo-1106 model. The chatbot utilizes OpenAI function calling to decide when to use tools and in case of db error it retries. 6 | 7 | https://github.com/crazycloud/data-analysis-llm-agent/assets/1109740/0ede2932-643c-4a2f-b557-40e9571ba841 8 | 9 | ## How to run it 10 | 11 | ```python 12 | cd 13 | pip install -r requirements.txt 14 | chainlit run src/data-analysis-llm-agent/app.py --port 8002 15 | ``` 16 | 17 | ## Available Tools 18 | 19 | The chatbot has access to a range of tools, including: 20 | Database Query: Execute database queries to retrieve data. 21 | Plot Chart: Generate visualizations to help users understand data insights. 22 | 23 | ## Code 24 | 25 | **app.py**: The main application file, which sets up the Chainlit framework and defines the chatbot's logic. 26 | **bot.py**: The chatbot class which handles conversation history, talking to llm and parallel function calling. 27 | **utils.py**: Utility functions for db introspection and format conversion. 28 | **tools.py**: Tool functions for executing database queries and plotting charts. 29 | **.env**: openai api key 30 | 31 | ## Data 32 | 33 | It uses simple sqlite3 database of movie and actors from https://github.com/slackhq/sqlite-python-connect/. The schema is very simple with only two tables but should work with more complex schema. 34 | 35 | ## How it Works 36 | 37 | Here's a high-level overview of how the application works: 38 | 39 | - The user sends a message to the chatbot. 40 | - The response may include tool calls. Tool calls include fetching results from database or generating plots. 41 | - The tool results are added back to the list of conversation messages. Everything including tool results, error messages are added to the conversation and sent back to llm to get a second response. 42 | - The Execution loop is run for MAX_ITER times if each new response has a tool call. 43 | - The chatbot sends the response back to the user, including any plots or tables generated by the tool calls. 44 | 45 | ![Function Calling with DB Query tool and Visualization tool](./assets/flow.png) 46 | 47 | ## Key Takeaways 48 | 49 | 1. Importance of Foreign Key Constraints 50 | Providing foreign key constraints in the database schema is crucial for generating accurate and efficient SQL queries. Without them, the LLM may generate multiple parallel function calls with separate queries or incorrect queries. By including foreign key constraints, the LLM can create SQL queries with proper joins, ensuring more accurate data retrieval. 51 | 52 | 2. LLM's Limited Domain Knowledge 53 | The LLM has knowledge of the database schema but doesn't know about the underlying data. For instance, it may not be aware of the actual data values in a column, leading to incorrect queries. If severity table a column status, the LLM generated a query with 'where status = 'LOW'' despite the actual values being 'CRITICAL', and 'NORMAL'. 54 | 55 | 3. Multi-Step Flow for Error Handling 56 | A multi-step execution flow is necessary to handle errors encountered during SQL query execution. By providing the error message along with the previous conversation history, the LLM can reflect and correct its mistakes. This ensures a more robust and accurate conversation flow. 57 | 58 | 4. Valid but Incorrect SQL Queries 59 | The LLM may generate valid but incorrect SQL queries, which can lead to incorrect results without any error messages. This raises concerns about trusting the LLM's responses. When I asked "provide top 10 movies", it responded with 10 movies but when I asked how are this top movies, it's responded with "The top 10 movies are based on the initial 10 movies in the database." 60 | 61 | 5. Handling Different Data Scales 62 | The LLM may not always be aware of the different scales used in various data columns. For instance, it may generate a query to find drastic differences in Metacritic and IMDB scores without considering that they are on different scales (0-100 and 0-10, respectively). 63 | -------------------------------------------------------------------------------- /assets/data analysis with llm agent demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crazycloud/data-analysis-llm-agent/47e3dabc709ddd777064d518e63fc43df649463a/assets/data analysis with llm agent demo.gif -------------------------------------------------------------------------------- /assets/flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crazycloud/data-analysis-llm-agent/47e3dabc709ddd777064d518e63fc43df649463a/assets/flow.png -------------------------------------------------------------------------------- /chainlit.md: -------------------------------------------------------------------------------- 1 | # Conversational AI with Function Calling 2 | 3 | ## Overview 4 | 5 | The chatbot is designed to provide data analysis insights based on a predefined schema. It is built using Chainlit and OpenAI's GPT-3.5-turbo-1106 model. The chatbot utilizes OpenAI function calling to decide when to use tools and in case of db error it retries. 6 | 7 | ## Available Tools 8 | 9 | The chatbot has access to a range of tools, including: 10 | Database Query: Execute database queries to retrieve data. 11 | Plot Chart: Generate visualizations to help users understand data insights. 12 | 13 | ## Architecture 14 | 15 | The application consists of the following components: 16 | 17 | **app.py**: The main application file, which sets up the Chainlit framework and defines the chatbot's logic. 18 | **bot.py**: The chatbot's logic, which handles incoming user messages and generates responses using the OpenAI API. 19 | **utils.py**: Utility functions for db introspection and format conversion 20 | **tools.py**: Tool functions for executing database queries and plotting charts. 21 | **.env**: openai api key 22 | 23 | ## How it Works 24 | 25 | Here's a high-level overview of how the application works: 26 | 27 | - The user sends a message to the chatbot. 28 | - The response may include tool calls. Tool calls include fetching results from database or generating plots. 29 | - The tool results are added back to the list of conversation messages. Everything including tool results, error messages are added to the conversation and sent back to llm to get a second response. 30 | - The Execution loop is run for MAX_ITER times if each new response has a tool call. 31 | - The chatbot sends the response back to the user, including any plots or tables generated by the tool calls. 32 | 33 | ## Conclusion 34 | 35 | This repository contains a chatbot application built using Chainlit and OpenAI's GPT-3.5-turbo-1106 model. The chatbot provides data analysis insights based on a predefined schema and tools, utilizing Agent AI and reflection capabilities to improve its accuracy. 36 | -------------------------------------------------------------------------------- /chatbot.log: -------------------------------------------------------------------------------- 1 | Created default chainlit markdown file at /Users/stitch/Documents/code-23/data analysis agent/chainlit.md 2 | Your app is available at http://localhost:8000 3 | Translation file for en-GB not found. Using default translation en-US. 4 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 5 | Translation file for en-GB not found. Using default translation en-US. 6 | Your app is available at http://localhost:8000 7 | Translation file for en-GB not found. Using default translation en-US. 8 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 9 | Your app is available at http://localhost:8000 10 | Translation file for en-GB not found. Using default translation en-US. 11 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 12 | Translation file for en-GB not found. Using default translation en-US. 13 | Translation file for en-GB not found. Using default translation en-US. 14 | Translation file for en-GB not found. Using default translation en-US. 15 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 16 | Translation file for en-GB not found. Using default translation en-US. 17 | HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK" 18 | User message: top 10 movies 19 | Assistant response: None 20 | Calling query_db with {'sql_query': 'SELECT title, director, year, rating, genres FROM movies LIMIT 10'} 21 | Tool Call: {'tool_call_id': 'call_IEC6mGcIJXShLYSmqCHyNWPo', 'role': 'tool', 'name': 'query_db', 'content': '| title | director | year | rating | genres |\n| --- | --- | --- | --- | --- |\n| 12 Angry Men | Sidney Lumet | 1957 | APPROVED | Crime, Drama |\n| 12 Years a Slave | Steve McQueen | 2013 | R | Biography, Drama, History |\n| 2001: A Space Odyssey | Stanley Kubrick | 1968 | G | Adventure, Sci-Fi |\n| 3 Idiots | Rajkumar Hirani | 2009 | PG-13 | Comedy, Drama |\n| 8½ | Federico Fellini | 1963 | NOT RATED | Drama |\n| A Beautiful Mind | Ron Howard | 2001 | PG-13 | Biography, Drama |\n| A Clockwork Orange | Stanley Kubrick | 1971 | R | Crime, Drama, Sci-Fi |\n| A Separation | Asghar Farhadi | 2011 | PG-13 | Drama, Mystery |\n| A Wednesday | Neeraj Pandey | 2008 | NOT RATED | Crime, Drama, Mystery |\n| Alien | Ridley Scott | 1979 | R | Horror, Sci-Fi |\n'} 22 | HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK" 23 | HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK" 24 | User message: how are these top 10 ? 25 | Assistant response: The top 10 movies are based on the initial 10 movies in the database. If you have specific criteria or ratings in mind for what defines the "top" movies, please let me know and I can retrieve movies based on those criteria. 26 | HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK" 27 | User message: when I say top 10 I mean best reviewed 28 | Assistant response: None 29 | Calling query_db with {'sql_query': 'SELECT title, director, year, rating, genres, imdb_score, imdb_votes FROM movies ORDER BY imdb_score DESC, imdb_votes DESC LIMIT 10'} 30 | Tool Call: {'tool_call_id': 'call_xh1zEhwga5nvbSypNmwDcrmT', 'role': 'tool', 'name': 'query_db', 'content': "| title | director | year | rating | genres | imdb_score | imdb_votes |\n| --- | --- | --- | --- | --- | --- | --- |\n| The Shawshank Redemption | Frank Darabont | 1994 | R | Drama | 9.3 | 1967060 |\n| The Godfather | Francis Ford Coppola | 1972 | R | Crime, Drama | 9.2 | 1353121 |\n| The Dark Knight | Christopher Nolan | 2008 | PG-13 | Action, Crime, Drama | 9 | 1937798 |\n| The Godfather: Part II | Francis Ford Coppola | 1974 | R | Crime, Drama | 9 | 931660 |\n| Pulp Fiction | Quentin Tarantino | 1994 | R | Crime, Drama | 8.9 | 1537588 |\n| The Lord of the Rings: The Return of the King | Peter Jackson | 2003 | PG-13 | Adventure, Drama, Fantasy | 8.9 | 1408815 |\n| Schindler's List | Steven Spielberg | 1993 | R | Biography, Drama, History | 8.9 | 1016413 |\n| The Good, the Bad and the Ugly | Sergio Leone | 1966 | R | Western | 8.9 | 586129 |\n| 12 Angry Men | Sidney Lumet | 1957 | APPROVED | Crime, Drama | 8.9 | 551194 |\n| Inception | Christopher Nolan | 2010 | PG-13 | Action, Adventure, Sci-Fi | 8.8 | 1721888 |\n"} 31 | HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK" 32 | Your app is available at http://localhost:8000 33 | Translation file for en-GB not found. Using default translation en-US. 34 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 35 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 36 | HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK" 37 | User message: top 10 movies 38 | Assistant response: None 39 | Calling query_db with {'sql_query': 'SELECT title, director, year, rating, genres, runtime FROM movies LIMIT 10'} 40 | Tool Call: {'tool_call_id': 'call_wUsmhAlOM5NzfBWsUPvFrp2A', 'role': 'tool', 'name': 'query_db', 'content': '| title | director | year | rating | genres | runtime |\n| --- | --- | --- | --- | --- | --- |\n| 12 Angry Men | Sidney Lumet | 1957 | APPROVED | Crime, Drama | 96 |\n| 12 Years a Slave | Steve McQueen | 2013 | R | Biography, Drama, History | 134 |\n| 2001: A Space Odyssey | Stanley Kubrick | 1968 | G | Adventure, Sci-Fi | 149 |\n| 3 Idiots | Rajkumar Hirani | 2009 | PG-13 | Comedy, Drama | 170 |\n| 8½ | Federico Fellini | 1963 | NOT RATED | Drama | 138 |\n| A Beautiful Mind | Ron Howard | 2001 | PG-13 | Biography, Drama | 135 |\n| A Clockwork Orange | Stanley Kubrick | 1971 | R | Crime, Drama, Sci-Fi | 136 |\n| A Separation | Asghar Farhadi | 2011 | PG-13 | Drama, Mystery | 123 |\n| A Wednesday | Neeraj Pandey | 2008 | NOT RATED | Crime, Drama, Mystery | 104 |\n| Alien | Ridley Scott | 1979 | R | Horror, Sci-Fi | 116 |\n'} 41 | Translation file for en-GB not found. Using default translation en-US. 42 | HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK" 43 | Translation file for en-GB not found. Using default translation en-US. 44 | Your app is available at http://localhost:8002 45 | Translation file for en-GB not found. Using default translation en-US. 46 | Translation file for en-GB not found. Using default translation en-US. 47 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 48 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 49 | Translation file for en-GB not found. Using default translation en-US. 50 | HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK" 51 | User message: scatter plot of number of movies over last 10 years 52 | Assistant response: None 53 | Calling query_db with {'sql_query': 'SELECT year as year, COUNT(id) as num_movies FROM movies GROUP BY year ORDER BY year DESC LIMIT 10'} 54 | Tool Call: {'tool_call_id': 'call_i7HI6vtspd19ODB4EDthpnKL', 'role': 'tool', 'name': 'query_db', 'content': '| year | num_movies |\n| --- | --- |\n| 2018 | 3 |\n| 2017 | 4 |\n| 2016 | 5 |\n| 2015 | 4 |\n| 2014 | 6 |\n| 2013 | 4 |\n| 2012 | 4 |\n| 2011 | 5 |\n| 2010 | 5 |\n| 2009 | 6 |\n'} 55 | HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK" 56 | Calling plot_chart with {'plot_type': 'scatter', 'x_values': ['2018', '2017', '2016', '2015', '2014', '2013', '2012', '2011', '2010', '2009'], 'y_values': [3, 4, 5, 4, 6, 4, 4, 5, 5, 6], 'plot_title': 'Number of Movies Over Last 10 Years', 'x_label': 'Year', 'y_label': 'Number of Movies'} 57 | Tool Call: {'tool_call_id': 'call_7T0jc70vdUxFOp8hdBg1lu8r', 'role': 'tool', 'name': 'plot_chart', 'content': Figure({ 58 | 'data': [{'marker': {'color': '#df84ff', 'line': {'width': 1}, 'opacity': 0.7, 'size': 10}, 59 | 'mode': 'markers', 60 | 'type': 'scatter', 61 | 'x': [2018, 2017, 2016, 2015, 2014, 2013, 2012, 2011, 2010, 2009], 62 | 'y': [3, 4, 5, 4, 6, 4, 4, 5, 5, 6]}], 63 | 'layout': {'margin': {'b': 60, 'l': 60, 'r': 60, 't': 80}, 64 | 'paper_bgcolor': '#f8f8f8', 65 | 'plot_bgcolor': '#f8f8f8', 66 | 'template': '...', 67 | 'title': {'font': {'color': '#333', 'family': 'Arial', 'size': 20}, 68 | 'text': 'Number of Movies Over Last 10 Years Scatter Chart'}, 69 | 'xaxis': {'gridcolor': '#f0f0f0', 70 | 'tickfont': {'size': 14}, 71 | 'title': {'font': {'size': 18}, 'text': 'Year'}}, 72 | 'yaxis': {'gridcolor': '#f0f0f0', 73 | 'tickfont': {'size': 14}, 74 | 'title': {'font': {'size': 18}, 'text': 'Number of Movies'}}} 75 | })} 76 | HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK" 77 | Your app is available at http://localhost:8002 78 | Translation file for en-GB not found. Using default translation en-US. 79 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 80 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 81 | HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK" 82 | User message: show top movies based on imdb scores 83 | Assistant response: None 84 | Calling query_db with {'sql_query': 'SELECT title, imdb_score FROM movies ORDER BY imdb_score DESC LIMIT 5'} 85 | Tool Call: {'tool_call_id': 'call_wmDffeitXXM3cpkB0PYtR4gS', 'role': 'tool', 'name': 'query_db', 'content': '| title | imdb_score |\n| --- | --- |\n| The Shawshank Redemption | 9.3 |\n| The Godfather | 9.2 |\n| The Dark Knight | 9 |\n| The Godfather: Part II | 9 |\n| 12 Angry Men | 8.9 |\n'} 86 | HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK" 87 | Calling plot_chart with {'plot_type': 'bar', 'x_values': ['The Shawshank Redemption', 'The Godfather', 'The Dark Knight', 'The Godfather: Part II', '12 Angry Men'], 'y_values': [9.3, 9.2, 9, 9, 8.9], 'plot_title': 'Top Movies Based on IMDB Scores', 'x_label': 'Movies', 'y_label': 'IMDB Scores'} 88 | Tool Call: {'tool_call_id': 'call_7unT5WZUu9ySKj4rY1DlO481', 'role': 'tool', 'name': 'plot_chart', 'content': Figure({ 89 | 'data': [{'marker': {'color': '#24C8BF', 'line': {'width': 1}}, 90 | 'type': 'bar', 91 | 'x': [The Shawshank Redemption, The Godfather, The Dark Knight, The 92 | Godfather: Part II, 12 Angry Men], 93 | 'y': [9.3, 9.2, 9, 9, 8.9]}], 94 | 'layout': {'margin': {'b': 60, 'l': 60, 'r': 60, 't': 80}, 95 | 'paper_bgcolor': '#f8f8f8', 96 | 'plot_bgcolor': '#f8f8f8', 97 | 'template': '...', 98 | 'title': {'font': {'color': '#333', 'family': 'Arial', 'size': 20}, 99 | 'text': 'Top Movies Based on IMDB Scores Bar Chart'}, 100 | 'xaxis': {'gridcolor': '#f0f0f0', 101 | 'tickfont': {'size': 14}, 102 | 'title': {'font': {'size': 18}, 'text': 'Movies'}}, 103 | 'yaxis': {'gridcolor': '#f0f0f0', 104 | 'tickfont': {'size': 14}, 105 | 'title': {'font': {'size': 18}, 'text': 'IMDB Scores'}}} 106 | })} 107 | HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK" 108 | HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK" 109 | User message: tell me about popular actors 110 | Assistant response: None 111 | Calling query_db with {'sql_query': 'SELECT name, COUNT(name) as appearance_count FROM actors GROUP BY name ORDER BY appearance_count DESC LIMIT 5'} 112 | Tool Call: {'tool_call_id': 'call_Axv1ZFZHPwzOk4nZ1eFXmCq9', 'role': 'tool', 'name': 'query_db', 'content': '| name | appearance_count |\n| --- | --- |\n| Paul Bateman | 5 |\n| Norman Gay | 4 |\n| Noriko Honma | 4 |\n| Kevin Spacey | 4 |\n| John Rhys-Davies | 4 |\n'} 113 | HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK" 114 | HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK" 115 | User message: show me movie trends in last 5 years 116 | Assistant response: None 117 | Calling query_db with {'sql_query': "SELECT year, COUNT(title) as movie_count FROM movies WHERE year >= (strftime('%Y', 'now') - 5) GROUP BY year ORDER BY year"} 118 | Tool Call: {'tool_call_id': 'call_HoIevkGplv4Wo9RaRY4PpHAu', 'role': 'tool', 'name': 'query_db', 'content': '| year | movie_count |\n| --- | --- |\n'} 119 | HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK" 120 | HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK" 121 | User message: ok, over 10 years 122 | Assistant response: None 123 | Calling query_db with {'sql_query': "SELECT year, COUNT(title) as movie_count FROM movies WHERE year >= (strftime('%Y', 'now') - 10) GROUP BY year ORDER BY year"} 124 | Tool Call: {'tool_call_id': 'call_jOhpymM38RyaoyR6iqDhuktu', 'role': 'tool', 'name': 'query_db', 'content': '| year | movie_count |\n| --- | --- |\n| 2014 | 6 |\n| 2015 | 4 |\n| 2016 | 5 |\n| 2017 | 4 |\n| 2018 | 3 |\n'} 125 | HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK" 126 | HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK" 127 | User message: plot it 128 | Assistant response: None 129 | Calling plot_chart with {'plot_type': 'line', 'x_values': ['2014', '2015', '2016', '2017', '2018'], 'y_values': [6, 4, 5, 4, 3], 'plot_title': 'Movie Trends Over the Last 10 Years', 'x_label': 'Year', 'y_label': 'Number of Movies'} 130 | Tool Call: {'tool_call_id': 'call_BNrfo3QxesPmNOWqROfebX6s', 'role': 'tool', 'name': 'plot_chart', 'content': Figure({ 131 | 'data': [{'line': {'color': '#ff9900', 'width': 2}, 132 | 'marker': {'color': '#ff9900', 'line': {'width': 1}, 'size': 8}, 133 | 'mode': 'lines+markers', 134 | 'type': 'scatter', 135 | 'x': [2014, 2015, 2016, 2017, 2018], 136 | 'y': [6, 4, 5, 4, 3]}], 137 | 'layout': {'margin': {'b': 60, 'l': 60, 'r': 60, 't': 80}, 138 | 'paper_bgcolor': '#f8f8f8', 139 | 'plot_bgcolor': '#f8f8f8', 140 | 'template': '...', 141 | 'title': {'font': {'color': '#333', 'family': 'Arial', 'size': 20}, 142 | 'text': 'Movie Trends Over the Last 10 Years Line Chart'}, 143 | 'xaxis': {'gridcolor': '#f0f0f0', 144 | 'tickfont': {'size': 14}, 145 | 'title': {'font': {'size': 18}, 'text': 'Year'}}, 146 | 'yaxis': {'gridcolor': '#f0f0f0', 147 | 'tickfont': {'size': 14}, 148 | 'title': {'font': {'size': 18}, 'text': 'Number of Movies'}}} 149 | })} 150 | HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK" 151 | Translation file for en-GB not found. Using default translation en-US. 152 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "data-analysis-convai" 3 | version = "0.1.0" 4 | description = "Conversation AI for data analysis using Function Calling and Agent Execution. Query database to get result and display it in conversation ux using chainlit" 5 | authors = ["sourabh shrishrimal"] 6 | license = "Apache 2.0" 7 | readme = "README.md" 8 | 9 | [tool.poetry.dependencies] 10 | python = "^3.10" 11 | openai = "^1.24.1" 12 | python-dotenv = "^1.0.1" 13 | plotly = "^5.21.0" 14 | psycopg2-binary = "^2.9.9" 15 | chainlit = "^1.0.506" 16 | 17 | [build-system] 18 | requires = ["poetry-core"] 19 | build-backend = "poetry.core.masonry.api" 20 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | chainlit==1.2.3 2 | openai==4.5.6 3 | httpx==0.23.0 4 | logging==0.9.1 5 | os==0.1.1 6 | json==2.0.9 7 | asyncio==0.10.0 -------------------------------------------------------------------------------- /src/data-analysis-llm-agent/app.py: -------------------------------------------------------------------------------- 1 | import chainlit as cl 2 | from dotenv import load_dotenv 3 | import logging 4 | 5 | # Load environment variables from .env file 6 | load_dotenv("../.env") 7 | from plotly.graph_objs import Figure 8 | 9 | from utils import generate_sqlite_table_info_query, format_table_info 10 | from tools import tools_schema, run_sqlite_query, plot_chart 11 | from bot import ChatBot 12 | 13 | # Configure logging 14 | logging.basicConfig(filename='chatbot.log', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') 15 | 16 | logger = logging.getLogger() 17 | logger.addHandler(logging.FileHandler('chatbot.log')) 18 | 19 | MAX_ITER = 5 20 | schema_table_pairs = [] 21 | 22 | tool_run_sqlite_query = cl.step(type="tool", show_input="json", language="str")(run_sqlite_query) 23 | tool_plot_chart = cl.step(type="tool", show_input="json", language="json")(plot_chart) 24 | original_run_sqlite_query = tool_run_sqlite_query.__wrapped__ 25 | # cl.instrument_openai() 26 | # for automatic steps 27 | 28 | @cl.on_chat_start 29 | async def on_chat_start(): 30 | # build schema query 31 | table_info_query = generate_sqlite_table_info_query(schema_table_pairs) 32 | 33 | # execute query 34 | result, column_names = await original_run_sqlite_query(table_info_query, markdown=False) 35 | 36 | # format result into string to be used in prompt 37 | # table_info = format_table_info(result, column_names) 38 | table_info = '\n'.join([item[0] for item in result]) 39 | 40 | system_message = f"""You are an expert in data analysis. You will provided valuable insights for business user based on their request. 41 | Before responding, You will make sure that user ask pertains to data analysis on provided schema, else decline. 42 | If user request some data, you will build sql query based on the user request for sqlite db from the provided schema/table details and call query_db tools to fetch data from database with the correct/relevant query that gives correct result. 43 | You have access to tool to execute database query and get results and to plot the query results. 44 | One you have provided the data, you will do reflection to see if you have provided correct data or not. because you don't know the data beforehand but only the schema so you might discover some new insights while reflecting. 45 | 46 | Follow this Guidelines 47 | - It is very important that if you need certain inputs to proceed or are not sure about anything, you may ask question, but try to use your intelligence to understand user intention and also let user know if you make assumptions. 48 | - In the response message do not provide technical details like sql, table or column details, the response will be read by business user not technical person. 49 | - provide rich markdown response - if it is table data show it in markdown table format 50 | - In case you get a database error, you will reflect and try to call the correct sql query 51 | - Limit top N queries to 5 and let the user know that you have limited results 52 | - Limit number of columns to 5-8. Wisely Choose top columns to query in SQL queries based on the user request 53 | - when user asks for all records - limit results to 10 and tell them they you are limiting records 54 | - in SQL queries to fetch data, you must cast date and numeric columns into readable form(easy to read in string format) 55 | - Design robust sql queries that takes care of uppercase, lowercase or some variations because you don't know the complete data or list of enumerable values in columns. 56 | - Pay careful attention to the schema and table details I have provided below. Only use columns and tables mentioned in the schema details 57 | 58 | Here are complete schema details with column details: 59 | {table_info}""" 60 | 61 | # print(system_message) 62 | 63 | tool_functions = { 64 | "query_db": tool_run_sqlite_query, 65 | "plot_chart": tool_plot_chart 66 | } 67 | 68 | cl.user_session.set("bot", ChatBot(system_message, tools_schema, tool_functions)) 69 | 70 | 71 | @cl.on_message 72 | async def on_message(message: cl.Message): 73 | bot = cl.user_session.get("bot") 74 | 75 | msg = cl.Message(author="Assistant", content="") 76 | await msg.send() 77 | 78 | # step 1: user request and first response from the bot 79 | response_message = await bot(message.content) 80 | msg.content = response_message.content or "" 81 | 82 | # pending message to be sent 83 | if len(msg.content)>0: 84 | await msg.update() 85 | 86 | 87 | # step 2: check tool_calls - as long as there are tool calls and it doesn't cross MAX_ITER count, call iteratively 88 | cur_iter = 0 89 | tool_calls = response_message.tool_calls 90 | while cur_iter <= MAX_ITER: 91 | 92 | # if tool_calls: 93 | if tool_calls: 94 | bot.messages.append(response_message) # add tool call to messages before calling executing function calls 95 | response_message, function_responses = await bot.call_functions(tool_calls) 96 | 97 | # response_message is response after completing function calls and sending it back to the bot 98 | if response_message.content and len(response_message.content)>0: 99 | await cl.Message(author="Assistant", content=response_message.content).send() 100 | 101 | # reassign tool_calls from new response 102 | tool_calls = response_message.tool_calls 103 | 104 | # some responses like charts should be displayed explicitly 105 | function_responses_to_display = [res for res in function_responses if res['name'] in bot.exclude_functions] 106 | for function_res in function_responses_to_display: 107 | # plot chart 108 | if isinstance(function_res["content"], Figure): 109 | chart = cl.Plotly(name="chart", figure=function_res['content'], display="inline") 110 | await cl.Message(author="Assistant", content="", elements=[chart]).send() 111 | else: 112 | break 113 | cur_iter += 1 114 | -------------------------------------------------------------------------------- /src/data-analysis-llm-agent/bot.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import logging 3 | import os 4 | import json 5 | 6 | 7 | import httpx 8 | from openai import AsyncOpenAI 9 | 10 | logging.info(f"User message") 11 | 12 | model = "gpt-3.5-turbo-1106" 13 | client = AsyncOpenAI( 14 | api_key=os.environ.get("OPENAI_API_KEY") 15 | ) 16 | 17 | # Main chatbot class 18 | class ChatBot: 19 | def __init__(self, system, tools, tool_functions): 20 | self.system = system 21 | self.tools = tools 22 | self.exclude_functions = ["plot_chart"] 23 | self.tool_functions = tool_functions 24 | self.messages = [] 25 | if self.system: 26 | self.messages.append({"role": "system", "content": system}) 27 | 28 | async def __call__(self, message): 29 | self.messages.append({"role": "user", "content": f"""{message}"""}) 30 | response_message = await self.execute() 31 | # for function call sometimes this can be empty 32 | if response_message.content: 33 | self.messages.append({"role": "assistant", "content": response_message.content}) 34 | 35 | logging.info(f"User message: {message}") 36 | logging.info(f"Assistant response: {response_message.content}") 37 | 38 | return response_message 39 | 40 | async def execute(self): 41 | #print(self.messages) 42 | completion = await client.chat.completions.create( 43 | model=model, 44 | messages=self.messages, 45 | tools = self.tools 46 | ) 47 | print(completion) 48 | assistant_message = completion.choices[0].message 49 | 50 | return assistant_message 51 | 52 | async def call_function(self, tool_call): 53 | function_name = tool_call.function.name 54 | function_to_call = self.tool_functions[function_name] 55 | function_args = json.loads(tool_call.function.arguments) 56 | logging.info(f"Calling {function_name} with {function_args}") 57 | function_response = await function_to_call(**function_args) 58 | 59 | return { 60 | "tool_call_id": tool_call.id, 61 | "role": "tool", 62 | "name": function_name, 63 | "content": function_response, 64 | } 65 | 66 | async def call_functions(self, tool_calls): 67 | 68 | # Use asyncio.gather to make function calls in parallel 69 | function_responses = await asyncio.gather( 70 | *(self.call_function(tool_call) for tool_call in tool_calls) 71 | ) 72 | 73 | # Extend conversation with all function responses 74 | responses_in_str = [{**item, "content": str(item["content"])} for item in function_responses] 75 | 76 | # Log each tool call object separately 77 | for res in function_responses: 78 | logging.info(f"Tool Call: {res}") 79 | 80 | self.messages.extend(responses_in_str) 81 | 82 | response_message = await self.execute() 83 | return response_message, function_responses 84 | -------------------------------------------------------------------------------- /src/data-analysis-llm-agent/chatbot.log: -------------------------------------------------------------------------------- 1 | Your app is available at http://localhost:8002 2 | Translation file for en-GB not found. Using default translation en-US. 3 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 4 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 5 | Translation file for en-GB not found. Using default translation en-US. 6 | HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK" 7 | User message: Which actors have appeared in the most movies? 8 | Assistant response: None 9 | Calling query_db with {'sql_query': 'SELECT name, COUNT(movie_id) AS movie_count FROM actors GROUP BY name ORDER BY movie_count DESC LIMIT 5'} 10 | Tool Call: {'tool_call_id': 'call_ifOJWx8ZhOFdaDf35vmMmGCj', 'role': 'tool', 'name': 'query_db', 'content': '| name | movie_count |\n| --- | --- |\n| Paul Bateman | 5 |\n| Norman Gay | 4 |\n| Noriko Honma | 4 |\n| Kevin Spacey | 4 |\n| John Rhys-Davies | 4 |\n'} 11 | HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK" 12 | Translation file for en-GB not found. Using default translation en-US. 13 | HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK" 14 | User message: scatter plot 15 | Assistant response: I have listed the top 5 actors who have appeared in the most movies. Now, I will create a scatter plot to visualize the number of movies in which each actor has appeared. 16 | Calling plot_chart with {'plot_type': 'scatter', 'x_values': ['Paul Bateman', 'Norman Gay', 'Noriko Honma', 'Kevin Spacey', 'John Rhys-Davies'], 'y_values': [5, 4, 4, 4, 4], 'plot_title': 'Actors vs. Number of Movies', 'x_label': 'Actor Name', 'y_label': 'Number of Movies'} 17 | Tool Call: {'tool_call_id': 'call_euGBgaGllkPlw9Hs4iIkZ6fl', 'role': 'tool', 'name': 'plot_chart', 'content': Figure({ 18 | 'data': [{'marker': {'color': '#df84ff', 'line': {'width': 1}, 'opacity': 0.7, 'size': 10}, 19 | 'mode': 'markers', 20 | 'type': 'scatter', 21 | 'x': [Paul Bateman, Norman Gay, Noriko Honma, Kevin Spacey, John 22 | Rhys-Davies], 23 | 'y': [5, 4, 4, 4, 4]}], 24 | 'layout': {'margin': {'b': 60, 'l': 60, 'r': 60, 't': 80}, 25 | 'paper_bgcolor': '#f8f8f8', 26 | 'plot_bgcolor': '#f8f8f8', 27 | 'template': '...', 28 | 'title': {'font': {'color': '#333', 'family': 'Arial', 'size': 20}, 29 | 'text': 'Actors vs. Number of Movies Scatter Chart'}, 30 | 'xaxis': {'gridcolor': '#f0f0f0', 31 | 'tickfont': {'size': 14}, 32 | 'title': {'font': {'size': 18}, 'text': 'Actor Name'}}, 33 | 'yaxis': {'gridcolor': '#f0f0f0', 34 | 'tickfont': {'size': 14}, 35 | 'title': {'font': {'size': 18}, 'text': 'Number of Movies'}}} 36 | })} 37 | HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK" 38 | HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK" 39 | User message: scatter plot of number of movies over last 10 years 40 | Assistant response: None 41 | Calling query_db with {'sql_query': 'SELECT m.year AS movie_year, COUNT(a.id) AS movie_count FROM actors a JOIN movies m ON a.movie_id = m.id GROUP BY m.year ORDER BY m.year'} 42 | Tool Call: {'tool_call_id': 'call_e9xZQxpnk6XIXIIwIcCdGpxc', 'role': 'tool', 'name': 'query_db', 'content': '| movie_year | movie_count |\n| --- | --- |\n| 1921 | 40 |\n| 1924 | 6 |\n| 1925 | 101 |\n| 1926 | 27 |\n| 1927 | 27 |\n| 1928 | 13 |\n| 1931 | 64 |\n| 1934 | 26 |\n| 1936 | 22 |\n| 1939 | 236 |\n| 1940 | 112 |\n| 1941 | 167 |\n| 1942 | 43 |\n| 1944 | 11 |\n| 1946 | 49 |\n| 1948 | 30 |\n| 1949 | 19 |\n| 1950 | 54 |\n| 1952 | 113 |\n| 1953 | 52 |\n| 1954 | 150 |\n| 1955 | 22 |\n| 1957 | 152 |\n| 1958 | 52 |\n| 1959 | 134 |\n| 1960 | 44 |\n| 1961 | 76 |\n| 1962 | 57 |\n| 1963 | 86 |\n| 1964 | 19 |\n| 1965 | 24 |\n| 1966 | 80 |\n| 1967 | 23 |\n| 1968 | 78 |\n| 1969 | 21 |\n| 1971 | 61 |\n| 1972 | 51 |\n| 1973 | 67 |\n| 1974 | 103 |\n| 1975 | 165 |\n| 1976 | 121 |\n| 1977 | 147 |\n| 1978 | 49 |\n| 1979 | 79 |\n| 1980 | 219 |\n| 1981 | 78 |\n| 1982 | 170 |\n| 1983 | 232 |\n| 1984 | 254 |\n| 1985 | 107 |\n| 1986 | 126 |\n| 1987 | 124 |\n| 1988 | 135 |\n| 1989 | 82 |\n| 1990 | 119 |\n| 1991 | 95 |\n| 1992 | 59 |\n| 1993 | 273 |\n| 1994 | 315 |\n| 1995 | 406 |\n| 1996 | 100 |\n| 1997 | 272 |\n| 1998 | 242 |\n| 1999 | 202 |\n| 2000 | 259 |\n| 2001 | 374 |\n| 2002 | 425 |\n| 2003 | 257 |\n| 2004 | 210 |\n| 2005 | 199 |\n| 2006 | 222 |\n| 2007 | 207 |\n| 2008 | 243 |\n| 2009 | 217 |\n| 2010 | 228 |\n| 2011 | 299 |\n| 2012 | 359 |\n| 2013 | 396 |\n| 2014 | 379 |\n| 2015 | 213 |\n| 2016 | 354 |\n| 2017 | 187 |\n| 2018 | 119 |\n'} 43 | HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK" 44 | Calling plot_chart with {'plot_type': 'scatter', 'x_values': ['1921', '1924', '1925', '1926', '1927', '1928', '1931', '1934', '1936', '1939'], 'y_values': [40, 6, 101, 27, 27, 13, 64, 26, 22, 236], 'plot_title': 'Number of Movies Over Last 10 Years', 'x_label': 'Year', 'y_label': 'Number of Movies'} 45 | Tool Call: {'tool_call_id': 'call_PoeNqpadqNCdoMXNNQyVipQk', 'role': 'tool', 'name': 'plot_chart', 'content': Figure({ 46 | 'data': [{'marker': {'color': '#df84ff', 'line': {'width': 1}, 'opacity': 0.7, 'size': 10}, 47 | 'mode': 'markers', 48 | 'type': 'scatter', 49 | 'x': [1921, 1924, 1925, 1926, 1927, 1928, 1931, 1934, 1936, 1939], 50 | 'y': [40, 6, 101, 27, 27, 13, 64, 26, 22, 236]}], 51 | 'layout': {'margin': {'b': 60, 'l': 60, 'r': 60, 't': 80}, 52 | 'paper_bgcolor': '#f8f8f8', 53 | 'plot_bgcolor': '#f8f8f8', 54 | 'template': '...', 55 | 'title': {'font': {'color': '#333', 'family': 'Arial', 'size': 20}, 56 | 'text': 'Number of Movies Over Last 10 Years Scatter Chart'}, 57 | 'xaxis': {'gridcolor': '#f0f0f0', 58 | 'tickfont': {'size': 14}, 59 | 'title': {'font': {'size': 18}, 'text': 'Year'}}, 60 | 'yaxis': {'gridcolor': '#f0f0f0', 61 | 'tickfont': {'size': 14}, 62 | 'title': {'font': {'size': 18}, 'text': 'Number of Movies'}}} 63 | })} 64 | HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK" 65 | Your app is available at http://localhost:8002 66 | Translation file for en-GB not found. Using default translation en-US. 67 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 68 | Translation file for en-GB not found. Using default translation en-US. 69 | Translation file for en-GB not found. Using default translation en-US. 70 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 71 | 1 change detected 72 | File modified: chainlit.md. Reloading app... 73 | User message 74 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 75 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 76 | Translation file for en-GB not found. Using default translation en-US. 77 | Translation file for en-GB not found. Using default translation en-US. 78 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 79 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 80 | 1 change detected 81 | 1 change detected 82 | File modified: chainlit.md. Reloading app... 83 | File modified: chainlit.md. Reloading app... 84 | User message 85 | User message 86 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 87 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 88 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 89 | Translation file for en-GB not found. Using default translation en-US. 90 | Translation file for en-GB not found. Using default translation en-US. 91 | Translation file for en-GB not found. Using default translation en-US. 92 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 93 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 94 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 95 | 1 change detected 96 | 1 change detected 97 | 1 change detected 98 | File modified: chainlit.md. Reloading app... 99 | File modified: chainlit.md. Reloading app... 100 | File modified: chainlit.md. Reloading app... 101 | User message 102 | User message 103 | User message 104 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 105 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 106 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 107 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 108 | Translation file for en-GB not found. Using default translation en-US. 109 | Translation file for en-GB not found. Using default translation en-US. 110 | Translation file for en-GB not found. Using default translation en-US. 111 | Translation file for en-GB not found. Using default translation en-US. 112 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 113 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 114 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 115 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 116 | 1 change detected 117 | 1 change detected 118 | 1 change detected 119 | 1 change detected 120 | File modified: chainlit.md. Reloading app... 121 | File modified: chainlit.md. Reloading app... 122 | File modified: chainlit.md. Reloading app... 123 | File modified: chainlit.md. Reloading app... 124 | User message 125 | User message 126 | User message 127 | User message 128 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 129 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 130 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 131 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 132 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 133 | Translation file for en-GB not found. Using default translation en-US. 134 | Translation file for en-GB not found. Using default translation en-US. 135 | Translation file for en-GB not found. Using default translation en-US. 136 | Translation file for en-GB not found. Using default translation en-US. 137 | Translation file for en-GB not found. Using default translation en-US. 138 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 139 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 140 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 141 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 142 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 143 | 1 change detected 144 | 1 change detected 145 | 1 change detected 146 | 1 change detected 147 | 1 change detected 148 | File modified: chainlit.md. Reloading app... 149 | File modified: chainlit.md. Reloading app... 150 | File modified: chainlit.md. Reloading app... 151 | File modified: chainlit.md. Reloading app... 152 | File modified: chainlit.md. Reloading app... 153 | User message 154 | User message 155 | User message 156 | User message 157 | User message 158 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 159 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 160 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 161 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 162 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 163 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 164 | Translation file for en-GB not found. Using default translation en-US. 165 | Translation file for en-GB not found. Using default translation en-US. 166 | Translation file for en-GB not found. Using default translation en-US. 167 | Translation file for en-GB not found. Using default translation en-US. 168 | Translation file for en-GB not found. Using default translation en-US. 169 | Translation file for en-GB not found. Using default translation en-US. 170 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 171 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 172 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 173 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 174 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 175 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 176 | 1 change detected 177 | 1 change detected 178 | 1 change detected 179 | 1 change detected 180 | 1 change detected 181 | 1 change detected 182 | File modified: chainlit.md. Reloading app... 183 | File modified: chainlit.md. Reloading app... 184 | File modified: chainlit.md. Reloading app... 185 | File modified: chainlit.md. Reloading app... 186 | File modified: chainlit.md. Reloading app... 187 | File modified: chainlit.md. Reloading app... 188 | User message 189 | User message 190 | User message 191 | User message 192 | User message 193 | User message 194 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 195 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 196 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 197 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 198 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 199 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 200 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 201 | Translation file for en-GB not found. Using default translation en-US. 202 | Translation file for en-GB not found. Using default translation en-US. 203 | Translation file for en-GB not found. Using default translation en-US. 204 | Translation file for en-GB not found. Using default translation en-US. 205 | Translation file for en-GB not found. Using default translation en-US. 206 | Translation file for en-GB not found. Using default translation en-US. 207 | Translation file for en-GB not found. Using default translation en-US. 208 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 209 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 210 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 211 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 212 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 213 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 214 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 215 | 1 change detected 216 | 1 change detected 217 | 1 change detected 218 | 1 change detected 219 | 1 change detected 220 | 1 change detected 221 | 1 change detected 222 | File modified: chainlit.md. Reloading app... 223 | File modified: chainlit.md. Reloading app... 224 | File modified: chainlit.md. Reloading app... 225 | File modified: chainlit.md. Reloading app... 226 | File modified: chainlit.md. Reloading app... 227 | File modified: chainlit.md. Reloading app... 228 | File modified: chainlit.md. Reloading app... 229 | User message 230 | User message 231 | User message 232 | User message 233 | User message 234 | User message 235 | User message 236 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 237 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 238 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 239 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 240 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 241 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 242 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 243 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 244 | Translation file for en-GB not found. Using default translation en-US. 245 | Translation file for en-GB not found. Using default translation en-US. 246 | Translation file for en-GB not found. Using default translation en-US. 247 | Translation file for en-GB not found. Using default translation en-US. 248 | Translation file for en-GB not found. Using default translation en-US. 249 | Translation file for en-GB not found. Using default translation en-US. 250 | Translation file for en-GB not found. Using default translation en-US. 251 | Translation file for en-GB not found. Using default translation en-US. 252 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 253 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 254 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 255 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 256 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 257 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 258 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 259 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 260 | 1 change detected 261 | 1 change detected 262 | 1 change detected 263 | 1 change detected 264 | 1 change detected 265 | 1 change detected 266 | 1 change detected 267 | 1 change detected 268 | File modified: chainlit.md. Reloading app... 269 | File modified: chainlit.md. Reloading app... 270 | File modified: chainlit.md. Reloading app... 271 | File modified: chainlit.md. Reloading app... 272 | File modified: chainlit.md. Reloading app... 273 | File modified: chainlit.md. Reloading app... 274 | File modified: chainlit.md. Reloading app... 275 | File modified: chainlit.md. Reloading app... 276 | User message 277 | User message 278 | User message 279 | User message 280 | User message 281 | User message 282 | User message 283 | User message 284 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 285 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 286 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 287 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 288 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 289 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 290 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 291 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 292 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 293 | Translation file for en-GB not found. Using default translation en-US. 294 | Translation file for en-GB not found. Using default translation en-US. 295 | Translation file for en-GB not found. Using default translation en-US. 296 | Translation file for en-GB not found. Using default translation en-US. 297 | Translation file for en-GB not found. Using default translation en-US. 298 | Translation file for en-GB not found. Using default translation en-US. 299 | Translation file for en-GB not found. Using default translation en-US. 300 | Translation file for en-GB not found. Using default translation en-US. 301 | Translation file for en-GB not found. Using default translation en-US. 302 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 303 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 304 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 305 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 306 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 307 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 308 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 309 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 310 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 311 | 1 change detected 312 | 1 change detected 313 | 1 change detected 314 | 1 change detected 315 | 1 change detected 316 | 1 change detected 317 | 1 change detected 318 | 1 change detected 319 | 1 change detected 320 | File modified: chainlit.md. Reloading app... 321 | File modified: chainlit.md. Reloading app... 322 | File modified: chainlit.md. Reloading app... 323 | File modified: chainlit.md. Reloading app... 324 | File modified: chainlit.md. Reloading app... 325 | File modified: chainlit.md. Reloading app... 326 | File modified: chainlit.md. Reloading app... 327 | File modified: chainlit.md. Reloading app... 328 | File modified: chainlit.md. Reloading app... 329 | User message 330 | User message 331 | User message 332 | User message 333 | User message 334 | User message 335 | User message 336 | User message 337 | User message 338 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 339 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 340 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 341 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 342 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 343 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 344 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 345 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 346 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 347 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 348 | Translation file for en-GB not found. Using default translation en-US. 349 | Translation file for en-GB not found. Using default translation en-US. 350 | Translation file for en-GB not found. Using default translation en-US. 351 | Translation file for en-GB not found. Using default translation en-US. 352 | Translation file for en-GB not found. Using default translation en-US. 353 | Translation file for en-GB not found. Using default translation en-US. 354 | Translation file for en-GB not found. Using default translation en-US. 355 | Translation file for en-GB not found. Using default translation en-US. 356 | Translation file for en-GB not found. Using default translation en-US. 357 | Translation file for en-GB not found. Using default translation en-US. 358 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 359 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 360 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 361 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 362 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 363 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 364 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 365 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 366 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 367 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 368 | 1 change detected 369 | 1 change detected 370 | 1 change detected 371 | 1 change detected 372 | 1 change detected 373 | 1 change detected 374 | 1 change detected 375 | 1 change detected 376 | 1 change detected 377 | 1 change detected 378 | File modified: chainlit.md. Reloading app... 379 | File modified: chainlit.md. Reloading app... 380 | File modified: chainlit.md. Reloading app... 381 | File modified: chainlit.md. Reloading app... 382 | File modified: chainlit.md. Reloading app... 383 | File modified: chainlit.md. Reloading app... 384 | File modified: chainlit.md. Reloading app... 385 | File modified: chainlit.md. Reloading app... 386 | File modified: chainlit.md. Reloading app... 387 | File modified: chainlit.md. Reloading app... 388 | User message 389 | User message 390 | User message 391 | User message 392 | User message 393 | User message 394 | User message 395 | User message 396 | User message 397 | User message 398 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 399 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 400 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 401 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 402 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 403 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 404 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 405 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 406 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 407 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 408 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 409 | Translation file for en-GB not found. Using default translation en-US. 410 | Translation file for en-GB not found. Using default translation en-US. 411 | Translation file for en-GB not found. Using default translation en-US. 412 | Translation file for en-GB not found. Using default translation en-US. 413 | Translation file for en-GB not found. Using default translation en-US. 414 | Translation file for en-GB not found. Using default translation en-US. 415 | Translation file for en-GB not found. Using default translation en-US. 416 | Translation file for en-GB not found. Using default translation en-US. 417 | Translation file for en-GB not found. Using default translation en-US. 418 | Translation file for en-GB not found. Using default translation en-US. 419 | Translation file for en-GB not found. Using default translation en-US. 420 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 421 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 422 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 423 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 424 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 425 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 426 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 427 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 428 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 429 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 430 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 431 | 1 change detected 432 | 1 change detected 433 | 1 change detected 434 | 1 change detected 435 | 1 change detected 436 | 1 change detected 437 | 1 change detected 438 | 1 change detected 439 | 1 change detected 440 | 1 change detected 441 | 1 change detected 442 | File modified: chainlit.md. Reloading app... 443 | File modified: chainlit.md. Reloading app... 444 | File modified: chainlit.md. Reloading app... 445 | File modified: chainlit.md. Reloading app... 446 | File modified: chainlit.md. Reloading app... 447 | File modified: chainlit.md. Reloading app... 448 | File modified: chainlit.md. Reloading app... 449 | File modified: chainlit.md. Reloading app... 450 | File modified: chainlit.md. Reloading app... 451 | File modified: chainlit.md. Reloading app... 452 | File modified: chainlit.md. Reloading app... 453 | User message 454 | User message 455 | User message 456 | User message 457 | User message 458 | User message 459 | User message 460 | User message 461 | User message 462 | User message 463 | User message 464 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 465 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 466 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 467 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 468 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 469 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 470 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 471 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 472 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 473 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 474 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 475 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 476 | Translation file for en-GB not found. Using default translation en-US. 477 | Translation file for en-GB not found. Using default translation en-US. 478 | Translation file for en-GB not found. Using default translation en-US. 479 | Translation file for en-GB not found. Using default translation en-US. 480 | Translation file for en-GB not found. Using default translation en-US. 481 | Translation file for en-GB not found. Using default translation en-US. 482 | Translation file for en-GB not found. Using default translation en-US. 483 | Translation file for en-GB not found. Using default translation en-US. 484 | Translation file for en-GB not found. Using default translation en-US. 485 | Translation file for en-GB not found. Using default translation en-US. 486 | Translation file for en-GB not found. Using default translation en-US. 487 | Translation file for en-GB not found. Using default translation en-US. 488 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 489 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 490 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 491 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 492 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 493 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 494 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 495 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 496 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 497 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 498 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 499 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 500 | 1 change detected 501 | 1 change detected 502 | 1 change detected 503 | 1 change detected 504 | 1 change detected 505 | 1 change detected 506 | 1 change detected 507 | 1 change detected 508 | 1 change detected 509 | 1 change detected 510 | 1 change detected 511 | 1 change detected 512 | File modified: chainlit.md. Reloading app... 513 | File modified: chainlit.md. Reloading app... 514 | File modified: chainlit.md. Reloading app... 515 | File modified: chainlit.md. Reloading app... 516 | File modified: chainlit.md. Reloading app... 517 | File modified: chainlit.md. Reloading app... 518 | File modified: chainlit.md. Reloading app... 519 | File modified: chainlit.md. Reloading app... 520 | File modified: chainlit.md. Reloading app... 521 | File modified: chainlit.md. Reloading app... 522 | File modified: chainlit.md. Reloading app... 523 | File modified: chainlit.md. Reloading app... 524 | User message 525 | User message 526 | User message 527 | User message 528 | User message 529 | User message 530 | User message 531 | User message 532 | User message 533 | User message 534 | User message 535 | User message 536 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 537 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 538 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 539 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 540 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 541 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 542 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 543 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 544 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 545 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 546 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 547 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 548 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 549 | 1 change detected 550 | 1 change detected 551 | 1 change detected 552 | 1 change detected 553 | 1 change detected 554 | 1 change detected 555 | 1 change detected 556 | 1 change detected 557 | 1 change detected 558 | 1 change detected 559 | 1 change detected 560 | 1 change detected 561 | 1 change detected 562 | File modified: chainlit.md. Reloading app... 563 | File modified: chainlit.md. Reloading app... 564 | File modified: chainlit.md. Reloading app... 565 | File modified: chainlit.md. Reloading app... 566 | File modified: chainlit.md. Reloading app... 567 | File modified: chainlit.md. Reloading app... 568 | File modified: chainlit.md. Reloading app... 569 | File modified: chainlit.md. Reloading app... 570 | File modified: chainlit.md. Reloading app... 571 | File modified: chainlit.md. Reloading app... 572 | File modified: chainlit.md. Reloading app... 573 | File modified: chainlit.md. Reloading app... 574 | File modified: chainlit.md. Reloading app... 575 | User message 576 | User message 577 | User message 578 | User message 579 | User message 580 | User message 581 | User message 582 | User message 583 | User message 584 | User message 585 | User message 586 | User message 587 | User message 588 | Translation file for en-GB not found. Using default translation en-US. 589 | Translation file for en-GB not found. Using default translation en-US. 590 | Translation file for en-GB not found. Using default translation en-US. 591 | Translation file for en-GB not found. Using default translation en-US. 592 | Translation file for en-GB not found. Using default translation en-US. 593 | Translation file for en-GB not found. Using default translation en-US. 594 | Translation file for en-GB not found. Using default translation en-US. 595 | Translation file for en-GB not found. Using default translation en-US. 596 | Translation file for en-GB not found. Using default translation en-US. 597 | Translation file for en-GB not found. Using default translation en-US. 598 | Translation file for en-GB not found. Using default translation en-US. 599 | Translation file for en-GB not found. Using default translation en-US. 600 | Translation file for en-GB not found. Using default translation en-US. 601 | Translation file for en-GB not found. Using default translation en-US. 602 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 603 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 604 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 605 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 606 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 607 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 608 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 609 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 610 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 611 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 612 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 613 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 614 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 615 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 616 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 617 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 618 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 619 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 620 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 621 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 622 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 623 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 624 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 625 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 626 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 627 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 628 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 629 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 630 | 1 change detected 631 | 1 change detected 632 | 1 change detected 633 | 1 change detected 634 | 1 change detected 635 | 1 change detected 636 | 1 change detected 637 | 1 change detected 638 | 1 change detected 639 | 1 change detected 640 | 1 change detected 641 | 1 change detected 642 | 1 change detected 643 | 1 change detected 644 | File modified: chainlit.md. Reloading app... 645 | File modified: chainlit.md. Reloading app... 646 | File modified: chainlit.md. Reloading app... 647 | File modified: chainlit.md. Reloading app... 648 | File modified: chainlit.md. Reloading app... 649 | File modified: chainlit.md. Reloading app... 650 | File modified: chainlit.md. Reloading app... 651 | File modified: chainlit.md. Reloading app... 652 | File modified: chainlit.md. Reloading app... 653 | File modified: chainlit.md. Reloading app... 654 | File modified: chainlit.md. Reloading app... 655 | File modified: chainlit.md. Reloading app... 656 | File modified: chainlit.md. Reloading app... 657 | File modified: chainlit.md. Reloading app... 658 | User message 659 | User message 660 | User message 661 | User message 662 | User message 663 | User message 664 | User message 665 | User message 666 | User message 667 | User message 668 | User message 669 | User message 670 | User message 671 | User message 672 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 673 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 674 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 675 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 676 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 677 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 678 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 679 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 680 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 681 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 682 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 683 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 684 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 685 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 686 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 687 | Translation file for en-GB not found. Using default translation en-US. 688 | Translation file for en-GB not found. Using default translation en-US. 689 | Translation file for en-GB not found. Using default translation en-US. 690 | Translation file for en-GB not found. Using default translation en-US. 691 | Translation file for en-GB not found. Using default translation en-US. 692 | Translation file for en-GB not found. Using default translation en-US. 693 | Translation file for en-GB not found. Using default translation en-US. 694 | Translation file for en-GB not found. Using default translation en-US. 695 | Translation file for en-GB not found. Using default translation en-US. 696 | Translation file for en-GB not found. Using default translation en-US. 697 | Translation file for en-GB not found. Using default translation en-US. 698 | Translation file for en-GB not found. Using default translation en-US. 699 | Translation file for en-GB not found. Using default translation en-US. 700 | Translation file for en-GB not found. Using default translation en-US. 701 | Translation file for en-GB not found. Using default translation en-US. 702 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 703 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 704 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 705 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 706 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 707 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 708 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 709 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 710 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 711 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 712 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 713 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 714 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 715 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 716 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 717 | 1 change detected 718 | 1 change detected 719 | 1 change detected 720 | 1 change detected 721 | 1 change detected 722 | 1 change detected 723 | 1 change detected 724 | 1 change detected 725 | 1 change detected 726 | 1 change detected 727 | 1 change detected 728 | 1 change detected 729 | 1 change detected 730 | 1 change detected 731 | 1 change detected 732 | File deleted: app1.py. Reloading app... 733 | File deleted: app1.py. Reloading app... 734 | File deleted: app1.py. Reloading app... 735 | File deleted: app1.py. Reloading app... 736 | File deleted: app1.py. Reloading app... 737 | File deleted: app1.py. Reloading app... 738 | File deleted: app1.py. Reloading app... 739 | File deleted: app1.py. Reloading app... 740 | File deleted: app1.py. Reloading app... 741 | File deleted: app1.py. Reloading app... 742 | File deleted: app1.py. Reloading app... 743 | File deleted: app1.py. Reloading app... 744 | File deleted: app1.py. Reloading app... 745 | File deleted: app1.py. Reloading app... 746 | File deleted: app1.py. Reloading app... 747 | User message 748 | User message 749 | User message 750 | User message 751 | User message 752 | User message 753 | User message 754 | User message 755 | User message 756 | User message 757 | User message 758 | User message 759 | User message 760 | User message 761 | User message 762 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 763 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 764 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 765 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 766 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 767 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 768 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 769 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 770 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 771 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 772 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 773 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 774 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 775 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 776 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 777 | Translated markdown file for en-US not found. Defaulting to chainlit.md. 778 | Translation file for en-GB not found. Using default translation en-US. 779 | Translation file for en-GB not found. Using default translation en-US. 780 | Translation file for en-GB not found. Using default translation en-US. 781 | Translation file for en-GB not found. Using default translation en-US. 782 | Translation file for en-GB not found. Using default translation en-US. 783 | Translation file for en-GB not found. Using default translation en-US. 784 | Translation file for en-GB not found. Using default translation en-US. 785 | Translation file for en-GB not found. Using default translation en-US. 786 | Translation file for en-GB not found. Using default translation en-US. 787 | Translation file for en-GB not found. Using default translation en-US. 788 | Translation file for en-GB not found. Using default translation en-US. 789 | Translation file for en-GB not found. Using default translation en-US. 790 | Translation file for en-GB not found. Using default translation en-US. 791 | Translation file for en-GB not found. Using default translation en-US. 792 | Translation file for en-GB not found. Using default translation en-US. 793 | Translation file for en-GB not found. Using default translation en-US. 794 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 795 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 796 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 797 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 798 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 799 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 800 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 801 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 802 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 803 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 804 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 805 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 806 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 807 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 808 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 809 | Translated markdown file for en-GB not found. Defaulting to chainlit.md. 810 | Translation file for en-GB not found. Using default translation en-US. 811 | Translation file for en-GB not found. Using default translation en-US. 812 | Translation file for en-GB not found. Using default translation en-US. 813 | Translation file for en-GB not found. Using default translation en-US. 814 | Translation file for en-GB not found. Using default translation en-US. 815 | Translation file for en-GB not found. Using default translation en-US. 816 | Translation file for en-GB not found. Using default translation en-US. 817 | Translation file for en-GB not found. Using default translation en-US. 818 | Translation file for en-GB not found. Using default translation en-US. 819 | Translation file for en-GB not found. Using default translation en-US. 820 | Translation file for en-GB not found. Using default translation en-US. 821 | Translation file for en-GB not found. Using default translation en-US. 822 | Translation file for en-GB not found. Using default translation en-US. 823 | Translation file for en-GB not found. Using default translation en-US. 824 | Translation file for en-GB not found. Using default translation en-US. 825 | Translation file for en-GB not found. Using default translation en-US. 826 | Translation file for en-GB not found. Using default translation en-US. 827 | Translation file for en-GB not found. Using default translation en-US. 828 | Translation file for en-GB not found. Using default translation en-US. 829 | Translation file for en-GB not found. Using default translation en-US. 830 | Translation file for en-GB not found. Using default translation en-US. 831 | Translation file for en-GB not found. Using default translation en-US. 832 | Translation file for en-GB not found. Using default translation en-US. 833 | Translation file for en-GB not found. Using default translation en-US. 834 | Translation file for en-GB not found. Using default translation en-US. 835 | Translation file for en-GB not found. Using default translation en-US. 836 | Translation file for en-GB not found. Using default translation en-US. 837 | Translation file for en-GB not found. Using default translation en-US. 838 | Translation file for en-GB not found. Using default translation en-US. 839 | Translation file for en-GB not found. Using default translation en-US. 840 | Translation file for en-GB not found. Using default translation en-US. 841 | Translation file for en-GB not found. Using default translation en-US. 842 | Translation file for en-GB not found. Using default translation en-US. 843 | Translation file for en-GB not found. Using default translation en-US. 844 | Translation file for en-GB not found. Using default translation en-US. 845 | Translation file for en-GB not found. Using default translation en-US. 846 | Translation file for en-GB not found. Using default translation en-US. 847 | Translation file for en-GB not found. Using default translation en-US. 848 | Translation file for en-GB not found. Using default translation en-US. 849 | Translation file for en-GB not found. Using default translation en-US. 850 | Translation file for en-GB not found. Using default translation en-US. 851 | Translation file for en-GB not found. Using default translation en-US. 852 | Translation file for en-GB not found. Using default translation en-US. 853 | Translation file for en-GB not found. Using default translation en-US. 854 | Translation file for en-GB not found. Using default translation en-US. 855 | Translation file for en-GB not found. Using default translation en-US. 856 | Translation file for en-GB not found. Using default translation en-US. 857 | Translation file for en-GB not found. Using default translation en-US. 858 | -------------------------------------------------------------------------------- /src/data-analysis-llm-agent/tools.py: -------------------------------------------------------------------------------- 1 | import psycopg2 2 | import sqlite3 3 | import os 4 | import plotly.graph_objs as go 5 | import plotly.io as pio 6 | from utils import convert_to_json, json_to_markdown_table 7 | 8 | # function calling 9 | # avialable tools 10 | tools_schema = [ 11 | { 12 | "type": "function", 13 | "function": { 14 | "name": "query_db", 15 | "description": "Fetch data from postgres database", 16 | "parameters": { 17 | "type": "object", 18 | "properties": { 19 | "sql_query": { 20 | "type": "string", 21 | "description": "complete and correct sql query to fulfil user request.", 22 | } 23 | }, 24 | "required": ["sql_query"], 25 | }, 26 | } 27 | }, 28 | { 29 | "type": "function", 30 | "function": { 31 | "name": "plot_chart", 32 | "description": "Plot Bar or Linechart to visualize the result of sql query", 33 | "parameters": { 34 | "type": "object", 35 | "properties": { 36 | "plot_type": { 37 | "type": "string", 38 | "description": "which plot type either bar or line or scatter", 39 | }, 40 | "x_values": { 41 | "type": "array", 42 | "description": "list of x values for plotting", 43 | "items": { 44 | "type": "string" 45 | } 46 | }, 47 | "y_values": { 48 | "type": "array", 49 | "description": "list of y axis values for plotting", 50 | "items": { 51 | "type": "number" 52 | } 53 | }, 54 | "plot_title": { 55 | "type": "string", 56 | "description": "Descriptive Title for the plot", 57 | }, 58 | "x_label": { 59 | "type": "string", 60 | "description": "Label for the x axis", 61 | }, 62 | "y_label": { 63 | "type": "string", 64 | "description": "label for the y axis", 65 | } 66 | }, 67 | "required": ["plot_type","x_values","y_values","plot_title","x_label","y_label"], 68 | }, 69 | } 70 | } 71 | ] 72 | 73 | 74 | async def run_postgres_query(sql_query, markdown=True): 75 | connection = None # Initialize connection variable outside the try block 76 | try: 77 | # Establish the connection 78 | connection = psycopg2.connect( 79 | dbname=os.getenv('DB_NAME'), 80 | user=os.getenv('DB_USER'), 81 | password=os.getenv('DB_PASSWORD'), 82 | host=os.getenv('DB_HOST'), 83 | port=os.getenv('DB_PORT') 84 | ) 85 | print("Connected to the database!") 86 | 87 | # Create a cursor object 88 | cursor = connection.cursor() 89 | 90 | # Execute the query 91 | cursor.execute(sql_query) 92 | 93 | # Fetch the column names 94 | column_names = [desc[0] for desc in cursor.description] 95 | 96 | # Fetch all rows 97 | result = cursor.fetchall() 98 | if markdown: 99 | # get result in json 100 | json_data = convert_to_json(result,column_names) 101 | markdown_data = json_to_markdown_table(json_data) 102 | 103 | return markdown_data 104 | 105 | return result, column_names 106 | except (Exception, psycopg2.Error) as error: 107 | print("Error while executing the query:", error) 108 | if markdown: 109 | return f"Error while executing the query: {error}" 110 | return [], [] 111 | 112 | finally: 113 | # Close the cursor and connection 114 | if connection: 115 | cursor.close() 116 | connection.close() 117 | print("PostgreSQL connection is closed") 118 | 119 | 120 | async def run_sqlite_query(sql_query, markdown=True): 121 | connection = None 122 | try: 123 | # Establish the connection 124 | db_path = os.path.join(os.path.dirname(__file__), '../data/movies.db') 125 | print(db_path) 126 | connection = sqlite3.connect(db_path) 127 | 128 | # Create a cursor object 129 | cursor = connection.cursor() 130 | 131 | # Execute the query 132 | cursor.execute(sql_query) 133 | 134 | # Fetch the column names 135 | column_names = [desc[0] for desc in cursor.description] 136 | 137 | # Fetch all rows 138 | result = cursor.fetchall() 139 | if markdown: 140 | # get result in json 141 | json_data = convert_to_json(result,column_names) 142 | markdown_data = json_to_markdown_table(json_data) 143 | return markdown_data 144 | 145 | return result, column_names 146 | except sqlite3.Error as error: 147 | print("Error while executing the query:", error) 148 | if markdown: 149 | return f"Error while executing the query: {error}" 150 | return [], [] 151 | 152 | finally: 153 | # Close the cursor and connection 154 | if connection: 155 | cursor.close() 156 | connection.close() 157 | print("SQLite connection is closed") 158 | 159 | async def plot_chart(x_values, y_values, plot_title, x_label, y_label, plot_type='line', save_path="tmp/tmp.png"): 160 | """ 161 | Generate a bar chart, line chart, or scatter plot based on input data using Plotly. 162 | 163 | Parameters: 164 | x_values (array-like): Input values for the x-axis. 165 | y_values (array-like): Input values for the y-axis. 166 | plot_type (str, optional): Type of plot to generate ('bar', 'line', or 'scatter'). Default is 'line'. 167 | save_path (str, optional): Path to save the plot image locally. If None, the plot image will not be saved locally. 168 | 169 | Returns: 170 | str: Data URI of the plot image. 171 | """ 172 | # Validate input lengths 173 | if len(x_values) != len(y_values): 174 | raise ValueError("Lengths of x_values and y_values must be the same.") 175 | 176 | # Define plotly trace based on plot_type 177 | # Define plotly trace based on plot_type 178 | if plot_type == 'bar': 179 | trace = go.Bar(x=x_values, y=y_values, marker=dict(color='#24C8BF', line=dict(width=1))) 180 | elif plot_type == 'scatter': 181 | trace = go.Scatter(x=x_values, y=y_values, mode='markers', marker=dict(color='#df84ff', size=10, opacity=0.7, line=dict(width=1))) 182 | elif plot_type == 'line': 183 | trace = go.Scatter(x=x_values, y=y_values, mode='lines+markers', marker=dict(color='#ff9900', size=8, line=dict(width=1)), line=dict(width=2, color='#ff9900')) 184 | 185 | # Create layout for the plot 186 | layout = go.Layout( 187 | title=f'{plot_title} {plot_type.capitalize()} Chart', 188 | title_font=dict(size=20, family='Arial', color='#333'), 189 | xaxis=dict(title=x_label, titlefont=dict(size=18), tickfont=dict(size=14), gridcolor='#f0f0f0'), 190 | yaxis=dict(title=y_label, titlefont=dict(size=18), tickfont=dict(size=14), gridcolor='#f0f0f0'), 191 | margin=dict(l=60, r=60, t=80, b=60), 192 | plot_bgcolor='#f8f8f8', 193 | paper_bgcolor='#f8f8f8' 194 | ) 195 | 196 | # Create figure and add trace to it 197 | fig = go.Figure(data=[trace], layout=layout) 198 | 199 | return fig 200 | -------------------------------------------------------------------------------- /src/data-analysis-llm-agent/utils.py: -------------------------------------------------------------------------------- 1 | import sqlite3 2 | 3 | EXTRA_SCHEMA_INFO = """ 4 | """ 5 | 6 | 7 | async def run_db_query(sql_query): 8 | connection = None 9 | try: 10 | # Establish the connection 11 | connection = sqlite3.connect('../data/movies.db') 12 | 13 | # Create a cursor object 14 | cursor = connection.cursor() 15 | 16 | # Execute the query 17 | cursor.execute(sql_query) 18 | 19 | # Fetch the column names 20 | column_names = [desc[0] for desc in cursor.description] 21 | 22 | # Fetch all rows 23 | result = cursor.fetchall() 24 | 25 | return result, column_names 26 | except sqlite3.Error as error: 27 | print("Error while executing the query:", error) 28 | return [], [] 29 | finally: 30 | # Close the cursor and connection 31 | if connection: 32 | cursor.close() 33 | connection.close() 34 | print("SQLite connection is closed") 35 | 36 | 37 | def generate_postgres_table_info_query(schema_table_pairs): 38 | query = """ 39 | SELECT 40 | cols.table_schema, 41 | cols.table_name, 42 | cols.column_name, 43 | cols.data_type, 44 | coalesce(com.description, '') as column_description 45 | FROM 46 | information_schema.columns cols 47 | LEFT JOIN 48 | pg_class cl ON cl.relname = cols.table_name 49 | LEFT JOIN 50 | pg_description com ON com.objoid = cl.oid AND com.objsubid = cols.ordinal_position 51 | WHERE 52 | (cols.table_schema, cols.table_name) IN ({}); 53 | """.format(', '.join(["('{}', '{}')".format(schema, table) for schema, table in schema_table_pairs])) 54 | 55 | return query 56 | 57 | def generate_sqlite_table_info_query(schema_table_pairs): 58 | sql_query = """SELECT 59 | sql 60 | FROM 61 | sqlite_master m 62 | WHERE 63 | m.type='table' AND m.name NOT LIKE 'sqlite_%';""" 64 | 65 | return sql_query 66 | 67 | def format_table_info(results, columns): 68 | table_info = "" 69 | current_table = None 70 | 71 | for row in results: 72 | table_schema = row[columns.index('table_schema')] 73 | table_name = row[columns.index('table_name')] 74 | column_name = row[columns.index('column_name')] 75 | data_type = row[columns.index('data_type')] 76 | column_description = row[columns.index('column_description')] 77 | 78 | if current_table != table_name: 79 | if current_table is not None: 80 | table_info += "\n\n" 81 | table_info += f"""Table Name: "{table_schema}"."{table_name}"\n""" 82 | table_info += f"----------\n" 83 | current_table = table_name 84 | table_info += f"Following are Column Name(Datatype) and Description:\n" 85 | 86 | table_info += f"{column_name}({data_type})" 87 | if column_description: 88 | table_info += f" - {column_description}\n" 89 | else: 90 | table_info += '\n' 91 | 92 | return table_info 93 | 94 | def format_sample_data(column_names, data_records): 95 | formatted_data = "" 96 | for col_name in column_names: 97 | # Get unique non-empty values for the column 98 | values = set(record[column_names.index(col_name)] for record in data_records if record[column_names.index(col_name)] is not None and record[column_names.index(col_name)] != '') 99 | if values: # Check if values exist 100 | formatted_data += f"{col_name}: " 101 | sample_values = ', '.join(str(value) for value in list(values)[:3]) # Display first 3 unique values 102 | if len(values) > 3: 103 | sample_values += ", ..." 104 | formatted_data += sample_values + '\n' 105 | 106 | return formatted_data 107 | 108 | def generate_sample_data_query(schema, table, N): 109 | return f"""SELECT * FROM "{schema}"."{table}" ORDER BY RANDOM() LIMIT {N};""" 110 | 111 | 112 | # formatting data 113 | def convert_to_json1(rows, column_names): 114 | results = [] 115 | 116 | for row in rows: 117 | # Convert row data into a dictionary with column names as keys 118 | row_dict = dict(zip(column_names, row)) 119 | results.append(list(row_dict.values())) # Append row values as a list 120 | 121 | # Construct the JSON data structure 122 | json_data = {"columns": column_names, "data": results} 123 | return json_data 124 | 125 | 126 | 127 | # formatting data 128 | def convert_to_json(rows, column_names): 129 | results = [] 130 | for row in rows: 131 | row_dict = dict(zip(column_names, row)) 132 | results.append(row_dict) 133 | 134 | # Serialize the results and column names into a JSON string 135 | json_data ={"columns": column_names, "data": results} 136 | return json_data 137 | 138 | 139 | def json_to_markdown_table(json_data): 140 | # Extract columns and data from JSON 141 | columns = json_data["columns"] 142 | data = json_data["data"] 143 | 144 | # Generate Markdown table header 145 | markdown_table = "| " + " | ".join(columns) + " |\n" 146 | markdown_table += "| " + " | ".join(["---"] * len(columns)) + " |\n" 147 | 148 | # Generate Markdown table rows 149 | for row in data: 150 | markdown_table += "| " + " | ".join(str(row[column]) for column in columns) + " |\n" 151 | 152 | return markdown_table 153 | -------------------------------------------------------------------------------- /src/data/movies.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crazycloud/data-analysis-llm-agent/47e3dabc709ddd777064d518e63fc43df649463a/src/data/movies.db --------------------------------------------------------------------------------