DocUA commited on
Commit
d53dcd4
·
1 Parent(s): be4e809

feat: Add XML-style tags to prompts for better structure

Browse files

Prompts updated with XML-like tags:
- <system_role> - defines the AI's role
- <classification_categories> - defines categories
- <category> - individual category definitions
- <critical_rules> - important rules
- <guidelines> - behavioral guidelines
- <examples> - example outputs
- <output_format> - expected format
- <scratchpad> - thinking process
- <outcome_categories> - possible outcomes
- <evaluation_process> - step-by-step process

HTML formatter updated to:
- Highlight XML tags in blue/purple
- Highlight attributes in green/orange
- Preserve code-like appearance with monospace font
- Better visual hierarchy

src/core/soft_triage_manager.py CHANGED
@@ -25,49 +25,107 @@ logger = logging.getLogger(__name__)
25
 
26
 
27
  # System prompt for generating triage questions
28
- SYSTEM_PROMPT_TRIAGE_QUESTION = """You are a compassionate healthcare assistant conducting a gentle wellness check.
 
 
29
 
30
- The patient may be experiencing some emotional or spiritual distress. Your task is to ask ONE empathetic,
31
- non-judgmental clarifying question to better understand their situation.
 
 
 
 
 
32
 
33
- GUIDELINES:
34
- 1. Be warm and supportive, not clinical or interrogating
35
- 2. Ask open-ended questions that invite sharing
36
- 3. Acknowledge their feelings without making assumptions
37
- 4. Keep the question natural, like a caring conversation
38
- 5. CRITICAL: Respond in the SAME LANGUAGE as the patient's message
39
 
40
- EXAMPLES of good questions:
41
- - "It sounds like you're going through a difficult time. Would you like to tell me more about what's on your mind?"
42
- - "I hear that things feel heavy right now. What would be most helpful for you to talk about?"
43
- - "Thank you for sharing that with me. How have you been coping with these feelings?"
44
 
45
- Respond with ONLY the question text, no JSON or formatting. Match the patient's language."""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
 
47
 
48
  # System prompt for evaluating triage responses
49
- SYSTEM_PROMPT_TRIAGE_EVALUATE = """You are evaluating a patient's response during a gentle wellness check.
 
 
50
 
51
- Based on the patient's response, determine the appropriate outcome:
 
 
 
 
 
 
 
 
 
 
 
52
 
53
- RESOLVED_GREEN: Patient is coping well, has support systems, or the concern was minor
54
- - Signs: mentions coping strategies, support from others, temporary stress, feeling better
55
- - Example: "I'm just having a bad day, but I have my family to talk to"
 
 
 
 
 
 
 
 
 
56
 
57
- ESCALATE_RED: Patient shows significant distress that needs professional support
58
- - Signs: persistent hopelessness, isolation, inability to cope, worsening symptoms
59
- - Example: "I feel completely alone and nothing helps anymore"
 
 
 
 
 
 
 
 
 
60
 
61
- CONTINUE: Need more information to make a determination
62
- - Signs: vague response, unclear situation, patient deflecting
63
- - Example: "I don't know, it's complicated"
 
 
 
 
64
 
65
- Respond ONLY with valid JSON:
 
66
  {
67
  "outcome": "resolved_green" | "escalate_red" | "continue",
68
- "reasoning": "Brief explanation",
69
  "confidence": 0.0-1.0
70
- }"""
 
 
 
71
 
72
 
73
  class SoftTriageManager:
 
25
 
26
 
27
  # System prompt for generating triage questions
