Decoo commited on
Commit
fa98eea
Β·
1 Parent(s): f3a5b42

modified app.py

Browse files
Files changed (1) hide show
  1. app.py +218 -81
app.py CHANGED
@@ -1,7 +1,7 @@
1
  import gradio as gr
2
  import json
3
  import os
4
- from pathlib import Path
5
 
6
  # Data folder paths
7
  DATA_BASE = "Viewer/Data/Our_system"
@@ -24,14 +24,158 @@ def get_available_events():
24
  events.add(event_name)
25
  return sorted(list(events))
26
 
27
- def get_folder_index(folder_key):
28
- """Create index.json for a folder"""
29
- folder = FOLDER_MAP.get(folder_key)
30
- if not folder or not os.path.exists(folder):
31
- return []
32
-
33
- files = [f for f in os.listdir(folder) if f.endswith('_combined_data.json')]
34
- return files
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
 
36
  def save_feedback(event, format_type, view_type, rating, comment):
37
  """Save feedback to JSON file"""
@@ -40,18 +184,14 @@ def save_feedback(event, format_type, view_type, rating, comment):
40
 
41
  feedback_dir = "feedback"
42
  os.makedirs(feedback_dir, exist_ok=True)
43
-
44
  feedback_file = os.path.join(feedback_dir, "feedback.json")
45
 
46
- # Load existing feedback
47
  if os.path.exists(feedback_file):
48
  with open(feedback_file, 'r', encoding='utf-8') as f:
49
  feedbacks = json.load(f)
50
  else:
51
  feedbacks = []
52
 
53
- # Add new feedback
54
- from datetime import datetime
55
  feedbacks.append({
56
  "timestamp": datetime.now().isoformat(),
57
  "event": event,
@@ -61,84 +201,86 @@ def save_feedback(event, format_type, view_type, rating, comment):
61
  "comment": comment
62
  })
63
 
64
- # Save
65
  with open(feedback_file, 'w', encoding='utf-8') as f:
66
  json.dump(feedbacks, f, indent=2, ensure_ascii=False)
67
 
68
  return "βœ… Thank you for your feedback!"
69
 
70
- # Create index.json files for each folder
71
- print("Creating index files...")
72
- for key, folder in FOLDER_MAP.items():
73
- if os.path.exists(folder):
74
- index_path = os.path.join(folder, "index.json")
75
- files = get_folder_index(key)
76
- with open(index_path, 'w') as f:
77
- json.dump(files, f)
78
- print(f"Created {index_path} with {len(files)} files")
79
- else:
80
- print(f"WARNING: Folder {folder} does not exist")
81
 
82
- # Read HTML file - prova diversi percorsi possibili
83
- html_paths = ["Viewer/viewer_v2.html", "viewer_v2.html", "./viewer_v2.html"]
84
- original_html = None
85
-
86
- for html_path in html_paths:
87
- if os.path.exists(html_path):
88
- with open(html_path, "r", encoding="utf-8") as f:
89
- original_html = f.read()
90
- print(f"βœ… Found HTML at: {html_path}")
91
- break
92
-
93
- if original_html is None:
94
- print("❌ ERROR: viewer_v2.html not found in any expected location!")
95
- print(f"Current directory: {os.getcwd()}")
96
- print(f"Files in current directory: {os.listdir('.')}")
97
- if os.path.exists('Viewer'):
98
- print(f"Files in Viewer directory: {os.listdir('Viewer')}")
99
- original_html = "<h1>Error: viewer_v2.html not found</h1><p>Please check the file structure.</p>"
100
 
101
  # Create Gradio interface
102
- with gr.Blocks(title="Report Viewer", theme=gr.themes.Soft()) as demo:
103
- gr.Markdown("# πŸ“Š Our Report Viewer")
104
- gr.Markdown("Explore events organized by topics or SDGs")
 
 
 
 
 
105
 
106
  with gr.Tab("πŸ“– Viewer"):
107
- gr.HTML(original_html)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
 
109
  with gr.Tab("πŸ’¬ Feedback"):
110
  gr.Markdown("### Leave your feedback on the results")
111
 
112
  with gr.Row():
113
- fb_event = gr.Dropdown(
114
- choices=get_available_events(),
115
- label="Event",
116
- value=None
117
- )
118
- fb_format = gr.Radio(
119
- choices=["qa", "summary"],
120
- label="Format",
121
- value="qa"
122
- )
123
- fb_view = gr.Radio(
124
- choices=["subtopics", "sdgs"],
125
- label="View",
126
- value="subtopics"
127
- )
128
 
