77from typing import Dict , List
88
99
10- # pages/ml_serving_invoke.py
1110dash .register_page (
1211 __name__ ,
1312 path = "/bi/genie" ,
2322except Exception :
2423 w = None
2524
25+ code_snippet = '''```python
26+ import pandas as pd
27+ from databricks.sdk import WorkspaceClient
28+
29+
30+ def get_query_result(statement_id):
31+ # For simplicity, let's say data fits in one chunk, query.manifest.total_chunk_count = 1
32+
33+ result = w.statement_execution.get_statement(statement_id)
34+ return pd.DataFrame(
35+ result.result.data_array, columns=[i.name for i in result.manifest.schema.columns]
36+ )
37+
38+
39+ def process_genie_response(response):
40+ for i in response.attachments:
41+ if i.text:
42+ print(f"A: {i.text.content}")
43+ elif i.query:
44+ data = get_query_result(i.query.statement_id)
45+ print(f"A: {i.query.description}")
46+ print(f"Data: {data}")
47+ print(f"Generated code: {i.query.query}")
48+
49+
50+ # Configuration
51+ w = WorkspaceClient()
52+ genie_space_id = "01f0023d28a71e599b5a62f4117516d4"
53+
54+ prompt = "Ask a question..."
55+ follow_up_prompt = "Ask a follow-up..."
56+
57+ # Start the conversation
58+ conversation = w.genie.start_conversation_and_wait(genie_space_id, prompt)
59+ process_genie_response(conversation)
60+
61+ # Continue the conversation
62+ follow_up_conversation = w.genie.create_message_and_wait(
63+ genie_space_id, conversation.conversation_id, follow_up_prompt
64+ )
65+ process_genie_response(follow_up_conversation)
66+ ```'''
67+
2668
2769def dash_dataframe (df : pd .DataFrame ) -> dash .dash_table .DataTable :
2870 table = dash .dash_table .DataTable (
@@ -50,7 +92,6 @@ def dash_dataframe(df: pd.DataFrame) -> dash.dash_table.DataTable:
5092 "whiteSpace" : "normal" ,
5193 "height" : "auto" ,
5294 },
53-
5495 page_size = 10 ,
5596 page_action = "native" ,
5697 sort_action = "native" ,
@@ -65,12 +106,13 @@ def format_message_display(chat_history: List[Dict]) -> List[Dict]:
65106 for message in chat_history :
66107 display = []
67108 if "content" in message :
68- display .append (dcc .Markdown (message ["content" ]))
109+ role = "You: " if message ["role" ] == "user" else f"{ message ['role' ].capitalize ()} : "
110+ display .append (dcc .Markdown (f"{ role } { message ['content' ]} " ))
69111 if "data" in message :
70112 display .append (message ["data" ])
71113 if "code" in message :
72114 display .append (dcc .Markdown (f"```sql { message ['code' ]} ```" , className = "border rounded p-3" ))
73- chat_display .append (html .Div (display , className = f"chat-message { message [ 'role' ] } -message" ))
115+ chat_display .append (html .Div (display , style = { "borderBottom" : "2px solid rgba(0, 0, 0, 0.2)" , "margin" : "5px 0 0 0" } ))
74116
75117 return chat_display
76118
@@ -132,7 +174,7 @@ def layout():
132174 dbc .Form ([
133175 dbc .Label ("Genie Space ID:" , className = "mt-3" ),
134176 dbc .Input (
135- id = "genie-space-id-input " ,
177+ id = "genie-space-id" ,
136178 type = "text" ,
137179 placeholder = "01efe16a65e21836acefb797ae6a8fe4" ,
138180 style = {
@@ -149,13 +191,17 @@ def layout():
149191 style = {
150192 "backgroundColor" : "#f8f9fa" ,
151193 "border" : "1px solid #dee2e6" ,
152- "boxShadow" : "inset 0 1px 2px rgba(0,0,0,0.075)"
194+ "boxShadow" : "inset 0 1px 2px rgba(0,0,0,0.075)" ,
195+ "margin" : "5px 0 0 0" ,
153196 }
154197 ),
155198 dbc .Button (
156199 "Chat" ,
157200 id = "chat-button" ,
158- color = "primary"
201+ color = "primary" ,
202+ style = {
203+ "margin" : "5px 0 0 0" ,
204+ }
159205 )
160206 ])
161207 ], className = "mb-4" ),
@@ -164,55 +210,14 @@ def layout():
164210 html .Div (id = "chat-history" , className = "mt-4" ),
165211 dcc .Store (id = "chat-history-store" ),
166212 dcc .Store (id = "conversation-id" ),
167-
168- # Status/error messages
169- html . Div ( id = "status-area-genie" , className = "mt-3" )
213+ dbc . Button ( "New Chat" , id = "clear-button" , n_clicks = 0 , className = "mt-3" ),
214+ dbc . Button ( "Open Genie" , id = "genie-button" , target = "_blank" , href = "" , style = { "display" : "none" }, className = "mt-3" ),
215+
170216 ], className = "p-3" ),
171217
172218 # Code snippet tab
173219 dbc .Tab (label = "Code snippet" , children = [
174- dcc .Markdown ('''```python
175- import pandas as pd
176- from databricks.sdk import WorkspaceClient
177-
178-
179- def get_query_result(statement_id):
180- # For simplicity, let's say data fits in one chunk, query.manifest.total_chunk_count = 1
181-
182- result = w.statement_execution.get_statement(statement_id)
183- return pd.DataFrame(
184- result.result.data_array, columns=[i.name for i in result.manifest.schema.columns]
185- )
186-
187-
188- def process_genie_response(response):
189- for i in response.attachments:
190- if i.text:
191- print(f"A: {i.text.content}")
192- elif i.query:
193- data = get_query_result(i.query.statement_id)
194- print(f"A: {i.query.description}")
195- print(f"Data: {data}")
196- print(f"Generated code: {i.query.query}")
197-
198-
199- # Configuration
200- w = WorkspaceClient()
201- genie_space_id = "01f0023d28a71e599b5a62f4117516d4"
202-
203- prompt = "Ask a question..."
204- follow_up_prompt = "Ask a follow-up..."
205-
206- # Start the conversation
207- conversation = w.genie.start_conversation_and_wait(genie_space_id, prompt)
208- process_genie_response(conversation)
209-
210- # Continue the conversation
211- follow_up_conversation = w.genie.create_message_and_wait(
212- genie_space_id, conversation.conversation_id, follow_up_prompt
213- )
214- process_genie_response(follow_up_conversation)
215- ```''' , className = "p-4 border rounded" )
220+ dcc .Markdown (code_snippet , className = "p-4 border rounded" )
216221 ], className = "p-3" ),
217222
218223 # Requirements tab
@@ -245,46 +250,67 @@ def process_genie_response(response):
245250 ], className = "mb-4" )
246251 ], fluid = True , className = "py-4" )
247252
253+
254+ # Callbacks handle interactions
255+
248256@callback (
249257 [Output ("chat-history-store" , "data" , allow_duplicate = True ),
250258 Output ("chat-history" , "children" , allow_duplicate = True ),
251- Output ("conversation-id" , "value" , allow_duplicate = True )],
259+ Output ("conversation-id" , "value" , allow_duplicate = True ), ],
252260 Input ("chat-button" , "n_clicks" ),
253- [State ("genie-space-id-input " , "value" ),
261+ [State ("genie-space-id" , "value" ),
254262 State ("conversation-id" , "value" ),
255263 State ("prompt" , "value" ),
256264 State ("chat-history-store" , "data" )],
257- prevent_initial_call = True
265+ prevent_initial_call = True ,
258266)
259267def update_chat (n_clicks , genie_space_id , conversation_id , prompt , chat_history ):
260268 if not all ([genie_space_id , prompt ]):
261- return dash .no_update , dbc .Alert (
262- "Please fill in all fields" ,
263- color = "warning"
264- )
265-
269+ return dash .no_update , dbc .Alert ("Please fill in all fields" , color = "warning" )
270+
266271 chat_history = chat_history or []
272+ chat_history .append ({"role" : "user" , "content" : prompt })
267273
268274 try :
269275 if conversation_id :
270- conversation = w .genie .create_message_and_wait (
271- genie_space_id , conversation_id , prompt
272- )
273- chat_history = process_genie_response (conversation , chat_history )
276+ conversation = w .genie .create_message_and_wait (genie_space_id , conversation_id , prompt )
274277 else :
275278 conversation = w .genie .start_conversation_and_wait (genie_space_id , prompt )
276279 conversation_id = conversation .conversation_id
277- chat_history = process_genie_response (conversation , chat_history )
278280
281+ chat_history = process_genie_response (conversation , chat_history )
279282 chat_display = format_message_display (chat_history )
280283
281284 return chat_history , chat_display , conversation_id
282-
285+
283286 except Exception as e :
284- return dash .no_update , dbc .Alert (
285- f"An error occurred: { str (e )} " ,
286- color = "danger"
287- )
287+ return dash .no_update , dbc .Alert (f"An error occurred: { str (e )} " , color = "danger" )
288+
289+
290+ @callback (
291+ [Output ("chat-history-store" , "data" , allow_duplicate = True ),
292+ Output ("chat-history" , "children" , allow_duplicate = True ),
293+ Output ("conversation-id" , "value" , allow_duplicate = True ),],
294+ Input ("clear-button" , "n_clicks" ),
295+ prevent_initial_call = True ,
296+ )
297+ def clear_chat (n_clicks ):
298+ return [], [], None if n_clicks else (dash .no_update , dash .no_update , None )
299+
300+
301+ @callback (
302+ [Output ("genie-button" , "href" ), Output ("genie-button" , "style" )],
303+ State ("genie-space-id" , "value" ),
304+ Input ("conversation-id" , "value" ),
305+ )
306+ def update_href (genie_space_id , conversation_id ):
307+ if not conversation_id :
308+ return "" , {"display" : "none" }
309+
310+ href = f"{ w .config .host } /genie/rooms/{ genie_space_id } /chats/{ conversation_id } "
311+
312+ return href , {"margin" : "0 0 0 5px" }
313+
288314
289315# Make layout available at module level
290316__all__ = ["layout" ]
0 commit comments