Update app.py
Browse files
app.py
CHANGED
@@ -151,7 +151,20 @@ def create_reranking_interface(task_data):
|
|
151 |
ranking_inputs = []
|
152 |
validation_indicators = []
|
153 |
|
154 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
155 |
with gr.Box():
|
156 |
for i, doc in enumerate(samples[0]["candidates"]):
|
157 |
row_class = "document-row-even" if i % 2 == 0 else "document-row-odd"
|
@@ -165,7 +178,7 @@ def create_reranking_interface(task_data):
|
|
165 |
label=f"Document {i+1}",
|
166 |
interactive=False,
|
167 |
elem_classes=["document-text"],
|
168 |
-
lines=
|
169 |
)
|
170 |
doc_containers.append(doc_box)
|
171 |
|
@@ -217,9 +230,9 @@ def create_reranking_interface(task_data):
|
|
217 |
font-size: 16px !important;
|
218 |
line-height: 1.6 !important;
|
219 |
padding: 10px !important;
|
220 |
-
min-height:
|
221 |
-
height: auto !important;
|
222 |
-
overflow-y: visible !important;
|
223 |
}
|
224 |
|
225 |
.rank-dropdown select {
|
@@ -236,11 +249,15 @@ def create_reranking_interface(task_data):
|
|
236 |
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25) !important;
|
237 |
}
|
238 |
|
239 |
-
.tool-
|
240 |
-
|
|
|
|
|
|
|
241 |
}
|
242 |
|
243 |
-
.
|
|
|
244 |
padding-top: 8px !important;
|
245 |
}
|
246 |
|
@@ -284,6 +301,75 @@ def create_reranking_interface(task_data):
|
|
284 |
|
285 |
return results + [all_valid] # Return validation indicators and validity flag
|
286 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
287 |
def load_sample(sample_id):
|
288 |
"""Load a specific sample into the interface."""
|
289 |
sample = next((s for s in samples if s["id"] == sample_id), None)
|
@@ -383,120 +469,35 @@ def create_reranking_interface(task_data):
|
|
383 |
except Exception as e:
|
384 |
return f"Error saving results: {str(e)}"
|
385 |
|
386 |
-
#
|
387 |
def assign_sequential_ranks():
|
388 |
return [str(i+1) for i in range(len(samples[0]["candidates"]))]
|
389 |
|
390 |
-
# Function to assign reverse ranks
|
391 |
def assign_reverse_ranks():
|
392 |
n = len(samples[0]["candidates"])
|
393 |
return [str(n-i) for i in range(n)]
|
394 |
|
395 |
-
# Function to clear all rankings
|
396 |
def clear_rankings():
|
397 |
return [""] * len(samples[0]["candidates"])
|
398 |
|
399 |
-
#
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
# Verify we have enough rankings
|
407 |
-
if len(args) < len(ranking_inputs) + 1:
|
408 |
-
return "Error: Not enough ranking inputs provided", progress_text.value
|
409 |
-
|
410 |
-
sample_id = args[-1]
|
411 |
-
rankings = args[:len(ranking_inputs)]
|
412 |
-
|
413 |
-
# First validate the rankings
|
414 |
-
validation_results = validate_rankings(*rankings)
|
415 |
-
all_valid = validation_results[-1] # Last item is validity flag
|
416 |
-
validation_indicators_values = validation_results[:-1] # Remove validity flag
|
417 |
-
|
418 |
-
# Update validation indicators
|
419 |
-
for i, result in enumerate(validation_indicators_values):
|
420 |
-
if i < len(validation_indicators):
|
421 |
-
validation_indicators[i].update(value=result)
|
422 |
-
|
423 |
-
# Check for duplicate rankings
|
424 |
-
if all_valid:
|
425 |
-
try:
|
426 |
-
processed_rankings = [int(r) for r in rankings]
|
427 |
-
if len(set(processed_rankings)) != len(processed_rankings):
|
428 |
-
dup_ranks = {}
|
429 |
-
for i, r in enumerate(processed_rankings):
|
430 |
-
if r in dup_ranks:
|
431 |
-
dup_ranks[r].append(i)
|
432 |
-
else:
|
433 |
-
dup_ranks[r] = [i]
|
434 |
-
|
435 |
-
# Highlight duplicates with error styling
|
436 |
-
for rank, indices in dup_ranks.items():
|
437 |
-
if len(indices) > 1:
|
438 |
-
for idx in indices:
|
439 |
-
if idx < len(validation_indicators):
|
440 |
-
validation_indicators[idx].update(
|
441 |
-
value=f'<span style="color: #dc3545; font-weight: bold;">⚠️ Duplicate rank {rank}</span>'
|
442 |
-
)
|
443 |
-
|
444 |
-
return "⚠️ Each document must have a unique rank. Please fix duplicate rankings.", progress_text.value
|
445 |
-
except:
|
446 |
-
pass
|
447 |
-
|
448 |
-
# If not all valid, return error message
|
449 |
-
if not all_valid:
|
450 |
-
return "⚠️ Please assign a rank to all documents before submitting", progress_text.value
|
451 |
-
|
452 |
-
# Save the validated rankings
|
453 |
-
status, progress = save_ranking(rankings, sample_id)
|
454 |
-
|
455 |
-
# Provide clear success feedback
|
456 |
-
if "✅" in status:
|
457 |
-
for i in range(len(validation_indicators)):
|
458 |
-
validation_indicators[i].update(
|
459 |
-
value=f'<span style="color: #28a745; font-weight: bold;">✓ Saved</span>'
|
460 |
-
)
|
461 |
-
|
462 |
-
return status, progress
|
463 |
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
if r is not None and r != "":
|
476 |
-
clean_rankings.append(int(r))
|
477 |
-
|
478 |
-
if len(clean_rankings) != len(set(clean_rankings)):
|
479 |
-
used_ranks = {}
|
480 |
-
for i, r in enumerate(rankings):
|
481 |
-
if r is not None and r != "":
|
482 |
-
rank = int(r)
|
483 |
-
if rank in used_ranks:
|
484 |
-
used_ranks[rank].append(i)
|
485 |
-
else:
|
486 |
-
used_ranks[rank] = [i]
|
487 |
-
|
488 |
-
results = []
|
489 |
-
for i, r in enumerate(rankings):
|
490 |
-
if r is not None and r != "":
|
491 |
-
rank = int(r)
|
492 |
-
if len(used_ranks[rank]) > 1:
|
493 |
-
results.append(f'<span style="color: #dc3545; font-weight: bold;">⚠️ Duplicate rank {rank}</span>')
|
494 |
-
else:
|
495 |
-
results.append(f'<span style="color: #28a745; font-weight: bold;">✓ Rank {rank}</span>')
|
496 |
-
else:
|
497 |
-
results.append('<span style="color: #dc3545; font-weight: bold;">⚠️ Missing</span>')
|
498 |
-
|
499 |
-
return results
|
500 |
|
501 |
# Wire up events (Gradio 3.x syntax)
|
502 |
submit_btn.click(
|
@@ -557,7 +558,7 @@ def create_reranking_interface(task_data):
|
|
557 |
)
|
558 |
|
559 |
# Connect validation to ranking inputs for real-time feedback
|
560 |
-
for
|
561 |
ranking.change(
|
562 |
fn=on_ranking_change,
|
563 |
inputs=ranking_inputs,
|
|
|
151 |
ranking_inputs = []
|
152 |
validation_indicators = []
|
153 |
|
154 |
+
# Add back the quick ranking tools with improved styling
|
155 |
+
# Add a nicely formatted header for the ranking tools
|
156 |
+
with gr.Box(elem_classes=["tool-container"]):
|
157 |
+
with gr.Row(equal_height=True):
|
158 |
+
with gr.Column(scale=3):
|
159 |
+
gr.Markdown("### Quick Ranking Tools", elem_classes=["section-header"])
|
160 |
+
with gr.Column(scale=2):
|
161 |
+
sequential_btn = gr.Button("Rank in Order (1,2,3...)", variant="secondary", size="sm")
|
162 |
+
with gr.Column(scale=2):
|
163 |
+
reverse_btn = gr.Button("Reverse Order (n,n-1,...)", variant="secondary", size="sm")
|
164 |
+
with gr.Column(scale=2):
|
165 |
+
clear_btn = gr.Button("Clear All Rankings", variant="secondary", size="sm")
|
166 |
+
|
167 |
+
# Adjust the document display for more reasonable textbox size
|
168 |
with gr.Box():
|
169 |
for i, doc in enumerate(samples[0]["candidates"]):
|
170 |
row_class = "document-row-even" if i % 2 == 0 else "document-row-odd"
|
|
|
178 |
label=f"Document {i+1}",
|
179 |
interactive=False,
|
180 |
elem_classes=["document-text"],
|
181 |
+
lines=4, # Reduce to 4 visible lines
|
182 |
)
|
183 |
doc_containers.append(doc_box)
|
184 |
|
|
|
230 |
font-size: 16px !important;
|
231 |
line-height: 1.6 !important;
|
232 |
padding: 10px !important;
|
233 |
+
min-height: 100px !important; /* Reduce minimum height */
|
234 |
+
height: auto !important;
|
235 |
+
overflow-y: visible !important;
|
236 |
}
|
237 |
|
238 |
.rank-dropdown select {
|
|
|
249 |
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25) !important;
|
250 |
}
|
251 |
|
252 |
+
.tool-container {
|
253 |
+
margin-bottom: 20px !important;
|
254 |
+
background-color: #f8f9fa !important;
|
255 |
+
border-left: 4px solid #6c757d !important;
|
256 |
+
padding: 10px !important;
|
257 |
}
|
258 |
|
259 |
+
.section-header {
|
260 |
+
margin: 0 !important;
|
261 |
padding-top: 8px !important;
|
262 |
}
|
263 |
|
|
|
301 |
|
302 |
return results + [all_valid] # Return validation indicators and validity flag
|
303 |
|
304 |
+
def on_ranking_change(*rankings):
|
305 |
+
"""Validate rankings whenever any ranking dropdown changes."""
|
306 |
+
validation_results = validate_rankings(*rankings)
|
307 |
+
return validation_results[:-1] # Return only the validation indicators
|
308 |
+
|
309 |
+
def submit_rankings(*args):
|
310 |
+
"""Submit rankings with improved validation and user feedback."""
|
311 |
+
# Get the last argument (sample_id) and the rankings
|
312 |
+
if len(args) < 1:
|
313 |
+
return "Error: No arguments provided", progress_text.value
|
314 |
+
|
315 |
+
# Verify we have enough rankings
|
316 |
+
if len(args) < len(ranking_inputs) + 1:
|
317 |
+
return "Error: Not enough ranking inputs provided", progress_text.value
|
318 |
+
|
319 |
+
sample_id = args[-1]
|
320 |
+
rankings = args[:len(ranking_inputs)]
|
321 |
+
|
322 |
+
# First validate the rankings
|
323 |
+
validation_results = validate_rankings(*rankings)
|
324 |
+
all_valid = validation_results[-1] # Last item is validity flag
|
325 |
+
validation_indicators_values = validation_results[:-1] # Remove validity flag
|
326 |
+
|
327 |
+
# Update validation indicators
|
328 |
+
for i, result in enumerate(validation_indicators_values):
|
329 |
+
if i < len(validation_indicators):
|
330 |
+
validation_indicators[i].update(value=result)
|
331 |
+
|
332 |
+
# Check for duplicate rankings
|
333 |
+
if all_valid:
|
334 |
+
try:
|
335 |
+
processed_rankings = [int(r) for r in rankings]
|
336 |
+
if len(set(processed_rankings)) != len(processed_rankings):
|
337 |
+
dup_ranks = {}
|
338 |
+
for i, r in enumerate(processed_rankings):
|
339 |
+
if r in dup_ranks:
|
340 |
+
dup_ranks[r].append(i)
|
341 |
+
else:
|
342 |
+
dup_ranks[r] = [i]
|
343 |
+
|
344 |
+
# Highlight duplicates with error styling
|
345 |
+
for rank, indices in dup_ranks.items():
|
346 |
+
if len(indices) > 1:
|
347 |
+
for idx in indices:
|
348 |
+
if idx < len(validation_indicators):
|
349 |
+
validation_indicators[idx].update(
|
350 |
+
value=f'<span style="color: #dc3545; font-weight: bold;">⚠️ Duplicate rank {rank}</span>'
|
351 |
+
)
|
352 |
+
|
353 |
+
return "⚠️ Each document must have a unique rank. Please fix duplicate rankings.", progress_text.value
|
354 |
+
except:
|
355 |
+
pass
|
356 |
+
|
357 |
+
# If not all valid, return error message
|
358 |
+
if not all_valid:
|
359 |
+
return "⚠️ Please assign a rank to all documents before submitting", progress_text.value
|
360 |
+
|
361 |
+
# Save the validated rankings
|
362 |
+
status, progress = save_ranking(rankings, sample_id)
|
363 |
+
|
364 |
+
# Provide clear success feedback
|
365 |
+
if "✅" in status:
|
366 |
+
for i in range(len(validation_indicators)):
|
367 |
+
validation_indicators[i].update(
|
368 |
+
value=f'<span style="color: #28a745; font-weight: bold;">✓ Saved</span>'
|
369 |
+
)
|
370 |
+
|
371 |
+
return status, progress
|
372 |
+
|
373 |
def load_sample(sample_id):
|
374 |
"""Load a specific sample into the interface."""
|
375 |
sample = next((s for s in samples if s["id"] == sample_id), None)
|
|
|
469 |
except Exception as e:
|
470 |
return f"Error saving results: {str(e)}"
|
471 |
|
472 |
+
# Define functions for the quick ranking buttons
|
473 |
def assign_sequential_ranks():
|
474 |
return [str(i+1) for i in range(len(samples[0]["candidates"]))]
|
475 |
|
|
|
476 |
def assign_reverse_ranks():
|
477 |
n = len(samples[0]["candidates"])
|
478 |
return [str(n-i) for i in range(n)]
|
479 |
|
|
|
480 |
def clear_rankings():
|
481 |
return [""] * len(samples[0]["candidates"])
|
482 |
|
483 |
+
# Connect quick ranking buttons
|
484 |
+
sequential_btn.click(
|
485 |
+
fn=assign_sequential_ranks,
|
486 |
+
inputs=None,
|
487 |
+
outputs=ranking_inputs
|
488 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
489 |
|
490 |
+
reverse_btn.click(
|
491 |
+
fn=assign_reverse_ranks,
|
492 |
+
inputs=None,
|
493 |
+
outputs=ranking_inputs
|
494 |
+
)
|
495 |
|
496 |
+
clear_btn.click(
|
497 |
+
fn=clear_rankings,
|
498 |
+
inputs=None,
|
499 |
+
outputs=ranking_inputs
|
500 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
501 |
|
502 |
# Wire up events (Gradio 3.x syntax)
|
503 |
submit_btn.click(
|
|
|
558 |
)
|
559 |
|
560 |
# Connect validation to ranking inputs for real-time feedback
|
561 |
+
for ranking in ranking_inputs:
|
562 |
ranking.change(
|
563 |
fn=on_ranking_change,
|
564 |
inputs=ranking_inputs,
|