129
- fb_rating = gr.Slider(
130
- minimum=1,
131
- maximum=5,
132
- step=1,
133
- label="Rating (1-5 stars)",
134
- value=3
135
- )
136
-
137
- fb_comment = gr.Textbox(
138
- label="Comment (optional)",
139
- lines=5,
140
- placeholder="Write your feedback here..."
141
- )
142
 
143
  fb_submit = gr.Button("Submit Feedback", variant="primary")
144
  fb_output = gr.Textbox(label="Status", interactive=False)
@@ -150,9 +292,4 @@ with gr.Blocks(title="Report Viewer", theme=gr.themes.Soft()) as demo:
150
  )
151
 
152
  if __name__ == "__main__":
153
- # Launch with file serving enabled
154
- demo.launch(
155
- server_name="0.0.0.0", # Necessario per Hugging Face Spaces
156
- server_port=7860, # Porta standard di Gradio
157
- allowed_paths=[".", "Viewer", "Viewer/Data"] # Permetti accesso a piΓΉ cartelle
158
- )
 
1
  import gradio as gr
2
  import json
3
  import os
4
+ from datetime import datetime
5
 
6
  # Data folder paths
7
  DATA_BASE = "Viewer/Data/Our_system"
 
24
  events.add(event_name)
25
  return sorted(list(events))
26
 
