Update thicc/app.py
Browse files- thicc/app.py +83 -18
thicc/app.py
CHANGED
|
@@ -4,22 +4,88 @@ from data.data_loader import list_services, load_services_data, HOSPITALS
|
|
| 4 |
from insurance import plans, cost_estimator
|
| 5 |
from insurance.coverage_explainer import CoverageExplainer
|
| 6 |
|
| 7 |
-
#
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
value="PPO",
|
| 11 |
-
label="Select plan",
|
| 12 |
-
)
|
| 13 |
|
| 14 |
-
hospital_dropdown = gr.Dropdown(
|
| 15 |
-
choices=list(HOSPITALS.keys()),
|
| 16 |
-
value=list(HOSPITALS.keys())[0],
|
| 17 |
-
label="Select a Hospital",
|
| 18 |
-
)
|
| 19 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 20 |
|
| 21 |
-
|
| 22 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
|
| 24 |
# --- 1) Coverage questions first ---
|
| 25 |
if CoverageExplainer.identify_coverage_question(message):
|
|
@@ -80,7 +146,7 @@ def respond(message, history, plan_name: str, hospital_name: str) -> str:
|
|
| 80 |
service_description = service_data.iloc[0]["description"]
|
| 81 |
price = service_data.iloc[0]["negotiated_rate"]
|
| 82 |
|
| 83 |
-
# Map
|
| 84 |
if plan_name == "No Insurance":
|
| 85 |
plan = plans.NO_INSURANCE_PLAN
|
| 86 |
else:
|
|
@@ -105,7 +171,7 @@ Because you selected **No Insurance**, this demo assumes you pay the full negoti
|
|
| 105 |
• Your insurance covers: $0.00
|
| 106 |
• You pay: ${cost:.2f}
|
| 107 |
|
| 108 |
-
If you want to see how deductibles, copays, and coinsurance work,
|
| 109 |
• "What is a deductible?"
|
| 110 |
• "Explain coinsurance"
|
| 111 |
"""
|
|
@@ -155,9 +221,8 @@ demo = gr.ChatInterface(
|
|
| 155 |
• Coverage terms: "What is a deductible?" or "Explain coinsurance"
|
| 156 |
• Available services: "What services are available?"
|
| 157 |
""",
|
| 158 |
-
additional_inputs=[plan_dropdown, hospital_dropdown],
|
| 159 |
-
additional_inputs_accordion="Tell us about your insurance plan and hospital",
|
| 160 |
)
|
| 161 |
|
| 162 |
if __name__ == "__main__":
|
| 163 |
-
|
|
|
|
|
|
| 4 |
from insurance import plans, cost_estimator
|
| 5 |
from insurance.coverage_explainer import CoverageExplainer
|
| 6 |
|
| 7 |
+
# Valid options for hospitals and plans (used in the conversational flow)
|
| 8 |
+
HOSPITAL_CHOICES = list(HOSPITALS.keys())
|
| 9 |
+
PLAN_CHOICES = list(plans.SAMPLE_PLANS.keys()) + ["No Insurance"]
|
|
|
|
|
|
|
|
|
|
| 10 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
|
| 12 |
+
def _extract_hospital_and_plan(text: str):
|
| 13 |
+
"""Best-effort extraction of hospital and plan names from free text."""
|
| 14 |
+
if not text:
|
| 15 |
+
return None, None
|
| 16 |
+
|
| 17 |
+
lower = text.lower()
|
| 18 |
+
hospital_name = None
|
| 19 |
+
plan_name = None
|
| 20 |
+
|
| 21 |
+
# Match hospitals by substring
|
| 22 |
+
for name in HOSPITAL_CHOICES:
|
| 23 |
+
if name.lower() in lower:
|
| 24 |
+
hospital_name = name
|
| 25 |
+
|
| 26 |
+
# Match plans by key
|
| 27 |
+
for plan_key in plans.SAMPLE_PLANS.keys():
|
| 28 |
+
if plan_key.lower() in lower:
|
| 29 |
+
plan_name = plan_key
|
| 30 |
+
|
| 31 |
+
# Allow "no insurance" as a phrase
|
| 32 |
+
if "no insurance" in lower:
|
| 33 |
+
plan_name = "No Insurance"
|
| 34 |
+
|
| 35 |
+
return hospital_name, plan_name
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
def _get_current_hospital_and_plan(message, history):
|
| 39 |
+
"""
|
| 40 |
+
Look through the chat history (and latest message) for the most recent
|
| 41 |
+
hospital & plan mentioned by the user.
|
| 42 |
+
"""
|
| 43 |
+
hospital_name = None
|
| 44 |
+
plan_name = None
|
| 45 |
+
|
| 46 |
+
# History is a list of [user, bot] message pairs
|
| 47 |
+
for user_msg, bot_msg in history or []:
|
| 48 |
+
h, p = _extract_hospital_and_plan(user_msg)
|
| 49 |
+
if h:
|
| 50 |
+
hospital_name = h
|
| 51 |
+
if p:
|
| 52 |
+
plan_name = p
|
| 53 |
+
|
| 54 |
+
# Also extract from the current message
|
| 55 |
+
h, p = _extract_hospital_and_plan(message)
|
| 56 |
+
if h:
|
| 57 |
+
hospital_name = h
|
| 58 |
+
if p:
|
| 59 |
+
plan_name = p
|
| 60 |
|
| 61 |
+
return hospital_name, plan_name
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
def respond(message, history) -> str:
|
| 65 |
+
"""Main response function - now handles hospital/plan conversationally."""
|
| 66 |
+
|
| 67 |
+
# Determine the user's current hospital & plan from history/message
|
| 68 |
+
hospital_name, plan_name = _get_current_hospital_and_plan(message, history)
|
| 69 |
+
|
| 70 |
+
# If either is missing, show the options and ask the user to choose
|
| 71 |
+
if hospital_name is None or plan_name is None:
|
| 72 |
+
hospitals_list = "\n".join(f"• {name}" for name in HOSPITAL_CHOICES)
|
| 73 |
+
plans_list = "\n".join(f"• {name}" for name in PLAN_CHOICES)
|
| 74 |
+
|
| 75 |
+
return f"""Hi, I'm the THICC Cost Chatbot. 🏥
|
| 76 |
+
|
| 77 |
+
Before I can estimate your costs, tell me **which hospital** you're using and **what insurance plan** you have.
|
| 78 |
+
|
| 79 |
+
**Hospitals I currently support:**
|
| 80 |
+
{hospitals_list}
|
| 81 |
+
|
| 82 |
+
**Insurance options I support:**
|
| 83 |
+
{plans_list}
|
| 84 |
+
|
| 85 |
+
Please reply with something like:
|
| 86 |
+
• "I'm going to UCLA Medical Center and I have a PPO plan."
|
| 87 |
+
• "Cedars-Sinai Medical Center with No Insurance."
|
| 88 |
+
"""
|
| 89 |
|
| 90 |
# --- 1) Coverage questions first ---
|
| 91 |
if CoverageExplainer.identify_coverage_question(message):
|
|
|
|
| 146 |
service_description = service_data.iloc[0]["description"]
|
| 147 |
price = service_data.iloc[0]["negotiated_rate"]
|
| 148 |
|
| 149 |
+
# Map plan name -> InsurancePlan object
|
| 150 |
if plan_name == "No Insurance":
|
| 151 |
plan = plans.NO_INSURANCE_PLAN
|
| 152 |
else:
|
|
|
|
| 171 |
• Your insurance covers: $0.00
|
| 172 |
• You pay: ${cost:.2f}
|
| 173 |
|
| 174 |
+
If you want to see how deductibles, copays, and coinsurance work, try asking:
|
| 175 |
• "What is a deductible?"
|
| 176 |
• "Explain coinsurance"
|
| 177 |
"""
|
|
|
|
| 221 |
• Coverage terms: "What is a deductible?" or "Explain coinsurance"
|
| 222 |
• Available services: "What services are available?"
|
| 223 |
""",
|
|
|
|
|
|
|
| 224 |
)
|
| 225 |
|
| 226 |
if __name__ == "__main__":
|
| 227 |
+
# Keep SSR disabled for Hugging Face Spaces stability
|
| 228 |
+
demo.launch(ssr_mode=False)
|