Files
doczyai-pipelines/src/file_processing.py
T
2024-09-30 15:20:14 +01:00

137 lines
5.3 KiB
Python

import os
import pandas as pd
import config
import preprocess
import table_funcs
import prompt_funcs
import prompts
import claude_funcs
import postprocessingfuncs
import postprocess
def clean_td(td):
td_clean = []
for d in td:
new_d = {}
for k, v in d.items():
if 'DATE' in k:
new_d[k] = v if isinstance(v, list) else [v]
elif k not in ['page_num', 'Filename']:
if isinstance(v, str) and ',' in v:
new_d[k] = [item.strip() for item in v.split(',')]
elif v == 'N/A':
new_d[k] = []
else:
new_d[k] = [v] if isinstance(v, str) else v
else:
new_d[k] = v
td_clean.append(new_d)
return td_clean
def get_unique_keys(dicts):
keys = set()
for d in dicts:
keys.update(d.keys())
return keys
def get_unique_date_fields(td_results):
unique_date_fields = {}
for td in td_results:
for key, value in td.items():
if 'DATE' in key:
if key not in unique_date_fields:
unique_date_fields[key] = set()
unique_date_fields[key].update(value if isinstance(value, list) else [value])
for key in unique_date_fields:
unique_date_fields[key] = list(unique_date_fields[key])
return unique_date_fields
def merge_results(td_results, bu_results, text_dict):
all_keys = get_unique_keys(td_results) | get_unique_keys(bu_results)
date_fields = get_unique_date_fields(td_results)
merged_results = []
for bu in bu_results:
merged = {key: bu.get(key, "") for key in all_keys}
td_on_page = [td for td in td_results if td['page_num'] == bu['page_num']]
for td in td_on_page:
for key, value in td.items():
if not merged[key]:
merged[key] = value
elif isinstance(value, list) and value and not isinstance(merged[key], list):
merged[key] = value
elif isinstance(value, list) and value:
merged[key].extend(value)
for date_key, date_values in date_fields.items():
if date_key not in merged or not merged[date_key]:
merged[date_key] = date_values
else:
merged[date_key].extend([val for val in date_values if val not in merged[date_key]])
for key in all_keys:
if isinstance(merged[key], list) and len(merged[key]) > 1:
page_num = bu['page_num']
page_text = text_dict.get(page_num, "")
prompt = prompts.GENERATE_PROMPT(bu, td_on_page, page_text, field_name=key, values=merged[key])
response = claude_funcs.invoke_claude_3(prompt, max_tokens=4000)
try:
selected_value = response.strip()
merged[key] = selected_value
except Exception as e:
print(f"Error processing LLM response for key {key}: {e}")
merged[key] = ', '.join(merged[key])
merged_results.append(merged)
return merged_results
def process_file(file_object):
################## INITIATE PROCESSING ##################
filename, contract_text = file_object
if config.VERBOSE: print(f"Processing {filename}...")
################## CREATE OUTPUT DIRECTORIES ##################
base_filename = os.path.splitext(filename)[0].strip()
output_dir = os.path.join(config.OUTPUT_DIRECTORY, base_filename)
os.makedirs(output_dir, exist_ok=True)
################## PREPROCESS ##################
contract_text = preprocess.clean_newlines(contract_text)
text_dict = preprocess.split_text(contract_text)
text_dict = table_funcs.align_and_format_tables(text_dict)
text_dict = preprocess.highlight_rates(text_dict)
################## RUN TOP DOWN ##################
td_results = prompt_funcs.run_top_down(filename, text_dict) # Returns list of dictionaries for each page
pd.DataFrame(td_results).to_csv(os.path.join(output_dir, config.TD_RESULTS_NAME), index=False)
print(f"Top Down Complete - {filename}")
################## RUN BOTTOM UP ##################
bu_results = prompt_funcs.run_bottom_up(filename, text_dict) # Returns list of dictionaries
pd.DataFrame(bu_results).to_csv(os.path.join(output_dir, config.BU_RESULTS_NAME), index=False)
print(f"Bottom Up Complete - {filename}")
################## COMBINE TOP DOWN AND BOTTOM UP ##################
combined_results = merge_results(clean_td(td_results), bu_results, text_dict)
print(f"TD/BU Merge Complete - {filename} ")
################## WRITE UNPROCESSED OUTPUT ##################
combined_df = pd.DataFrame(combined_results)
combined_df.to_csv(os.path.join(output_dir, config.UNPROCESSED_RESULTS_NAME), index=False)
################## RUN POSTPROCESSING ##################
combined_df = combined_df.applymap(postprocessingfuncs.sanitize_value)
post_processed_combined_df = postprocess.postprocess_results(combined_df)
post_processed_combined_df.to_csv(os.path.join(output_dir, config.PROCESSED_RESULTS_NAME), index=False)
print(f"Postprocessing Complete - {filename} ")
print(f"Output Complete - {filename} ")