Decoo commited on
Commit
2b5af8f
Β·
1 Parent(s): 16c6ca2

fixed app.py

Browse files
Files changed (2) hide show
  1. app.py +263 -24
  2. requirements.txt +1 -0
app.py CHANGED
@@ -1,36 +1,275 @@
1
  import gradio as gr
 
 
 
2
 
3
- # Load your custom HTML
4
- def load_html():
5
- # Load from file - replace "visualization.html" with your actual filename
6
- with open("./Viewer/viewer_v2.html", "r", encoding="utf-8") as f:
7
- return f.read()
 
 
8
 
9
- # Create the Gradio interface
10
- with gr.Blocks(title="Humanitarian Sector Results") as demo:
11
- gr.Markdown("""
12
- # 🌍 Humanitarian Sector Results Visualization
13
 
14
- This space presents the results of our analysis. Your feedback is valuable to improve our work!
 
 
 
 
 
15
 
16
- ### How to contribute:
17
- - Explore the data visualized below
18
- - Use the "Community" tab above to leave feedback
19
- - Report any anomalies or suggestions for new analyses
20
- """)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
- # HTML component to display your content
23
- html_output = gr.HTML(value=load_html())
24
 
25
- gr.Markdown("""
26
- ---
27
- ### πŸ’¬ Leave your feedback
 
 
 
28
 
29
- Use the "Community" tab at the top of this Space to discuss results or start a discussion!
 
 
 
 
30
 
31
- **Contact**: [Your email or GitHub link]
32
- """)
 
 
 
33
 
34
- # Launch the app
35
  if __name__ == "__main__":
36
  demo.launch()
 
1
  import gradio as gr
2
+ import json
3
+ import os
4
+ from pathlib import Path
5
 
6
+ # Percorsi delle cartelle
7
+ FOLDER_MAP = {
8
+ "qa_subtopics": "Viewer/Data/Our_system/QA+Topics",
9
+ "qa_sdgs": "Viewer/Data/Our_system/QA+SDGs",
10
+ "summary_subtopics": "Viewer/Data/Our_system/Summary+Topics",
11
+ "summary_sdgs": "Viewer/Data/Our_system/Summary+SDG"
12
+ }
13
 
14
+ def get_available_events():
15
+ """Ottiene la lista di tutti gli eventi disponibili"""
16
+ all_events = set()
 
17
 
18
+ for folder_path in FOLDER_MAP.values():
19
+ if os.path.exists(folder_path):
20
+ for file in os.listdir(folder_path):
21
+ if file.endswith("_combined_data.json"):
22
+ event_name = file.replace("_combined_data.json", "")
23
+ all_events.add(event_name)
24
 
25
+ return sorted(list(all_events))
26
+
27
+ def load_event_data(event_name, format_type, view_type):
28
+ """Carica i dati per un evento specifico"""
29
+ if not event_name:
30
+ return None
31
+
32
+ key = f"{format_type}_{view_type}"
33
+ folder = FOLDER_MAP.get(key)
34
+
35
+ if not folder:
36
+ return None
37
+
38
+ filepath = os.path.join(folder, f"{event_name}_combined_data.json")
39
+
40
+ try:
41
+ with open(filepath, 'r', encoding='utf-8') as f:
42
+ return json.load(f)
43
+ except Exception as e:
44
+ print(f"Error loading {filepath}: {e}")
45
+ return None
46
+
47
+ def process_citations(text, contexts):
48
+ """Processa le citazioni nel testo"""
49
+ if not text or not contexts:
50
+ return text or ""
51
+
52
+ import re
53
+ citation_regex = r'\[(\d+)\]'
54
+
55
+ def replace_citation(match):
56
+ citation_id = match.group(1)
57
+ ctx = contexts.get(citation_id, {})
58
+ if ctx:
59
+ title = ctx.get('title', 'No title')
60
+ url = ctx.get('url', '#')
61
+ context = ctx.get('context', 'No context')
62
+ return f'<span class="citation" title="{context[:200]}...">[{citation_id}]</span>'
63
+ return match.group(0)
64
+
65
+ return re.sub(citation_regex, replace_citation, text)
66
+
67
+ def render_qa_content(cluster):
68
+ """Renderizza contenuto Q&A"""
69
+ qas = cluster.get('questions_and_answers', [])
70
+ if not qas:
71
+ return '<div class="no-data">No questions and answers available</div>'
72
+
73
+ html = ""
74
+ for qa in qas:
75
+ question = qa.get('question') or qa.get('Question', 'No question provided')
76
+ answer = qa.get('updated_retrieved_answer') or qa.get('retrieved_answer') or qa.get('answer') or qa.get('updated_answer', 'No answer available')
77
+ contexts = qa.get('used_contexts', {})
78
+
79
+ html += f'''
80
+ <div class="qa-item">
81
+ <div class="question">❓ {question}</div>
82
+ <div class="answer">{process_citations(answer, contexts)}</div>
83
+ </div>
84
+ '''
85
+
86
+ return html
87
+
88
+ def render_summary_content(cluster):
89
+ """Renderizza contenuto summary"""
90
+ summary = cluster.get('cluster_summary', 'No cluster summary available')
91
+ contexts = cluster.get('used_contexts', {})
92
+
93
+ return f'<div class="cluster-summary">{process_citations(summary, contexts)}</div>'
94
+
95
+ def render_clusters(clusters, format_type):
96
+ """Renderizza tutti i cluster"""
97
+ if not clusters:
98
+ return '<div class="no-data">No content available for this view.</div>'
99
+
100
+ html = ""
101
+ for cluster in clusters:
102
+ cluster_headline = cluster.get('cluster_headline') or cluster.get('cluster_id', 'Cluster')
103
+
104
+ if format_type == 'summary':
105
+ content = render_summary_content(cluster)
106
+ else:
107
+ content = render_qa_content(cluster)
108
+
109
+ html += f'''
110
+ <div class="cluster">
111
+ <div class="cluster-header">🎯 {cluster_headline}</div>
112
+ <div class="cluster-content">{content}</div>
113
+ </div>
114
+ '''
115
+
116
+ return html
117
+
118
+ def process_file_data(file_data, format_type):
119
+ """Processa i dati del file per estrarre i cluster"""
120
+ if isinstance(file_data.get('clusters'), list):
121
+ return file_data['clusters']
122
+
123
+ ignore_keys = ['file_name', 'summary', 'summary_contexts']
124
+ clusters = []
125
+
126
+ for key, value in file_data.items():
127
+ if key in ignore_keys:
128
+ continue
129
+
130
+ if format_type == 'qa':
131
+ clusters.append({
132
+ 'cluster_headline': key,
133
+ 'questions_and_answers': value if isinstance(value, list) else []
134
+ })
135
+ else:
136
+ if isinstance(value, list):
137
+ first_item = value[0] if value else {}
138
+ joined = '\n\n'.join([
139
+ v.get('cluster_summary') or v.get('summary', '')
140
+ for v in value if isinstance(v, dict)
141
+ ])
142
+ clusters.append({
143
+ 'cluster_headline': key,
144
+ 'cluster_summary': joined or 'No cluster summary available',
145
+ 'used_contexts': first_item.get('used_contexts', {})
146
+ })
147
+ elif isinstance(value, str):
148
+ clusters.append({
149
+ 'cluster_headline': key,
150
+ 'cluster_summary': value,
151
+ 'used_contexts': {}
152
+ })
153
+ elif isinstance(value, dict):
154
+ clusters.append({
155
+ 'cluster_headline': key,
156
+ 'cluster_summary': value.get('cluster_summary') or value.get('summary', 'No cluster summary available'),
157
+ 'used_contexts': value.get('used_contexts', {})
158
+ })
159
+
160
+ return clusters
161
+
162
+ def generate_html(event_name, format_type, view_type):
163
+ """Genera l'HTML completo per visualizzare i dati"""
164
+
165
+ if not event_name:
166
+ return """
167
+ <div class="container">
168
+ <div class="no-data">
169
+ <h2>Please select an event from the dropdown above.</h2>
170
+ </div>
171
+ </div>
172
+ """
173
+
174
+ data = load_event_data(event_name, format_type, view_type)
175
+
176
+ if not data:
177
+ return f"""
178
+ <div class="container">
179
+ <div class="no-data">
180
+ <h2>⚠ Error loading data</h2>
181
+ <p>Could not load data for: <strong>{event_name}</strong></p>
182
+ </div>
183
+ </div>
184
+ """
185
+
186
+ file_name = data.get('file_name', event_name)
187
+ summary = data.get('summary', 'No summary available')
188
+ summary_contexts = data.get('summary_contexts', {})
189
+
190
+ clusters = process_file_data(data, format_type)
191
+ clusters_html = render_clusters(clusters, format_type)
192
+
193
+ html = f'''
194
+ <div class="file-section">
195
+ <div class="file-header">πŸ“„ {file_name}</div>
196
+ <div class="file-content">
197
+ <div class="summary">
198
+ <strong>Summary:</strong><br>
199
+ {process_citations(summary, summary_contexts)}
200
+ </div>
201
+ {clusters_html}
202
+ </div>
203
+ </div>
204
+ '''
205
+
206
+ return html
207
+
208
+ # CSS per lo styling
209
+ CSS = """
210
+ * { margin: 0; padding: 0; box-sizing: border-box; }
211
+ body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; }
212
+ .container { max-width: 1200px; margin: 0 auto; padding: 20px; }
213
+ .file-section { margin-bottom: 40px; border: 2px solid #e1e5e9; border-radius: 12px; overflow: hidden; }
214
+ .file-header { background: linear-gradient(135deg, #667eea, #764ba2); color: white; padding: 20px; font-size: 1.3em; font-weight: 600; }
215
+ .file-content { padding: 25px; }
216
+ .summary { background: #f8f9fa; border-left: 4px solid #667eea; padding: 20px; margin: 20px 0; border-radius: 0 8px 8px 0; line-height: 1.6; white-space: pre-wrap; }
217
+ .cluster { margin: 30px 0; border: 1px solid #dee2e6; border-radius: 10px; overflow: hidden; }
218
+ .cluster-header { background: linear-gradient(45deg, #28a745, #20c997); color: white; padding: 15px 20px; font-weight: 600; font-size: 1.1em; }
219
+ .cluster-content { padding: 20px; }
220
+ .cluster-summary { background: #e8f5e8; border-radius: 8px; padding: 15px; line-height: 1.6; white-space: pre-wrap; }
221
+ .qa-item { margin-bottom: 20px; padding: 15px; background: #f8f9fa; border-radius: 8px; border-left: 4px solid #007bff; }
222
+ .question { font-weight: 600; color: #495057; margin-bottom: 10px; font-size: 1.05em; }
223
+ .answer { color: #6c757d; line-height: 1.5; white-space: pre-wrap; }
224
+ .no-data { text-align: center; color: #6c757d; font-style: italic; padding: 40px; }
225
+ .citation { display: inline; background: #007bff; color: white; padding: 2px 6px; border-radius: 4px; font-size: 0.85em; font-weight: 600; margin: 0 2px; cursor: help; }
226
+ """
227
+
228
+ # Crea l'interfaccia Gradio
229
+ with gr.Blocks(css=CSS, title="UNICEF StoryLine Report Viewer") as demo:
230
+ gr.Markdown("# πŸ“Š UNICEF StoryLine Report Viewer")
231
+ gr.Markdown("Select an event and view to visualize the data")
232
+
233
+ with gr.Row():
234
+ with gr.Column(scale=1):
235
+ event_dropdown = gr.Dropdown(
236
+ choices=get_available_events(),
237
+ label="Select Event",
238
+ value=None
239
+ )
240
+
241
+ format_radio = gr.Radio(
242
+ choices=["qa", "summary"],
243
+ label="Presented as",
244
+ value="qa"
245
+ )
246
+
247
+ view_radio = gr.Radio(
248
+ choices=["subtopics", "sdgs"],
249
+ label="Arranged by",
250
+ value="subtopics"
251
+ )
252
 
253
+ output_html = gr.HTML(label="Report Content")
 
254
 
255
+ # Aggiorna l'output quando cambiano i controlli
256
+ event_dropdown.change(
257
+ fn=generate_html,
258
+ inputs=[event_dropdown, format_radio, view_radio],
259
+ outputs=output_html
260
+ )
261
 
262
+ format_radio.change(
263
+ fn=generate_html,
264
+ inputs=[event_dropdown, format_radio, view_radio],
265
+ outputs=output_html
266
+ )
267
 
268
+ view_radio.change(
269
+ fn=generate_html,
270
+ inputs=[event_dropdown, format_radio, view_radio],
271
+ outputs=output_html
272
+ )
273
 
 
274
  if __name__ == "__main__":
275
  demo.launch()
requirements.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ gradio==4.44.0