Tialo commited on
Commit
2dad6a6
·
verified ·
1 Parent(s): 39ddcc8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +121 -35
app.py CHANGED
@@ -19,25 +19,41 @@ def initialize_pipeline():
19
  )
20
  return D2GLLMPipeline("d2g_pipeline", model_storage=ms, filling_llm="my_filling_model")
21
 
22
- def load_dialog_data(json_file: str, custom_dialog_json: Optional[str] = None) -> List[Dict[str, str]]:
23
- """Load dialog data from JSON file or custom JSON string"""
24
  if json_file == "custom" and custom_dialog_json:
25
  try:
26
- return json.loads(custom_dialog_json)
27
  except json.JSONDecodeError as e:
28
  gr.Error(f"Invalid JSON format in custom dialog: {str(e)}")
29
  return []
 
 
 
 
 
 
 
 
 
 
 
30
 
31
- file_path = f"{json_file}.json"
32
- try:
33
- with open(file_path, 'r') as f:
34
- return json.load(f)
35
- except FileNotFoundError:
36
- gr.Error(f"File {file_path} not found!")
37
- return []
38
- except json.JSONDecodeError:
39
- gr.Error(f"Invalid JSON format in {file_path}!")
40
  return []
 
 
 
 
 
 
 
 
 
 
 
 
41
 
42
  def create_network_visualization(graph: nx.Graph) -> go.Figure:
43
  """Create a Plotly network visualization from NetworkX graph"""
@@ -149,9 +165,12 @@ def create_network_visualization(graph: nx.Graph) -> go.Figure:
149
 
150
  return fig
151
 
152
- def create_chat_visualization(dialog_data: List[Dict[str, str]]) -> str:
153
- """Create a chat-like visualization of the dialog"""
154
- chat_html = """
 
 
 
155
  <div style="max-height: 500px; overflow-y: auto; border: 1px solid #ddd; border-radius: 10px; padding: 20px; background-color: #f9f9f9;">
156
  """
157
 
@@ -183,46 +202,57 @@ def create_chat_visualization(dialog_data: List[Dict[str, str]]) -> str:
183
  chat_html += "</div>"
184
  return chat_html
185
 
186
- def process_dialog_and_visualize(dialog_choice: str, custom_dialog: str = "") -> tuple:
187
  """Process the selected dialog and create visualization"""
188
  try:
189
  # Load the selected dialog data
190
- dialog_data = load_dialog_data(dialog_choice, custom_dialog if dialog_choice == "custom" else None)
 
 
 
191
 
192
- if not dialog_data:
193
- return None, "Failed to load dialog data", ""
194
 
195
  # Initialize pipeline
196
  pipe = initialize_pipeline()
197
 
198
- # Process the data
199
- data = PipelineRawDataType(dialogs=dialog_data)
200
  graph, report = pipe.invoke(data)
201
 
202
  # Create visualization
203
  fig = create_network_visualization(graph.graph)
204
 
205
- # Create chat visualization
206
- chat_viz = create_chat_visualization(dialog_data)
 
207
 
208
  # Create summary information
209
  num_nodes = graph.graph.number_of_nodes()
210
  num_edges = graph.graph.number_of_edges()
 
211
 
212
  summary = f"""
213
  ## Graph Summary
214
  - **Number of nodes**: {num_nodes}
215
  - **Number of edges**: {num_edges}
216
- - **Dialog turns**: {len(dialog_data)}
 
 
217
 
218
  ## Processing Report
219
- Generated graph from {len(dialog_data)} dialog turns with {num_nodes} nodes and {num_edges} edges.
220
  """
221
 
222
- return fig, summary, chat_viz
 
 
 
 
223
 
224
  except Exception as e:
225
- return None, f"Error processing dialog: {str(e)}", ""
226
 
227
  # Create the Gradio interface
228
  def create_gradio_app():
@@ -230,10 +260,14 @@ def create_gradio_app():
230
  gr.Markdown("# Dialog2Graph Interactive Visualizer")
231
  gr.Markdown("Select a dialog dataset to process and visualize as a graph network using Plotly.")
