pnicewiczoig commited on
Commit
6eec04e
·
1 Parent(s): b184be4

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +219 -0
app.py ADDED
@@ -0,0 +1,219 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ os.environ['SENTENCE_TRANSFORMERS_HOME'] = './.cache'
3
+
4
+ few_shots = {"What are the top 10 performing areas?": "SELECT TOP 10 destn_area_name, AVG(score) AS AvgScore FROM All_data GROUP BY destn_area_name ORDER BY AvgScore DESC",
5
+ "What are the worst 10 performing areas?": "SELECT TOP 10 destn_area_name, AVG(score) AS AvgScore FROM All_data GROUP BY destn_area_name ORDER BY AvgScore ASC",
6
+ "What districts have the highest volume of mail?": "SELECT TOP 10 destn_district_name, COUNT(*) AS Volume FROM All_data GROUP BY destn_district_name ORDER BY Volume DESC",
7
+ "What districts have the lowest volume of mail?": "SELECT TOP 10 destn_district_name, COUNT(*) AS Volume FROM All_data GROUP BY destn_district_name ORDER BY Volume ASC",
8
+ "What are the top 10 performing districts?": "SELECT TOP 10 destn_district_name, AVG(score) AS AvgScore FROM All_data GROUP BY destn_district_name ORDER BY AvgScore DESC",
9
+ "What are the worst 10 performing districts?": "SELECT TOP 10 destn_district_name, AVG(score) AS AvgScore FROM All_data GROUP BY destn_district_name ORDER BY AvgScore ASC",
10
+ "What districts gave the fastest delivery time?": "SELECT TOP 10 destn_district_name, AVG(avg_days_todelr) AS AvgDeliveryTime FROM All_data GROUP BY destn_district_name ORDER BY AvgDeliveryTime ASC"}
11
+
12
+ from langchain.embeddings import HuggingFaceEmbeddings
13
+ #from langchain.vectorstores import FAISS
14
+ from langchain.schema import Document
15
+
16
+ from langchain.vectorstores import Chroma
17
+ from langchain.llms import AzureMLOnlineEndpoint
18
+ import chromadb
19
+ from langchain.chat_models.azureml_endpoint import ContentFormatterBase
20
+ import json
21
+
22
+ from langchain.chains import create_sql_query_chain
23
+
24
+ import chainlit as cl
25
+
26
+
27
+ from typing import Dict
28
+
29
+ embeddings_model_name = 'sentence-transformers/msmarco-distilbert-base-tas-b'
30
+ embeddings = HuggingFaceEmbeddings(model_name=embeddings_model_name)
31
+
32
+ few_shot_docs = [Document(page_content=question, metadata={'sql_query': few_shots[question]}) for question in few_shots.keys()]
33
+ vector_db = Chroma.from_documents(few_shot_docs, embeddings)
34
+ retriever = vector_db.as_retriever()
35
+
36
+ # Create custom tool and append it as a new tool in the create_sql_agent function:
37
+ from langchain.agents.agent_toolkits import create_retriever_tool
38
+
39
+ tool_description = """
40
+ This tool will help answers questions about the USPS Service Performance Measurement (SPM) data.
41
+ """
42
+
43
+ retriever_tool = create_retriever_tool(
44
+ retriever,
45
+ name='spm_chat',
46
+ description=tool_description
47
+ )
48
+ custom_tool_list = [retriever_tool]
49
+
50
+ # Now we can create the agent, adjusting the standard SQL Agent suffix to consider our use case.
51
+ # Although the most straightforward way to handle this would be to include it just in the tool description,
52
+ # this is often not enough and we need to specify it in the agent prompt using the suffix argument in the constructor.
53
+
54
+ from langchain.agents import create_sql_agent, AgentType
55
+ from langchain.agents.agent_toolkits import SQLDatabaseToolkit
56
+ from langchain.utilities import SQLDatabase
57
+ from langchain.chat_models import ChatOpenAI
58
+
59
+ import os
60
+
61
+ PWD = os.environ['SQL_PWD']
62
+ SQL_USR_NM = os.environ['SQL_USR_NM']
63
+ SQL_HOST = os.environ['SQL_HOST']
64
+ SQL_TBL = os.environ['SQL_TBL']
65
+
66
+ conn_str = "mssql+pyodbc://" + SQL_USR_NM + ":" + PWD + "@" + SQL_HOST + "/" + SQL_TBL + "?driver=ODBC+Driver+18+for+SQL+Server"
67
+
68
+ # Create the SQLDatabase object
69
+ db = SQLDatabase.from_uri(conn_str)
70
+
71
+ model_name = os.environ['MODEL_NAME']
72
+ endpoint_api_key = os.environ['ENDPOINT_API_KEY']
73
+ endpoint_url = os.environ['ENDPOINT_URL']
74
+
75
+ class CustomFormatter(ContentFormatterBase):
76
+ content_type = "application/json"
77
+ accepts = "application/json"
78
+
79
+ def format_request_payload(self, prompt: str, model_kwargs: Dict) -> bytes:
80
+ print(model_kwargs)
81
+ input_str = json.dumps(
82
+ {
83
+ "input_data": {
84
+ "input_string": [
85
+ {
86
+ "role": "user",
87
+ "content": prompt
88
+ }
89
+ ],
90
+ "parameters": {
91
+ "temperature": 0.6,
92
+ "top_p": 0.9,
93
+ "max_new_tokens": 20000
94
+ }
95
+ }
96
+ }
97
+ )
98
+ return str.encode(input_str)
99
+
100
+ def format_response_payload(self, output: bytes) -> str:
101
+ response_json = json.loads(output)
102
+ return response_json["output"]
103
+
104
+
105
+
106
+ llm = AzureMLOnlineEndpoint(endpoint_name=model_name,
107
+ endpoint_api_key=endpoint_api_key,
108
+ endpoint_url=endpoint_url,
109
+ content_formatter = CustomFormatter())#,
110
+
111
+ toolkit = SQLDatabaseToolkit(db=db, llm=llm)
112
+
113
+ custom_suffix = """
114
+ Compose a query in the All_data table in the db database.
115
+ Here is a description of each column:
116
+ destn_area_name: The name of the destination area.
117
+ destn_district_name: The name of the destination district.
118
+ score: The score of the destination area.
119
+ avg_days_todelr: The average number of days to deliver to the destination area.
120
+ time_per: The time period of the data.
121
+ orgn_area: The code of the origin area.
122
+ orgn_dist: The code of the origin district.
123
+ orgn_area_name: The name of the origin area.
124
+ orgn_dist_name: The name of the origin district.
125
+ destn_area: The code of the destination area.
126
+ destn_dist: The code of the destination district.
127
+ destn_area_name: The name of the destination area.
128
+ destn_dist_name: The name of the destination district.
129
+ prodt: The product type.
130
+ rptg_start_date: The start date of the reporting period.
131
+ rptg_end_date: The end date of the reporting period.
132
+ mo: The month of the reporting period.
133
+ pstl_qtr: The quarter of the Postal reporting period.
134
+ pstl_yr: The year of the Postal reporting period.
135
+ score: The score of the destination area.
136
+ score_plus_1: The score of the destination area plus 1.
137
+ """
138
+
139
+ agent = create_sql_agent(llm=llm,
140
+ toolkit=toolkit,
141
+ verbose=True,
142
+ # agent_type=AgentType.SELF_ASK_WITH_SEARCH,
143
+ extra_tools=custom_tool_list,
144
+ suffix=custom_suffix,
145
+ handle_parsing_errors=True
146
+ )
147
+
148
+ from langchain.prompts import PromptTemplate
149
+
150
+
151
+ def build_sql_chain(llm, db):
152
+
153
+ dialect = "Azure SQL"
154
+ table_info = "All_data"
155
+ few_shots = {"What are the top 10 performing areas?": "SELECT TOP 10 destn_area_name, AVG(score) AS AvgScore FROM All_data GROUP BY destn_area_name ORDER BY AvgScore DESC",
156
+ "What are the worst 10 performing areas?": "SELECT TOP 10 destn_area_name, AVG(score) AS AvgScore FROM All_data GROUP BY destn_area_name ORDER BY AvgScore ASC",
157
+ "What districts have the highest volume of mail?": "SELECT TOP 10 destn_district_name, COUNT(*) AS Volume FROM All_data GROUP BY destn_district_name ORDER BY Volume DESC",
158
+ "What districts have the lowest volume of mail?": "SELECT TOP 10 destn_district_name, COUNT(*) AS Volume FROM All_data GROUP BY destn_district_name ORDER BY Volume ASC",
159
+ "What are the top 10 performing districts?": "SELECT TOP 10 destn_district_name, AVG(score) AS AvgScore FROM All_data GROUP BY destn_district_name ORDER BY AvgScore DESC",
160
+ "What are the worst 10 performing districts?": "SELECT TOP 10 destn_district_name, AVG(score) AS AvgScore FROM All_data GROUP BY destn_district_name ORDER BY AvgScore ASC",
161
+ "What districts gave the fastest delivery time?": "SELECT TOP 10 destn_district_name, AVG(avg_days_todelr) AS AvgDeliveryTime FROM All_data GROUP BY destn_district_name ORDER BY AvgDeliveryTime ASC"}
162
+ fs = str(few_shots)
163
+
164
+
165
+ TEMPLATE = """Given an input question, first create a syntactically correct {dialect} query to run, then look at the results of the query and return the answer.
166
+ Use the following format:
167
+
168
+ Question: "Question here"
169
+ SQLQuery: "SQL Query to run"
170
+ SQLResult: "Result of the SQLQuery"
171
+ Answer: "Final answer here"
172
+
173
+ Only use the following tables:
174
+
175
+ {table_info}.
176
+
177
+ Some examples of SQL queries that correspond to questions are:
178
+
179
+ \{"What are the top 10 performing areas?": "SELECT TOP 10 destn_area_name, AVG(score) AS AvgScore FROM All_data GROUP BY destn_area_name ORDER BY AvgScore DESC",
180
+ "What are the worst 10 performing areas?": "SELECT TOP 10 destn_area_name, AVG(score) AS AvgScore FROM All_data GROUP BY destn_area_name ORDER BY AvgScore ASC",
181
+ "What districts have the highest volume of mail?": "SELECT TOP 10 destn_district_name, COUNT(*) AS Volume FROM All_data GROUP BY destn_district_name ORDER BY Volume DESC",
182
+ "What districts have the lowest volume of mail?": "SELECT TOP 10 destn_district_name, COUNT(*) AS Volume FROM All_data GROUP BY destn_district_name ORDER BY Volume ASC",
183
+ "What are the top 10 performing districts?": "SELECT TOP 10 destn_district_name, AVG(score) AS AvgScore FROM All_data GROUP BY destn_district_name ORDER BY AvgScore DESC",
184
+ "What are the worst 10 performing districts?": "SELECT TOP 10 destn_district_name, AVG(score) AS AvgScore FROM All_data GROUP BY destn_district_name ORDER BY AvgScore ASC",
185
+ "What districts gave the fastest delivery time?": "SELECT TOP 10 destn_district_name, AVG(avg_days_todelr) AS AvgDeliveryTime FROM All_data GROUP BY destn_district_name ORDER BY AvgDeliveryTime ASC"\}
186
+
187
+ Question: {input}"""
188
+
189
+ CUSTOM_PROMPT = PromptTemplate(
190
+ input_variables=["input", "table_info", "dialect"], template=TEMPLATE
191
+ )
192
+
193
+ # Set verbose=True to see the full prompt:
194
+ return create_sql_query_chain(llm=llm, db=db)
195
+
196
+ sql_chain = build_sql_chain(llm, db)
197
+
198
+ @cl.on_chat_start
199
+ def main():
200
+ # Parse the command line arguments
201
+ # args = parse_arguments()
202
+
203
+
204
+ # activate/deactivate the streaming StdOut callback for LLMs
205
+ #callbacks = [StreamingStdOutCallbackHandler()]
206
+
207
+ sql_chain = build_sql_chain(llm, db)
208
+
209
+
210
+ @cl.on_message
211
+ async def msg(message: str):
212
+ # Retrieve the chain from the user session
213
+ # sql_chain = cl.user_session.get("sql_chain") # type: RetrievalQA
214
+ m = message.content
215
+ res = sql_chain.invoke({"question": m})
216
+ # Call the chain asynchronously
217
+
218
+ print(res)
219
+ await cl.Message(content=res).send()