Updated Lesser Of methodology

This commit is contained in:
Katon Minhas
2024-06-21 15:04:33 -07:00
committed by Michael McGuinness
parent 484c943386
commit 7ac8f5a1ba
4 changed files with 122 additions and 29 deletions
+1
View File
@@ -452,3 +452,4 @@ def clean_dates(df):
df.loc[idx, 'LOB_PRICING_TERMS_TERMINATION_DATE'] = 'N/A'
return df
+48 -2
View File
@@ -1,5 +1,6 @@
import json
import difflib
import config
import prompts
@@ -8,8 +9,44 @@ import dict_operations
import utils
import postprocessingfuncs
def get_least_similar(dict_list, original_dict, field):
print(f"Running similarity for {field}")
min_similarity = float('inf')
least_similar_dict = None
for dictionary in dict_list:
# Extract the methodology text
field_text = dictionary[field]
print(f"Field text: {field_text}")
# Compute similarity using difflib
similarity = difflib.SequenceMatcher(None, field_text, original_dict[field]).ratio()
print(f"Simlarity: {similarity}")
# If the similarity is less than the current minimum, update the minimum and the corresponding dictionary
if similarity < min_similarity:
min_similarity = similarity
least_similar_dict = dictionary
return least_similar_dict
def run_bottom_up_lesser(d, text_dict, tokens=8000):
def get_lesser_of_dict(dict_list, original_dict):
unique_rates = list({d['REIMBURSEMENT_RATE'] for d in dict_list})
unique_fees = list({d['REIMBURSEMENT_FLAT_FEE'] for d in dict_list})
# If the rates are different, return the lesser of dict with a different rate than original
if len(unique_rates) > 1:
least_similar_dict = get_least_similar(dict_list, original_dict, 'REIMBURSEMENT_RATE')
elif len(unique_fees) > 1:
least_similar_dict = get_least_similar(dict_list, original_dict, 'REIMBURSEMENT_FLAT_FEE')
else:
least_similar_dict = get_least_similar(dict_list, original_dict, 'FULL_METHODOLOGY')
return least_similar_dict
def run_bottom_up_lesser(d, text_dict, tokens=4000):
"""
Processes specific clauses or conditions within the document text, such as 'lesser of' or 'greater of',
using a language model to analyze and extract relevant data from the identified text segment.
@@ -31,7 +68,16 @@ def run_bottom_up_lesser(d, text_dict, tokens=8000):
prompt = prompts.BOTTOM_UP_LESSER(d, text_dict[d['page_num']])
lesser_of_answer = claude_funcs.invoke_claude_3(prompt, max_tokens=tokens)
lesser_of_dict = dict_operations.secondary_string_to_dict(lesser_of_answer)
lesser_of_dict_list = dict_operations.primary_string_to_dict({d['page_num'] : lesser_of_answer}, d['Filename'])
print(lesser_of_dict_list)
# If lesser of is Y
if len(lesser_of_dict_list) > 1:
lesser_of_dict = get_lesser_of_dict(lesser_of_dict_list, d)
else:
d['LESSER_OF_LANGUAGE_IND'] = 'N'
d['GREATER_OF_LANGUAGE_IND'] = 'N'
return ({}, d)
lesser_of_dict['page_num'] = d['page_num']
if lesser_of_dict['LESSER_OF_LANGUAGE_IND'] == 'Y' or lesser_of_dict['GREATER_OF_LANGUAGE_IND'] == 'Y':
lesser_of_dict['SERVICE'] = d['SERVICE']
+11 -7
View File
@@ -78,25 +78,29 @@ def BOTTOM_UP_LESSER(d, page):
### PAGE START ### {page} ### PAGE END
The above text contains a number of reimbursement terms. For the rest of this request, focus only on the specific term listed below:
Service: {d['SERVICE']}
Original_Methodology: {d['FULL_METHODOLOGY']}
Original_Dictionary:
- Original_Service: {d['SERVICE']}
- Original_Rate: {d['REIMBURSEMENT_RATE']}
- Original_Flat_Fee: {d['REIMBURSEMENT_FLAT_FEE']}
- Original_Methodology: {d['FULL_METHODOLOGY']}
Your job is to identify if there is any 'lesser of' language or 'greater of' language that pertains to the specific service and methodology above.
Note that a 'lesser of'/'greater of' statement may not be directly written for a given Service, but that does not necessarily mean that it doesn't apply.
Read and analyze the page, then populate a JSON dictionary with the following fields (descriptions provided):
Read and analyze the page, then populate two JSON dictionaries with the following fields (descriptions provided):
'LESSER_OF_LANGUAGE_IND' : Write 'Y' if there is 'lesser of' language somewhere on the page that applies to the Service and Original_Methodology. Write 'N' if not.
'GREATER_OF_LANGUAGE_IND' : Write 'Y' if there is 'greater of' language somewhere on the page that applies to the Service and Original_Methodology. Write 'N' if not.
'FULL_METHODOLOGY' : If either of the above are 'Y', what is the reimbursement the lesser or greater of? Do not write the full sentence - only include the half of the lesser/greater of statement that is NOT Original_Methodology. For example, if the reimbursement is the lesser of X or Original_Methodology, return only X.
'FULL_METHODOLOGY' : If either of the above are 'Y', what is the reimbursement the lesser or greater of? Do not write the full sentence.
'REIMBURSEMENT_RATE' : If the Lesser/Greater Of Methodology is a percent of something, write just the numeric percent value here. Only include percentages. If not, write N/A.
'REIMBURSEMENT_FLAT_FEE' : If the Lesser/Greater Of Methodology is a dollar value, write just the numeric value here. Only include dollar values. If not, write N/A.
For REIMBURSEMENT_RATE and REIMBURSEMENT_FLAT_FEE, do NOT include the Rate or Flat Fee from Original_Methodology.
If either LESSER_OF_LANGUAGE_IND or GREATER_OF_LANGUAGE_IND is 'Y', then both dictionaries must be populated. One of the dictionaries will have REIMBURSEMENT_RATE, REIMBURSEMENT_FLAT_FEE, and FULL_METHODOLOGY values equal to the Original term.
Fill the first dictionary with the values corresponding to the LEFT half of the Lesser/Greater Of Statement, and the second dictionary with the RIGHT half of the Lesser/Greater Of Statement.
Note that in some cases, the REIMBURSEMENT_RATE will not be explicitly written. It may say something like "Provider's billed charges", which is essentially equivalent to "100% of Provider's billed charges". In these cases, assign REIMBURSEMENT_RATE a value of 100%.
If both LESSER_OF_LANGUAGE_IND and GREATER_OF_LANGUAGE_IND are 'N', return a list with just the original dictionary.
Only return the dictionary, with no other commentary or explanation. Ensure you abide by proper JSON formatting.
Only return the list of dictionaries, with no other commentary or explanation. Ensure you abide by proper JSON formatting.
"""
def BOTTOM_UP_EXCEPT_ESC(d, page):
+62 -20
View File
@@ -17,34 +17,76 @@ import prompts
import prompt_funcs
import claude_funcs
import merge_funcs
import dict_operations
# input_dict = utils.read_input()
input_dict = utils.read_input()
# (filename, contract_text) = list(input_dict.items())[0]
(filename, contract_text) = list(input_dict.items())[0]
# contract_text = preprocess.clean_newlines(contract_text)
# contract_text = preprocess.clean_billed_charges(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)
# for page_num, page_text in text_dict.items():
# if page_num == '31':
# prompt = prompts.TOP_DOWN_PRIMARY(page_text)
# answer = claude_funcs.invoke_claude_3(prompt, max_tokens=4000)
# answer_dict = json.loads(answer)
# print(answer_dict)
contract_text = preprocess.clean_newlines(contract_text)
contract_text = preprocess.clean_billed_charges(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)
# bu_results = prompt_funcs.run_bottom_up(filename, text_dict) # Returns list of dictionaries
# print(bu_results)
def BOTTOM_UP_LESSER(d, page):
return f"""
### PAGE START ### {page} ### PAGE END
The above text contains a number of reimbursement terms. For the rest of this request, focus only on the specific term listed below:
Original_Dictionary:
- Original_Service: {d['SERVICE']}
- Original_Rate: {d['REIMBURSEMENT_RATE']}
- Original_Flat_Fee: {d['REIMBURSEMENT_FLAT_FEE']}
- Original_Methodology: {d['FULL_METHODOLOGY']}
Your job is to identify if there is any 'lesser of' language or 'greater of' language that pertains to the specific service and methodology above.
Note that a 'lesser of'/'greater of' statement may not be directly written for a given Service, but that does not necessarily mean that it doesn't apply.
Read and analyze the page, then populate two JSON dictionaries with the following fields (descriptions provided):
'LESSER_OF_LANGUAGE_IND' : Write 'Y' if there is 'lesser of' language somewhere on the page that applies to the Service and Original_Methodology. Write 'N' if not.
'GREATER_OF_LANGUAGE_IND' : Write 'Y' if there is 'greater of' language somewhere on the page that applies to the Service and Original_Methodology. Write 'N' if not.
'FULL_METHODOLOGY' : If either of the above are 'Y', what is the reimbursement the lesser or greater of? Do not write the full sentence.
'REIMBURSEMENT_RATE' : If the Lesser/Greater Of Methodology is a percent of something, write just the numeric percent value here. Only include percentages. If not, write N/A.
'REIMBURSEMENT_FLAT_FEE' : If the Lesser/Greater Of Methodology is a dollar value, write just the numeric value here. Only include dollar values. If not, write N/A.
If either LESSER_OF_LANGUAGE_IND or GREATER_OF_LANGUAGE_IND is 'Y', then both dictionaries must be populated. One of the dictionaries will have REIMBURSEMENT_RATE, REIMBURSEMENT_FLAT_FEE, and FULL_METHODOLOGY values equal to the Original term.
Fill the first dictionary with the values corresponding to the LEFT half of the Lesser/Greater Of Statement, and the second dictionary with the RIGHT half of the Lesser/Greater Of Statement.
If both LESSER_OF_LANGUAGE_IND and GREATER_OF_LANGUAGE_IND are 'N', return a list with just the original dictionary.
Only return the list of dictionaries, with no other commentary or explanation. Ensure you abide by proper JSON formatting.
"""
d = {'SERVICE': 'Inpatient Services',
'REIMBURSEMENT_FLAT_FEE': 'N/A',
'REIMBURSEMENT_RATE': '105%',
'FULL_METHODOLOGY': "The lesser of 105% of the West Virginia Medicaid DRG (based on Hospital's current DHHR payment rate) or 100% of Hospital's allowable billed charges.",
'page_num': '26',
'Filename': 'App Regional Healthcare_Hospital Agreement_20160414_Dually Executed WV MCD-C13439125AA.txt'}
answer = prompt_funcs.run_bottom_up_lesser(d, text_dict)
print(answer)
# answer_strings = prompt_funcs.run_bottom_up_primary({'3' : text_dict['3']}, 8000)
# answer_dicts = dict_operations.primary_string_to_dict(answer_strings, filename)
# answer_dicts_filtered = postprocessingfuncs.filter_service_column(answer_dicts)
# print(answer_dicts_filtered)
# for d in answer_dicts_filtered:
# print(f"Original dictionary: {d}")
# # Bottom Up Lesser
# if config.RUN_LESSER:
# lesser_object = prompt_funcs.run_bottom_up_lesser(d.copy(), text_dict.copy(), tokens=4000)
# print(f"Lesser dictionary: {lesser_object}")
sample_results = pd.read_csv('output/ASMG MU/combined_results_post_processed.csv')
df = postprocessingfuncs.clean_dates(sample_results)
print(df)