Spaces:
Sleeping
Sleeping
Updated the PROMPT_ENTRY_CLASSIFIER function to simplify query formation without clinical context. Added easy logging for dynamic queries in the EnhancedMainLifestyleAssistant class, including markers for successful use and Fallback. Fixed time formatting to UTC in the EntryClassifier class. Removed unnecessary comments and improved code structure.
Browse files- prompts.py +3 -8
- src/core/ai_client.py +2 -5
- src/core/core_classes.py +36 -3
prompts.py
CHANGED
|
@@ -84,13 +84,8 @@ OUTPUT FORMAT (JSON only):
|
|
| 84 |
# ===== PROMPT FUNCTIONS =====
|
| 85 |
|
| 86 |
def PROMPT_ENTRY_CLASSIFIER(clinical_background, user_message):
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
Active problems: {"; ".join(clinical_background.active_problems[:5]) if clinical_background.active_problems else "none"}
|
| 90 |
-
Current medications: {"; ".join(clinical_background.current_medications[:5]) if clinical_background.current_medications else "none"}
|
| 91 |
-
Critical alerts: {"; ".join(clinical_background.critical_alerts) if clinical_background.critical_alerts else "none"}
|
| 92 |
-
|
| 93 |
-
PATIENT MESSAGE: "{user_message}"
|
| 94 |
|
| 95 |
ANALYSIS REQUIRED:
|
| 96 |
Classify this patient communication and determine the appropriate system mode based on content analysis and safety considerations."""
|
|
@@ -387,4 +382,4 @@ PATIENT'S NEW MESSAGE: "{user_message}"
|
|
| 387 |
ANALYSIS REQUIRED:
|
| 388 |
Analyze the situation and determine the best action for this lifestyle coaching session."""
|
| 389 |
|
| 390 |
-
# ===== DEPRECATED: Old lifestyle assistant prompt =====
|
|
|
|
| 84 |
# ===== PROMPT FUNCTIONS =====
|
| 85 |
|
| 86 |
def PROMPT_ENTRY_CLASSIFIER(clinical_background, user_message):
|
| 87 |
+
"""Build minimal prompt for entry classification without clinical context."""
|
| 88 |
+
return f"""PATIENT MESSAGE: "{user_message}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 89 |
|
| 90 |
ANALYSIS REQUIRED:
|
| 91 |
Classify this patient communication and determine the appropriate system mode based on content analysis and safety considerations."""
|
|
|
|
| 382 |
ANALYSIS REQUIRED:
|
| 383 |
Analyze the situation and determine the best action for this lifestyle coaching session."""
|
| 384 |
|
| 385 |
+
# ===== DEPRECATED: Old lifestyle assistant prompt =====
|
src/core/ai_client.py
CHANGED
|
@@ -143,10 +143,7 @@ class GeminiClient(BaseAIClient):
|
|
| 143 |
):
|
| 144 |
if chunk.text:
|
| 145 |
response_text += chunk.text
|
| 146 |
-
|
| 147 |
-
# Log the interaction
|
| 148 |
-
self._log_interaction(system_prompt, user_prompt, response_text, "gemini")
|
| 149 |
-
|
| 150 |
return response_text
|
| 151 |
|
| 152 |
except Exception as e:
|
|
@@ -441,4 +438,4 @@ if __name__ == "__main__":
|
|
| 441 |
print(f" Test response: {response[:100]}...")
|
| 442 |
|
| 443 |
except Exception as e:
|
| 444 |
-
print(f" Error: {e}")
|
|
|
|
| 143 |
):
|
| 144 |
if chunk.text:
|
| 145 |
response_text += chunk.text
|
| 146 |
+
|
|
|
|
|
|
|
|
|
|
| 147 |
return response_text
|
| 148 |
|
| 149 |
except Exception as e:
|
|
|
|
| 438 |
print(f" Test response: {response[:100]}...")
|
| 439 |
|
| 440 |
except Exception as e:
|
| 441 |
+
print(f" Error: {e}")
|
src/core/core_classes.py
CHANGED
|
@@ -304,6 +304,26 @@ class EnhancedMainLifestyleAssistant:
|
|
| 304 |
self.composition_performance_tracker = FailsafeTracker()
|
| 305 |
print("🔄 Fallback to static prompt mode activated")
|
| 306 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 307 |
# === EXISTING METHODS PRESERVED UNCHANGED ===
|
| 308 |
|
| 309 |
def set_custom_system_prompt(self, custom_prompt: str):
|
|
@@ -358,6 +378,8 @@ class EnhancedMainLifestyleAssistant:
|
|
| 358 |
self.composition_performance_tracker.record_success()
|
| 359 |
if DynamicPromptConfig.DEBUG_MODE:
|
| 360 |
print("🧠 Using dynamically composed prompt")
|
|
|
|
|
|
|
| 361 |
return dynamic_prompt
|
| 362 |
|
| 363 |
except Exception as e:
|
|
@@ -374,6 +396,8 @@ class EnhancedMainLifestyleAssistant:
|
|
| 374 |
attempted = self._should_attempt_dynamic_composition(session_context, lifestyle_profile)
|
| 375 |
if attempted and lifestyle_profile is not None and not isinstance(self.composition_performance_tracker, FailsafeTracker):
|
| 376 |
suffix = f"\n\n[Dynamic Context]\nPatient: {getattr(lifestyle_profile, 'patient_name', 'Пацієнт')}\nMode: static-fallback"
|
|
|
|
|
|
|
| 377 |
return (self.default_system_prompt or "") + suffix
|
| 378 |
return self.default_system_prompt
|
| 379 |
|
|
@@ -465,7 +489,12 @@ class EnhancedMainLifestyleAssistant:
|
|
| 465 |
print(f"✅ Dynamic prompt composed using: {', '.join(assembly_result.components_used)}")
|
| 466 |
if assembly_result.assembly_notes:
|
| 467 |
print(f"📝 Assembly notes: {'; '.join(assembly_result.assembly_notes)}")
|
| 468 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 469 |
return assembly_result.assembled_prompt
|
| 470 |
|
| 471 |
except Exception as e:
|
|
@@ -1149,13 +1178,17 @@ class EntryClassifier:
|
|
| 1149 |
if classification["V"] not in ["on", "off", "hybrid"]:
|
| 1150 |
classification["V"] = "off" # fallback
|
| 1151 |
|
|
|
|
|
|
|
|
|
|
| 1152 |
return classification
|
| 1153 |
except:
|
| 1154 |
from datetime import datetime
|
| 1155 |
return {
|
| 1156 |
"K": "Lifestyle Mode",
|
| 1157 |
"V": "off",
|
| 1158 |
-
|
|
|
|
| 1159 |
}
|
| 1160 |
|
| 1161 |
class TriageExitClassifier:
|
|
@@ -1631,4 +1664,4 @@ __all__ = [
|
|
| 1631 |
'LifestyleSessionManager',
|
| 1632 |
'DynamicPromptSystemMonitor',
|
| 1633 |
'get_enhanced_architecture_summary'
|
| 1634 |
-
]
|
|
|
|
| 304 |
self.composition_performance_tracker = FailsafeTracker()
|
| 305 |
print("🔄 Fallback to static prompt mode activated")
|
| 306 |
|
| 307 |
+
# --- Lightweight logging for dynamic prompt transparency ---
|
| 308 |
+
def _log_dynamic_marker(self, message: str):
|
| 309 |
+
"""Write a short marker to dynamic prompts log when enabled.
|
| 310 |
+
Respects LOG_PROMPTS env var; creates a simple file handler once.
|
| 311 |
+
"""
|
| 312 |
+
try:
|
| 313 |
+
import logging, os
|
| 314 |
+
if os.getenv("LOG_PROMPTS", "false").lower() != "true":
|
| 315 |
+
return
|
| 316 |
+
logger = logging.getLogger("dynamic_prompts")
|
| 317 |
+
if not logger.handlers:
|
| 318 |
+
logger.setLevel(logging.INFO)
|
| 319 |
+
fh = logging.FileHandler('dynamic_prompts.log', encoding='utf-8')
|
| 320 |
+
fh.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))
|
| 321 |
+
logger.addHandler(fh)
|
| 322 |
+
logger.info(message)
|
| 323 |
+
except Exception:
|
| 324 |
+
# Never break flow due to logging
|
| 325 |
+
pass
|
| 326 |
+
|
| 327 |
# === EXISTING METHODS PRESERVED UNCHANGED ===
|
| 328 |
|
| 329 |
def set_custom_system_prompt(self, custom_prompt: str):
|
|
|
|
| 378 |
self.composition_performance_tracker.record_success()
|
| 379 |
if DynamicPromptConfig.DEBUG_MODE:
|
| 380 |
print("🧠 Using dynamically composed prompt")
|
| 381 |
+
# Marker: dynamic prompt successfully used
|
| 382 |
+
self._log_dynamic_marker("[DYNAMIC_PROMPT] used=success")
|
| 383 |
return dynamic_prompt
|
| 384 |
|
| 385 |
except Exception as e:
|
|
|
|
| 396 |
attempted = self._should_attempt_dynamic_composition(session_context, lifestyle_profile)
|
| 397 |
if attempted and lifestyle_profile is not None and not isinstance(self.composition_performance_tracker, FailsafeTracker):
|
| 398 |
suffix = f"\n\n[Dynamic Context]\nPatient: {getattr(lifestyle_profile, 'patient_name', 'Пацієнт')}\nMode: static-fallback"
|
| 399 |
+
# Marker: dynamic attempted but fell back to static
|
| 400 |
+
self._log_dynamic_marker("[DYNAMIC_PROMPT] fallback=static")
|
| 401 |
return (self.default_system_prompt or "") + suffix
|
| 402 |
return self.default_system_prompt
|
| 403 |
|
|
|
|
| 489 |
print(f"✅ Dynamic prompt composed using: {', '.join(assembly_result.components_used)}")
|
| 490 |
if assembly_result.assembly_notes:
|
| 491 |
print(f"📝 Assembly notes: {'; '.join(assembly_result.assembly_notes)}")
|
| 492 |
+
# Minimal marker without PHI
|
| 493 |
+
try:
|
| 494 |
+
comps = ','.join(assembly_result.components_used)
|
| 495 |
+
self._log_dynamic_marker(f"[DYNAMIC_PROMPT] components={comps}")
|
| 496 |
+
except Exception:
|
| 497 |
+
pass
|
| 498 |
return assembly_result.assembled_prompt
|
| 499 |
|
| 500 |
except Exception as e:
|
|
|
|
| 1178 |
if classification["V"] not in ["on", "off", "hybrid"]:
|
| 1179 |
classification["V"] = "off" # fallback
|
| 1180 |
|
| 1181 |
+
# Переважно підставляємо серверний timestamp (UTC), ігноруючи T з LLM
|
| 1182 |
+
from datetime import datetime, timezone
|
| 1183 |
+
classification["T"] = datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")
|
| 1184 |
return classification
|
| 1185 |
except:
|
| 1186 |
from datetime import datetime
|
| 1187 |
return {
|
| 1188 |
"K": "Lifestyle Mode",
|
| 1189 |
"V": "off",
|
| 1190 |
+
# Використовуємо UTC timestamp у fallback
|
| 1191 |
+
"T": datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")
|
| 1192 |
}
|
| 1193 |
|
| 1194 |
class TriageExitClassifier:
|
|
|
|
| 1664 |
'LifestyleSessionManager',
|
| 1665 |
'DynamicPromptSystemMonitor',
|
| 1666 |
'get_enhanced_architecture_summary'
|
| 1667 |
+
]
|