Spaces:
Sleeping
Sleeping
feat: Add HTML formatting for prompt visualization
Browse files- Added format_prompt_with_html() function
- Highlights sections with colored headers
- Highlights keywords (IMPORTANT, CRITICAL, etc.)
- Highlights bullet points and numbered lists
- Highlights JSON/code blocks
- Styled status messages with colored boxes
- Better visual hierarchy for prompt structure
src/interface/simplified_gradio_app.py
CHANGED
|
@@ -171,25 +171,31 @@ def create_simplified_interface():
|
|
| 171 |
apply_prompt_btn = gr.Button("β
Apply Changes", variant="primary", scale=2)
|
| 172 |
reset_prompt_btn = gr.Button("π Reset to Default", variant="secondary", scale=1)
|
| 173 |
|
| 174 |
-
prompt_status = gr.
|
| 175 |
|
| 176 |
with gr.Column(scale=1):
|
| 177 |
gr.Markdown("### π Prompt Info")
|
| 178 |
-
prompt_info_display = gr.
|
| 179 |
-
|
|
|
|
| 180 |
|
| 181 |
-
Available prompts
|
| 182 |
-
-
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
|
| 186 |
-
|
|
|
|
|
|
|
| 187 |
|
| 188 |
-
|
| 189 |
-
-
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
|
|
|
|
|
|
|
|
|
| 193 |
""")
|
| 194 |
|
| 195 |
# Instructions tab
|
|
@@ -252,6 +258,70 @@ For emergencies, please call emergency services immediately.
|
|
| 252 |
return handle_message(example_text, history, session)
|
| 253 |
|
| 254 |
# Prompt editing handlers
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 255 |
def load_prompt(prompt_name: str):
|
| 256 |
"""Load selected prompt for editing."""
|
| 257 |
from src.core.spiritual_monitor import SYSTEM_PROMPT_SPIRITUAL_MONITOR
|
|
@@ -274,15 +344,29 @@ For emergencies, please call emergency services immediately.
|
|
| 274 |
|
| 275 |
prompt_text = prompts.get(prompt_name, "")
|
| 276 |
|
|
|
|
|
|
|
|
|
|
| 277 |
info = f"""**Loaded:** {prompt_name}
|
| 278 |
|
| 279 |
**Length:** {len(prompt_text)} characters
|
| 280 |
**Lines:** {len(prompt_text.split(chr(10)))} lines
|
| 281 |
|
| 282 |
**Status:** Ready to edit
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 283 |
"""
|
| 284 |
|
| 285 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 286 |
|
| 287 |
def apply_prompt_changes(prompt_name: str, prompt_text: str, session: SimplifiedSessionData):
|
| 288 |
"""Apply custom prompt changes."""
|
|
@@ -290,7 +374,11 @@ For emergencies, please call emergency services immediately.
|
|
| 290 |
session = SimplifiedSessionData()
|
| 291 |
|
| 292 |
if not prompt_text.strip():
|
| 293 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 294 |
|
| 295 |
# Store custom prompt in session
|
| 296 |
if not hasattr(session, 'custom_prompts'):
|
|
@@ -317,19 +405,27 @@ For emergencies, please call emergency services immediately.
|
|
| 317 |
import src.config.prompts as p
|
| 318 |
p.SYSTEM_PROMPT_SOFT_MEDICAL_TRIAGE = prompt_text
|
| 319 |
|
| 320 |
-
status = f"""
|
|
|
|
| 321 |
|
| 322 |
-
|
| 323 |
-
|
| 324 |
-
|
| 325 |
|
| 326 |
-
|
| 327 |
-
|
|
|
|
|
|
|
|
|
|
| 328 |
|
| 329 |
return status, session
|
| 330 |
|
| 331 |
except Exception as e:
|
| 332 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 333 |
|
| 334 |
def reset_prompt(prompt_name: str, session: SimplifiedSessionData):
|
| 335 |
"""Reset prompt to default."""
|
|
@@ -346,7 +442,12 @@ To revert, use "Reset to Default" button."""
|
|
| 346 |
# Reapply default
|
| 347 |
apply_status, session = apply_prompt_changes(prompt_name, prompt_text, session)
|
| 348 |
|
| 349 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 350 |
|
| 351 |
# Bind events
|
| 352 |
demo.load(
|
|
|
|
| 171 |
apply_prompt_btn = gr.Button("β
Apply Changes", variant="primary", scale=2)
|
| 172 |
reset_prompt_btn = gr.Button("π Reset to Default", variant="secondary", scale=1)
|
| 173 |
|
| 174 |
+
prompt_status = gr.HTML(value="", visible=True)
|
| 175 |
|
| 176 |
with gr.Column(scale=1):
|
| 177 |
gr.Markdown("### π Prompt Info")
|
| 178 |
+
prompt_info_display = gr.HTML(value="""
|
| 179 |
+
<div style="font-family: system-ui; padding: 1em; background-color: #f9fafb; border-radius: 8px;">
|
| 180 |
+
<p><strong>Select a prompt to edit</strong></p>
|
| 181 |
|
| 182 |
+
<p><strong>Available prompts:</strong></p>
|
| 183 |
+
<ul style="margin-left: 1em;">
|
| 184 |
+
<li>π Spiritual Monitor</li>
|
| 185 |
+
<li>π‘ Triage Questions</li>
|
| 186 |
+
<li>π Triage Evaluation</li>
|
| 187 |
+
<li>π₯ Medical Assistant</li>
|
| 188 |
+
<li>π©Ί Soft Triage</li>
|
| 189 |
+
</ul>
|
| 190 |
|
| 191 |
+
<p><strong>Tips:</strong></p>
|
| 192 |
+
<ul style="margin-left: 1em;">
|
| 193 |
+
<li>Load prompt first</li>
|
| 194 |
+
<li>Edit carefully</li>
|
| 195 |
+
<li>Test changes</li>
|
| 196 |
+
<li>Reset if needed</li>
|
| 197 |
+
</ul>
|
| 198 |
+
</div>
|
| 199 |
""")
|
| 200 |
|
| 201 |
# Instructions tab
|
|
|
|
| 258 |
return handle_message(example_text, history, session)
|
| 259 |
|
| 260 |
# Prompt editing handlers
|
| 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 |
+
)
|
| 291 |
+
|
| 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 |
+
)
|
| 299 |
+
|
| 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(
|
| 307 |
+
f'\\b({keyword})\\b',
|
| 308 |
+
r'<strong style="color: #dc2626; background-color: #fef2f2; padding: 2px 4px; border-radius: 3px;">\1</strong>',
|
| 309 |
+
formatted,
|
| 310 |
+
flags=re.IGNORECASE
|
| 311 |
+
)
|
| 312 |
+
|
| 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 |
+
|
| 325 |
def load_prompt(prompt_name: str):
|
| 326 |
"""Load selected prompt for editing."""
|
| 327 |
from src.core.spiritual_monitor import SYSTEM_PROMPT_SPIRITUAL_MONITOR
|
|
|
|
| 344 |
|
| 345 |
prompt_text = prompts.get(prompt_name, "")
|
| 346 |
|
| 347 |
+
# Format with HTML for display
|
| 348 |
+
formatted_html = format_prompt_with_html(prompt_text)
|
| 349 |
+
|
| 350 |
info = f"""**Loaded:** {prompt_name}
|
| 351 |
|
| 352 |
**Length:** {len(prompt_text)} characters
|
| 353 |
**Lines:** {len(prompt_text.split(chr(10)))} lines
|
| 354 |
|
| 355 |
**Status:** Ready to edit
|
| 356 |
+
|
| 357 |
+
---
|
| 358 |
+
|
| 359 |
+
### π Formatted Preview:
|
| 360 |
+
|
| 361 |
+
{formatted_html}
|
| 362 |
"""
|
| 363 |
|
| 364 |
+
load_status = """<div style="padding: 1em; background-color: #ecfdf5; border-left: 4px solid #10b981; border-radius: 4px;">
|
| 365 |
+
<h4 style="color: #059669; margin-top: 0;">β
Prompt Loaded</h4>
|
| 366 |
+
<p style="margin-bottom: 0;">Ready to edit. Make your changes and click "Apply Changes".</p>
|
| 367 |
+
</div>"""
|
| 368 |
+
|
| 369 |
+
return prompt_text, info, load_status
|
| 370 |
|
| 371 |
def apply_prompt_changes(prompt_name: str, prompt_text: str, session: SimplifiedSessionData):
|
| 372 |
"""Apply custom prompt changes."""
|
|
|
|
| 374 |
session = SimplifiedSessionData()
|
| 375 |
|
| 376 |
if not prompt_text.strip():
|
| 377 |
+
error_html = """<div style="padding: 1em; background-color: #fef2f2; border-left: 4px solid #dc2626; border-radius: 4px;">
|
| 378 |
+
<h4 style="color: #dc2626; margin-top: 0;">β Error</h4>
|
| 379 |
+
<p style="margin-bottom: 0;">Prompt cannot be empty</p>
|
| 380 |
+
</div>"""
|
| 381 |
+
return error_html, session
|
| 382 |
|
| 383 |
# Store custom prompt in session
|
| 384 |
if not hasattr(session, 'custom_prompts'):
|
|
|
|
| 405 |
import src.config.prompts as p
|
| 406 |
p.SYSTEM_PROMPT_SOFT_MEDICAL_TRIAGE = prompt_text
|
| 407 |
|
| 408 |
+
status = f"""<div style="padding: 1em; background-color: #ecfdf5; border-left: 4px solid #10b981; border-radius: 4px;">
|
| 409 |
+
<h4 style="color: #059669; margin-top: 0;">β
Prompt Applied Successfully</h4>
|
| 410 |
|
| 411 |
+
<p><strong>Prompt:</strong> {prompt_name}</p>
|
| 412 |
+
<p><strong>Length:</strong> {len(prompt_text)} characters</p>
|
| 413 |
+
<p><strong>Session:</strong> <code>{session.session_id[:8]}...</code></p>
|
| 414 |
|
| 415 |
+
<p style="color: #d97706; margin-bottom: 0;">
|
| 416 |
+
β οΈ <strong>Note:</strong> Changes are active for this session only.
|
| 417 |
+
To revert, use "Reset to Default" button.
|
| 418 |
+
</p>
|
| 419 |
+
</div>"""
|
| 420 |
|
| 421 |
return status, session
|
| 422 |
|
| 423 |
except Exception as e:
|
| 424 |
+
error_html = f"""<div style="padding: 1em; background-color: #fef2f2; border-left: 4px solid #dc2626; border-radius: 4px;">
|
| 425 |
+
<h4 style="color: #dc2626; margin-top: 0;">β Error Applying Prompt</h4>
|
| 426 |
+
<p style="margin-bottom: 0;"><code>{str(e)}</code></p>
|
| 427 |
+
</div>"""
|
| 428 |
+
return error_html, session
|
| 429 |
|
| 430 |
def reset_prompt(prompt_name: str, session: SimplifiedSessionData):
|
| 431 |
"""Reset prompt to default."""
|
|
|
|
| 442 |
# Reapply default
|
| 443 |
apply_status, session = apply_prompt_changes(prompt_name, prompt_text, session)
|
| 444 |
|
| 445 |
+
reset_status = """<div style="padding: 1em; background-color: #eff6ff; border-left: 4px solid #3b82f6; border-radius: 4px;">
|
| 446 |
+
<h4 style="color: #2563eb; margin-top: 0;">π Reset to Default</h4>
|
| 447 |
+
<p style="margin-bottom: 0;">Prompt has been restored to its original version.</p>
|
| 448 |
+
</div>"""
|
| 449 |
+
|
| 450 |
+
return prompt_text, info, reset_status, session
|
| 451 |
|
| 452 |
# Bind events
|
| 453 |
demo.load(
|