progress bar is constantly updated
Browse files
app.py
CHANGED
@@ -517,31 +517,26 @@ class HallucinationDetectorApp:
|
|
517 |
# Get total feedback count
|
518 |
total_count = self.feedback_collection.count_documents({})
|
519 |
|
520 |
-
# Get
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
}}
|
536 |
-
]
|
537 |
-
avg_result = list(self.feedback_collection.aggregate(avg_pipeline))
|
538 |
-
avg_confidence = avg_result[0]["average"] if avg_result else 0
|
539 |
|
540 |
return {
|
541 |
"total_feedback": total_count,
|
542 |
-
"
|
543 |
-
"
|
544 |
-
"average_confidence": round(avg_confidence, 2)
|
545 |
}
|
546 |
except Exception as e:
|
547 |
logger.error("Error getting feedback stats: %s", str(e), exc_info=True)
|
@@ -1288,41 +1283,14 @@ def create_interface():
|
|
1288 |
None
|
1289 |
]
|
1290 |
|
1291 |
-
# Helper function to submit feedback
|
1292 |
def combine_feedback(fb_input, fb_text, results):
|
1293 |
combined_feedback = f"{fb_input}: {fb_text}" if fb_text else fb_input
|
1294 |
if not results:
|
1295 |
-
return "No results to attach feedback to."
|
1296 |
|
1297 |
response = detector.save_feedback(results, combined_feedback)
|
1298 |
-
|
1299 |
-
# Get updated stats
|
1300 |
-
stats = detector.get_feedback_stats()
|
1301 |
-
if stats:
|
1302 |
-
stats_html = f"""
|
1303 |
-
<div class="stats-section" style="margin-top: 15px;">
|
1304 |
-
<div class="stat-item">
|
1305 |
-
<div class="stat-value">{stats['total_feedback']}</div>
|
1306 |
-
<div class="stat-label">Total Feedback</div>
|
1307 |
-
</div>
|
1308 |
-
<div class="stat-item">
|
1309 |
-
<div class="stat-value">{stats['hallucinations_detected']}</div>
|
1310 |
-
<div class="stat-label">Hallucinations Found</div>
|
1311 |
-
</div>
|
1312 |
-
<div class="stat-item">
|
1313 |
-
<div class="stat-value">{stats['no_hallucinations']}</div>
|
1314 |
-
<div class="stat-label">No Hallucinations</div>
|
1315 |
-
</div>
|
1316 |
-
<div class="stat-item">
|
1317 |
-
<div class="stat-value">{stats['average_confidence']}</div>
|
1318 |
-
<div class="stat-label">Avg. Confidence</div>
|
1319 |
-
</div>
|
1320 |
-
</div>
|
1321 |
-
"""
|
1322 |
-
else:
|
1323 |
-
stats_html = ""
|
1324 |
-
|
1325 |
-
return response, stats_html
|
1326 |
|
1327 |
# Create the interface
|
1328 |
with gr.Blocks(css=css, theme=gr.themes.Soft()) as interface:
|
@@ -1416,6 +1384,102 @@ def create_interface():
|
|
1416 |
# Add feedback stats display
|
1417 |
feedback_stats = gr.HTML(visible=True)
|
1418 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1419 |
# Feedback section
|
1420 |
with gr.Accordion("Provide Feedback", open=False, visible=False) as feedback_accordion:
|
1421 |
gr.Markdown("### Help Improve the System")
|
@@ -1436,29 +1500,7 @@ def create_interface():
|
|
1436 |
feedback_button = gr.Button("Submit Feedback", variant="secondary")
|
1437 |
feedback_status = gr.Textbox(label="Feedback Status", interactive=False, visible=False)
|
1438 |
|
1439 |
-
#
|
1440 |
-
initial_stats = detector.get_feedback_stats()
|
1441 |
-
if initial_stats:
|
1442 |
-
feedback_stats.value = f"""
|
1443 |
-
<div class="stats-section">
|
1444 |
-
<div class="stat-item">
|
1445 |
-
<div class="stat-value">{initial_stats['total_feedback']}</div>
|
1446 |
-
<div class="stat-label">Total Feedback</div>
|
1447 |
-
</div>
|
1448 |
-
<div class="stat-item">
|
1449 |
-
<div class="stat-value">{initial_stats['hallucinations_detected']}</div>
|
1450 |
-
<div class="stat-label">Hallucinations Found</div>
|
1451 |
-
</div>
|
1452 |
-
<div class="stat-item">
|
1453 |
-
<div class="stat-value">{initial_stats['no_hallucinations']}</div>
|
1454 |
-
<div class="stat-label">No Hallucinations</div>
|
1455 |
-
</div>
|
1456 |
-
<div class="stat-item">
|
1457 |
-
<div class="stat-value">{initial_stats['average_confidence']}</div>
|
1458 |
-
<div class="stat-label">Avg. Confidence</div>
|
1459 |
-
</div>
|
1460 |
-
</div>
|
1461 |
-
"""
|
1462 |
|
1463 |
# Hidden state to store results for feedback
|
1464 |
hidden_results = gr.State()
|
@@ -1478,7 +1520,7 @@ def create_interface():
|
|
1478 |
feedback_button.click(
|
1479 |
fn=combine_feedback,
|
1480 |
inputs=[feedback_input, feedback_text, hidden_results],
|
1481 |
-
outputs=[feedback_status
|
1482 |
)
|
1483 |
|
1484 |
# Footer
|
|
|
517 |
# Get total feedback count
|
518 |
total_count = self.feedback_collection.count_documents({})
|
519 |
|
520 |
+
# Get accuracy stats based on user feedback
|
521 |
+
correct_predictions = 0
|
522 |
+
|
523 |
+
# Fetch all feedback documents
|
524 |
+
feedback_docs = list(self.feedback_collection.find({}, {"user_feedback": 1}))
|
525 |
+
|
526 |
+
# Count correct predictions based on user feedback
|
527 |
+
for doc in feedback_docs:
|
528 |
+
if "user_feedback" in doc:
|
529 |
+
# If feedback starts with "Yes", it's a correct prediction
|
530 |
+
if doc["user_feedback"].startswith("Yes"):
|
531 |
+
correct_predictions += 1
|
532 |
+
|
533 |
+
# Calculate accuracy percentage
|
534 |
+
accuracy = correct_predictions / max(total_count, 1)
|
|
|
|
|
|
|
|
|
535 |
|
536 |
return {
|
537 |
"total_feedback": total_count,
|
538 |
+
"correct_predictions": correct_predictions,
|
539 |
+
"accuracy": accuracy
|
|
|
540 |
}
|
541 |
except Exception as e:
|
542 |
logger.error("Error getting feedback stats: %s", str(e), exc_info=True)
|
|
|
1283 |
None
|
1284 |
]
|
1285 |
|
1286 |
+
# Helper function to submit feedback
|
1287 |
def combine_feedback(fb_input, fb_text, results):
|
1288 |
combined_feedback = f"{fb_input}: {fb_text}" if fb_text else fb_input
|
1289 |
if not results:
|
1290 |
+
return "No results to attach feedback to."
|
1291 |
|
1292 |
response = detector.save_feedback(results, combined_feedback)
|
1293 |
+
return response
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1294 |
|
1295 |
# Create the interface
|
1296 |
with gr.Blocks(css=css, theme=gr.themes.Soft()) as interface:
|
|
|
1384 |
# Add feedback stats display
|
1385 |
feedback_stats = gr.HTML(visible=True)
|
1386 |
|
1387 |
+
# Function to continuously update stats
|
1388 |
+
def update_stats():
|
1389 |
+
stats = detector.get_feedback_stats()
|
1390 |
+
if stats:
|
1391 |
+
total = stats['total_feedback']
|
1392 |
+
correct = stats['correct_predictions']
|
1393 |
+
|
1394 |
+
# Get accuracy directly from the stats
|
1395 |
+
accuracy = stats['accuracy']
|
1396 |
+
|
1397 |
+
# Format accuracy percentage
|
1398 |
+
accuracy_pct = f"{accuracy * 100:.1f}%"
|
1399 |
+
|
1400 |
+
stats_html = f"""
|
1401 |
+
<div class="stats-section" style="background-color: #e8f5e9; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); margin-top: 5px;">
|
1402 |
+
<div class="stat-item">
|
1403 |
+
<div class="stat-value" style="font-size: 2em; color: #2e7d32;">{total}</div>
|
1404 |
+
<div class="stat-label" style="font-weight: bold;">Total Responses</div>
|
1405 |
+
</div>
|
1406 |
+
<div class="stat-item">
|
1407 |
+
<div class="stat-value" style="font-size: 2em; color: #2e7d32;">{accuracy_pct}</div>
|
1408 |
+
<div class="stat-label" style="font-weight: bold;">Correct Predictions</div>
|
1409 |
+
</div>
|
1410 |
+
</div>
|
1411 |
+
<div style="text-align: center; margin-top: 10px; font-style: italic; color: #666;">
|
1412 |
+
Based on user feedback: {correct} correct out of {total} total predictions
|
1413 |
+
</div>
|
1414 |
+
"""
|
1415 |
+
return stats_html
|
1416 |
+
return ""
|
1417 |
+
|
1418 |
+
# Set up interval to update stats
|
1419 |
+
with gr.Row(elem_id="stats-container"):
|
1420 |
+
with gr.Column():
|
1421 |
+
gr.Markdown("### 📊 Live Prediction Accuracy")
|
1422 |
+
gr.Markdown("_Auto-refreshes every 5 seconds from MongoDB based on user feedback_")
|
1423 |
+
live_stats = gr.HTML(update_stats())
|
1424 |
+
|
1425 |
+
# Add loading animation style
|
1426 |
+
gr.HTML("""
|
1427 |
+
<style>
|
1428 |
+
@keyframes pulse {
|
1429 |
+
0% { opacity: 0.6; }
|
1430 |
+
50% { opacity: 1; }
|
1431 |
+
100% { opacity: 0.6; }
|
1432 |
+
}
|
1433 |
+
.refreshing::after {
|
1434 |
+
content: "⟳";
|
1435 |
+
display: inline-block;
|
1436 |
+
margin-left: 8px;
|
1437 |
+
animation: pulse 1.5s infinite ease-in-out;
|
1438 |
+
color: #2e7d32;
|
1439 |
+
}
|
1440 |
+
#stats-container {
|
1441 |
+
border: 1px solid #e0e0e0;
|
1442 |
+
border-radius: 10px;
|
1443 |
+
padding: 15px;
|
1444 |
+
margin: 10px 0;
|
1445 |
+
background-color: #2762d7;
|
1446 |
+
}
|
1447 |
+
</style>
|
1448 |
+
<div class="refreshing" style="text-align: right; font-size: 0.8em; color: #666;">Auto-refreshing</div>
|
1449 |
+
""")
|
1450 |
+
|
1451 |
+
# Create a refresh button that will be auto-clicked
|
1452 |
+
refresh_btn = gr.Button("Refresh Stats", visible=False)
|
1453 |
+
refresh_btn.click(
|
1454 |
+
fn=update_stats,
|
1455 |
+
outputs=[live_stats]
|
1456 |
+
)
|
1457 |
+
|
1458 |
+
# Add JavaScript to auto-refresh the statistics
|
1459 |
+
gr.HTML("""
|
1460 |
+
<script>
|
1461 |
+
// Auto-refresh stats every 5 seconds
|
1462 |
+
function setupAutoRefresh() {
|
1463 |
+
const refreshInterval = 5000; // 5 seconds
|
1464 |
+
setInterval(() => {
|
1465 |
+
// Find the refresh button by its text and click it
|
1466 |
+
const refreshButtons = Array.from(document.querySelectorAll('button'));
|
1467 |
+
const refreshBtn = refreshButtons.find(btn => btn.textContent.includes('Refresh Stats'));
|
1468 |
+
if (refreshBtn) {
|
1469 |
+
refreshBtn.click();
|
1470 |
+
}
|
1471 |
+
}, refreshInterval);
|
1472 |
+
}
|
1473 |
+
|
1474 |
+
// Set up the auto-refresh after the page loads
|
1475 |
+
if (window.gradio_loaded) {
|
1476 |
+
setupAutoRefresh();
|
1477 |
+
} else {
|
1478 |
+
document.addEventListener('DOMContentLoaded', setupAutoRefresh);
|
1479 |
+
}
|
1480 |
+
</script>
|
1481 |
+
""")
|
1482 |
+
|
1483 |
# Feedback section
|
1484 |
with gr.Accordion("Provide Feedback", open=False, visible=False) as feedback_accordion:
|
1485 |
gr.Markdown("### Help Improve the System")
|
|
|
1500 |
feedback_button = gr.Button("Submit Feedback", variant="secondary")
|
1501 |
feedback_status = gr.Textbox(label="Feedback Status", interactive=False, visible=False)
|
1502 |
|
1503 |
+
# Stats are now displayed in the live stats section
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1504 |
|
1505 |
# Hidden state to store results for feedback
|
1506 |
hidden_results = gr.State()
|
|
|
1520 |
feedback_button.click(
|
1521 |
fn=combine_feedback,
|
1522 |
inputs=[feedback_input, feedback_text, hidden_results],
|
1523 |
+
outputs=[feedback_status]
|
1524 |
)
|
1525 |
|
1526 |
# Footer
|