27
+ def load_event_data(event_name, format_type, view_type):
28
+ """Load and render event data as HTML"""
29
+ if not event_name:
30
+ return '<div style="text-align: center; padding: 40px; color: #6c757d;"><h2>Please select an event from the dropdown above.</h2></div>'
31
+
32
+ key = f"{format_type}_{view_type}"
33
+ folder = FOLDER_MAP.get(key)
34
+ filename = f"{folder}/{event_name}_combined_data.json"
35
+
36
+ try:
37
+ with open(filename, 'r', encoding='utf-8') as f:
38
+ data = json.load(f)
39
+
40
+ return render_data_as_html(data, event_name, format_type, view_type)
41
+ except FileNotFoundError:
42
+ return f'<div style="text-align: center; padding: 40px;"><h2>⚠ File not found</h2><p>{filename}</p></div>'
43
+ except Exception as e:
44
+ return f'<div style="text-align: center; padding: 40px;"><h2>⚠ Error</h2><p>{str(e)}</p></div>'
45
+
46
+ def render_data_as_html(data, event_name, format_type, view_type):
47
+ """Render JSON data as HTML"""
48
+
49
+ # Estrai informazioni
50
+ file_name = data.get('file_name', event_name)
51
+ summary = data.get('summary', 'No summary available')
52
+ summary_contexts = data.get('summary_contexts', {})
53
+
54
+ # Process clusters
55
+ clusters = process_clusters(data, format_type)
56
+
57
+ # Render HTML
58
+ html_parts = [f'''
59
+ <div style="margin-bottom: 40px; border: 2px solid #e1e5e9; border-radius: 12px; overflow: hidden;">
60
+ <div style="background: linear-gradient(135deg, #667eea, #764ba2); color: white; padding: 20px; font-size: 1.3em; font-weight: 600;">
61
+ πŸ“„ {escape_html(file_name)}
62
+ </div>
63
+ <div style="padding: 25px;">
64
+ <div style="background: #f8f9fa; border-left: 4px solid #667eea; padding: 20px; margin: 20px 0; border-radius: 0 8px 8px 0; line-height: 1.6;">
65
+ <strong>Summary:</strong><br>{process_citations(escape_html(summary), summary_contexts)}
66
+ </div>
67
+ ''']
68
+
69
+ # Render clusters
70
+ for cluster in clusters:
71
+ html_parts.append(render_cluster(cluster, format_type))
72
+
73
+ html_parts.append('</div></div>')
74
+
75
+ return ''.join(html_parts)
76
+
77
+ def process_clusters(data, format_type):
78
+ """Extract clusters from data"""
79
+ if 'clusters' in data and isinstance(data['clusters'], list):
80
+ return data['clusters']
81
+
82
+ ignore_keys = ['file_name', 'summary', 'summary_contexts']
83
+ clusters = []
84
+
85
+ for key, value in data.items():
86
+ if key in ignore_keys:
87
+ continue
88
+
89
+ if format_type == 'qa':
90
+ clusters.append({
91
+ 'cluster_headline': key,
92
+ 'questions_and_answers': value if isinstance(value, list) else []
93
+ })
94
+ else:
95
+ if isinstance(value, list):
96
+ summary_text = '\n\n'.join([
97
+ v.get('cluster_summary') or v.get('summary', '')
98
+ for v in value if isinstance(v, dict)
99
+ ])
100
+ clusters.append({
101
+ 'cluster_headline': key,
102
+ 'cluster_summary': summary_text or 'No summary',
103
+ 'used_contexts': value[0].get('used_contexts', {}) if value else {}
104
+ })
105
+ elif isinstance(value, dict):
106
+ clusters.append({
107
+ 'cluster_headline': key,
108
+ 'cluster_summary': value.get('cluster_summary') or value.get('summary', 'No summary'),
109
+ 'used_contexts': value.get('used_contexts', {})
110
+ })
111
+
112
+ return clusters
113
+
114
+ def render_cluster(cluster, format_type):
115
+ """Render a single cluster as HTML"""
116
+ header = cluster.get('cluster_headline', 'Cluster')
117
+
118
+ html = f'''
119
+ <div style="margin: 30px 0; border: 1px solid #dee2e6; border-radius: 10px; overflow: hidden;">
120
+ <details>
121
+ <summary style="background: linear-gradient(45deg, #28a745, #20c997); color: white; padding: 15px 20px; font-weight: 600; font-size: 1.1em; cursor: pointer;">
122
+ 🎯 {escape_html(header)}
123
+ </summary>
124
+ <div style="padding: 20px;">
125
+ '''
126
+
127
+ if format_type == 'summary':
128
+ summary_text = cluster.get('cluster_summary', 'No summary')
129
+ contexts = cluster.get('used_contexts', {})
130
+ html += f'<div style="background: #e8f5e8; border-radius: 8px; padding: 15px; line-height: 1.6;">{process_citations(escape_html(summary_text), contexts)}</div>'
131
+ else:
132
+ qas = cluster.get('questions_and_answers', [])
133
+ if not qas:
134
+ html += '<div style="text-align: center; color: #6c757d; font-style: italic;">No Q&A available</div>'
135
+ else:
136
+ for qa in qas:
137
+ question = qa.get('question') or qa.get('Question', 'No question')
138
+ answer = qa.get('updated_retrieved_answer') or qa.get('retrieved_answer') or qa.get('answer', 'No answer')
139
+ contexts = qa.get('used_contexts') or qa.get('summary_contexts', {})
140
+
141
+ html += f'''
142
+ <div style="margin-bottom: 20px; padding: 15px; background: #f8f9fa; border-radius: 8px; border-left: 4px solid #007bff;">
143
+ <div style="font-weight: 600; color: #495057; margin-bottom: 10px; font-size: 1.05em;">
144
+ ❓ {escape_html(question)}
145
+ </div>
146
+ <div style="color: #6c757d; line-height: 1.5;">
147
+ {process_citations(escape_html(answer), contexts)}
148
+ </div>
149
+ </div>
150
+ '''
151
+
152
+ html += '</div></details></div>'
153
+ return html
154
+
155
+ def process_citations(text, contexts):
156
+ """Add citation links to text"""
157
+ import re
158
+
159
+ def replace_citation(match):
160
+ cit_id = match.group(1)
161
+ ctx = contexts.get(cit_id, {})
162
+
163
+ if not ctx:
164
+ return match.group(0)
165
+
166
+ title = ctx.get('title', 'Source')
167
+ url = ctx.get('url', '#')
168
+ context_text = ctx.get('context', 'No context available')
169
+
170
+ return f'<a href="{url}" target="_blank" title="{escape_html(context_text)[:200]}..." style="background: #007bff; color: white; padding: 2px 6px; border-radius: 4px; font-size: 0.85em; text-decoration: none; margin: 0 2px;">[{cit_id}]</a>'
171
+
172
+ return re.sub(r'\[(\d+)\]', replace_citation, text)
173
+
174
+ def escape_html(text):
175
+ """Escape HTML special characters"""
176
+ if not text:
177
+ return ''
178
+ return str(text).replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;').replace('"', '&quot;').replace("'", '&#039;')
179
 
180
  def save_feedback(event, format_type, view_type, rating, comment):
181
  """Save feedback to JSON file"""
 