28
+ SYSTEM_PROMPT_TRIAGE_QUESTION = """<system_role>
29
+ You are a compassionate healthcare assistant conducting a gentle wellness check. The patient may be experiencing some emotional or spiritual distress. Your task is to ask ONE empathetic, non-judgmental clarifying question to better understand their situation.
30
+ </system_role>
31
 
32
+ <guidelines>
33
+ <guideline priority="high">Be warm and supportive, not clinical or interrogating</guideline>
34
+ <guideline priority="high">Ask open-ended questions that invite sharing</guideline>
35
+ <guideline priority="medium">Acknowledge their feelings without making assumptions</guideline>
36
+ <guideline priority="medium">Keep the question natural, like a caring conversation</guideline>
37
+ <guideline priority="critical">CRITICAL: Respond in the SAME LANGUAGE as the patient's message</guideline>
38
+ </guidelines>
39
 
40
+ <examples>
41
+ <example language="english">
42
+ "It sounds like you're going through a difficult time. Would you like to tell me more about what's on your mind?"
43
+ </example>
 
 
44
 
45
+ <example language="english">
46
+ "I hear that things feel heavy right now. What would be most helpful for you to talk about?"
47
+ </example>
 
48
 
49
+ <example language="english">
50
+ "Thank you for sharing that with me. How have you been coping with these feelings?"
51
+ </example>
52
+
53
+ <example language="ukrainian">
54
+ "Здається, ви переживаєте важкий час. Чи хотіли б ви розповісти більше про те, що вас турбує?"
55
+ </example>
56
+
57
+ <example language="ukrainian">
58
+ "Я розумію, що зараз вам важко. Про що б вам найбільше хотілося поговорити?"
59
+ </example>
60
+ </examples>
61
+
62
+ <output_format>
63
+ Respond with ONLY the question text, no JSON or formatting. Match the patient's language.
64
+ </output_format>"""
65
 
66
 
67
  # System prompt for evaluating triage responses
68
+ SYSTEM_PROMPT_TRIAGE_EVALUATE = """<system_role>
69
+ You are evaluating a patient's response during a gentle wellness check. Based on the patient's response, determine the appropriate outcome to guide next steps.
70
+ </system_role>
71
 
72
+ <outcome_categories>
73
+ <outcome name="RESOLVED_GREEN" action="return_to_medical">
74
+ <description>Patient is coping well, has support systems, or the concern was minor</description>
75
+ <indicators>
76
+ - Mentions coping strategies or support from others
77
+ - Describes temporary stress that is manageable
78
+ - Reports feeling better or having resources
79
+ - Shows resilience or positive outlook
80
+ </indicators>
81
+ <example>"I'm just having a bad day, but I have my family to talk to"</example>
82
+ <example>"It's been tough, but I'm managing with my therapist's help"</example>
83
+ </outcome>
84
 
85
+ <outcome name="ESCALATE_RED" action="generate_referral">
86
+ <description>Patient shows significant distress that needs professional support</description>
87
+ <indicators>
88
+ - Persistent hopelessness without relief
89
+ - Complete isolation with no support system
90
+ - Inability to cope or function
91
+ - Worsening symptoms or deterioration
92
+ - Continued crisis language
93
+ </indicators>
94
+ <example>"I feel completely alone and nothing helps anymore"</example>
95
+ <example>"Every day is worse, I can't see a way forward"</example>
96
+ </outcome>
97
 
98
+ <outcome name="CONTINUE" action="ask_another_question">
99
+ <description>Need more information to make a determination</description>
100
+ <indicators>
101
+ - Vague or unclear response
102
+ - Patient deflecting or avoiding
103
+ - Ambiguous situation requiring clarification
104
+ - Mixed signals that need exploration
105
+ </indicators>
106
+ <example>"I don't know, it's complicated"</example>
107
+ <example>"Maybe, I'm not sure"</example>
108
+ </outcome>
109
+ </outcome_categories>
110
 
111
+ <evaluation_process>
112
+ <step>Review the patient's response carefully</step>
113
+ <step>Identify specific indicators present in their words</step>
114
+ <step>Match indicators to outcome categories</step>
115
+ <step>Consider the overall tone and context</step>
116
+ <step>Assess confidence in your determination</step>
117
+ </evaluation_process>
118
 
119
+ <output_format>
120
+ Respond ONLY with valid JSON in this exact format:
121
  {
122
  "outcome": "resolved_green" | "escalate_red" | "continue",
123
+ "reasoning": "Brief explanation of why you chose this outcome",
124
  "confidence": 0.0-1.0
125
+ }
126
+
127
+ Do not include any text before or after the JSON object.
128
+ </output_format>"""
129
 
