Spaces:
Running
Running
Commit ·
440e996
1
Parent(s): e5f88a5
11tg
Browse files- app.py +106 -15
- project_status.md +22 -2
app.py
CHANGED
|
@@ -128,16 +128,54 @@ def load_documents():
|
|
| 128 |
return []
|
| 129 |
|
| 130 |
def save_evaluation(data):
|
| 131 |
-
"""Save evaluation
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 141 |
|
| 142 |
def get_results():
|
| 143 |
"""Get evaluation results for display."""
|
|
@@ -259,6 +297,18 @@ def index():
|
|
| 259 |
session['evaluator_name'] = evaluator_name
|
| 260 |
|
| 261 |
flash("File uploaded successfully!")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 262 |
return redirect(url_for('evaluate'))
|
| 263 |
|
| 264 |
except Exception as inner_e:
|
|
@@ -314,18 +364,59 @@ def evaluate():
|
|
| 314 |
|
| 315 |
# Process POST request (form submission)
|
| 316 |
if request.method == 'POST':
|
| 317 |
-
# Process evaluation form...
|
| 318 |
try:
|
| 319 |
# Get current document
|
| 320 |
documents = load_documents()
|
| 321 |
log_error(f"Loaded {len(documents)} documents for POST")
|
| 322 |
|
| 323 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 324 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 325 |
except Exception as e:
|
| 326 |
-
|
| 327 |
-
|
| 328 |
-
|
|
|
|
| 329 |
|
| 330 |
# Handle GET request (display evaluation form)
|
| 331 |
try:
|
|
|
|
| 128 |
return []
|
| 129 |
|
| 130 |
def save_evaluation(data):
|
| 131 |
+
"""Save evaluation data to CSV file."""
|
| 132 |
+
try:
|
| 133 |
+
# Ensure the data directory exists
|
| 134 |
+
ensure_data_directory()
|
| 135 |
+
|
| 136 |
+
# Log the data being saved
|
| 137 |
+
log_error(f"Attempting to save evaluation for {data.get('document_title')} by {data.get('investigator_name')}")
|
| 138 |
+
|
| 139 |
+
eval_path = os.path.join(DATA_DIR, 'evaluations.csv')
|
| 140 |
+
|
| 141 |
+
# Check if the file exists already
|
| 142 |
+
file_exists = os.path.exists(eval_path)
|
| 143 |
+
|
| 144 |
+
# Add timestamp to the data
|
| 145 |
+
data['timestamp'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
| 146 |
+
|
| 147 |
+
# Try to open with write permissions - if this fails, we'll catch the exception
|
| 148 |
+
with open(eval_path, 'a', newline='', encoding='utf-8') as f:
|
| 149 |
+
writer = csv.DictWriter(f, fieldnames=data.keys())
|
| 150 |
+
|
| 151 |
+
# Write header only if it's a new file
|
| 152 |
+
if not file_exists:
|
| 153 |
+
writer.writeheader()
|
| 154 |
+
|
| 155 |
+
# Write the data row
|
| 156 |
+
writer.writerow(data)
|
| 157 |
+
|
| 158 |
+
log_error(f"Successfully saved evaluation to {eval_path}")
|
| 159 |
+
return True
|
| 160 |
+
|
| 161 |
+
except Exception as e:
|
| 162 |
+
log_error(f"Error saving evaluation: {str(e)}")
|
| 163 |
+
# Attempt to save to a backup location as fallback
|
| 164 |
+
try:
|
| 165 |
+
backup_path = os.path.join('/tmp', 'evaluation_backup.csv')
|
| 166 |
+
log_error(f"Trying backup location: {backup_path}")
|
| 167 |
+
|
| 168 |
+
with open(backup_path, 'a', newline='', encoding='utf-8') as f:
|
| 169 |
+
writer = csv.DictWriter(f, fieldnames=data.keys())
|
| 170 |
+
if not os.path.exists(backup_path) or os.path.getsize(backup_path) == 0:
|
| 171 |
+
writer.writeheader()
|
| 172 |
+
writer.writerow(data)
|
| 173 |
+
|
| 174 |
+
log_error(f"Saved to backup location: {backup_path}")
|
| 175 |
+
return True
|
| 176 |
+
except Exception as backup_error:
|
| 177 |
+
log_error(f"Backup save also failed: {str(backup_error)}")
|
| 178 |
+
return False
|
| 179 |
|
| 180 |
def get_results():
|
| 181 |
"""Get evaluation results for display."""
|
|
|
|
| 297 |
session['evaluator_name'] = evaluator_name
|
| 298 |
|
| 299 |
flash("File uploaded successfully!")
|
| 300 |
+
|
| 301 |
+
# After uploading documents.csv successfully, copy template_documents if it doesn't exist
|
| 302 |
+
documents_path = os.path.join(DATA_DIR, 'documents.csv')
|
| 303 |
+
|
| 304 |
+
# If user uploaded file, ensure we save the evaluator name persistently
|
| 305 |
+
if evaluator_name:
|
| 306 |
+
store_evaluator_name(evaluator_name)
|
| 307 |
+
|
| 308 |
+
# Also create a direct access link they can bookmark
|
| 309 |
+
direct_link = url_for('evaluate', evaluator=evaluator_name, _external=True)
|
| 310 |
+
flash(f"Bookmark this link for direct access to your evaluation: {direct_link}")
|
| 311 |
+
|
| 312 |
return redirect(url_for('evaluate'))
|
| 313 |
|
| 314 |
except Exception as inner_e:
|
|
|
|
| 364 |
|
| 365 |
# Process POST request (form submission)
|
| 366 |
if request.method == 'POST':
|
|
|
|
| 367 |
try:
|
| 368 |
# Get current document
|
| 369 |
documents = load_documents()
|
| 370 |
log_error(f"Loaded {len(documents)} documents for POST")
|
| 371 |
|
| 372 |
+
if not documents:
|
| 373 |
+
flash("No documents available for evaluation.")
|
| 374 |
+
return redirect(url_for('index'))
|
| 375 |
+
|
| 376 |
+
document = documents[0]
|
| 377 |
+
log_error(f"Processing evaluation for document: {document.get('filename')}")
|
| 378 |
+
|
| 379 |
+
# Prepare evaluation data
|
| 380 |
+
evaluation_data = {
|
| 381 |
+
'document_title': document.get('filename', 'Unknown'),
|
| 382 |
+
'description': document.get('description', ''),
|
| 383 |
+
'mrn': document.get('mrn', ''),
|
| 384 |
+
'investigator_name': evaluator_name,
|
| 385 |
+
}
|
| 386 |
+
|
| 387 |
+
# Get criteria scores
|
| 388 |
+
for i, criterion in enumerate(CRITERIA):
|
| 389 |
+
score_key = f"criteria_{i}"
|
| 390 |
+
if score_key in request.form:
|
| 391 |
+
evaluation_data[criterion] = request.form[score_key]
|
| 392 |
|
| 393 |
+
# Get note origin assessment
|
| 394 |
+
if 'note_origin' in request.form:
|
| 395 |
+
evaluation_data['note_origin'] = request.form['note_origin']
|
| 396 |
+
log_error(f"Note origin: {evaluation_data['note_origin']}")
|
| 397 |
+
|
| 398 |
+
# Save evaluation data
|
| 399 |
+
save_result = save_evaluation(evaluation_data)
|
| 400 |
+
|
| 401 |
+
if save_result:
|
| 402 |
+
flash("Evaluation saved successfully!")
|
| 403 |
+
|
| 404 |
+
# Check if all documents have been evaluated
|
| 405 |
+
remaining_docs = len(load_documents())
|
| 406 |
+
if remaining_docs == 0:
|
| 407 |
+
flash("All documents have been evaluated. Thank you!")
|
| 408 |
+
return redirect(url_for('results'))
|
| 409 |
+
|
| 410 |
+
# Redirect to next document
|
| 411 |
+
return redirect(url_for('evaluate'))
|
| 412 |
+
else:
|
| 413 |
+
flash("Error saving evaluation. Please try again.")
|
| 414 |
+
|
| 415 |
except Exception as e:
|
| 416 |
+
error_msg = f"Error processing evaluation: {str(e)}"
|
| 417 |
+
log_error(error_msg)
|
| 418 |
+
log_error(traceback.format_exc())
|
| 419 |
+
flash(error_msg)
|
| 420 |
|
| 421 |
# Handle GET request (display evaluation form)
|
| 422 |
try:
|
project_status.md
CHANGED
|
@@ -39,6 +39,15 @@
|
|
| 39 |
- Improved error messages for file upload problems
|
| 40 |
- Added handling for common CSV format variations and column name mismatches
|
| 41 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
## Current Status
|
| 43 |
- Application is ready for deployment on Hugging Face Spaces
|
| 44 |
- All necessary files have been created and configured
|
|
@@ -55,6 +64,14 @@
|
|
| 55 |
- MRN tracking for patient chart identification
|
| 56 |
- Realistic clinical note examples included in sample files
|
| 57 |
- Enhanced error reporting and diagnosis capabilities
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
|
| 59 |
## Next Steps
|
| 60 |
- Deploy application to Hugging Face Spaces
|
|
@@ -63,6 +80,9 @@
|
|
| 63 |
- Data visualization for evaluation results
|
| 64 |
- Custom evaluation criteria configuration
|
| 65 |
- User authentication for multiple evaluators (if needed in the future)
|
| 66 |
-
|
|
|
|
|
|
|
|
|
|
| 67 |
## Open Questions
|
| 68 |
-
- None at this time
|
|
|
|
| 39 |
- Improved error messages for file upload problems
|
| 40 |
- Added handling for common CSV format variations and column name mismatches
|
| 41 |
|
| 42 |
+
## Latest Updates
|
| 43 |
+
- Implemented robust evaluation saving with backup mechanisms
|
| 44 |
+
- Added detailed error logging for troubleshooting save failures
|
| 45 |
+
- Created failsafe storage for evaluations when primary storage fails
|
| 46 |
+
- Enhanced form submission handling with better validation
|
| 47 |
+
- Added direct access bookmark system for evaluators
|
| 48 |
+
- Improved file handling to prevent data loss
|
| 49 |
+
- Addressed issues with Hugging Face Spaces environment-specific limitations
|
| 50 |
+
|
| 51 |
## Current Status
|
| 52 |
- Application is ready for deployment on Hugging Face Spaces
|
| 53 |
- All necessary files have been created and configured
|
|
|
|
| 64 |
- MRN tracking for patient chart identification
|
| 65 |
- Realistic clinical note examples included in sample files
|
| 66 |
- Enhanced error reporting and diagnosis capabilities
|
| 67 |
+
- All core functionality is working, including:
|
| 68 |
+
- File upload and document parsing
|
| 69 |
+
- Evaluation form with note origin assessment
|
| 70 |
+
- Results viewing and CSV export
|
| 71 |
+
- Multiple access paths for better user experience
|
| 72 |
+
- Robust error handling and recovery mechanisms
|
| 73 |
+
- Comprehensive logging for troubleshooting
|
| 74 |
+
- Note origin assessment (Human vs AI) feature fully implemented
|
| 75 |
|
| 76 |
## Next Steps
|
| 77 |
- Deploy application to Hugging Face Spaces
|
|
|
|
| 80 |
- Data visualization for evaluation results
|
| 81 |
- Custom evaluation criteria configuration
|
| 82 |
- User authentication for multiple evaluators (if needed in the future)
|
| 83 |
+
- Finalize testing in Hugging Face Spaces environment
|
| 84 |
+
- Create user guide for sustainable deployment
|
| 85 |
+
- Consider adding analytics for evaluation trends
|
| 86 |
+
|
| 87 |
## Open Questions
|
| 88 |
+
- None at this time - focusing on reliability and data integrity
|