Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -178,32 +178,57 @@ def _first_text(value) -> str:
|
|
| 178 |
return ""
|
| 179 |
|
| 180 |
|
| 181 |
-
# tier-aware,
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
|
| 186 |
-
|
| 187 |
-
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 191 |
}
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 197 |
|
| 198 |
|
| 199 |
def _build_summary(parsed: dict) -> str:
|
| 200 |
-
"""Compose a
|
| 201 |
|
| 202 |
-
|
| 203 |
-
|
| 204 |
-
|
| 205 |
-
|
| 206 |
-
Prefers the trained `plain_language_summary` verbatim when
|
| 207 |
"""
|
| 208 |
if not isinstance(parsed, dict):
|
| 209 |
return ""
|
|
@@ -213,24 +238,25 @@ def _build_summary(parsed: dict) -> str:
|
|
| 213 |
return direct.strip()
|
| 214 |
|
| 215 |
tier = _normalize_tier(parsed.get("risk_tier"))
|
| 216 |
-
|
|
|
|
| 217 |
|
| 218 |
-
# one concrete
|
|
|
|
| 219 |
for key in ("recommended_next_step", "action_steps", "resources",
|
| 220 |
"clinical_rationale", "risk_factors"):
|
| 221 |
action = _first_text(parsed.get(key))
|
| 222 |
if action:
|
| 223 |
-
|
| 224 |
-
|
| 225 |
-
parts.append(f"A helpful next step: {action}")
|
| 226 |
break
|
| 227 |
|
| 228 |
escalate = (parsed.get("escalation_required") in (True, "true", "True", "yes", 1)
|
| 229 |
or (tier is not None and tier >= 2))
|
| 230 |
if escalate:
|
| 231 |
-
|
| 232 |
|
| 233 |
-
return
|
| 234 |
|
| 235 |
|
| 236 |
def _synthesize(text: str) -> tuple[int, np.ndarray]:
|
|
|
|
| 178 |
return ""
|
| 179 |
|
| 180 |
|
| 181 |
+
# tier-aware openers, written to be spoken aloud like a person talking, not a report.
|
| 182 |
+
# each has a connector for folding a next-step in naturally instead of a labeled clause.
|
| 183 |
+
_TIER_VOICE = {
|
| 184 |
+
0: dict(
|
| 185 |
+
opener="Thanks for sharing that with me. From what you've described, things "
|
| 186 |
+
"don't sound like they're at a crisis point right now.",
|
| 187 |
+
connector="That said, it can still help to",
|
| 188 |
+
),
|
| 189 |
+
1: dict(
|
| 190 |
+
opener="I can hear that you're going through a tough time. What you're "
|
| 191 |
+
"describing sounds like real distress, and it's worth taking seriously.",
|
| 192 |
+
connector="One thing that might help is to",
|
| 193 |
+
),
|
| 194 |
+
2: dict(
|
| 195 |
+
opener="I'm genuinely concerned about what you've shared. This sounds serious, "
|
| 196 |
+
"and I want you to know your safety matters right now.",
|
| 197 |
+
connector="Please",
|
| 198 |
+
),
|
| 199 |
+
3: dict(
|
| 200 |
+
opener="What you've told me sounds like an emergency, and I'm worried about "
|
| 201 |
+
"your safety right now.",
|
| 202 |
+
connector="Right now, please",
|
| 203 |
+
),
|
| 204 |
}
|
| 205 |
+
_DEFAULT_VOICE = dict(
|
| 206 |
+
opener="Thank you for trusting me with this. Whatever you're going through, "
|
| 207 |
+
"you don't have to face it alone.",
|
| 208 |
+
connector="It could help to",
|
| 209 |
+
)
|
| 210 |
+
# always-on safety line for higher tiers, regardless of what JSON fields exist
|
| 211 |
+
_SAFETY_LINE = ("And if you're ever in immediate danger, please call your local "
|
| 212 |
+
"emergency number, or reach out to a crisis line right away.")
|
| 213 |
+
|
| 214 |
+
|
| 215 |
+
def _lowercase_lead(s: str) -> str:
|
| 216 |
+
"""Lowercase a sentence's first letter so it reads naturally mid-sentence."""
|
| 217 |
+
return s[:1].lower() + s[1:] if s else s
|
| 218 |
+
|
| 219 |
+
|
| 220 |
+
def _strip_trailing_period(s: str) -> str:
|
| 221 |
+
return s[:-1] if s.endswith(".") else s
|
| 222 |
|
| 223 |
|
| 224 |
def _build_summary(parsed: dict) -> str:
|
| 225 |
+
"""Compose a warm, conversational, tier-aware spoken triage summary.
|
| 226 |
|
| 227 |
+
Written for a synthetic chain-of-thought triage adapter: it talks to the person
|
| 228 |
+
the way a caring listener would, folds in one concrete next step as part of the
|
| 229 |
+
same flowing sentence rather than a labeled clause, and always closes high-risk
|
| 230 |
+
tiers with a safety line -- even when the model drifts off-schema.
|
| 231 |
+
Prefers the trained `plain_language_summary` verbatim when present.
|
| 232 |
"""
|
| 233 |
if not isinstance(parsed, dict):
|
| 234 |
return ""
|
|
|
|
| 238 |
return direct.strip()
|
| 239 |
|
| 240 |
tier = _normalize_tier(parsed.get("risk_tier"))
|
| 241 |
+
voice = _TIER_VOICE.get(tier, _DEFAULT_VOICE)
|
| 242 |
+
sentence = voice["opener"]
|
| 243 |
|
| 244 |
+
# fold one concrete next step into the same breath as the opener, instead of
|
| 245 |
+
# a separate labeled sentence
|
| 246 |
for key in ("recommended_next_step", "action_steps", "resources",
|
| 247 |
"clinical_rationale", "risk_factors"):
|
| 248 |
action = _first_text(parsed.get(key))
|
| 249 |
if action:
|
| 250 |
+
action = _strip_trailing_period(_lowercase_lead(action.strip()))
|
| 251 |
+
sentence = f"{sentence} {voice['connector']} {action}."
|
|
|
|
| 252 |
break
|
| 253 |
|
| 254 |
escalate = (parsed.get("escalation_required") in (True, "true", "True", "yes", 1)
|
| 255 |
or (tier is not None and tier >= 2))
|
| 256 |
if escalate:
|
| 257 |
+
sentence = f"{sentence} {_SAFETY_LINE}"
|
| 258 |
|
| 259 |
+
return sentence.strip()
|
| 260 |
|
| 261 |
|
| 262 |
def _synthesize(text: str) -> tuple[int, np.ndarray]:
|