PragmaticPete commited on
Commit
7dcf7f6
·
verified ·
1 Parent(s): ddd6cae

Upload 4 files

Browse files
logic/care_gap_engine.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # File: logic/care_gap_engine.py
2
+
3
+ import pandas as pd
4
+ from datetime import datetime
5
+
6
+ def evaluate_care_gaps(df: pd.DataFrame, config):
7
+ today = datetime.today()
8
+ rules = config["care_gap_rules"]
9
+ results = []
10
+
11
+ for _, row in df.iterrows():
12
+ gaps = []
13
+
14
+ if row['gender'] == 'F' and rules['Breast Cancer Screening']['min_age'] <= row['age'] <= rules['Breast Cancer Screening']['max_age']:
15
+ if not row['last_mammogram'] or (today - pd.to_datetime(row['last_mammogram'], errors='coerce')).days > rules['Breast Cancer Screening']['interval_days']:
16
+ gaps.append("Breast Cancer Screening")
17
+
18
+ if rules['Colorectal Cancer Screening']['min_age'] <= row['age'] <= rules['Colorectal Cancer Screening']['max_age']:
19
+ if not row['last_colonoscopy'] or (today - pd.to_datetime(row['last_colonoscopy'], errors='coerce')).days > rules['Colorectal Cancer Screening']['interval_days']:
20
+ gaps.append("Colorectal Cancer Screening")
21
+
22
+ if row.get('systolic_bp', '') != "" and pd.to_numeric(row['systolic_bp'], errors='coerce') > rules['Blood Pressure Control']['bp_threshold']:
23
+ gaps.append("Blood Pressure Control")
24
+
25
+ if row.get('hba1c_value', '') != "" and pd.to_numeric(row['hba1c_value'], errors='coerce') >= 9:
26
+ gaps.append("Diabetes: Poor HbA1c Control")
27
+
28
+ if row.get('FollowUp_Scheduled', '').strip().lower() == 'no' or row.get('Primary_Care_Established', '').strip().lower() == 'no':
29
+ gaps.append("Follow-Up Care")
30
+
31
+ if row.get('Previous_Readmissions', '').isdigit() and int(row['Previous_Readmissions']) >= 3:
32
+ gaps.append("Readmission Risk")
33
+
34
+ results.append({
35
+ 'patient_id': row['patient_id'],
36
+ 'care_gaps': gaps
37
+ })
38
+
39
+ return pd.DataFrame(results)
logic/exporter.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # File: logic/exporter.py
2
+
3
+ from docx import Document
4
+ import os
5
+ import io
6
+ import zipfile
7
+
8
+ def export_to_docx_and_zip(report_data, summaries, output_dir="assets/sample_reports"):
9
+ zip_buffer = io.BytesIO()
10
+ with zipfile.ZipFile(zip_buffer, "w") as zipf:
11
+ for _, row in report_data.iterrows():
12
+ pid = row['patient_id']
13
+ doc = Document()
14
+ doc.add_heading(f'Patient Summary: {pid}', 0)
15
+ doc.add_paragraph(f"Risk Score: {row['risk_score']}")
16
+ doc.add_paragraph(f"Projected Revenue Gain: ${row['projected_gain']}")
17
+ doc.add_paragraph("Care Gaps:")
18
+ for gap in row['care_gaps']:
19
+ doc.add_paragraph(f"• {gap}", style='List Bullet')
20
+ doc.add_paragraph("\nSummary:")
21
+ doc.add_paragraph(summaries[pid])
22
+
23
+ doc_path = f"Patient_{pid}_Report.docx"
24
+ temp_stream = io.BytesIO()
25
+ doc.save(temp_stream)
26
+ zipf.writestr(doc_path, temp_stream.getvalue())
27
+
28
+ zip_buffer.seek(0)
29
+ return zip_buffer, report_data['patient_id'].tolist()
logic/financial_model.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # File: logic/financial_model.py
2
+
3
+ def estimate_financial_recovery(care_gaps_df, patient_data, base_rate, sdoh_keys):
4
+ results = []
5
+ hcc_weights = {
6
+ 'HCC18': 0.4, 'HCC85': 0.5, 'HCC19': 0.3
7
+ }
8
+
9
+ for _, row in care_gaps_df.iterrows():
10
+ patient = patient_data[patient_data['patient_id'] == row['patient_id']].iloc[0]
11
+ hccs = [h.strip() for h in str(patient.get('hcc_codes', '')).split(';') if h.strip() in hcc_weights]
12
+ risk_score = sum(hcc_weights[h] for h in hccs)
13
+
14
+ sdoh_count = sum(1 for key in sdoh_keys if str(patient.get(key, '')).strip().lower() == 'yes')
15
+ sdoh_modifier = 1 + 0.05 * sdoh_count # Each SDOH adds 5% to the opportunity
16
+
17
+ care_gap_count = len(row['care_gaps'])
18
+ expected_gain = base_rate * (risk_score * 0.02 * care_gap_count) * sdoh_modifier
19
+
20
+ results.append({
21
+ 'patient_id': row['patient_id'],
22
+ 'risk_score': round(risk_score, 2),
23
+ 'projected_gain': round(expected_gain, 2)
24
+ })
25
+
26
+ return pd.DataFrame(results)
logic/nlp_report.py ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # File: logic/nlp_report.py
2
+
3
+ from huggingface_hub import hf_hub_download
4
+ from llama_cpp import Llama
5
+ import logging
6
+
7
+ MODEL_REPO = "bartowski/deepcogito_cogito-v1-preview-llama-8B-GGUF"
8
+ MODEL_FILENAME = "deepcogito_cogito-v1-preview-llama-8B-Q8_0.gguf"
9
+
10
+ model_path = hf_hub_download(
11
+ repo_id=MODEL_REPO,
12
+ filename=MODEL_FILENAME,
13
+ cache_dir="models"
14
+ )
15
+
16
+ llm = Llama(
17
+ model_path=model_path,
18
+ n_ctx=2048,
19
+ chat_format="chatml",
20
+ verbose=False
21
+ )
22
+
23
+ def generate_patient_summary(patient_row, tone="executive", override_prompt=None):
24
+ try:
25
+ gaps = patient_row['care_gaps']
26
+ gain = patient_row['projected_gain']
27
+ score = patient_row['risk_score']
28
+
29
+ social_flags = []
30
+ if str(patient_row.get("Lives_Alone", "")).strip().lower() == "yes":
31
+ social_flags.append("lives alone")
32
+ if str(patient_row.get("Housing_Instability", "")).strip().lower() == "yes":
33
+ social_flags.append("experiencing housing instability")
34
+ if str(patient_row.get("Transportation_Access", "")).strip().lower() == "yes":
35
+ social_flags.append("has limited transportation access")
36
+ if str(patient_row.get("Food_Insecurity", "")).strip().lower() == "yes":
37
+ social_flags.append("faces food insecurity")
38
+ if str(patient_row.get("Primary_Care_Established", "")).strip().lower() == "no":
39
+ social_flags.append("does not have a primary care provider")
40
+ if str(patient_row.get("FollowUp_Scheduled", "")).strip().lower() == "no":
41
+ social_flags.append("has no follow-up scheduled")
42
+
43
+ social_context = "; ".join(social_flags) if social_flags else "no major social risk factors identified"
44
+
45
+ base_prompt = override_prompt or f"""
46
+ You are a healthcare analyst creating summaries for value-based care programs.
47
+ Tone: {tone}
48
+
49
+ Patient ID: {patient_row['patient_id']}
50
+ Risk Score: {score}
51
+ Projected Revenue Gain: ${gain}
52
+ Care Gaps Identified: {', '.join(gaps)}
53
+ Social Risk Factors: {social_context}
54
+
55
+ Write a concise and insightful clinical summary, including key gaps and social considerations. Offer targeted recommendations.
56
+ """
57
+
58
+ response = llm.create_chat_completion(
59
+ messages=[{"role": "user", "content": base_prompt}]
60
+ )
61
+
62
+ if "choices" in response and response["choices"]:
63
+ return response["choices"][0]["message"]["content"]
64
+ else:
65
+ return "[Error] No summary returned."
66
+ except Exception as e:
67
+ logging.error(f"LLM error: {e}")
68
+ return "[Error generating summary]"