File size: 7,281 Bytes
8a693e2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
"""

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)