File size: 6,563 Bytes
4851168
9005b70
4851168
9005b70
4851168
9005b70
4851168
 
77a4e9c
 
4851168
 
 
 
2fb8b13
4851168
9005b70
4851168
 
2fb8b13
9005b70
 
4851168
2fb8b13
 
4851168
 
9005b70
 
50337b2
9005b70
 
4851168
2f57648
2fb8b13
4851168
9005b70
 
4851168
2fb8b13
4851168
 
2f57648
4851168
2f57648
4851168
2fb8b13
2f57648
 
4851168
2fb8b13
4851168
 
 
2fb8b13
4851168
 
 
 
 
 
 
 
2fb8b13
4851168
 
2fb8b13
12ef2a8
4851168
2fb8b13
4851168
 
 
 
 
2f57648
2fb8b13
4851168
 
 
2fb8b13
2f57648
4851168
2fb8b13
 
4851168
2fb8b13
4851168
 
2fb8b13
ec2da61
2f57648
 
4851168
2f57648
4851168
 
2fb8b13
4851168
 
 
 
 
2fb8b13
4851168
 
 
2fb8b13
4851168
 
2fb8b13
4851168
ec2da61
 
 
 
4851168
 
2fb8b13
4851168
 
2fb8b13
ec2da61
 
4851168
 
 
2fb8b13
ec2da61
 
4e0694e
 
ec2da61
4e0694e
ec2da61
4e0694e
 
 
2fb8b13
4e0694e
ec2da61
4e0694e
 
2fb8b13
4e0694e
 
4851168
2fb8b13
ec2da61
 
4e0694e
 
 
 
 
4851168
2fb8b13
ec2da61
 
 
 
 
 
 
 
 
 
 
 
4851168
 
 
 
 
ec2da61
 
 
4851168
835a735
4851168
 
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
import gradio as gr
from PIL import Image # to open / display image
import os
import sqlite3 # DB for SQL operation, analytical db
import google.generativeai as genai
import time # 

# Initialize Gemini
gemini_key = os.getenv("gemini_key")
genai.configure(api_key=gemini_key)
genai_model = genai.GenerativeModel('gemini-pro')

class SQLPromptModel:
    def __init__(self, database):
        # Initialize with database file path and create connection
        self.database = database
        self.conn = sqlite3.connect(self.database) # create connection to DB  
        
    def fetch_table_schema(self, table_name):
        # Get database table structure
        # In order to execute SQL statements and fetch results from SQL queries, 
        #we will need to use a database cursor. Call con.cursor() to create the Cursor:
        cursor = self.conn.cursor()
        # PRAGMA table_info returns: 
        # (id, name, type, notnull, default_value, primary_key)
        cursor.execute(f"PRAGMA table_info({table_name})")
        schema = cursor.fetchall()
        if schema:
            return schema 
        else:
            return None
        #return schema if schema else None

    def text2sql_gemini(self, schema, def_query, user_query=None):
        # Convert table columns to string format
        table_columns = ', '.join([f"{col[1]} {col[2]}" for col in schema])
        #col[1] - column name/index 
        #col[2] - column data type 
        
        # Create prompt for Gemini AI
        prompt = f"""Below are SQL table schemas paired with instructions that describe a task.
        Using valid SQLite, write a response that appropriately completes the request for the provided tables.
        ### Instruction: {def_query} ### 
        Input: CREATE TABLE sql_pdf({table_columns});
        ### Response: (Return only generated query based on def_query , nothing extra)"""

        # Replace default prompt with user input if provided
        if user_query is not None:
            prompt = prompt.replace(def_query, user_query + " ")
            
        # Get SQL query from Gemini
        completion = genai_model.generate_content(prompt)
        generated_query = completion.text
        
        # Extract just the SQL query
        start_index = generated_query.find("SELECT")
        end_index = generated_query.find(";", start_index) + 1
        
        if start_index != -1 and end_index != 0:
            return generated_query[start_index:end_index]
        return generated_query

    def execute_query(self, query):
        # Execute SQL query and get results
        cur = self.conn.cursor()
        cur.execute(query)
        # Get column names
        print(cur.description)
        columns = [header[0] for header in cur.description]
        # Get all rows
        rows = [row for row in cur.fetchall()]
        cur.close()
        self.conn.commit()
        return rows, columns

def execute_sql_query(user_query):
    # Database file path
    database = r"sql_pdf.db"
    sql_model = SQLPromptModel(database)
    
    # Default prompt if none provided
    def_query = "Give complete details of properties in India"
    
    # Try operation up to 3 times
    for _ in range(3):
        try:
            # Get database structure
            table_schema = sql_model.fetch_table_schema("sql_pdf")
            if table_schema:
                # Generate and execute query
                # strip() -> removed initial & after query spaces 
                if user_query.strip():
                    query = sql_model.text2sql_gemini(table_schema, def_query, user_query)
                else:
                    query = sql_model.text2sql_gemini(table_schema, def_query, def_query)
                    
                rows, columns = sql_model.execute_query(query)
                # Return formatted results
                return {"Query": query, "Results": rows, "Columns": columns}
            else:
                return {"error": "Table schema not found."}
        except Exception as e:
            print(f"An error occurred: {e}")
            time.sleep(1)  # Wait 1 second before retry
    return {"error": "Failed to execute query after 3 retries."}

# Load the image
# Load database schema image
image = Image.open(os.path.join(os.path.abspath(''), "house_excel_sheet.png"))

# Create web interface
with gr.Blocks(title="House Database Query") as demo:
    # Header Markdown -> descrption
    # one # -> heading
    # two ## -> sub heading
    # three ### -> sub minor heading
    gr.Markdown("# House Database Query System")
    
    # Display database schema image
    gr.Image(image)
    
    # Description
    # Markdown -> description/note
    # three ### -> sub minor heading
    gr.Markdown("""### The database contains information about different properties including their fundamental details. 
                You can query this database using natural language.""")
    
    # Input section
    # gr.Row() -> Create new row layout  to organize components
    # horizontal
    with gr.Row():
        query_input = gr.Textbox(
            lines=2,# 2 lines max will be visible 
            label="Database Query",
            # Display hints for user until they start typing 
            placeholder="Enter your query or choose from examples below. Default: 'Properties in India'"
        )
    
    # Submit button section
    with gr.Row():
        # variant="primary" -> default style/color
        submit_btn = gr.Button("Submit Query", variant="primary")
    
    # Results section
    with gr.Row():
        query_output = gr.JSON(label="Query Results")
    
    # Connect button click to query function
    # Click event
    
    submit_btn.click(
        fn=execute_sql_query,
        inputs=query_input,
        outputs=query_output
    )
    
    # Example queries section
    # gr.Examples(
    #     examples=[
    #         "Properties in France",
    #         "Properties greater than an acre",
    #         "Properties with more than 400 bedrooms"
    #     ],
    #     inputs=query_input,
    #     outputs=query_output,
    #     fn=execute_sql_query
    # )
       # Example queries section
    example = gr.Examples(
        examples=[
            "Properties in France",
            "Properties greater than an acre",
            "Properties with more than 400 bedrooms"
        ],
        inputs=query_input
        # outputs=query_output,
        # fn=execute_sql_query
    )
# When calling/running directly,  script gets executed
if __name__ == "__main__":
    demo.launch(share=True)