Spaces:
Running
Running
| """ | |
| utils/feedback.py | |
| Unified feedback handler for Clinical Research Chatbot. | |
| Includes: | |
| 1️⃣ Feedback Queue (unanswered/low-confidence queries) | |
| 2️⃣ User Voting (👍 Helpful / 👎 Not Helpful) | |
| """ | |
| import os | |
| import json | |
| from datetime import datetime | |
| # ---------------------------- | |
| # File Paths | |
| # ---------------------------- | |
| FEEDBACK_QUEUE_LOG = "logs/feedback_queue.jsonl" | |
| FEEDBACK_VOTES_LOG = "logs/feedback_votes.jsonl" | |
| # ---------------------------- | |
| # Feedback Queue (for Admin Review) | |
| # ---------------------------- | |
| def log_feedback(query: str, notes: str = "", sources=None): | |
| """ | |
| Store unanswered or low-confidence queries for admin review. | |
| Saves to JSONL (one entry per line). | |
| """ | |
| entry = { | |
| "timestamp": datetime.utcnow().isoformat(), | |
| "query": query, | |
| "notes": notes, | |
| "sources": sources or [], | |
| } | |
| os.makedirs(os.path.dirname(FEEDBACK_QUEUE_LOG), exist_ok=True) | |
| with open(FEEDBACK_QUEUE_LOG, "a", encoding="utf-8") as f: | |
| f.write(json.dumps(entry, ensure_ascii=False) + "\n") | |
| print(f"📝 Feedback queued for admin review: {query}") | |
| def load_feedback(limit: int = 20): | |
| """ | |
| Load last N feedback entries for admin dashboard. | |
| """ | |
| if not os.path.exists(FEEDBACK_QUEUE_LOG): | |
| return [] | |
| with open(FEEDBACK_QUEUE_LOG, "r", encoding="utf-8") as f: | |
| lines = f.readlines() | |
| entries = [json.loads(line) for line in lines] | |
| return entries[-limit:] | |
| def clear_feedback(): | |
| """ | |
| Clear feedback log (admin only). | |
| """ | |
| if os.path.exists(FEEDBACK_QUEUE_LOG): | |
| os.remove(FEEDBACK_QUEUE_LOG) | |
| print("🗑️ Feedback log cleared.") | |
| # ---------------------------- | |
| # User Voting (for “Helpful / Not Helpful”) | |
| # ---------------------------- | |
| def save_vote_feedback(query: str, vote: str, context=None): | |
| """ | |
| Log user votes (👍 / 👎) on chatbot responses. | |
| """ | |
| entry = { | |
| "timestamp": datetime.utcnow().isoformat(), | |
| "query": query, | |
| "vote": vote, | |
| "context": context or {}, | |
| } | |
| os.makedirs(os.path.dirname(FEEDBACK_VOTES_LOG), exist_ok=True) | |
| try: | |
| with open(FEEDBACK_VOTES_LOG, "a", encoding="utf-8") as f: | |
| f.write(json.dumps(entry, ensure_ascii=False) + "\n") | |
| print(f"🗳️ User voted '{vote}' for query: {query}") | |
| except Exception as e: | |
| print(f"⚠️ Failed to save vote feedback: {e}") | |
| def load_votes(limit: int = 50): | |
| """ | |
| Load last N user votes for analysis. | |
| """ | |
| if not os.path.exists(FEEDBACK_VOTES_LOG): | |
| return [] | |
| with open(FEEDBACK_VOTES_LOG, "r", encoding="utf-8") as f: | |
| lines = f.readlines() | |
| entries = [json.loads(line) for line in lines] | |
| return entries[-limit:] | |
| def clear_votes(): | |
| """ | |
| Clear user voting log (admin only). | |
| """ | |
| if os.path.exists(FEEDBACK_VOTES_LOG): | |
| os.remove(FEEDBACK_VOTES_LOG) | |
| print("🗑️ User vote feedback cleared.") | |