Hanan-Alnakhal's picture
Upload 12 files
8a693e2 verified
raw
history blame
7.28 kB
"""
Lab Report Decoder - Flask Application
Professional web interface for lab report analysis
"""
from flask import Flask, render_template, request, jsonify, session
from werkzeug.utils import secure_filename
import os
import tempfile
import secrets
from pdf_extractor import LabReportExtractor
from rag_engine import LabReportRAG
from dotenv import load_dotenv
load_dotenv()
app = Flask(__name__)
app.secret_key = os.getenv('SECRET_KEY', secrets.token_hex(16))
# Note: No OpenAI API key needed - using Hugging Face models!
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 # 16MB max file size
app.config['UPLOAD_FOLDER'] = tempfile.gettempdir()
# Initialize RAG system (singleton)
rag_system = None
def get_rag_system():
"""Lazy load RAG system"""
global rag_system
if rag_system is None:
rag_system = LabReportRAG()
return rag_system
@app.route('/')
def index():
"""Main page"""
return render_template('index.html')
@app.route('/api/upload', methods=['POST'])
def upload_file():
"""Handle PDF upload and extraction"""
try:
if 'file' not in request.files:
return jsonify({'error': 'No file provided'}), 400
file = request.files['file']
if file.filename == '':
return jsonify({'error': 'No file selected'}), 400
if not file.filename.lower().endswith('.pdf'):
return jsonify({'error': 'Only PDF files are allowed'}), 400
# Save file temporarily
filename = secure_filename(file.filename)
filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
file.save(filepath)
try:
# Extract lab results
extractor = LabReportExtractor()
results = extractor.extract_from_pdf(filepath)
if not results:
return jsonify({'error': 'No lab results found in PDF'}), 400
# Convert to JSON-serializable format
results_data = [
{
'test_name': r.test_name,
'value': r.value,
'unit': r.unit,
'reference_range': r.reference_range,
'status': r.status
}
for r in results
]
# Store in session
session['results'] = results_data
return jsonify({
'success': True,
'results': results_data,
'count': len(results_data)
})
finally:
# Clean up temp file
if os.path.exists(filepath):
os.remove(filepath)
except Exception as e:
return jsonify({'error': str(e)}), 500
@app.route('/api/explain', methods=['POST'])
def explain_results():
"""Generate explanations for lab results"""
try:
results_data = session.get('results')
if not results_data:
return jsonify({'error': 'No results found. Please upload a PDF first.'}), 400
# Convert back to LabResult objects
from pdf_extractor import LabResult
results = [
LabResult(
test_name=r['test_name'],
value=r['value'],
unit=r['unit'],
reference_range=r['reference_range'],
status=r['status']
)
for r in results_data
]
# Generate explanations
rag = get_rag_system()
explanations = rag.explain_all_results(results)
return jsonify({
'success': True,
'explanations': explanations
})
except Exception as e:
return jsonify({'error': str(e)}), 500
@app.route('/api/ask', methods=['POST'])
def ask_question():
"""Answer follow-up questions"""
try:
data = request.get_json()
question = data.get('question', '').strip()
if not question:
return jsonify({'error': 'No question provided'}), 400
results_data = session.get('results')
if not results_data:
return jsonify({'error': 'No results found. Please upload a PDF first.'}), 400
# Convert back to LabResult objects
from pdf_extractor import LabResult
results = [
LabResult(
test_name=r['test_name'],
value=r['value'],
unit=r['unit'],
reference_range=r['reference_range'],
status=r['status']
)
for r in results_data
]
# Get answer
rag = get_rag_system()
answer = rag.answer_followup_question(question, results)
return jsonify({
'success': True,
'question': question,
'answer': answer
})
except Exception as e:
return jsonify({'error': str(e)}), 500
@app.route('/api/summary', methods=['GET'])
def get_summary():
"""Generate overall summary"""
try:
results_data = session.get('results')
if not results_data:
return jsonify({'error': 'No results found. Please upload a PDF first.'}), 400
# Convert back to LabResult objects
from pdf_extractor import LabResult
results = [
LabResult(
test_name=r['test_name'],
value=r['value'],
unit=r['unit'],
reference_range=r['reference_range'],
status=r['status']
)
for r in results_data
]
# Generate summary
rag = get_rag_system()
summary = rag.generate_summary(results)
# Calculate statistics
stats = {
'total': len(results),
'normal': sum(1 for r in results if r.status == 'normal'),
'high': sum(1 for r in results if r.status == 'high'),
'low': sum(1 for r in results if r.status == 'low'),
'unknown': sum(1 for r in results if r.status == 'unknown')
}
return jsonify({
'success': True,
'summary': summary,
'stats': stats
})
except Exception as e:
return jsonify({'error': str(e)}), 500
@app.route('/api/clear', methods=['POST'])
def clear_session():
"""Clear session data"""
session.clear()
return jsonify({'success': True})
@app.errorhandler(413)
def request_entity_too_large(error):
return jsonify({'error': 'File too large. Maximum size is 16MB.'}), 413
@app.errorhandler(500)
def internal_error(error):
return jsonify({'error': 'Internal server error'}), 500
if __name__ == '__main__':
if not(os.path.isdir('chroma_db/')):
os.system("python build_vector_db.py")
#any available port
port = int(os.environ.get("PORT", 5000))
app.run(host="0.0.0.0", port=port)