232
 
 
 
 
 
233
  with gr.Row():
234
  with gr.Column(scale=1):
235
  dialog_selector = gr.Radio(
236
- choices=["dialog1", "dialog2", "dialog3", "custom"],
237
  label="Select Dialog Dataset",
238
  value="dialog1",
239
  info="Choose one of the available dialog datasets or use custom JSON"
@@ -258,6 +292,7 @@ def create_gradio_app():
258
  - **dialog1**: Hotel booking conversation
259
  - **dialog2**: Food delivery conversation
260
  - **dialog3**: Technical support conversation
 
261
  - **custom**: Provide your own dialog as JSON
262
  """)
263
 
@@ -270,8 +305,46 @@ def create_gradio_app():
270
 
271
  with gr.Column(scale=1):
272
  gr.Markdown("### Dialog Conversation")
 
 
 
 
 
 
273
  chat_output = gr.HTML(label="Chat Visualization")
274
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
275
  # Event handlers
276
  def toggle_custom_input(choice):
277
  return gr.update(visible=(choice == "custom"))
@@ -284,21 +357,34 @@ def create_gradio_app():
284
 
285
  process_btn.click(
286
  fn=process_dialog_and_visualize,
287
- inputs=[dialog_selector, custom_dialog_input],
288
- outputs=[plot_output, summary_output, chat_output]
 
 
 
 
 
 
 
 
 
 
 
 
 
289
  )
290
 
291
  # Auto-process on selection change (but not for custom to avoid premature processing)
292
- def auto_process(choice, custom_text):
293
  if choice != "custom":
294
- return process_dialog_and_visualize(choice, custom_text)
295
  else:
296
- return None, "Select 'Process Dialog & Generate Graph' to process custom dialog", ""
297
 
298
  dialog_selector.change(
299
  fn=auto_process,
300
- inputs=[dialog_selector, custom_dialog_input],
301
- outputs=[plot_output, summary_output, chat_output]
302
  )
303
 
304
  return app
 
19
  )
20
  return D2GLLMPipeline("d2g_pipeline", model_storage=ms, filling_llm="my_filling_model")
21
 
22
+ def load_dialog_data(json_file: str, custom_dialog_json: Optional[str] = None) -> List[List[Dict[str, str]]]:
23
+ """Load dialog data from JSON file or custom JSON string and ensure it's in list[list[dict]] format"""
24
  if json_file == "custom" and custom_dialog_json:
25
  try:
26
+ data = json.loads(custom_dialog_json)
27
  except json.JSONDecodeError as e:
28
  gr.Error(f"Invalid JSON format in custom dialog: {str(e)}")
29
  return []
30
+ else:
31
+ file_path = f"{json_file}.json"
32
+ try:
33
+ with open(file_path, 'r') as f:
34
+ data = json.load(f)
35
+ except FileNotFoundError:
36
+ gr.Error(f"File {file_path} not found!")
37
+ return []
38
+ except json.JSONDecodeError:
39
+ gr.Error(f"Invalid JSON format in {file_path}!")
40
+ return []
41
 
42
+ # Convert to list[list[dict]] format if needed
43
+ if not data:
 
 
 
 
 
 
 
44
  return []
45
+
46
+ # Check if it's already list[list[dict]]
47
+ if isinstance(data, list) and len(data) > 0:
48
+ if isinstance(data[0], list):
49
+ # Already in list[list[dict]] format
50
+ return data
51
+ elif isinstance(data[0], dict):
52
+ # Convert list[dict] to list[list[dict]]
53
+ return [data]
54
+
55
+ # If it's something else, wrap it in double list
56
+ return [data] if isinstance(data, list) else [[data]]
57
 
58
  def create_network_visualization(graph: nx.Graph) -> go.Figure:
59
  """Create a Plotly network visualization from NetworkX graph"""
 
165
 
166
  return fig
167
 
168
+ def create_chat_visualization(dialog_data: List[Dict[str, str]], dialog_index: int = 0, total_dialogs: int = 1) -> str:
169
+ """Create a chat-like visualization of the dialog with navigation info"""
170
+ chat_html = f"""
171
+ <div style="margin-bottom: 10px; text-align: center; font-weight: bold; color: #666;">
172
+ Dialog {dialog_index + 1} of {total_dialogs}
173
+ </div>
174
  <div style="max-height: 500px; overflow-y: auto; border: 1px solid #ddd; border-radius: 10px; padding: 20px; background-color: #f9f9f9;">
175
  """
176
 
 
202
  chat_html += "</div>"
203
  return chat_html
204
 
205
+ def process_dialog_and_visualize(dialog_choice: str, custom_dialog: str = "", current_dialog_index: int = 0) -> tuple:
206
  """Process the selected dialog and create visualization"""
207
  try:
208
  # Load the selected dialog data
209
+ dialog_data_list = load_dialog_data(dialog_choice, custom_dialog if dialog_choice == "custom" else None)
210
+
211
+ if not dialog_data_list:
212
+ return None, "Failed to load dialog data", "", 0, len(dialog_data_list), gr.update(visible=False), gr.update(visible=False)
213
 
214
+ # Ensure current_dialog_index is within bounds
215
+ current_dialog_index = max(0, min(current_dialog_index, len(dialog_data_list) - 1))
216
 
217
  # Initialize pipeline
218
  pipe = initialize_pipeline()
219
 
220
+ # Process the data (use all dialogs for graph generation)
221
+ data = PipelineRawDataType(dialogs=dialog_data_list)
222
  graph, report = pipe.invoke(data)
223
 
224
  # Create visualization
225
  fig = create_network_visualization(graph.graph)
226
 
227
+ # Create chat visualization for the current dialog
228
+ current_dialog = dialog_data_list[current_dialog_index]
229
+ chat_viz = create_chat_visualization(current_dialog, current_dialog_index, len(dialog_data_list))
230
 
231
  # Create summary information
232
  num_nodes = graph.graph.number_of_nodes()
233
  num_edges = graph.graph.number_of_edges()
234
+ total_turns = sum(len(dialog) for dialog in dialog_data_list)
235
 
236
  summary = f"""
237
  ## Graph Summary
238
  - **Number of nodes**: {num_nodes}
239
  - **Number of edges**: {num_edges}
240
+ - **Total dialogs**: {len(dialog_data_list)}
241
+ - **Total dialog turns**: {total_turns}
242
+ - **Currently viewing**: Dialog {current_dialog_index + 1} ({len(current_dialog)} turns)
243
 
244
  ## Processing Report
245
+ Generated graph from {len(dialog_data_list)} dialog(s) with {total_turns} total turns resulting in {num_nodes} nodes and {num_edges} edges.
246
  """
247
 
248
+ # Show navigation buttons only if there are multiple dialogs
249
+ show_nav = len(dialog_data_list) > 1
250
+
251
+ return (fig, summary, chat_viz, current_dialog_index, len(dialog_data_list),
252
+ gr.update(visible=show_nav), gr.update(visible=show_nav))
253
 
254
  except Exception as e:
255
+ return None, f"Error processing dialog: {str(e)}", "", 0, 0, gr.update(visible=False), gr.update(visible=False)
256
 
257
  # Create the Gradio interface
258
  def create_gradio_app():
 
260
  gr.Markdown("# Dialog2Graph Interactive Visualizer")
261
  gr.Markdown("Select a dialog dataset to process and visualize as a graph network using Plotly.")
262
 
263
+ # State variables for dialog navigation
264
+ current_dialog_index_state = gr.State(0)
265
+ total_dialogs_state = gr.State(0)
266
+
267
  with gr.Row():
268
  with gr.Column(scale=1):
269
  dialog_selector = gr.Radio(
270
+ choices=["dialog1", "dialog2", "dialog3", "dialog4", "custom"],
271
  label="Select Dialog Dataset",
272
  value="dialog1",
273
  info="Choose one of the available dialog datasets or use custom JSON"
 
292
  - **dialog1**: Hotel booking conversation
293
  - **dialog2**: Food delivery conversation
294
  - **dialog3**: Technical support conversation
295
+ - **dialog4**: Multiple dialogs (calendar, support, subscription)
296
  - **custom**: Provide your own dialog as JSON
297
  """)
298
 
 
305
 
306
  with gr.Column(scale=1):
307
  gr.Markdown("### Dialog Conversation")
308
+
309
+ # Navigation controls for multiple dialogs
310
+ with gr.Row(visible=False) as nav_row:
311
+ prev_btn = gr.Button("← Previous Dialog", size="sm")
312
+ next_btn = gr.Button("Next Dialog →", size="sm")
313
+
314
  chat_output = gr.HTML(label="Chat Visualization")
315
 
316
+ # Navigation functions
317
+ def navigate_dialog(direction: int, current_index: int, total_dialogs: int, dialog_choice: str, custom_dialog: str):
318
+ if total_dialogs <= 1:
319
+ return current_index, "", ""
320
+
321
+ new_index = current_index + direction
322
+ new_index = max(0, min(new_index, total_dialogs - 1))
323
+
324
+ try:
325
+ dialog_data_list = load_dialog_data(dialog_choice, custom_dialog if dialog_choice == "custom" else None)
326
+ if dialog_data_list and new_index < len(dialog_data_list):
327
+ current_dialog = dialog_data_list[new_index]
328
+ chat_viz = create_chat_visualization(current_dialog, new_index, len(dialog_data_list))
329
+
330
+ total_turns = sum(len(dialog) for dialog in dialog_data_list)
331
+
332
+ summary = f"""
333
+ ## Graph Summary
334
+ - **Total dialogs**: {len(dialog_data_list)}
335
+ - **Total dialog turns**: {total_turns}
336
+ - **Currently viewing**: Dialog {new_index + 1} ({len(current_dialog)} turns)
337
+
338
+ ## Processing Report
339
+ Navigate between dialogs to view different conversations.
340
+ """
341
+
342
+ return new_index, summary, chat_viz
343
+ except Exception:
344
+ pass
345
+
346
+ return current_index, "", ""
347
+
348
  # Event handlers
349
  def toggle_custom_input(choice):
350
  return gr.update(visible=(choice == "custom"))
 
357
 
358
  process_btn.click(
359
  fn=process_dialog_and_visualize,
360
+ inputs=[dialog_selector, custom_dialog_input, current_dialog_index_state],
361
+ outputs=[plot_output, summary_output, chat_output, current_dialog_index_state, total_dialogs_state, nav_row, nav_row]
362
+ )
363
+
364
+ # Navigation button handlers
365
+ prev_btn.click(
366
+ fn=lambda curr_idx, total, choice, custom: navigate_dialog(-1, curr_idx, total, choice, custom),
367
+ inputs=[current_dialog_index_state, total_dialogs_state, dialog_selector, custom_dialog_input],
368
+ outputs=[current_dialog_index_state, summary_output, chat_output]
369
+ )
370
+
371
+ next_btn.click(
372
+ fn=lambda curr_idx, total, choice, custom: navigate_dialog(1, curr_idx, total, choice, custom),
373
+ inputs=[current_dialog_index_state, total_dialogs_state, dialog_selector, custom_dialog_input],
374
+ outputs=[current_dialog_index_state, summary_output, chat_output]
375
  )
376
 
377
  # Auto-process on selection change (but not for custom to avoid premature processing)
378
+ def auto_process(choice, custom_text, curr_idx):
379
  if choice != "custom":
380
+ return process_dialog_and_visualize(choice, custom_text, curr_idx)
381
  else:
382
+ return None, "Select 'Process Dialog & Generate Graph' to process custom dialog", "", 0, 0, gr.update(visible=False), gr.update(visible=False)
383
 
384
  dialog_selector.change(
385
  fn=auto_process,
386
+ inputs=[dialog_selector, custom_dialog_input, current_dialog_index_state],
387
+ outputs=[plot_output, summary_output, chat_output, current_dialog_index_state, total_dialogs_state, nav_row, nav_row]
388
  )
389
 
390
  return app