Resolve split reimb dates
This commit is contained in:
@@ -749,7 +749,7 @@ def prompt_lesser_of_check(
|
|||||||
"exhibit_reference": None,
|
"exhibit_reference": None,
|
||||||
}
|
}
|
||||||
|
|
||||||
logging.info(
|
logging.debug(
|
||||||
f"LESSER_OF_CHECK classification: scope={llm_answer_final['scope']}, "
|
f"LESSER_OF_CHECK classification: scope={llm_answer_final['scope']}, "
|
||||||
f"target={llm_answer_final['target_exhibit']}, "
|
f"target={llm_answer_final['target_exhibit']}, "
|
||||||
f"exhibit_ref={llm_answer_final.get('exhibit_reference')}, "
|
f"exhibit_ref={llm_answer_final.get('exhibit_reference')}, "
|
||||||
@@ -862,3 +862,21 @@ def provider_name_match_check(
|
|||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def prompt_split_reimb_dates(date_range: str, filename: str) -> dict:
|
||||||
|
prompt, _parser = prompt_templates.SPLIT_REIMB_DATES(date_range)
|
||||||
|
|
||||||
|
# Invoke LLM to split the date range
|
||||||
|
llm_answer_raw = llm_utils.invoke_claude(
|
||||||
|
prompt,
|
||||||
|
model_id="sonnet_latest",
|
||||||
|
filename=filename,
|
||||||
|
max_tokens=200,
|
||||||
|
cache=True,
|
||||||
|
instruction=prompt_templates.SPLIT_REIMB_DATES_INSTRUCTION(),
|
||||||
|
usage_label="SPLIT_REIMB_DATES",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Extract the effective and termination dates from the LLM output
|
||||||
|
llm_answer_final = _parser(llm_answer_raw)
|
||||||
|
return llm_answer_final
|
||||||
|
|
||||||
|
|||||||
@@ -54,13 +54,7 @@ def dynamic_primary(
|
|||||||
if not string_utils.is_empty(exhibit_text_answer):
|
if not string_utils.is_empty(exhibit_text_answer):
|
||||||
# Special handling for LOB: If both Medicare and Medicaid are detected, add Duals
|
# Special handling for LOB: If both Medicare and Medicaid are detected, add Duals
|
||||||
if field.field_name == "LOB":
|
if field.field_name == "LOB":
|
||||||
# Parse the discovered values (pipe-delimited or comma-separated)
|
values_lower = [val.lower() for val in exhibit_text_answer]
|
||||||
values_list = [
|
|
||||||
val.strip()
|
|
||||||
for val in exhibit_text_answer.replace(",", "|").split("|")
|
|
||||||
if val.strip()
|
|
||||||
]
|
|
||||||
values_lower = [val.lower() for val in values_list]
|
|
||||||
|
|
||||||
# Check if both Medicare and Medicaid are present (case-insensitive)
|
# Check if both Medicare and Medicaid are present (case-insensitive)
|
||||||
has_medicare = any("medicare" in val for val in values_lower)
|
has_medicare = any("medicare" in val for val in values_lower)
|
||||||
@@ -69,16 +63,16 @@ def dynamic_primary(
|
|||||||
# If both are present and Duals is not already in the list, add it
|
# If both are present and Duals is not already in the list, add it
|
||||||
if has_medicare and has_medicaid:
|
if has_medicare and has_medicaid:
|
||||||
if "duals" not in values_lower:
|
if "duals" not in values_lower:
|
||||||
exhibit_text_answer = (
|
if exhibit_text_answer:
|
||||||
exhibit_text_answer + " | Duals"
|
exhibit_text_answer.append("Duals")
|
||||||
if exhibit_text_answer
|
else:
|
||||||
else "Duals"
|
exhibit_text_answer = ["Duals"]
|
||||||
)
|
|
||||||
logging.debug(
|
logging.debug(
|
||||||
f"Added 'Duals' to LOB valid values because both Medicare and Medicaid were detected"
|
f"Added 'Duals' to LOB valid values because both Medicare and Medicaid were detected"
|
||||||
)
|
)
|
||||||
|
|
||||||
field.update_valid_values(exhibit_text_answer + " | N/A")
|
|
||||||
|
field.update_valid_values(exhibit_text_answer + ["N/A"])
|
||||||
dynamic_reimbursement_fields.add_field(field)
|
dynamic_reimbursement_fields.add_field(field)
|
||||||
dynamic_primary_fields.remove_field(field.field_name)
|
dynamic_primary_fields.remove_field(field.field_name)
|
||||||
# If the field is not found, add to Exhibit-Level answers (the answer will be N/A or similar)
|
# If the field is not found, add to Exhibit-Level answers (the answer will be N/A or similar)
|
||||||
|
|||||||
@@ -675,29 +675,16 @@ def split_reimb_dates(one_to_n_results: list, filename: str) -> list:
|
|||||||
date_range = str(record["REIMB_DATES"]).strip()
|
date_range = str(record["REIMB_DATES"]).strip()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Invoke LLM to split the date range
|
llm_answer_final = prompt_calls.prompt_split_reimb_dates(date_range, filename)
|
||||||
llm_output_raw = llm_utils.invoke_claude(
|
|
||||||
prompt_templates.SPLIT_REIMB_DATES(date_range),
|
|
||||||
model_id="sonnet_latest",
|
|
||||||
filename=filename,
|
|
||||||
max_tokens=200,
|
|
||||||
cache=True,
|
|
||||||
instruction=prompt_templates.SPLIT_REIMB_DATES_INSTRUCTION(),
|
|
||||||
usage_label="SPLIT_REIMB_DATES",
|
|
||||||
)
|
|
||||||
|
|
||||||
# Extract the effective and termination dates from the LLM output
|
|
||||||
llm_output_cleaned = string_utils.universal_json_load(llm_output_raw)
|
|
||||||
|
|
||||||
# Update the specific record with parsed dates
|
# Update the specific record with parsed dates
|
||||||
if llm_output_cleaned and isinstance(llm_output_cleaned, dict):
|
if llm_answer_final and isinstance(llm_answer_final, dict):
|
||||||
if "start_date" in llm_output_cleaned:
|
if "start_date" in llm_answer_final:
|
||||||
record["REIMB_EFFECTIVE_DT"] = llm_output_cleaned["start_date"]
|
record["REIMB_EFFECTIVE_DT"] = llm_answer_final["start_date"]
|
||||||
if "end_date" in llm_output_cleaned:
|
if "end_date" in llm_answer_final:
|
||||||
record["REIMB_TERMINATION_DT"] = llm_output_cleaned["end_date"]
|
record["REIMB_TERMINATION_DT"] = llm_answer_final["end_date"]
|
||||||
else:
|
else:
|
||||||
logging.error(
|
logging.error(
|
||||||
f"Invalid LLM output format for index {index}: {llm_output_cleaned}"
|
f"Invalid LLM output format for index {index}: {llm_answer_final}"
|
||||||
)
|
)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -856,26 +843,26 @@ def lesser_of_distribution(
|
|||||||
# GLOBAL: Store for cross-exhibit, don't add to results
|
# GLOBAL: Store for cross-exhibit, don't add to results
|
||||||
if scope == "GLOBAL":
|
if scope == "GLOBAL":
|
||||||
exhibit.add_lesser_of_statement(lesser_of_answer_dict)
|
exhibit.add_lesser_of_statement(lesser_of_answer_dict)
|
||||||
logging.info(
|
logging.debug(
|
||||||
f"Stored GLOBAL template from page {page_num} - NOT added to results"
|
f"Stored GLOBAL template from page {page_num} - NOT added to results"
|
||||||
)
|
)
|
||||||
|
|
||||||
# EXHIBIT_SPECIFIC (OTHER): Store for cross-exhibit, don't add to results
|
# EXHIBIT_SPECIFIC (OTHER): Store for cross-exhibit, don't add to results
|
||||||
elif scope == "EXHIBIT_SPECIFIC" and target == "OTHER":
|
elif scope == "EXHIBIT_SPECIFIC" and target == "OTHER":
|
||||||
exhibit.add_lesser_of_statement(lesser_of_answer_dict)
|
exhibit.add_lesser_of_statement(lesser_of_answer_dict)
|
||||||
logging.info(
|
logging.debug(
|
||||||
f"Stored cross-exhibit template from page {page_num} - NOT added to results"
|
f"Stored cross-exhibit template from page {page_num} - NOT added to results"
|
||||||
)
|
)
|
||||||
|
|
||||||
# EXHIBIT_SPECIFIC (CURRENT): Don't store (race condition), don't add to results
|
# EXHIBIT_SPECIFIC (CURRENT): Don't store (race condition), don't add to results
|
||||||
elif scope == "EXHIBIT_SPECIFIC" and target == "CURRENT":
|
elif scope == "EXHIBIT_SPECIFIC" and target == "CURRENT":
|
||||||
logging.info(
|
logging.debug(
|
||||||
f"CURRENT template from page {page_num} - handled via text search - NOT added to results"
|
f"CURRENT template from page {page_num} - handled via text search - NOT added to results"
|
||||||
)
|
)
|
||||||
|
|
||||||
# STANDALONE: Complete rate - ADD to results
|
# STANDALONE: Complete rate - ADD to results
|
||||||
elif scope == "STANDALONE":
|
elif scope == "STANDALONE":
|
||||||
logging.info(f"STANDALONE rate from page {page_num} - ADDED to results")
|
logging.debug(f"STANDALONE rate from page {page_num} - ADDED to results")
|
||||||
final_reimbursement_level_answers.append(
|
final_reimbursement_level_answers.append(
|
||||||
answer_dict
|
answer_dict
|
||||||
) # ← Only this gets added
|
) # ← Only this gets added
|
||||||
|
|||||||
Reference in New Issue
Block a user