-
Notifications
You must be signed in to change notification settings - Fork 1.5k
/
text-2-sql-query-db.py
182 lines (115 loc) · 5.95 KB
/
text-2-sql-query-db.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
""" This example shows an end-to-end recipe for querying SQL database using only natural language.
The example shows the following steps:
1. Loading "slim-sql-tool" and running initial tests to confirm installation.
2. Generating a SQL table from a sample CSV file included with the slim-sql-tool install.
3. Asking basic natural language questions:
A. Looks up the table schema
B. Packages the table schema with query
C. Runs inference to convert text into SQL
D. Queries the database with the generated SQL
E. Returns result
4. 'Two-step' query (starting on line 133) in which a customer name is pulled from a text using NER, and then
the name is 'dynamically' added to a natural language string, which is then converted using text-to-sql
and querying the database.
5. All work performed on an integrated 'llmware-sqlite-experimental.db' that can be deleted safely anytime
as part of experimentation lifecycle.
"""
import os
from llmware.agents import SQLTables, LLMfx
from llmware.models import ModelCatalog
from llmware.configs import LLMWareConfig
def load_slim_sql_tool():
""" First step is to install the slim-sql-tool locally """
# to cache locally the slim-sql-tool with config and test files
ModelCatalog().get_llm_toolkit(["sql"])
# to run tests to confirm correct installation and see the model in action
# note: the test results will include some minor errors - useful to learn how to sharpen prompts
ModelCatalog().tool_test_run("slim-sql-tool")
return 0
def hello_world_text_2_sql():
""" Illustrates a 'hello world' text-2-sql inference as part of an agent process. """
sample_table_schema = "CREATE TABLE customer_info (customer_name text, account_number integer, annual_spend integer)"
query = "What are the names of all customers with annual spend greater than $1000?"
agent = LLMfx(verbose=True)
response = agent.sql(query, sample_table_schema)
print("update: text-2-sql response - ", response)
return 0
def build_table(fp, fn, table_name):
""" This is the key method for taking a CSV file from a folder_path (fp), a proposed new table_name,
and creating a new table directly from the CSV. Note: this is useful for rapid prototyping and
experimentation - but should not be used for any serious production purpose. """
sql_db = SQLTables(experimental=True)
x = sql_db.create_new_table_from_csv(fp,fn,table_name=table_name)
print("update: successfully created new db table")
return 1
def delete_table(table_name):
""" Start fresh in testing - delete table in experimental local SQLite DB """
sql_db = SQLTables(experimental=True)
sql_db.delete_table(table_name,confirm_delete=True)
return True
def delete_db():
""" Start fresh in testing - deletes SQLite DB and starts over. """
sql_db = SQLTables(experimental=True)
sql_db.delete_experimental_db(confirm_delete=True)
return True
def sql_e2e_test_script(table_name="customers1",create_new_table=False):
""" This is the end-to-end execution script. """
# create table if needed to set up
if create_new_table:
sql_tool_repo_path = os.path.join(LLMWareConfig().get_model_repo_path(), "slim-sql-tool")
if not os.path.exists(sql_tool_repo_path):
ModelCatalog().load_model("llmware/slim-sql-tool")
files = os.listdir(sql_tool_repo_path)
csv_file = "customer_table.csv"
if csv_file in files:
build_table(sql_tool_repo_path, csv_file, table_name)
else:
print("something has gone wrong - could not find customer_table.csv with slim-sql-tool file package")
# query starts here
agent = LLMfx()
agent.load_tool("sql")
# Example 1 - direct query
query_list = ["Which customers are vip customers?",
"What is the highest annual spend of any customer?",
"Which customer has account number 1234953",
"Which customer has the lowest annual spend?",
"Is Susan Soinsin a vip customer?"]
for i, query in enumerate(query_list):
# this method is doing all of the work
# -- looks up the table schema in the db using the table_name
# -- packages the text-2-sql query prompt
# -- executes sql method to convert the prompt into a sql query
# -- attempts to execute the sql query on the db
# -- returns the db results as 'research' output
response = agent.query_db(query, table=table_name)
# Example 2 - use in a chain of inferences
text = ("This is Susan Soinsin calling - I am really upset about the poor customer service, "
"and would like to cancel my service.")
agent.load_tool("ner")
response = agent.ner(text=text)
customer_name = "No Customer"
# please note: this is just a demo recipe - any real life scenario would require significant preprocessing
# and error checking. :)
if "llm_response" in response:
if "people" in response["llm_response"]:
people = response["llm_response"]["people"]
if len(people) > 0:
customer_name = people[0]
print("ner response: ", customer_name, response)
# e.g., name = "Susan Soinsin"
query = f"Is {customer_name} a vip customer?"
print("query: ", query)
response = agent.query_db(query, table=table_name)
print("response: ", response)
for x in range(0,len(agent.research_list)):
print("research: ", x, agent.research_list[x])
return 0
if __name__ == "__main__":
# first - load and test the tools
load_slim_sql_tool()
# second - 'hello world' demo of using text2sql model
hello_world_text_2_sql()
# second - run an end-to-end test
sql_e2e_test_script(table_name="customer1",create_new_table=True)
# third - delete and start fresh for further testing
delete_table("customer1")