Jacqkues commited on
Commit
715cb68
·
verified ·
1 Parent(s): 66edb83

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +196 -0
  2. requirements.txt +6 -0
app.py ADDED
@@ -0,0 +1,196 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from database import Database
3
+ from filesource import FileSource
4
+ from agent import run_agent
5
+ from services.utils import get_db_scheme_from_uri
6
+ source = None
7
+
8
+
9
+ def connect_to_file(file):
10
+ """
11
+ This function is used to connect to a data source file like CSV or parquet
12
+
13
+ Parameters:
14
+ -----------
15
+ file : File
16
+ A file-like object (e.g., from a file upload or file picker) that contains structured data.
17
+
18
+ Returns:
19
+ --------
20
+ tuple
21
+ A tuple (schema, status) where:
22
+ - schema (str): A string representation of the data schema if successful, or an empty string on failure.
23
+ - status (str): A message indicating the success or failure of the connection.
24
+
25
+ """
26
+ global source
27
+ try:
28
+ source = FileSource(file.name)
29
+ status = source.connect()
30
+ schema = source._pretify_schema()
31
+ status = "Connection successful!"
32
+ except Exception as e:
33
+ schema = ""
34
+ status = f"Error: {str(e)}"
35
+ return schema, status
36
+
37
+ def generate_and_run_sql(prompt):
38
+ """
39
+ This function is used to give an answer to a user question related to a database or file source
40
+
41
+
42
+ Parameters:
43
+ -----------
44
+ prompt : str
45
+ A natural language instruction or question from the user (e.g., "Show me the top 10 customers by revenue").
46
+
47
+ Returns:
48
+ --------
49
+ str
50
+ The given response of the user question
51
+ Notes:
52
+ ------
53
+ - Requires a connected `source` (via `connect_to_file` or `connect_to_database`).
54
+ - Uses a language agent to interpret the prompt and generate an appropriate SQL query or explanation.
55
+ """
56
+ if source is None:
57
+ return "Please connect to a database or add a file"
58
+
59
+ answer = run_agent(source, prompt)
60
+ out = ""
61
+ for chunk in answer:
62
+ out += chunk
63
+ return out
64
+
65
+
66
+ def connect_to_database(db_url):
67
+ """
68
+ This function is used to connect to a database using the provided database URL and returns its schema.
69
+
70
+ Parameters:
71
+ -----------
72
+ db_url : str
73
+ A valid database connection string (e.g., "mysql://user:pass@host:port/dbname").
74
+
75
+ Returns:
76
+ --------
77
+ tuple
78
+ A tuple (schema, status) where:
79
+ - schema (str): A string representation of the database schema if the connection is successful,
80
+ or an empty string if it fails.
81
+ - status (str): A message indicating the result of the connection attempt.
82
+
83
+ Notes:
84
+ ------
85
+ - The dialect is extracted from the URI to determine the database type (e.g., MySQL, PostgreSQL).
86
+ """
87
+ global source
88
+ try:
89
+ dialect = get_db_scheme_from_uri(db_url)
90
+ source = Database(db_url, dialect)
91
+ status = source.connect()
92
+ schema = source._pretify_schema()
93
+ status = "Connection successful!"
94
+ except Exception as e:
95
+ schema = ""
96
+ status = f"Error: {str(e)}"
97
+ return schema, status
98
+ # Function to add user message to chat history
99
+ def user(user_message, chat_history):
100
+ chat_history.append({"role": "user", "content": user_message})
101
+ return "", chat_history
102
+
103
+ # Function to generate a bot response
104
+ def bot(chat_history):
105
+
106
+ if source is None:
107
+ chat_history.append({"role":"assistant","content":"please connect to a database before asking question"})
108
+ yield chat_history
109
+ else:
110
+ answer = run_agent(source,chat_history[-1]['content'])
111
+ chat_history.append({"role":"assistant","content":""})
112
+
113
+ for chunk in answer:
114
+ chat_history[-1]['content'] += chunk
115
+ yield chat_history
116
+
117
+ # Create the Gradio interface
118
+ with gr.Blocks( theme=gr.themes.Default(), css="""
119
+ .gr-button { margin: 5px; border-radius:16px; }
120
+ .gr-textbox, .gr-text-area, .gr-dropdown, .gr-json { border-radius: 8px; }
121
+ .gr-row { gap: 10px; }
122
+ .gr-tab { border-radius: 8px; }
123
+ .status-text { font-size: 0.9em; color: #555; }
124
+ .gr-json { max-height: 300px; overflow-y: auto; } /* Added scrolling for JSON */
125
+ """) as demo:
126
+ gr.Markdown(
127
+ f"""
128
+ # 🤖 MCP DB Answer
129
+ Your mcp server that allow you to talk to any database
130
+
131
+
132
+ Powered by Ibis it support : PostgreSQL , SQLite , MySQL , MSSQL , ClickHouse , BigQuery and many other
133
+
134
+
135
+ Also support .CSV and .parquet files
136
+
137
+ """,
138
+ elem_classes=["header"]
139
+ )
140
+
141
+ with gr.Column(scale=3):
142
+ with gr.Tabs():
143
+ with gr.TabItem("💬 Chat"):
144
+ with gr.Group():
145
+ main_chat_disp = gr.Chatbot(
146
+ label=None, height=400,
147
+ avatar_images=(None, "https://huggingface.co/spaces/Space-Share/bucket/resolve/main/images/pfp.webp"),
148
+ show_copy_button=True, render_markdown=True, sanitize_html=True, type='messages'
149
+ )
150
+ with gr.Row(variant="compact"):
151
+ user_msg_tb = gr.Textbox(
152
+ show_label=False, placeholder="Talk with your data...",
153
+ scale=7, lines=1, max_lines=3
154
+ )
155
+ send_btn = gr.Button("Send", variant="primary", scale=1, min_width=100)
156
+ with gr.TabItem("Config"):
157
+ with gr.Row():
158
+ # Left column for database configuration.
159
+ with gr.Column(scale=1):
160
+ gr.Markdown("## Database Configuration")
161
+ # Textbox for entering the database URL.
162
+ db_url_tb = gr.Textbox(
163
+ show_label=True, label="Database URL", placeholder="Enter the URL to connect to the database..."
164
+ )
165
+ # Button to connect to the database.
166
+ connect_btn = gr.Button("Connect", variant="primary")
167
+ gr.Markdown("## File Upload")
168
+ file_uploader = gr.File(
169
+ label="Upload File", file_types=[".csv", ".parquet", ".xls", ".xlsx"]
170
+ )
171
+ # Button to connect to the database.
172
+ load_btn = gr.Button("Load", variant="primary")
173
+
174
+ # Right column for displaying the database schema and status message.
175
+ with gr.Column(scale=3):
176
+ gr.Markdown("## Database Schema")
177
+ # Textarea to display the database schema.
178
+ schema_ta = gr.TextArea(
179
+ show_label=False, placeholder="Database schema will be displayed here...",
180
+ lines=20, max_lines=50, interactive=False
181
+ )
182
+ # Textbox to display the status message.
183
+ status_tb = gr.Textbox(
184
+ show_label=False, placeholder="Status message will be displayed here...",
185
+ lines=1, max_lines=1, interactive=False, elem_classes=["status-text"]
186
+ )
187
+ connect_btn.click(fn=connect_to_database, inputs=db_url_tb, outputs=[schema_ta, status_tb])
188
+ load_btn.click(fn=connect_to_file, inputs=file_uploader, outputs=[schema_ta, status_tb])
189
+ send_btn.click(fn=user, inputs=[user_msg_tb, main_chat_disp], outputs=[user_msg_tb, main_chat_disp], queue=False).then(
190
+ fn=bot, inputs=main_chat_disp, outputs=main_chat_disp
191
+ )
192
+ invisible_btn = gr.Button(visible=False)
193
+ invisible_btn.click(fn=generate_and_run_sql, inputs=[user_msg_tb], outputs=None)
194
+
195
+ if __name__ == "__main__":
196
+ demo.launch(mcp_server=True)
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ gradio[mcp]>=5.33.0
2
+ ibis-framework[duckdb,mssql,mysql,postgres,sqlite]>=10.5.0
3
+ openai>=1.84.0
4
+ pydantic>=2.11.5
5
+ sqlglot>=26.24.0
6
+ tabulate>=0.9.0