-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRAG_SampleSQLCode.py
234 lines (188 loc) · 13 KB
/
RAG_SampleSQLCode.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
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
Act as a python and gen ai expert. I wrote the below code. Please format the code with RAG framework,include concepts such as embedding, indexing, storing in vector store, scoring etc in my text to sql code below and give me working code. Here is my code - import os import asyncio from dotenv import load_dotenv # Add Azure OpenAI package from openai import AsyncAzureOpenAI import warnings warnings.filterwarnings("ignore") #Get configuration settings load_dotenv() azure_oai_endpoint = os.getenv("AZURE_OAI_ENDPOINT") azure_oai_key = os.getenv("AZURE_OAI_KEY") azure_oai_deployment = os.getenv("AZURE_OAI_DEPLOYMENT") # Set to True to print the full response from OpenAI for each call printFullResponse = True async def create_llm(): client = AsyncAzureOpenAI( azure_endpoint = azure_oai_endpoint, api_key=azure_oai_key, api_version="2024-02-15-preview" ) return client async def main(): try: client = await create_llm() while True: # Pause the app to allow the user to enter the system prompt print("------------------\nPausing the app to allow you to change the system prompt.\nPress enter to continue...") input() # Read in system message and prompt for user message system_text = open(file="system.txt", encoding="utf8").read().strip() user_text = input("Enter user message, or 'quit' to exit: ") if user_text.lower() == 'quit' or system_text.lower() == 'quit': print('Exiting program...') break await call_openai_model(system_message = system_text, user_message = user_text, model=azure_oai_deployment, client=client ) except Exception as ex: print(ex) async def call_openai_model(system_message, user_message, model, client): # Format and send the request to the model messages =[ {"role": "system", "content": system_message}, {"role": "user", "content": user_message}, ] print("\nSending request to Azure OpenAI model...\n") # Call the Azure OpenAI model response = await client.chat.completions.create( model=model, messages=messages, temperature=0.7, max_tokens=800 ) if printFullResponse: print("Response:\n" + response.choices[0].message.content + "\n") return response if __name__ == '__main__': asyncio.run(main())
ChatGPT
To incorporate concepts such as the Retrieval-Augmented Generation (RAG) framework, embeddings, indexing, storing in a vector store, and scoring into your text-to-SQL code, we'll use an additional library for handling vector stores (like FAISS or Pinecone) and work with embeddings. Below is an example implementation:
import os
import asyncio
from dotenv import load_dotenv
import warnings
from openai import AsyncAzureOpenAI
import faiss
import numpy as np
warnings.filterwarnings("ignore")
# Load configuration settings
load_dotenv()
azure_oai_endpoint = os.getenv("AZURE_OAI_ENDPOINT")
azure_oai_key = os.getenv("AZURE_OAI_KEY")
azure_oai_deployment = os.getenv("AZURE_OAI_DEPLOYMENT")
# Set to True to print the full response from OpenAI for each call
printFullResponse = True
# Initialize FAISS index
dimension = 768 # Assuming the embedding size is 768
index = faiss.IndexFlatL2(dimension)
async def create_llm():
client = AsyncAzureOpenAI(
azure_endpoint=azure_oai_endpoint,
api_key=azure_oai_key,
api_version="2024-02-15-preview"
)
return client
async def embed_text(client, text):
response = await client.embeddings.create(input=text, model="text-embedding-ada-002")
return np.array(response['data'][0]['embedding'])
async def main():
try:
client = await create_llm()
while True:
print("------------------\nPausing the app to allow you to change the system prompt.\nPress enter to continue...")
input()
system_text = open(file="system.txt", encoding="utf8").read().strip()
user_text = input("Enter user message, or 'quit' to exit: ")
if user_text.lower() == 'quit' or system_text.lower() == 'quit':
print('Exiting program...')
break
system_embedding = await embed_text(client, system_text)
user_embedding = await embed_text(client, user_text)
print("Indexing system message embedding...")
index.add(np.array([system_embedding]))
D, I = index.search(np.array([user_embedding]), k=1)
print(f"Embedding distance: {D[0][0]} (Lower is better)")
response = await call_openai_model(
system_message=system_text,
user_message=user_text,
model=azure_oai_deployment,
client=client
)
except Exception as ex:
print(ex)
async def call_openai_model(system_message, user_message, model, client):
messages = [
{"role": "system", "content": system_message},
{"role": "user", "content": user_message},
]
print("\nSending request to Azure OpenAI model...\n")
response = await client.chat.completions.create(
model=model,
messages=messages,
temperature=0.7,
max_tokens=800
)
if printFullResponse:
print("Response:\n" + response.choices[0].message.content + "\n")
return response
if __name__ == '__main__':
asyncio.run(main())
Key Additions:
Embedding: Added a function embed_text to generate embeddings for given texts using the OpenAI API.
Indexing: Used FAISS to create an index and add embeddings to it. FAISS is a library for efficient similarity search and clustering of dense vectors.
Scoring: After embedding the system and user texts, the embeddings are compared using the FAISS index to find the closest match, which helps in determining the relevance of the query.
Workflow:
System Initialization:
The LLM client is created.
FAISS index is initialized.
User Interaction:
The user is prompted to input messages.
The system and user messages are embedded using OpenAI embeddings.
The system message embedding is indexed, and the user message embedding is searched against this index to find the closest match and compute a similarity score.
Model Invocation:
The user and system messages are sent to the Azure OpenAI model for generating a response.
The response is printed if printFullResponse is True.
This code sets up a basic RAG framework by incorporating embeddings, indexing, and similarity scoring into your text-to-SQL solution.
can you write the code using langchain and below is the architecture it should have - Offline Data Prep: a set of example user questions and corresponding SQL queries (50-100 samples) should be collected and stored in JSON or CSV format. Then, each of these pairs should be embedded in a vector database . { "question": "Which product line had the highest sales in FY2022?" "sql_query": "SELECT value FROM table_1..." } (Runtime) User submits question - After the data preparation in step 1, the application starts in the same way as Architecture 1. The user submits a question, and the app sends the question first to the embeddings deployment of Azure OpenAI. Embed user’s question: Make a request to a text embeddings model, such as text-ada-002, to convert the user’s question to a vector. Retrieve few examples: Then retrieve the top 5 examples with the closest similarity (using Azure AI Search cosine similarity algorithm) and include them in the SQL Generation request to llm User asks a question: through a front end UI, the user submits a question. For example, “Generate a SQL query to find legacy policies with triggercode DOB_Null?” App makes a request to the LLM: the LLM is invoked with a prompt that might look like the following LLM responds with a SQL query: the LLM will generate a SQL query string as a response that might look like, “SELECT SUBSTRING(account.pmtid, 1, 10) AS legacy_pol_number FROM account JOIN trigger ON account.pmtid = trigger.pmtid WHERE trigger.trigcode = 'DOB_Null'; “. This string gets stored as a variable, to be used in the next step. Final LLM call performed: A second request is sent to the LLM, this time with the user’s original question, and the result of SQL Query. The prompt might look like: “Given the original question, the corresponding PostgreSQL query, and the execution results, produce a truthful and accurate natural language response to the original question. Question: {question}” Final Response: The LLM responds with the answer to the user’s question, based on the SQL query results.
Sure, I'll provide the Python code using the LangChain library to build your application. This code will follow the architecture you outlined. For this example, we'll assume you're using FAISS for vector storage and retrieval, and Streamlit for the frontend UI.
Step 1: Offline Data Preparation
First, prepare your example questions and SQL queries in a CSV file, examples.csv, with columns question and sql_query.
Step 2: Implementation in Python
Install Required Packages
Make sure you have the necessary packages installed. You can install them using pip:
pip install openai langchain faiss-cpu streamlit pandas
import os
import asyncio
import json
import pandas as pd
import numpy as np
from dotenv import load_dotenv
from openai import AsyncAzureOpenAI
import faiss
from langchain.llms import AzureOpenAI
from langchain.embeddings import OpenAIEmbeddings
from langchain.prompts import ChatPrompt
from langchain.vectorstores import FAISS
from langchain.chains import LLMChain
from langchain.chains.qa_with_sources import load_qa_with_sources_chain
import streamlit as st
# Load environment variables
load_dotenv()
azure_oai_endpoint = os.getenv("AZURE_OAI_ENDPOINT")
azure_oai_key = os.getenv("AZURE_OAI_KEY")
azure_oai_deployment = os.getenv("AZURE_OAI_DEPLOYMENT")
# Initialize OpenAI client
async def create_llm():
client = AsyncAzureOpenAI(
azure_endpoint=azure_oai_endpoint,
api_key=azure_oai_key,
api_version="2024-02-15-preview"
)
return client
# Load example data
examples_df = pd.read_csv('examples.csv')
examples = [{"question": row['question'], "sql_query": row['sql_query']} for index, row in examples_df.iterrows()]
# Generate embeddings for the example data
async def generate_embeddings(client, examples):
embeddings = OpenAIEmbeddings(model="text-embedding-ada-002", client=client)
example_texts = [example['question'] for example in examples]
example_vectors = await embeddings.embed_documents(example_texts)
return example_vectors
# Initialize FAISS index
async def initialize_index(client, examples):
example_vectors = await generate_embeddings(client, examples)
dimension = len(example_vectors[0])
index = FAISS(dimension=dimension)
index.add_texts(example_vectors)
return index
# Embed the user question
async def embed_question(client, question):
embeddings = OpenAIEmbeddings(model="text-embedding-ada-002", client=client)
question_vector = await embeddings.embed_documents([question])
return question_vector[0]
# Retrieve top 5 examples based on similarity
async def retrieve_examples(index, question_vector, examples, k=5):
distances, indices = index.search(np.array([question_vector]), k)
return [examples[i] for i in indices[0]]
# Main logic for handling the question and generating SQL query
async def handle_question(client, index, question, examples):
question_vector = await embed_question(client, question)
similar_examples = await retrieve_examples(index, question_vector, examples)
prompt_text = "\n".join([f"Example:\nQ: {ex['question']}\nA: {ex['sql_query']}" for ex in similar_examples])
prompt_text += f"\nUser question: {question}\nSQL query:"
llm = AzureOpenAI(client=client, deployment_name=azure_oai_deployment)
chain = LLMChain(llm=llm, prompt=ChatPrompt(template=prompt_text))
sql_query = await chain.arun()
return sql_query
# Streamlit UI
def main():
st.title("SQL Chatbot")
client = asyncio.run(create_llm())
index = asyncio.run(initialize_index(client, examples))
question = st.text_input("Enter your question:")
if st.button("Submit"):
sql_query = asyncio.run(handle_question(client, index, question, examples))
st.write(f"Generated SQL Query: {sql_query}")
if __name__ == "__main__":
main()
Explanation
Offline Data Preparation:
The example questions and corresponding SQL queries are loaded from a CSV file.
Embeddings and Vector Store Initialization:
Generate embeddings for the example questions using the text-embedding-ada-002 model.
Store these embeddings in a FAISS index.
User Interaction:
Embed the user's question and retrieve the top 5 most similar example questions using FAISS.
SQL Generation:
Construct a prompt using the retrieved examples and the user's question.
Use the LLM to generate the SQL query.
Streamlit UI:
A simple UI is provided for users to input their questions and view the generated SQL queries.
Running the Application
Save the code to a file, say text_to_sql_app.py, and run it using:
streamlit run text_to_sql_app.py
This will start a Streamlit server, and you can access the UI in your web browser to interact with the SQL generation chatbot.