184
 
185
  feedback_dir = "feedback"
186
  os.makedirs(feedback_dir, exist_ok=True)
 
187
  feedback_file = os.path.join(feedback_dir, "feedback.json")
188
 
 
189
  if os.path.exists(feedback_file):
190
  with open(feedback_file, 'r', encoding='utf-8') as f:
191
  feedbacks = json.load(f)
192
  else:
193
  feedbacks = []
194
 
 
 
195
  feedbacks.append({
196
  "timestamp": datetime.now().isoformat(),
197
  "event": event,
 
201
  "comment": comment
202
  })
203
 
 
204
  with open(feedback_file, 'w', encoding='utf-8') as f:
205
  json.dump(feedbacks, f, indent=2, ensure_ascii=False)
206
 
207
  return "βœ… Thank you for your feedback!"
208
 
209
+ # Get events
210
+ events = get_available_events()
 
 
 
 
 
 
 
 
 
211
 
212
+ # CSS personalizzato
213
+ custom_css = """
214
+ body {
215
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
216
+ }
217
+ .gradio-container {
218
+ max-width: 1200px !important;
219
+ }
220
+ """
 
 
 
 
 
 
 
 
 
221
 
222
  # Create Gradio interface
223
+ with gr.Blocks(title="Report Viewer", theme=gr.themes.Soft(), css=custom_css) as demo:
224
+
225
+ gr.Markdown("""
226
+ <div style="text-align: center; color: white; margin-bottom: 30px;">
227
+ <h1 style="font-size: 2.5em; margin-bottom: 10px; text-shadow: 2px 2px 4px rgba(0,0,0,0.3);">πŸ“Š Our Report Viewer</h1>
228
+ <p style="font-size: 1.2em; opacity: 0.9;">Explore events organized by topics or SDGs</p>
229
+ </div>
230
+ """)
231
 
232
  with gr.Tab("πŸ“– Viewer"):
233
+ with gr.Row():
234
+ with gr.Column(scale=2):
235
+ event_dropdown = gr.Dropdown(
236
+ choices=events,
237
+ label="Select Event",
238
+ value=None
239
+ )
240
+ with gr.Column(scale=1):
241
+ view_radio = gr.Radio(
242
+ choices=["subtopics", "sdgs"],
243
+ label="Arranged by",
244
+ value="subtopics"
245
+ )
246
+ with gr.Column(scale=1):
247
+ format_radio = gr.Radio(
248
+ choices=["qa", "summary"],
249
+ label="Presented as",
250
+ value="qa"
251
+ )
252
+
253
+ content_html = gr.HTML(
254
+ '<div style="text-align: center; padding: 40px; color: #6c757d;"><h2>Please select an event from the dropdown above.</h2></div>'
255
+ )
256
+
257
+ # Update on any change
258
+ event_dropdown.change(
259
+ load_event_data,
260
+ inputs=[event_dropdown, format_radio, view_radio],
261
+ outputs=content_html
262
+ )
263
+ format_radio.change(
264
+ load_event_data,
265
+ inputs=[event_dropdown, format_radio, view_radio],
266
+ outputs=content_html
267
+ )
268
+ view_radio.change(
269
+ load_event_data,
270
+ inputs=[event_dropdown, format_radio, view_radio],
271
+ outputs=content_html
272
+ )
273
 
274
  with gr.Tab("πŸ’¬ Feedback"):
275
  gr.Markdown("### Leave your feedback on the results")
276
 
277
  with gr.Row():
278
+ fb_event = gr.Dropdown(choices=events, label="Event")
279
+ fb_format = gr.Radio(choices=["qa", "summary"], label="Format", value="qa")
280
+ fb_view = gr.Radio(choices=["subtopics", "sdgs"], label="View", value="subtopics")
 
 
 
 
 
 
 
 
 
 
 
 
281
 
282
+ fb_rating = gr.Slider(minimum=1, maximum=5, step=1, label="Rating (1-5 stars)", value=3)
283
+ fb_comment = gr.Textbox(label="Comment (optional)", lines=5, placeholder="Write your feedback here...")
 
 
 
 
 
 
 
 
 
 
 
284
 
285
  fb_submit = gr.Button("Submit Feedback", variant="primary")
286
  fb_output = gr.Textbox(label="Status", interactive=False)
 
292
  )
293
 
294
  if __name__ == "__main__":
295
+ demo.launch()