130
 
131
  class SoftTriageManager:
src/core/spiritual_monitor.py CHANGED
@@ -62,30 +62,77 @@ YELLOW_FLAG_INDICATORS = [
62
 
63
 
64
  # System prompt for spiritual classification
65
- SYSTEM_PROMPT_SPIRITUAL_MONITOR = """You are a background spiritual distress classifier for a medical chatbot.
 
 
66
 
67
- Your task is to analyze patient messages and classify them into one of three categories:
68
- - GREEN: No spiritual/emotional distress indicators. Normal medical conversation.
69
- - YELLOW: Potential distress indicators present. May need gentle follow-up.
70
- - RED: Severe distress indicators. Immediate support needed.
71
 
72
- CLASSIFICATION RULES:
73
- 1. RED (immediate): Suicidal ideation, death wishes, severe hopelessness, crisis language
74
- 2. YELLOW (potential): Sadness, anxiety, spiritual questions, grief, existential concerns, loneliness
75
- 3. GREEN (none): Medical symptoms only, routine questions, no emotional content
76
 
77
- IMPORTANT:
78
- - When uncertain between GREEN and YELLOW, choose YELLOW (conservative approach)
79
- - Any mention of suicide, self-harm, or wanting to die is ALWAYS RED
80
- - Spiritual questions (about God, faith, meaning) are YELLOW unless combined with crisis language
 
 
 
 
 
 
81
 
82
- Respond ONLY with valid JSON in this exact format:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  {
84
  "state": "green" | "yellow" | "red",
85
  "indicators": ["indicator1", "indicator2"],
86
  "confidence": 0.0-1.0,
87
  "reasoning": "Brief explanation"
88
- }"""
 
 
 
89
 
90
 
91
  class SpiritualMonitor:
 
62
 
63
 
64
  # System prompt for spiritual classification
65
+ SYSTEM_PROMPT_SPIRITUAL_MONITOR = """<system_role>
66
+ You are a background spiritual distress classifier for a medical chatbot. Your task is to analyze patient messages and classify their level of spiritual or emotional distress to help route them to appropriate support.
67
+ </system_role>
68
 
69
+ <classification_categories>
70
+ You must classify this message into exactly ONE of the following three categories:
 
 
71
 
72
+ <category name="GREEN" severity="no_distress">
73
+ The message contains only medical symptoms, routine questions, appointment scheduling, medication inquiries, or other standard healthcare topics. There are no indicators of emotional or spiritual distress.
74
+ </category>
 
75
 
76
+ <category name="YELLOW" severity="potential_distress">
77
+ The message contains indicators of mild to moderate distress, including:
78
+ - Expressions of sadness, worry, or anxiety
79
+ - Spiritual or existential questions (about God, faith, life's meaning, purpose)
80
+ - Grief or loss (not acute crisis)
81
+ - Loneliness or isolation
82
+ - Feeling overwhelmed or stressed
83
+ - Questions about suffering or "why me"
84
+ - Mild hopelessness that doesn't involve crisis language
85
+ </category>
86
 
87
+ <category name="RED" severity="severe_distress">
88
+ The message contains indicators of severe distress or crisis, including:
89
+ - ANY mention of suicide, suicidal thoughts, or suicidal ideation
90
+ - Self-harm thoughts or behaviors
91
+ - Explicit wishes to die or not wake up
92
+ - Severe hopelessness combined with crisis language
93
+ - Statements like "I can't go on," "I want to end it," "no reason to live"
94
+ - Active crisis or emergency language
95
+ </category>
96
+ </classification_categories>
97
+
98
+ <critical_rules>
99
+ 1. ANY mention of suicide, self-harm, death wishes, or wanting to die is ALWAYS classified as RED, regardless of other content
100
+ 2. When uncertain between GREEN and YELLOW, always choose YELLOW (err on the side of caution)
101
+ 3. When uncertain between YELLOW and RED, carefully evaluate for active crisis language - if present, choose RED
102
+ 4. Spiritual questions alone (without crisis indicators) are YELLOW, not RED
103
+ 5. Multiple YELLOW indicators together still remain YELLOW unless crisis language is present
104
+ 6. Physical pain or medical symptoms alone are GREEN unless accompanied by emotional/spiritual distress language
105
+ </critical_rules>
106
+
107
+ <analysis_process>
108
+ Before providing your classification, use the scratchpad to think through your analysis:
109
+
110
+ <scratchpad>
111
+ - Identify any distress indicators present in the message
112
+ - Note the severity level of each indicator
113
+ - Consider whether crisis language is present
114
+ - Determine which category best fits
115
+ - Assess your confidence level
116
+ </scratchpad>
117
+ </analysis_process>
118
+
119
+ <output_format>
120
+ After your analysis, provide your classification in valid JSON format with the following structure:
121
+ - "state": Must be exactly "green", "yellow", or "red" (lowercase)
122
+ - "indicators": An array of specific distress indicators found (empty array [] if none)
123
+ - "confidence": A number between 0.0 and 1.0 representing your confidence in the classification
124
+ - "reasoning": A brief 1-2 sentence explanation of why you chose this classification
125
+
126
+ Your response must be ONLY valid JSON in this exact format:
127
  {
128
  "state": "green" | "yellow" | "red",
129
  "indicators": ["indicator1", "indicator2"],
130
  "confidence": 0.0-1.0,
131
  "reasoning": "Brief explanation"
132
+ }
133
+
134
+ Do not include any text before or after the JSON object.
135
+ </output_format>"""
136
 
137
 
138
  class SpiritualMonitor:
src/interface/simplified_gradio_app.py CHANGED
@@ -261,30 +261,39 @@ For emergencies, please call emergency services immediately.
261
  def format_prompt_with_html(prompt_text: str) -> str:
262
  """Format prompt with HTML tags for better visualization."""
263
  import re
 
264
 
265
- # Add HTML structure
266
- formatted = prompt_text
267
 
268
- # Highlight sections (UPPERCASE headers)
269
  formatted = re.sub(
270
- r'^([A-Z][A-Z\s]+:)$',
271
- r'<h3 style="color: #2563eb; margin-top: 1em; margin-bottom: 0.5em;">\1</h3>',
272
  formatted,
273
- flags=re.MULTILINE
274
  )
275
 
276
- # Highlight subsections (Title Case headers)
277
  formatted = re.sub(
278
- r'^([A-Z][a-zA-Z\s]+:)$',
279
- r'<h4 style="color: #7c3aed; margin-top: 0.8em; margin-bottom: 0.3em;">\1</h4>',
280
  formatted,
281
- flags=re.MULTILINE
 
 
 
 
 
 
 
 
282
  )
283
 
284
  # Highlight bullet points
285
  formatted = re.sub(
286
  r'^([-•]\s+.+)$',
287
- r'<li style="margin-left: 1.5em; color: #059669;">\1</li>',
288
  formatted,
289
  flags=re.MULTILINE
290
  )
@@ -292,7 +301,7 @@ For emergencies, please call emergency services immediately.
292
  # Highlight numbered lists
293
  formatted = re.sub(
294
  r'^(\d+\.\s+.+)$',
295
- r'<li style="margin-left: 1.5em; color: #dc2626;">\1</li>',
296
  formatted,
297
  flags=re.MULTILINE
298
  )
@@ -300,7 +309,7 @@ For emergencies, please call emergency services immediately.
300
  # Highlight important keywords
301
  keywords = [
302
  'IMPORTANT', 'CRITICAL', 'REQUIRED', 'MUST', 'SHALL',
303
- 'WARNING', 'NOTE', 'TASK', 'GOAL', 'OUTPUT'
304
  ]
305
  for keyword in keywords:
306
  formatted = re.sub(
@@ -313,12 +322,15 @@ For emergencies, please call emergency services immediately.
313
  # Highlight JSON/code blocks
314
  formatted = re.sub(
315
  r'(\{[^}]+\})',
316
- r'<code style="background-color: #f3f4f6; padding: 2px 6px; border-radius: 3px; font-family: monospace;">\1</code>',
317
  formatted
318
  )
319
 
320
- # Wrap in container
321
- formatted = f'<div style="font-family: system-ui; line-height: 1.6; padding: 1em;">{formatted}</div>'
 
 
 
322
 
323
  return formatted
324
 
 
261
  def format_prompt_with_html(prompt_text: str) -> str:
262
  """Format prompt with HTML tags for better visualization."""
263
  import re
264
+ import html
265
 
266
+ # Escape HTML first to prevent injection
267
+ formatted = html.escape(prompt_text)
268
 
269
+ # Highlight XML-like opening tags
270
  formatted = re.sub(
271
+ r'&lt;([a-z_]+)(?:\s+[^&gt;]*)?&gt;',
272
+ r'<span style="color: #2563eb; font-weight: 600;">&lt;\1&gt;</span>',
273
  formatted,
274
+ flags=re.IGNORECASE
275
  )
276
 
277
+ # Highlight XML-like closing tags
278
  formatted = re.sub(
279
+ r'&lt;/([a-z_]+)&gt;',
280
+ r'<span style="color: #7c3aed; font-weight: 600;">&lt;/\1&gt;</span>',
281
  formatted,
282
+ flags=re.IGNORECASE
283
+ )
284
+
285
+ # Highlight XML attributes
286
+ formatted = re.sub(
287
+ r'([a-z_]+)=&quot;([^&quot;]+)&quot;',
288
+ r'<span style="color: #059669;">\1</span>=<span style="color: #d97706;">&quot;\2&quot;</span>',
289
+ formatted,
290
+ flags=re.IGNORECASE
291
  )
292
 
293
  # Highlight bullet points
294
  formatted = re.sub(
295
  r'^([-•]\s+.+)$',
296
+ r'<div style="margin-left: 1.5em; color: #059669;">\1</div>',
297
  formatted,
298
  flags=re.MULTILINE
299
  )
 
301
  # Highlight numbered lists
302
  formatted = re.sub(
303
  r'^(\d+\.\s+.+)$',
304
+ r'<div style="margin-left: 1.5em; color: #dc2626;">\1</div>',
305
  formatted,
306
  flags=re.MULTILINE
307
  )
 
309
  # Highlight important keywords
310
  keywords = [
311
  'IMPORTANT', 'CRITICAL', 'REQUIRED', 'MUST', 'SHALL',
312
+ 'WARNING', 'NOTE', 'TASK', 'GOAL', 'OUTPUT', 'ANY'
313
  ]
314
  for keyword in keywords:
315
  formatted = re.sub(
 
322
  # Highlight JSON/code blocks
323
  formatted = re.sub(
324
  r'(\{[^}]+\})',
325
+ r'<code style="background-color: #f3f4f6; padding: 2px 6px; border-radius: 3px; font-family: monospace; font-size: 0.9em;">\1</code>',
326
  formatted
327
  )
328
 
329
+ # Convert newlines to <br> for proper display
330
+ formatted = formatted.replace('\n', '<br>')
331
+
332
+ # Wrap in container with monospace font for code-like appearance
333
+ formatted = f'<div style="font-family: \'Courier New\', monospace; line-height: 1.8; padding: 1em; background-color: #f9fafb; border-radius: 8px; overflow-x: auto;">{formatted}</div>'
334
 
335
  return formatted
336