File size: 5,407 Bytes
9643337
 
e79963f
8e325ca
 
9643337
 
ec26861
8e325ca
9643337
 
8e325ca
e79963f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9643337
 
 
 
 
8e325ca
e79963f
 
8e325ca
9643337
 
 
 
 
8e325ca
bfc2b2f
9643337
 
bfc2b2f
9643337
bfc2b2f
9643337
bfc2b2f
8e325ca
e79963f
 
8e325ca
bfc2b2f
 
 
c872cb2
bfc2b2f
8e325ca
9643337
 
 
 
 
 
 
 
 
 
 
8e325ca
 
9643337
 
 
bfc2b2f
8e325ca
9643337
 
 
 
 
 
 
 
 
 
 
8e325ca
bfc2b2f
9643337
bfc2b2f
9643337
 
 
 
 
 
 
 
 
 
 
bfc2b2f
9643337
 
bfc2b2f
 
9643337
 
 
bfc2b2f
 
9643337
 
8e325ca
bfc2b2f
 
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
import os
import tempfile
import hashlib
import gradio as gr

from embedding_manager import EmbeddingManager
from summarizer import PatientChartSummarizer
from hedis_engine import HedisComplianceEngine

APP_TITLE = "ChartWise AI"
DEFAULT_MEASURE_YEAR = 2024

# --- Simple in-process cache (per Space runtime) ---
# Maps content_hash -> vectordb
_VDB_CACHE = {}
_LAST_HASH = None  # optional: for quick reuse/debug

def _pdf_hash(pdf_bytes: bytes) -> str:
    return hashlib.sha256(pdf_bytes).hexdigest()

def _get_vectordb_from_bytes(pdf_bytes: bytes):
    """
    Return a cached vectordb for this PDF content if available,
    otherwise build it once and cache it for subsequent calls.
    """
    global _VDB_CACHE, _LAST_HASH

    content_hash = _pdf_hash(pdf_bytes)
    _LAST_HASH = content_hash

    if content_hash in _VDB_CACHE:
        print(f"[CACHE] Using cached vectordb for hash {content_hash[:12]}...")
        return _VDB_CACHE[content_hash]

    # Not cached yet: create temp file, build embeddings once, then cache
    with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp:
        tmp.write(pdf_bytes)
        pdf_path = tmp.name

    try:
        manager = EmbeddingManager(pdf_path)  # persists under ./embeddings/<temp_stem>
        vectordb = manager.get_or_create_embeddings()
        _VDB_CACHE[content_hash] = vectordb
        print(f"[CACHE] Cached vectordb for hash {content_hash[:12]}.")
        return vectordb
    finally:
        # Remove only the temp PDF; embeddings are persisted separately by EmbeddingManager
        try:
            os.unlink(pdf_path)
        except Exception:
            pass

# --- Handlers ---
def generate_patient_summary(pdf_file):
    try:
        if pdf_file is None:
            return "⚠️ Please upload a PDF file first."

        # Reuse embeddings if already built for this file
        vectordb = _get_vectordb_from_bytes(pdf_file)

        summarizer = PatientChartSummarizer(vectordb)
        result = summarizer.summarize_chart()
        return result
    except Exception as e:
        return f"❌ Error processing chart: {e}"

def generate_hedis_analysis(pdf_file, measure_name, measurement_year):
    try:
        if pdf_file is None:
            return "⚠️ Please upload a PDF file first."
        if not measure_name:
            return "⚠️ Please enter a HEDIS measure code (e.g., COL, BCS, CCS)."
        if not measurement_year:
            return "⚠️ Please enter a measurement year."

        # Reuse embeddings if already built for this file
        vectordb = _get_vectordb_from_bytes(pdf_file)

        hedis = HedisComplianceEngine(vectordb, measure_name, int(measurement_year))
        result = hedis.run()
        return result
    except Exception as e:
        return f"❌ Error processing HEDIS analysis: {e}"

# --- Gradio Theme ---
simple_theme = gr.themes.Soft(
    primary_hue=gr.themes.colors.blue,
    secondary_hue=gr.themes.colors.slate,
    neutral_hue=gr.themes.colors.slate,
).set(
    button_primary_background_fill="#1e40af",
    button_primary_background_fill_hover="#1d4ed8",
    button_primary_text_color="white",
    background_fill_primary="white",
    background_fill_secondary="#f8fafc",
)

# --- Interface ---
with gr.Blocks(theme=simple_theme, title="ChartWise AI") as interface:
    gr.HTML("<h1 style='text-align:center;color:#1e40af;'>🏥 ChartWise AI</h1>")
    gr.HTML("<p style='text-align:center;color:#64748b;'>Patient Chart Analysis &amp; HEDIS Compliance</p>")

    with gr.Row(equal_height=True):
        # Left: Patient Summary
        with gr.Column():
            gr.HTML("<h3 style='color:#1e40af;'>📋 Patient Chart Analysis</h3>")
            pdf_upload = gr.File(label="Upload Patient Chart (PDF)", file_types=[".pdf"], type="binary")
            summary_btn = gr.Button("📊 Generate Patient Summary", variant="primary")
            summary_output = gr.Markdown(
                label="Patient Summary Results",
                value="Upload a patient chart and click 'Generate Patient Summary' to see results here.",
                height=400
            )

        # Right: HEDIS
        with gr.Column():
            gr.HTML("<h3 style='color:#1e40af;'>🎯 HEDIS Measure Analysis</h3>")
            hedis_measure = gr.Textbox(
                label="HEDIS Measure Code",
                placeholder="e.g., COL, BCS, CCS, AAB",
                info="Measure code per NCQA HEDIS"
            )
            measurement_year = gr.Number(
                label="Measurement Year",
                value=DEFAULT_MEASURE_YEAR,
                precision=0,
                info="e.g., 2024"
            )
            hedis_btn = gr.Button("🎯 Run HEDIS Analysis", variant="secondary")
            hedis_output = gr.Markdown(
                label="HEDIS Analysis Results",
                value="Enter measure and year, then click 'Run HEDIS Analysis'.",
                height=400
            )

    # Wire events
    summary_btn.click(fn=generate_patient_summary, inputs=[pdf_upload], outputs=[summary_output])
    hedis_btn.click(fn=generate_hedis_analysis, inputs=[pdf_upload, hedis_measure, measurement_year], outputs=[hedis_output])

# Spaces auto-runs the script; these hints are fine, too:
if __name__ == "__main__":
    interface.queue().launch(server_name="0.0.0.0", server_port=int(os.environ.get("GRADIO_SERVER_PORT", "7860")))