Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -40,36 +40,67 @@ def create_reranking_interface(task_data):
|
|
40 |
</div>
|
41 |
'''
|
42 |
html += '</div>'
|
43 |
-
|
|
|
|
|
44 |
|
45 |
def save_ranking(order_json, sample_id):
|
46 |
"""Save the current ranking to results."""
|
47 |
try:
|
48 |
if not order_json or order_json == "[]":
|
49 |
return "⚠️ Drag documents to set the ranking before submitting.", progress_text.value
|
|
|
50 |
order = json.loads(order_json)
|
51 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
if len(order) != num_candidates:
|
53 |
return f"⚠️ Ranking order length mismatch. Expected {num_candidates}, got {len(order)}.", progress_text.value
|
|
|
54 |
rankings = [0] * num_candidates
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
|
|
|
|
|
|
|
|
60 |
if sorted(rankings) != list(range(1, num_candidates + 1)):
|
61 |
return "⚠️ Ranking validation failed. Ranks are not 1 to N.", progress_text.value
|
|
|
62 |
annotation = {"sample_id": sample_id, "rankings": rankings}
|
|
|
|
|
63 |
existing_idx = next((i for i, a in enumerate(results["annotations"]) if a["sample_id"] == sample_id), None)
|
64 |
if existing_idx is not None:
|
65 |
results["annotations"][existing_idx] = annotation
|
66 |
else:
|
67 |
results["annotations"].append(annotation)
|
|
|
68 |
completed_samples[sample_id] = True
|
69 |
-
|
70 |
-
with
|
71 |
-
|
72 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
except json.JSONDecodeError:
|
74 |
return "⚠️ Error decoding ranking order. Please try again.", progress_text.value
|
75 |
except Exception as e:
|
@@ -83,13 +114,23 @@ def create_reranking_interface(task_data):
|
|
83 |
sample = next((s for s in samples if s["id"] == sample_id), None)
|
84 |
if not sample:
|
85 |
return gr.update(), gr.update(value="[]"), gr.update(), gr.update()
|
|
|
86 |
existing_ranking = next((anno["rankings"] for anno in results["annotations"] if anno["sample_id"] == sample_id), None)
|
87 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
88 |
status = "Ready to rank" if not completed_samples.get(sample_id, False) else "Already ranked"
|
89 |
progress = f"Progress: {sum(completed_samples.values())}/{len(samples)}"
|
90 |
-
|
|
|
91 |
except Exception as e:
|
92 |
-
|
|
|
|
|
93 |
|
94 |
def next_sample_id(current_id):
|
95 |
current_idx = next((i for i, s in enumerate(samples) if s["id"] == current_id), -1)
|
@@ -108,9 +149,20 @@ def create_reranking_interface(task_data):
|
|
108 |
def save_results():
|
109 |
output_path = f"{task_data['task_name']}_human_results.json"
|
110 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
111 |
with open(output_path, "w") as f:
|
112 |
json.dump(results, f, indent=2)
|
113 |
-
|
|
|
114 |
except Exception as e:
|
115 |
return f"⚠️ Error saving results file: {str(e)}"
|
116 |
|
@@ -428,18 +480,27 @@ def create_reranking_interface(task_data):
|
|
428 |
line-height: 1.5;
|
429 |
word-break: break-word;
|
430 |
}
|
431 |
-
|
432 |
-
.rank-bg-
|
433 |
-
.rank-bg-
|
434 |
-
.rank-bg-
|
435 |
-
.rank-bg-
|
436 |
-
.rank-bg-
|
437 |
-
|
438 |
-
|
439 |
-
.rank-bg-
|
440 |
-
|
441 |
-
|
442 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
443 |
}
|
444 |
</style>
|
445 |
"""
|
|
|
40 |
</div>
|
41 |
'''
|
42 |
html += '</div>'
|
43 |
+
|
44 |
+
# Also return the computed order for proper initialization
|
45 |
+
return html, order
|
46 |
|
47 |
def save_ranking(order_json, sample_id):
|
48 |
"""Save the current ranking to results."""
|
49 |
try:
|
50 |
if not order_json or order_json == "[]":
|
51 |
return "⚠️ Drag documents to set the ranking before submitting.", progress_text.value
|
52 |
+
|
53 |
order = json.loads(order_json)
|
54 |
+
sample = next((s for s in samples if s["id"] == sample_id), None)
|
55 |
+
|
56 |
+
if not sample:
|
57 |
+
return "⚠️ Sample not found.", progress_text.value
|
58 |
+
|
59 |
+
num_candidates = len(sample["candidates"])
|
60 |
+
|
61 |
if len(order) != num_candidates:
|
62 |
return f"⚠️ Ranking order length mismatch. Expected {num_candidates}, got {len(order)}.", progress_text.value
|
63 |
+
|
64 |
rankings = [0] * num_candidates
|
65 |
+
try:
|
66 |
+
for rank_minus_1, doc_idx in enumerate(order):
|
67 |
+
if doc_idx < num_candidates:
|
68 |
+
rankings[doc_idx] = rank_minus_1 + 1
|
69 |
+
else:
|
70 |
+
raise ValueError(f"Invalid document index {doc_idx} found in order.")
|
71 |
+
except Exception as e:
|
72 |
+
return f"⚠️ Error processing ranking order: {str(e)}", progress_text.value
|
73 |
+
|
74 |
if sorted(rankings) != list(range(1, num_candidates + 1)):
|
75 |
return "⚠️ Ranking validation failed. Ranks are not 1 to N.", progress_text.value
|
76 |
+
|
77 |
annotation = {"sample_id": sample_id, "rankings": rankings}
|
78 |
+
|
79 |
+
# Check if this sample was already annotated
|
80 |
existing_idx = next((i for i, a in enumerate(results["annotations"]) if a["sample_id"] == sample_id), None)
|
81 |
if existing_idx is not None:
|
82 |
results["annotations"][existing_idx] = annotation
|
83 |
else:
|
84 |
results["annotations"].append(annotation)
|
85 |
+
|
86 |
completed_samples[sample_id] = True
|
87 |
+
|
88 |
+
# Save results with timestamp and better error handling
|
89 |
+
try:
|
90 |
+
output_path = f"{task_data['task_name']}_human_results.json"
|
91 |
+
with open(output_path, "w") as f:
|
92 |
+
json.dump(results, f, indent=2)
|
93 |
+
|
94 |
+
# Check if all samples are complete
|
95 |
+
all_completed = sum(completed_samples.values()) == len(samples)
|
96 |
+
completion_message = "🎉 All samples completed! You can save and submit your results." if all_completed else ""
|
97 |
+
|
98 |
+
return f"✅ Rankings saved successfully ({len(results['annotations'])}/{len(samples)} completed) {completion_message}", f"Progress: {sum(completed_samples.values())}/{len(samples)}"
|
99 |
+
except Exception as file_error:
|
100 |
+
print(f"Error saving file: {str(file_error)}")
|
101 |
+
# Still mark as completed in memory even if file save fails
|
102 |
+
return f"⚠️ Rankings recorded but file save failed: {str(file_error)}", f"Progress: {sum(completed_samples.values())}/{len(samples)}"
|
103 |
+
|
104 |
except json.JSONDecodeError:
|
105 |
return "⚠️ Error decoding ranking order. Please try again.", progress_text.value
|
106 |
except Exception as e:
|
|
|
114 |
sample = next((s for s in samples if s["id"] == sample_id), None)
|
115 |
if not sample:
|
116 |
return gr.update(), gr.update(value="[]"), gr.update(), gr.update()
|
117 |
+
|
118 |
existing_ranking = next((anno["rankings"] for anno in results["annotations"] if anno["sample_id"] == sample_id), None)
|
119 |
+
|
120 |
+
# Get both the HTML and the initial order
|
121 |
+
new_html, initial_order = generate_sortable_html(sample["candidates"], existing_ranking)
|
122 |
+
|
123 |
+
# Convert initial order to JSON string for state
|
124 |
+
initial_order_json = json.dumps(initial_order)
|
125 |
+
|
126 |
status = "Ready to rank" if not completed_samples.get(sample_id, False) else "Already ranked"
|
127 |
progress = f"Progress: {sum(completed_samples.values())}/{len(samples)}"
|
128 |
+
|
129 |
+
return sample["query"], new_html, initial_order_json, progress, status
|
130 |
except Exception as e:
|
131 |
+
import traceback
|
132 |
+
print(traceback.format_exc())
|
133 |
+
return gr.update(), gr.update(), "[]", gr.update(), f"Error loading sample: {str(e)}"
|
134 |
|
135 |
def next_sample_id(current_id):
|
136 |
current_idx = next((i for i, s in enumerate(samples) if s["id"] == current_id), -1)
|
|
|
149 |
def save_results():
|
150 |
output_path = f"{task_data['task_name']}_human_results.json"
|
151 |
try:
|
152 |
+
# Create backup with timestamp
|
153 |
+
from datetime import datetime
|
154 |
+
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
155 |
+
backup_path = f"{task_data['task_name']}_results_{timestamp}.json"
|
156 |
+
|
157 |
+
# First create a backup
|
158 |
+
with open(backup_path, "w") as f:
|
159 |
+
json.dump(results, f, indent=2)
|
160 |
+
|
161 |
+
# Then save to the main file
|
162 |
with open(output_path, "w") as f:
|
163 |
json.dump(results, f, indent=2)
|
164 |
+
|
165 |
+
return f"✅ Results saved to {output_path} ({len(results['annotations'])} annotations)\nBackup created at {backup_path}"
|
166 |
except Exception as e:
|
167 |
return f"⚠️ Error saving results file: {str(e)}"
|
168 |
|
|
|
480 |
line-height: 1.5;
|
481 |
word-break: break-word;
|
482 |
}
|
483 |
+
/* More professional color scheme for rank badges */
|
484 |
+
.rank-bg-1 .rank-badge { background-color: #1e40af; } /* Deep blue for top rank */
|
485 |
+
.rank-bg-2 .rank-badge { background-color: #3b82f6; } /* Medium blue */
|
486 |
+
.rank-bg-3 .rank-badge { background-color: #60a5fa; } /* Light blue */
|
487 |
+
.rank-bg-4 .rank-badge { background-color: #93c5fd; color: #1e3a8a; } /* Very light blue with dark text */
|
488 |
+
.rank-bg-5 .rank-badge { background-color: #bfdbfe; color: #1e3a8a; } /* Lightest blue with dark text */
|
489 |
+
|
490 |
+
/* Lower ranks get progressively more gray */
|
491 |
+
.rank-bg-6 .rank-badge, .rank-bg-7 .rank-badge {
|
492 |
+
background-color: #64748b;
|
493 |
+
}
|
494 |
+
.rank-bg-8 .rank-badge, .rank-bg-9 .rank-badge, .rank-bg-10 .rank-badge {
|
495 |
+
background-color: #94a3b8;
|
496 |
+
color: #0f172a;
|
497 |
+
}
|
498 |
+
.rank-bg-11 .rank-badge, .rank-bg-12 .rank-badge, .rank-bg-13 .rank-badge,
|
499 |
+
.rank-bg-14 .rank-badge, .rank-bg-15 .rank-badge, .rank-bg-16 .rank-badge,
|
500 |
+
.rank-bg-17 .rank-badge, .rank-bg-18 .rank-badge, .rank-bg-19 .rank-badge,
|
501 |
+
.rank-bg-20 .rank-badge {
|
502 |
+
background-color: #cbd5e1;
|
503 |
+
color: #0f172a;
|
504 |
}
|
505 |
</style>
|
506 |
"""
|