Spaces:
Running
Running
File size: 24,825 Bytes
73c6377 9788643 73c6377 9788643 757414a f73f660 757414a f73f660 757414a 3699d7c 4a17bbc 5021fcb 519ef23 79e52d8 4a17bbc 2c23d2c 79e52d8 519ef23 e42cea3 79e52d8 519ef23 79e52d8 4a17bbc 519ef23 79e52d8 519ef23 79e52d8 4a17bbc 8ff847b 79e52d8 519ef23 79e52d8 4a17bbc 519ef23 79e52d8 519ef23 79e52d8 4a17bbc 519ef23 79e52d8 519ef23 79e52d8 4a17bbc 519ef23 79e52d8 519ef23 79e52d8 4a17bbc 519ef23 79e52d8 519ef23 79e52d8 4a17bbc 88fa08b 2c23d2c 3699d7c 73c6377 4a17bbc 73c6377 3699d7c 73c6377 4a17bbc 73c6377 3699d7c 73c6377 88fa08b 73c6377 4a17bbc e42cea3 73c6377 3699d7c 73c6377 9788643 4a17bbc 5021fcb f73f660 5021fcb 4a17bbc e42cea3 4a17bbc 70b9c9d 4a17bbc 70b9c9d 4a17bbc 70b9c9d 5021fcb 70b9c9d 5021fcb 4a17bbc 5021fcb 4a17bbc 5021fcb 4a17bbc 70b9c9d 4a17bbc e42cea3 4a17bbc 70b9c9d 4a17bbc 70b9c9d 73c6377 3699d7c 73c6377 9788643 73c6377 9788643 73c6377 757414a 73c6377 757414a 73c6377 e42cea3 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 |
"""
HBV Patient Assessment Module
Evaluates patient eligibility for HBV treatment according to SASLT 2021 guidelines
"""
import logging
import json
import re
from typing import Dict, Any
from .config import get_llm
logger = logging.getLogger(__name__)
def clean_json_string(json_str: str) -> str:
"""
Clean a JSON string by properly escaping control characters within string values.
This handles cases where LLMs generate JSON with literal newlines, tabs, etc.
Args:
json_str: Raw JSON string that may contain unescaped control characters
Returns:
Cleaned JSON string with properly escaped control characters
"""
# First, try to identify string values in the JSON and escape control characters within them
# We need to be careful not to break the JSON structure itself
# Replace common control characters that appear in string values
# but preserve the JSON structure (newlines between key-value pairs are OK)
# Strategy: Parse character by character, track if we're inside a string value
result = []
in_string = False
escape_next = False
for i, char in enumerate(json_str):
if escape_next:
result.append(char)
escape_next = False
continue
if char == '\\':
result.append(char)
escape_next = True
continue
if char == '"':
in_string = not in_string
result.append(char)
continue
# If we're inside a string value, escape control characters
if in_string:
if char == '\n':
result.append('\\n')
elif char == '\r':
result.append('\\r')
elif char == '\t':
result.append('\\t')
elif char == '\b':
result.append('\\b')
elif char == '\f':
result.append('\\f')
elif ord(char) < 32: # Other control characters
result.append(f'\\u{ord(char):04x}')
else:
result.append(char)
else:
result.append(char)
return ''.join(result)
def normalize_recommendations(text: str) -> str:
"""
Normalize the recommendations string for concise, consistent formatting.
- Remove extra blank lines
- Trim trailing/leading whitespace on each line
- Add single blank line before section headers for readability
- Optionally cap length to avoid overly long outputs
"""
if not text:
return ""
# Normalize newlines
text = text.replace('\r\n', '\n').replace('\r', '\n')
# Split, strip, and drop empty lines
lines = [ln.strip() for ln in text.split('\n')]
lines = [ln for ln in lines if ln]
# Add spacing before section headers (lines ending with ':')
# but not before the first line
formatted_lines = []
section_headers = [
'Eligibility and Rationale:',
'Treatment Recommendations:',
'Monitoring and Follow-up:',
'Special Considerations:',
'References:'
]
for i, line in enumerate(lines):
# Add blank line before section headers (except first line)
if i > 0 and any(line.startswith(header) for header in section_headers):
formatted_lines.append('') # Add blank line
formatted_lines.append(line)
normalized = '\n'.join(formatted_lines)
# Soft cap length (keep whole content if already short)
max_len = 1800
if len(normalized) > max_len:
normalized = normalized[:max_len].rstrip()
return normalized
# SASLT 2021 Guidelines - Hardcoded Page Contents
SASLT_GUIDELINES = """
===== SASLT 2021 GUIDELINES: TREATMENT & MANAGEMENT =====
### 1. INITIATION OF TREATMENT [SASLT 2021, p. 6]
• Treatment indications should also take into account patient's age, health status, risk of HBV transmission, family history of HCC or cirrhosis and extrahepatic manifestations [SASLT 2021, p. 6]
• All patients with chronic hepatitis B (HBV DNA > 2,000 IU/mL, ALT > ULN), regardless of HBeAg status, and/or at least moderate liver necroinflammation or fibrosis (Grade A) [SASLT 2021, p. 6]
• Patients with cirrhosis (compensated or decompensated), with any detectable HBV DNA level and regardless of ALT levels (Grade A) [SASLT 2021, p. 6]
• Patients with HBV DNA > 20,000 IU/mL and ALT > 2xULN, regardless of the degree of fibrosis (Grade B) [SASLT 2021, p. 6]
• Patients with HBeAg-positive chronic HBV infection (persistently normal ALT and high HBV DNA levels) may be treated if they are > 30 years, regardless of the severity of liver histological lesions (Grade D) [SASLT 2021, p. 6]
• Patients with chronic HBV infection (HBV DNA > 2,000 IU/mL, ALT > ULN), regardless of HBeAg status, and a family history of HCC or cirrhosis and extrahepatic manifestations (Grade D) [SASLT 2021, p. 6]
• Non‑cirrhotic patients should be considered for treatment if they have HBV DNA levels >2,000 IU/mL, serum ALT >~40 IU/L and severity of liver disease assessed by liver biopsy showing at least moderate necroinflammation and/or at least moderate fibrosis.
Patients with HBV DNA greater than 20,000 IU/mL and ALT greater than 2x ULN can begin treatment without a liver biopsy.
Patients with HBV DNA >2,000 IU/mL and at least moderate fibrosis may initiate treatment even if ALT levels are normal.
### 2. MANAGEMENT ALGORITHM [SASLT 2021, p. 6]
• HBsAg positive with chronic HBV infection and no signs of chronic hepatitis → Monitor (HBsAg, HBeAg, HBV DNA, ALT, fibrosis assessment). Consider: risk of HCC, risk of HBV reactivation, extrahepatic manifestations, risk of HBV transmission [SASLT 2021, p. 6]
• CHB (with/without cirrhosis) → Start antiviral treatment if indicated, otherwise return to monitoring [SASLT 2021, p. 6]
• HBsAg negative, anti-HBc positive → No specialist follow-up (inform about HBV reactivation risk). In case of immunosuppression: start oral antiviral prophylaxis or monitor [SASLT 2021, p. 6]
### 3. MONITORING OF UNTREATED PATIENTS [SASLT 2021, p. 6-7]
• Patients with HBeAg-positive chronic HBV infection who are younger than 30 years should be followed at least every 3-6 months (Grade B) [SASLT 2021, p. 7]
• Patients with HBeAg-negative chronic HBV infection and serum HBV DNA <2,000 IU/ml should be followed every 6-12 months (Grade B) [SASLT 2021, p. 7]
• Patients with HBeAg-negative chronic HBV infection and serum HBV DNA ≥2,000 IU/ml should be followed every 3 months for the first year and thereafter every 6 months (Grade D) [SASLT 2021, p. 7]
### 4. CHRONIC HEPATITIS B (CHB) TREATMENT [SASLT 2021, p. 7-8]
• The treatment of choice is the long-term administration of a potent nucleos(t)ide analogue NA with a high barrier to resistance, regardless of the severity of liver disease (Grade A) [SASLT 2021, p. 8]
• Preferred regimens are ETV, TDF and TAF as monotherapies (Grade A) [SASLT 2021, p. 8]
• LAM, ADV and TBV are not recommended in the treatment of CHB (Grade A) [SASLT 2021, p. 8]
• TAF has demonstrated superior renal and bone density safety profiles compared with TDF in head-to-head trials [SASLT 2021, p. 8]
• International guidelines recommend switching individuals at high risk for bone or renal disease from TDF to either TAF or ETV [SASLT 2021, p. 8]
• TAF maintains a better safety profile unless the patient's creatinine clearance (CrCl) is less than 15 mL/minute [SASLT 2021, p. 8]
### 5. HBV-HCV COINFECTION [SASLT 2021, p. 8-9]
• Treatment of HCV through DAAs may lead to reactivation of HBV. Patients who meet the criteria for HBV treatment should be treated concurrently or before initiation of DAA (Grade A) [SASLT 2021, p. 9]
• HBV DNA and ALT should be monitored every four to eight weeks while on DAA and three months after completion of therapy (Grade D) [SASLT 2021, p. 9]
• ALT level should be monitored every four weeks while on DAA for patients who are HBsAg-negative but HBcAb-positive. If ALT starts to rise, HBsAg and HBV DNA must be obtained to determine the need to start HBV treatment (Grade D) [SASLT 2021, p. 9]
### 6. HBV-HDV COINFECTION [SASLT 2021, p. 9]
• HDV is a defective virus that requires HBsAg to envelop its delta antigen, causing coinfection with HBV or superinfection in chronic HBV patients [SASLT 2021, p. 9]
• Active HDV infection is defined by HDV IgM and RNA presence with unexplained LFT elevation [SASLT 2021, p. 9]
• Treatment goal: Suppression of HDV replication [SASLT 2021, p. 9]
• PEG-IFN for 1 year shows long-term benefits despite post-treatment viral relapse [SASLT 2021, p. 9]
• NA monotherapy is ineffective against HDV replication [SASLT 2021, p. 9]
### 7. HBV-HIV COINFECTION [SASLT 2021, p. 9]
• All HIV-positive patients with HBV co-infection should start ART irrespective of CD4 cell count (Grade A) [SASLT 2021, p. 9]
• HBV-HIV co-infected patients should be treated with TDF- or TAF-based ART regimen (Grade A) [SASLT 2021, p. 9]
### 8. IMMUNOCOMPROMISED PATIENTS [SASLT 2021, p. 9]
• Prophylaxis for all HBsAg-positive patients before chemotherapy or immunosuppressive therapy (Grade A) [SASLT 2021, p. 9]
• HBsAg-negative/anti-HBc-positive patients need HBV prophylaxis if receiving anti-CD20 or stem cell transplantation [SASLT 2021, p. 9]
• Continue prophylaxis for ≥6 months after immunosuppression (12 months for anti-CD20) [SASLT 2021, p. 9]
• All patients undergoing immunosuppressive treatment or chemotherapy, even short‑term courses, should be screened for HBsAg, anti‑HBc, and anti‑HBs (and HBV DNA, if HBsAg is already positive). [SASLT 2021, p. 9]
• We recommend prophylaxis for all patients with positive HBsAg before initiating chemotherapy or other immunosuppressive agents. [SASLT 2021, p. 9]
• For HBsAg-negative and anti-HBc positive patients, we recommend HBV prophylaxis if they are candidates for anti CD20 or are undergoing stem cell transplantation. [SASLT 2021, p. 9]
• We recommend starting HBV prophylaxis for HBsAg or anti‑HBc positive patients undergoing treatment with tumor necrosis factor (TNF) inhibitors. [SASLT 2021, p. 9]
• We recommend HBV prophylaxis for all patients who are HBsAg or anti-HBc positive before initiation of immunotherapy such as anti‑programmed cell death (PD) ‑1 and anti‑programmed cell death‑ligand 1 (PD‑L1) therapy. [SASLT 2021, p. 9]
### 9. PREGNANCY [SASLT 2021, p. 9-10]
• Screen all pregnant women for HBV in first trimester (Grade A) [SASLT 2021, p. 9]
• HBV vaccine is safe in pregnancy for non-immune women without chronic HBV. [SASLT 2021, p. 9]
• Treat pregnant women meeting standard therapy indications [SASLT 2021, p. 9]
• Start antiviral prophylaxis with TDF (or TAF) for HBV DNA >100,000 IU/mL at 24-28 weeks (Grade D) [SASLT 2021, p. 10]
• Switch to TDF/TAF if on ETV, ADV, or interferon during pregnancy (Grade D) [SASLT 2021, p. 10]
• Delivery mode based on obstetric indications only [SASLT 2021, p. 10]
• Breastfeeding permitted for HBsAg+ women on TDF (Grade B) [SASLT 2021, p. 10]
### KEY DEFINITIONS & CONTEXT
* **ALT (Alanine Aminotransferase):** Normal range in Adults falls between 4-42 units/L (U/L).
* **ULN (Upper Limit of Normal):** ULN means Upper Limit of Normal for ALT which is set at 40 units/L for the purpose of these guidelines.
* ** Necroinflammatory activity scale; A1 = mild, A2 = moderate, A3 = severe
Liver fibrosis is usually classified into five stages:
F0—no fibrosis; F1—mild fibrosis, pericellular collagen deposits; F2—moderate fibrosis, beginning bridging fibrosis; F3—severe fibrosis, defined as presence of numerous bridges and septa; F4—cirrhosis
"""
def assess_hbv_eligibility(patient_data: Dict[str, Any]) -> Dict[str, Any]:
"""
Assess patient eligibility for HBV treatment based on SASLT 2021 guidelines
using hardcoded guideline pages (3, 4, 6, 7, 8, 9, 10) and LLM analysis
Args:
patient_data: Dictionary containing patient clinical parameters
Returns:
Dictionary with assessment results:
- eligible: bool
- recommendations: str (comprehensive narrative with inline citations in format [SASLT 2021, Page X])
"""
try:
# # Check if HBsAg is positive (required for treatment consideration)
# if patient_data.get("hbsag_status") != "Positive":
# return {
# "eligible": False,
# "recommendations": "Patient is HBsAg negative. HBV treatment is not indicated. HBsAg positivity is required for HBV treatment consideration according to SASLT 2021 guidelines."
# }
# Use hardcoded SASLT 2021 guidelines instead of RAG retrieval
logger.info("Using hardcoded SASLT 2021 guidelines (Pages 3, 4, 6, 7, 8, 9, 10)")
# Define ALT ULN for context
sex = patient_data.get("sex", "Male")
#alt_uln = 35 if sex == "Male" else 25
# Format patient data for prompt
age = patient_data.get("age", "N/A")
pregnancy_status = patient_data.get("pregnancy_status", "N/A")
hbsag_status = patient_data.get("hbsag_status", "N/A")
duration_hbsag = patient_data.get("duration_hbsag_months", "N/A")
hbv_dna = patient_data.get("hbv_dna_level", 0)
hbeag_status = patient_data.get("hbeag_status", "N/A")
alt_level = patient_data.get("alt_level", 0)
fibrosis_stage = patient_data.get("fibrosis_stage", "N/A")
necroinflammatory = patient_data.get("necroinflammatory_activity", "N/A")
extrahepatic = patient_data.get("extrahepatic_manifestations", False)
immunosuppression = patient_data.get("immunosuppression_status", "None")
coinfections = patient_data.get("coinfections", [])
family_history = patient_data.get("family_history_cirrhosis_hcc", False)
comorbidities = patient_data.get("other_comorbidities", [])
# Create prompt for LLM to analyze patient against guidelines
analysis_prompt = f"""You are an HBV treatment eligibility assessment system. Analyze the patient data against the SASLT 2021 guidelines.
PATIENT DATA:
- Sex: {sex}
- Age: {age} years
- Pregnancy Status: {pregnancy_status}
- HBsAg Status: {hbsag_status}
- HBsAg Duration: {duration_hbsag} months
- HBV DNA Level: {hbv_dna:,.0f} IU/mL
- HBeAg Status: {hbeag_status}
- ALT Level: {alt_level}
- Fibrosis Stage: {fibrosis_stage}
- Necroinflammatory Activity: {necroinflammatory}
- Extrahepatic Manifestations: {extrahepatic}
- Immunosuppression: {immunosuppression}
- Coinfections: {', '.join(coinfections) if coinfections else 'None'}
- Family History (Cirrhosis/HCC): {family_history}
- Other Comorbidities: {', '.join(comorbidities) if comorbidities else 'None'}
SASLT 2021 GUIDELINES (Retrieved Context):
{SASLT_GUIDELINES}
Based STRICTLY on the SASLT 2021 guidelines and criteria provided above, assess this patient's eligibility for HBV antiviral treatment.
You MUST respond with a valid JSON object in this exact format:
{{
"eligible": true or false,
"recommendations": "Comprehensive assessment with inline citations"
}}
IMPORTANT JSON FORMATTING:
- Return ONLY valid JSON without markdown code blocks.
- You MUST use "\\n" to indicate line breaks inside the "recommendations" string and format the content as clear bullet lists prefixed with "- ".
- Do NOT include literal newline characters. Use \\n for every new bullet or line.
- Use SINGLE \\n between lines. Do NOT use \\n\\n (double newlines) anywhere.
CRITICAL ELIGIBILITY HIERARCHY:
1. **Check Special Populations FIRST (Pages 9-10):** "Eligible" means eligible for ANY antiviral intervention (treatment OR prophylaxis).
* If patient is **HBsAg-positive** AND **Immunosuppressed** (Page 9): Set **"eligible": true"** (for prophylaxis).
* If patient has **HBV-HIV coinfection** (Page 9): Set **"eligible": true"** (for ART).
* If patient is **Pregnant** with **HBV DNA > 100,000 IU/mL** (Page 10): Set **"eligible": true"** (for prophylaxis).
* If patient has **HBV-HCV coinfection** AND meets HBV treatment criteria (Page 9): Set **"eligible": true"**.
2. **Check Standard Criteria SECOND (Page 6):**
* If *not* eligible based on special populations, check standard criteria (HBV DNA, ALT, fibrosis, age, family history).
* If any Page 6 criteria are met (e.g., Cirrhosis, or HBV DNA > 2,000 + ALT > ULN + moderate fibrosis, etc.): Set **"eligible": true"**.
3. **If NO criteria from (1) or (2) are met:** Set **"eligible": false"**.
4. The "eligible" flag MUST be consistent with the "Eligibility and Rationale" bullet. Do not contradict yourself.
STRUCTURE AND CONTENT OF "recommendations" (CONCISE & ORGANIZED):
- Use ONLY these sections in this exact order, each as a header followed by 1-3 concise bullets:
1. "Eligibility and Rationale:" (1-2 bullets max, MUST state the primary reason for eligibility/ineligibility)
2. "Treatment Recommendations:" (1-3 bullets: first-line drugs if eligible, or "Treatment not indicated" if not eligible)
3. "Monitoring and Follow-up:" (1-2 bullets)
4. "Special Considerations:" (0-2 bullets, ONLY if applicable and *not* the primary reason for eligibility)
5. "References:" (1 line listing pages cited)
- OMIT "Additional Notes" and any other sections.
- Keep each bullet to ONE sentence (max 25 words per bullet).
- Total output: aim for 8-12 bullets maximum across all sections.
BULLETING AND CITATIONS RULES:
- Put citations at the end of each bullet using "[SASLT 2021, Page X]".
- Include evidence grade when available (e.g., "(Grade A)").
- Only cite pages 6–10 that actually contain the information.
STRICT ACCURACY AND CONSISTENCY RULES:
- **NO CONTRADICTIONS:** The "eligible" flag MUST match the rationale. Follow the CRITICAL ELIGIBILITY HIERARCHY.
- **Rationale First:** The Rationale MUST state the primary reason. If eligible due to immunosuppression, state that, even if Page 6 criteria are not met.
- **Use ONLY the provided SASLT 2021 content;** do NOT add external knowledge.
- **BREVITY:** Each bullet = 1 sentence, max 25 words. Total = 8-12 bullets max.
PAGE-TO-TOPIC MAPPING GUIDANCE (for correct citations):
- Page 6: Standard initiation of treatment criteria, management algorithm.
- Page 7: Monitoring of untreated patients, CHB treatment principles.
- Page 8: Treatment drugs/regimens (ETV, TDF, TAF), agents not recommended.
- Page 9: Special populations (HBV-HCV, HBV-HDV, HBV-HIV, Immunocompromised).
- Page 10: Pregnancy-related recommendations.
---
EXAMPLE OUTPUT (ELIGIBLE - STANDARD CRITERIA) - Use SINGLE \\n only:
{{
"eligible": true,
"recommendations": "Eligibility and Rationale:\\n- Eligible: HBV DNA > 2,000 IU/mL, ALT > ULN, moderate fibrosis (Grade A) [SASLT 2021, Page 6]\\nTreatment Recommendations:\\n- Start monotherapy with ETV, TDF, or TAF (Grade A) [SASLT 2021, Page 8]\\nMonitoring and Follow-up:\\n- Monitor treatment response per SASLT protocol [SASLT 2021, Page 7]\\nReferences:\\n- Pages 6, 7, 8: Treatment criteria, drugs, monitoring"
}}
---
EXAMPLE OUTPUT (NOT ELIGIBLE - STANDARD CRITERIA) - Use SINGLE \\n only:
{{
"eligible": false,
"recommendations": "Eligibility and Rationale:\\n- Not eligible: HBV DNA < 2,000 IU/mL, ALT ≤ ULN, no significant fibrosis [SASLT 2021, Page 6]\\nTreatment Recommendations:\\n- Treatment not indicated at this time [SASLT 2021, Page 6]\\nMonitoring and Follow-up:\\n- Monitor every 6-12 months (HBeAg-negative, HBV DNA < 2,000 IU/mL) (Grade B) [SASLT 2021, Page 7]\\nReferences:\\n- Pages 6, 7: Treatment criteria, monitoring protocols"
}}
---
EXAMPLE OUTPUT (ELIGIBLE - IMMUNOSUPPRESSION) - Use SINGLE \\n only:
{{
"eligible": true,
"recommendations": "Eligibility and Rationale:\\n- Eligible: HBsAg-positive patient requires prophylaxis for immunosuppressive therapy (Grade A) [SASLT 2021, Page 9]\\nTreatment Recommendations:\\n- Start antiviral prophylaxis (e.g., ETV, TDF, TAF) [SASLT 2021, Page 8, 9]\\nMonitoring and Follow-up:\\n- Continue prophylaxis for ≥6 months after immunosuppression (12 for anti-CD20) [SASLT 2021, Page 9]\\nReferences:\\n- Pages 8, 9: Prophylaxis criteria, drug options, monitoring"
}}
---
EXAMPLE OUTPUT (ELIGIBLE - HIV COINFECTION) - Use SINGLE \\n only:
{{
"eligible": true,
"recommendations": "Eligibility and Rationale:\\n- Eligible: Patient has HBV-HIV coinfection and should start ART (Grade A) [SASLT 2021, Page 9]\\nTreatment Recommendations:\\n- ART regimen must include TDF- or TAF-based therapy (Grade A) [SASLT 2021, Page 9]\\nMonitoring and Follow-up:\\n- Monitor patient closely after ART initiation for immune reconstitution [SASLT 2021, Page 9]\\nReferences:\\n- Page 9: HBV-HIV coinfection management, ART regimens"
}}
---
CRITICAL REQUIREMENTS:
1. Base assessment ONLY on SASLT 2021 guidelines provided.
2. Follow the CRITICAL ELIGIBILITY HIERARCHY to avoid contradictions.
3. Keep output SHORT: 8-12 bullets total, 1 sentence per bullet (max 25 words).
4. Use ONLY the 5 sections listed above.
5. Cite exact page at end of each bullet: [SASLT 2021, Page X].
6. Return ONLY valid JSON, no markdown, no extra text.
"""
# Log the complete prompt being sent to LLM
logger.info(f"\n{'='*80}")
logger.info(f"LLM PROMPT")
logger.info(f"{'='*80}")
logger.info(f"\n{analysis_prompt}\n")
logger.info(f"{'='*80}\n")
# Get LLM response
llm = get_llm()
logger.info("Sending prompt to LLM...")
response = llm.invoke(analysis_prompt)
logger.info("LLM response received")
# Extract JSON from response
response_text = response.content if hasattr(response, 'content') else str(response)
# Log LLM response
logger.info(f"\n{'='*80}")
logger.info(f"LLM RESPONSE")
logger.info(f"{'='*80}")
logger.info(f"\n{response_text}\n")
logger.info(f"{'='*80}\n")
# Try to parse JSON from response
try:
# Remove markdown code blocks if present
if '```json' in response_text:
json_start = response_text.find('```json') + 7
json_end = response_text.find('```', json_start)
response_text = response_text[json_start:json_end].strip()
elif '```' in response_text:
json_start = response_text.find('```') + 3
json_end = response_text.find('```', json_start)
response_text = response_text[json_start:json_end].strip()
# Find JSON in response (handle cases where LLM adds extra text)
json_start = response_text.find('{')
json_end = response_text.rfind('}') + 1
if json_start >= 0 and json_end > json_start:
json_str = response_text[json_start:json_end]
# Clean the JSON string to escape control characters within string values
cleaned_json_str = clean_json_string(json_str)
logger.debug(f"Cleaned JSON string (first 500 chars): {cleaned_json_str[:500]}")
# Parse the cleaned JSON
result = json.loads(cleaned_json_str)
logger.info(f"✅ Successfully parsed JSON response")
else:
raise ValueError("No JSON found in response")
# Validate and return result
normalized_recs = normalize_recommendations(result.get("recommendations", ""))
assessment_result = {
"eligible": result.get("eligible", False),
"recommendations": normalized_recs
}
# Log final assessment
logger.info(f"\n{'='*80}")
logger.info(f"FINAL ASSESSMENT")
logger.info(f"{'='*80}")
logger.info(f"Eligible: {assessment_result['eligible']}")
logger.info(f"Recommendations length: {len(assessment_result['recommendations'])} characters")
logger.info(f"{'='*80}\n")
return assessment_result
except (json.JSONDecodeError, ValueError) as e:
logger.error(f"Failed to parse LLM response as JSON: {e}")
logger.error(f"Response text: {response_text}")
# Fallback: return error response
return {
"eligible": False,
"recommendations": f"Error parsing assessment results. Please try again. Error details: {str(e)}"
}
except Exception as e:
logger.error(f"Error in assess_hbv_eligibility: {str(e)}")
raise |