diff --git a/fieldExtraction/src/investment/file_processing.py b/fieldExtraction/src/investment/file_processing.py index ed785e3..7015327 100644 --- a/fieldExtraction/src/investment/file_processing.py +++ b/fieldExtraction/src/investment/file_processing.py @@ -6,7 +6,7 @@ from src.investment import preprocessing_funcs, aarete_derived, dynamic_funcs, o from src.utils import io_utils, logging_utils, string_utils from constants.constants import Constants from src import config -from src.prompts.fieldset import FieldSet +from src.prompts.fieldset import FieldSet, Field from src.utils.string_utils import datetime_str @@ -121,6 +121,7 @@ def run_one_to_one_prompts( relationship="one_to_one", file_path=config.FIELD_JSON_PATH ).combine(dynamic_one_to_one_fields) + ################## RUN PROVIDER INFO ################## one_to_one_results, one_to_one_fields = tin_npi_funcs.run_provider_info_fields( contract_text, one_to_one_fields, text_dict, filename @@ -174,6 +175,7 @@ def run_one_to_n_prompts(text_dict: dict[str, str], one_to_n_results = [] first_reimbursement_page = '1' + previous_exhibit = None #################################### PROCESS EACH EXHIBIT SEPARATELY #################################### for exhibit_page, exhibit_page_nums in exhibit_chunk_mapping.items(): @@ -192,7 +194,25 @@ def run_one_to_n_prompts(text_dict: dict[str, str], ) ) # dict, FieldSet logging.debug(f"Exhibit Level Answers for {filename}, Page {exhibit_page}: {exhibit_level_answers}") - + + # Store original values before inheritance (for tracking in previous_exhibit) + original_exhibit_page_nums = exhibit_page_nums.copy() + original_exhibit_text = exhibit_text_original + original_dynamic_reimbursement_fields = dynamic_reimbursement_fields + + ############################### Check and Combine Exhibit Inheritance ############################### + # IF dynamic_reimbursement_fields is empty FieldSet, and previous exhibit's dynamic_reimbursement_fields is NOT empty, + # and the previous exhibit has NO reimbursement rows, then replace dynamic_reimbursement_fields with the previous + # exhibit's dynamic_reimbursement_field values AND set exhibit_page_nums = exhibit_page_nums for exhibit N-1 + exhibit_page_nums for exhibit N + should_inherit, exhibit_page_nums, dynamic_reimbursement_fields = ( + one_to_n_funcs.check_and_combine_exhibit_inheritance( + previous_exhibit, + exhibit_page_nums, + exhibit_text_original, + dynamic_reimbursement_fields, + ) + ) + all_exhibit_reimbursements, all_exhibit_special_case = [], [] #################################### PAGE-BY-PAGE REIMBURSEMENT PRIMARY #################################### for page_num in exhibit_page_nums: @@ -224,6 +244,20 @@ def run_one_to_n_prompts(text_dict: dict[str, str], ################################ Add to Total ############################### one_to_n_results += all_exhibit_rows + ################################ Store Current Exhibit for Next Iteration ############################### + # Store original (non-combined) values for next exhibit to potentially inherit from + # Determine if current exhibit had reimbursements + had_reimbursements = len(all_exhibit_reimbursements) > 0 or len(all_exhibit_special_case) > 0 + + previous_exhibit = { + 'exhibit_page': exhibit_page, + 'exhibit_page_nums': original_exhibit_page_nums, + 'exhibit_text_original': original_exhibit_text, + 'dynamic_reimbursement_fields': original_dynamic_reimbursement_fields, + 'exhibit_level_answers': exhibit_level_answers.copy(), + 'had_reimbursements': had_reimbursements + } + ################## Add N/A Dynamic or Exhibit to One-to-One ################## dynamic_one_to_one_fields = dynamic_funcs.get_dynamic_one_to_one_fields( one_to_n_results, constants diff --git a/fieldExtraction/src/investment/one_to_n_funcs.py b/fieldExtraction/src/investment/one_to_n_funcs.py index 1b131f5..2ad04b7 100644 --- a/fieldExtraction/src/investment/one_to_n_funcs.py +++ b/fieldExtraction/src/investment/one_to_n_funcs.py @@ -655,3 +655,74 @@ def lesser_of_distribution(reimbursement_level_answers: list[dict[str, str]], ex return final_reimbursement_level_answers +def check_and_combine_exhibit_inheritance( + previous_exhibit: dict | None, + current_exhibit_page_nums: list[str], + current_exhibit_text: str, + current_dynamic_fields: FieldSet, +) -> tuple[bool, list[str], FieldSet]: + """ + Check if inheritance should happen and combine exhibits if needed. + + Conditions for inheritance: + 1. Previous exhibit exists + 2. Current exhibit's dynamic_reimbursement_fields is empty FieldSet + 3. Previous exhibit's dynamic_reimbursement_fields is NOT empty + 4. Previous exhibit had NO reimbursement rows + + When inheritance happens: + - Replace current dynamic_reimbursement_fields with previous exhibit's dynamic_reimbursement_fields + - Combine exhibit_page_nums (previous + current) to provide context through simplify_exhibit + + Args: + previous_exhibit: Dict with keys: 'exhibit_page_nums', 'dynamic_reimbursement_fields', 'had_reimbursements' + current_exhibit_page_nums: List of page numbers for current exhibit + current_exhibit_text: Full text of current exhibit (not used in return, but kept for consistency) + current_dynamic_fields: FieldSet of dynamic fields found in current exhibit + + Returns: + Tuple of: + - should_inherit: bool indicating if inheritance happened + - combined_page_nums: list[str] (combined if inheritance, original otherwise) + - updated_dynamic_fields: FieldSet (replaced with previous if inheritance, original otherwise) + """ + # Check if previous exhibit exists + if previous_exhibit is None: + return False, current_exhibit_page_nums, current_dynamic_fields + + # Check if current exhibit's dynamic_reimbursement_fields is empty + current_field_names = current_dynamic_fields.list_fields() + current_is_empty = len(current_field_names) == 0 + + if not current_is_empty: + return False, current_exhibit_page_nums, current_dynamic_fields + + # Check if previous exhibit's dynamic_reimbursement_fields is NOT empty + prev_dynamic_fields = previous_exhibit['dynamic_reimbursement_fields'] + prev_field_names = prev_dynamic_fields.list_fields() + prev_is_not_empty = len(prev_field_names) > 0 + + if not prev_is_not_empty: + return False, current_exhibit_page_nums, current_dynamic_fields + + # Check if previous exhibit had NO reimbursement rows + prev_no_reimbursements = not previous_exhibit.get('had_reimbursements', True) + + if not prev_no_reimbursements: + return False, current_exhibit_page_nums, current_dynamic_fields + + # All conditions met - inheritance should happen + # Combine exhibit_page_nums (previous + current) + # This ensures simplify_exhibit will include context from both exhibits + combined_page_nums = previous_exhibit['exhibit_page_nums'] + current_exhibit_page_nums + + # Replace current dynamic_reimbursement_fields with previous exhibit's + updated_dynamic_fields = prev_dynamic_fields + + # Minimal logging: inheritance activated, pages being merged, and fields inherited + prev_pages = ', '.join(previous_exhibit.get('exhibit_page_nums', [])) + current_pages = ', '.join(current_exhibit_page_nums) + fields_str = ', '.join(prev_field_names) + logging.debug(f"Exhibit inheritance activated: merging pages {prev_pages} → {current_pages}, inheriting fields: {fields_str}") + + return True, combined_page_nums, updated_dynamic_fields