NathanPereira commited on
Commit
fceddd1
·
verified ·
1 Parent(s): 9717175

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +54 -28
app.py CHANGED
@@ -178,32 +178,57 @@ def _first_text(value) -> str:
178
  return ""
179
 
180
 
181
- # tier-aware, safety-first openers spoken to the person, not clinical labels
182
- _TIER_OPENERS = {
183
- 0: "Based on what you shared, this doesn't show signs of immediate crisis. "
184
- "It's still good to keep an eye on how you're feeling.",
185
- 1: "What you shared suggests some distress that's worth attending to. "
186
- "You don't have to handle this alone.",
187
- 2: "This sounds serious, and your safety matters. "
188
- "Please consider reaching out for support right away.",
189
- 3: "This sounds like an emergency and your safety is the priority right now. "
190
- "Please get help immediately.",
 
 
 
 
 
 
 
 
 
 
 
 
 
191
  }
192
- _DEFAULT_OPENER = ("Thank you for sharing this. Your wellbeing matters, "
193
- "and support is available if you need it.")
194
- # spoken safety line for the higher tiers, regardless of what JSON fields exist
195
- _SAFETY_LINE = ("If you are in immediate danger, call your local emergency number now, "
196
- "or contact a crisis line such as 988 in the US.")
 
 
 
 
 
 
 
 
 
 
 
 
197
 
198
 
199
  def _build_summary(parsed: dict) -> str:
200
- """Compose a calm, tier-aware spoken triage summary.
201
 
202
- Designed for a synthetic chain-of-thought triage adapter: it speaks to the
203
- person (supportive, non-clinical), states severity in plain language, offers
204
- one concrete next step pulled from whatever fields exist, and always adds a
205
- safety line for high/critical tiers -- even when the model drifts off-schema.
206
- Prefers the trained `plain_language_summary` verbatim when it is present.
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
- parts = [_TIER_OPENERS.get(tier, _DEFAULT_OPENER)]
 
217
 
218
- # one concrete, human next step from the most useful field available
 
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
- if not action.endswith((".", "!", "?")):
224
- action += "."
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
- parts.append(_SAFETY_LINE)
232
 
233
- return " ".join(p.strip() for p in parts if p and p.strip())
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]: