Merged in feature/rework_reimb_id (pull request #467)
Rework reimbursement ID to associate parts of "lesser of" (or other such coupled statement) with one another * refactor reimbursement ID generation with hashed service terms * reduce hash length for unique reimbursement ID generation * update reimbursement ID format to include 'exh_pg' for clarity * clean up testing.ipynb * one more formatting fix to testing.ipynb * Move reimb_id generation to postprocessing * move reimb_id function to postprocessing_funcs.py * refactor generate_reimb_ids to group by FILE_NAME and EXHIBIT_PAGE for ID generation * clean testing.ipynb further Approved-by: Katon Minhas
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Manual Test Bed\n",
|
||||
"Runs contracts through from `input_data`, but cannot yet automatically check them against the answer key (that workbook is unreliable in its answers)\n",
|
||||
"Runs contracts through from `input_data`\n",
|
||||
"\n",
|
||||
"To make this work: in `config.py`, change READ_MODE and RUN_MODE to 'local'.\n",
|
||||
"Create an .env in the base directory of your project according to these instructions:\n",
|
||||
@@ -16,7 +16,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@@ -26,7 +26,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@@ -34,194 +34,38 @@
|
||||
"TEST_DATA_INPUT_DIR = \"scripts/investment_field_testing/input_data\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"For now, we are no longer doing anything with the test bed"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# # Load target data from `scripts/investment_field_testing/input_data` directory\n",
|
||||
"\n",
|
||||
"# df_targets = pd.read_excel(TEST_DATA_INPUT_DIR + \"/test_bed_investment.xlsx\", sheet_name=\"test_bed_investment\")\n",
|
||||
"\n",
|
||||
"# print(df_targets.shape)\n",
|
||||
"\n",
|
||||
"# df_targets.head()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Also change config.RUN_MODE and config.READ_MODE to 'local'\n",
|
||||
"test_params = {}\n",
|
||||
"# test_params['local_input_dir'] = TEST_DATA_INPUT_DIR + \"/investment_228\"\n",
|
||||
"test_params['local_input_dir'] = TEST_DATA_INPUT_DIR + \"/mix_all_358\"\n",
|
||||
"test_params['local_input_dir'] = TEST_DATA_INPUT_DIR\n",
|
||||
"test_params['max_workers'] = 1\n",
|
||||
"test_params['input_files'] = [\"2001-11-01 California Emergency Physicians PSA_MU.txt\"] # you can specify specific files to run here"
|
||||
"test_params['input_files'] = [ # you can specify specific files to run here\n",
|
||||
" \"00-125434-Central MS Diagnostic, LLC-ICMProviderAgreement_78285.txt\",\n",
|
||||
" # \"20-2401676-Community Hospital of LaGrange County, Inc dba Parkview LaGrange Hospital-ICMProviderAgreement_89356_1.txt\",\n",
|
||||
" ]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"doczy-output exists\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from src.investment.main import main as investment_main"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Total Input Files : 1\n",
|
||||
"Processing 2001-11-01 California Emergency Physicians PSA_MU.txt...\n",
|
||||
"Preprocessing Complete - 2001-11-01 California Emergency Physicians PSA_MU.txt\n",
|
||||
"Running regex fields...\n",
|
||||
"Running smart chunked fields...\n",
|
||||
"\n",
|
||||
"fields: [<src.prompts.investment_prompts.Field object at 0x7f20a7569400>, <src.prompts.investment_prompts.Field object at 0x7f20a7569340>, <src.prompts.investment_prompts.Field object at 0x7f20a7569160>, <src.prompts.investment_prompts.Field object at 0x7f20a7569370>, <src.prompts.investment_prompts.Field object at 0x7f20a75693d0>]\n",
|
||||
"field_group_answer_raw: I'll analyze the contract and answer each question, then provide the final answers in JSON format.\n",
|
||||
"\n",
|
||||
"CONTRACT_AUTO_RENEWAL_TERM:\n",
|
||||
"The contract states in section 5.1: \"this agreement shall automatically renew for successive one year periods, unless terminated as set forth herein.\" Therefore, the auto-renewal term is one year.\n",
|
||||
"\n",
|
||||
"CONTRACT_EFFECTIVE_DT:\n",
|
||||
"The effective date is found on the signature page, which states: \"11/10/ 10-30-01\". This appears to be two dates, but following the instructions to preserve the exact format as it appears in the document, I'll use this as is.\n",
|
||||
"\n",
|
||||
"CONTRACT_TITLE:\n",
|
||||
"The title of the contract is found at the beginning of the document: \"CALIFORNIA ER PHYSICIANS PHYSICIAN GROUP SERVICES AGREEMENT\".\n",
|
||||
"\n",
|
||||
"CONTRACT_TERMINATION_DT:\n",
|
||||
"The contract does not specify a specific termination date. Section 5.1 states that the initial term is 12 months after the effective date, and it automatically renews for successive one-year periods unless terminated. Therefore, it's effectively \"year to year\".\n",
|
||||
"\n",
|
||||
"CONTRACT_AUTO_RENEWAL_IND:\n",
|
||||
"The contract does automatically renew according to section 5.1, so the answer is Y.\n",
|
||||
"\n",
|
||||
"Here's the final answer in JSON format:\n",
|
||||
"\n",
|
||||
"{\n",
|
||||
" \"CONTRACT_AUTO_RENEWAL_TERM\": \"one year\",\n",
|
||||
" \"CONTRACT_EFFECTIVE_DT\": \"11/10/ 10-30-01\",\n",
|
||||
" \"CONTRACT_TITLE\": \"CALIFORNIA ER PHYSICIANS PHYSICIAN GROUP SERVICES AGREEMENT\",\n",
|
||||
" \"CONTRACT_TERMINATION_DT\": \"year to year\",\n",
|
||||
" \"CONTRACT_AUTO_RENEWAL_IND\": \"Y\"\n",
|
||||
"}\n",
|
||||
"Running full context fields...\n",
|
||||
"One to One Complete - 2001-11-01 California Emergency Physicians PSA_MU.txt\n",
|
||||
"Postprocessing Complete - 2001-11-01 California Emergency Physicians PSA_MU.txt\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"df_out = investment_main(testing=True, test_params=test_params)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<div>\n",
|
||||
"<style scoped>\n",
|
||||
" .dataframe tbody tr th:only-of-type {\n",
|
||||
" vertical-align: middle;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe tbody tr th {\n",
|
||||
" vertical-align: top;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe thead th {\n",
|
||||
" text-align: right;\n",
|
||||
" }\n",
|
||||
"</style>\n",
|
||||
"<table border=\"1\" class=\"dataframe\">\n",
|
||||
" <thead>\n",
|
||||
" <tr style=\"text-align: right;\">\n",
|
||||
" <th></th>\n",
|
||||
" <th>CONTRACT_AUTO_RENEWAL_TERM</th>\n",
|
||||
" <th>CONTRACT_EFFECTIVE_DT</th>\n",
|
||||
" <th>CONTRACT_TITLE</th>\n",
|
||||
" <th>CONTRACT_TERMINATION_DT</th>\n",
|
||||
" <th>CONTRACT_AUTO_RENEWAL_IND</th>\n",
|
||||
" <th>CONTRACT_FILE_NAME</th>\n",
|
||||
" <th>CLIENT_NAME</th>\n",
|
||||
" <th>AARETE_DERIVED_TERMINATION_DATE</th>\n",
|
||||
" </tr>\n",
|
||||
" </thead>\n",
|
||||
" <tbody>\n",
|
||||
" <tr>\n",
|
||||
" <th>0</th>\n",
|
||||
" <td>one year</td>\n",
|
||||
" <td>10/30/2001</td>\n",
|
||||
" <td>CALIFORNIA ER PHYSICIANS PHYSICIAN GROUP SERVI...</td>\n",
|
||||
" <td>year to year</td>\n",
|
||||
" <td>Y</td>\n",
|
||||
" <td>2001-11-01 California Emergency Physicians PSA...</td>\n",
|
||||
" <td>Test-Client</td>\n",
|
||||
" <td>N/A</td>\n",
|
||||
" </tr>\n",
|
||||
" </tbody>\n",
|
||||
"</table>\n",
|
||||
"</div>"
|
||||
],
|
||||
"text/plain": [
|
||||
" CONTRACT_AUTO_RENEWAL_TERM CONTRACT_EFFECTIVE_DT \\\n",
|
||||
"0 one year 10/30/2001 \n",
|
||||
"\n",
|
||||
" CONTRACT_TITLE CONTRACT_TERMINATION_DT \\\n",
|
||||
"0 CALIFORNIA ER PHYSICIANS PHYSICIAN GROUP SERVI... year to year \n",
|
||||
"\n",
|
||||
" CONTRACT_AUTO_RENEWAL_IND \\\n",
|
||||
"0 Y \n",
|
||||
"\n",
|
||||
" CONTRACT_FILE_NAME CLIENT_NAME \\\n",
|
||||
"0 2001-11-01 California Emergency Physicians PSA... Test-Client \n",
|
||||
"\n",
|
||||
" AARETE_DERIVED_TERMINATION_DATE \n",
|
||||
"0 N/A "
|
||||
]
|
||||
},
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"df_out.head()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# The following is not functional because we first need to clean the test bed"
|
||||
"df_out, df_error = investment_main(testing=True, test_params=test_params)"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -230,109 +74,13 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# one_to_one_fields = []\n",
|
||||
"# for col in df_out.columns:\n",
|
||||
"# if df_out[col].nunique() == 1:\n",
|
||||
"# # print(col, df_out[col].nunique())\n",
|
||||
"# one_to_one_fields.append(col)\n",
|
||||
"\n",
|
||||
"# exclude_list = ['CARVEOUT_IND', # 1:n\n",
|
||||
"# \"GREATER_OF_IND\", # 1:n\n",
|
||||
"# \"REIMB_FEE_RATE\", # 1:n\n",
|
||||
"# \"NETWORK\", # dynamic\n",
|
||||
"# \"CLAIM_TYPE_CD\", # not found in the source spreadsheet\n",
|
||||
"# \"CONTRACT_AMENDMENT_NUM\", # not found in the source spreadsheet\n",
|
||||
"# \"PROV_GROUP_NAME_FULL\", # not found in the source spreadsheet\n",
|
||||
"# \"PROV_OTHER_NAME_FULL\", # This is called PROV_GROUP_NAME in the source spreadsheet\n",
|
||||
"# \"CONTRACT_FILE_NAME\", # not found in the source spreadsheet\n",
|
||||
"# \"CARVEOUT_CD\", # 1:n, also not found in the source spreadsheet\n",
|
||||
"# 'PAYER_NAME',\n",
|
||||
"# 'CLIENT_NAME',\n",
|
||||
" \n",
|
||||
"# ]\n",
|
||||
"\n",
|
||||
"# one_to_one_fields = [item for item in one_to_one_fields \n",
|
||||
"# if item not in exclude_list]\n",
|
||||
"\n",
|
||||
"# one_to_one_fields"
|
||||
"df_out"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# mapping_main_to_testbed = {\"AUTO_RENEWAL_TERM\" : \"AUTO_RENEWAL_TERM_LENGTH\", \"AARETE_DERIVED_TERMINATION_DT\" : \"TERMINATION_DT\"}\n",
|
||||
"\n",
|
||||
"# def apply_name_mapping(col: str):\n",
|
||||
"# if col in mapping_main_to_testbed:\n",
|
||||
"# return mapping_main_to_testbed[col]\n",
|
||||
"# return col"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# exclude_list = [\"CLAIM_TYPE_CD\"]\n",
|
||||
"\n",
|
||||
"# for field in one_to_one_fields:\n",
|
||||
"# field = apply_name_mapping(field)\n",
|
||||
"# # if field == \"AUTO_RENEWAL_TERM\":\n",
|
||||
"# # field = \"AUTO_RENEWAL_TERM_LENGTH\"\n",
|
||||
"# # elif field == \"AARETE_DERIVED_TERMINATION_DT\":\n",
|
||||
"# # field = \"TERMINATION_DT\"\n",
|
||||
"# # elif field == \"CLAIM_TYPE_CD\":\n",
|
||||
"# print(df_targets[field].head())"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# row = df_out[one_to_one_fields].iloc[0]\n",
|
||||
"# row"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# filter_target = df_targets[df_targets['Contract Name'] == 'Adena Health System National Template Agreement C19460229AA.txt']\n",
|
||||
"\n",
|
||||
"# for field, answer in row.items():\n",
|
||||
"# print(field, f\"LLM answer: {answer}\")\n",
|
||||
"# print(filter_target[apply_name_mapping(field)].iloc[0],\"\\n\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"\n",
|
||||
"# filter_target"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "doczy-smart-chunking-blZ6pB_m-py3.12",
|
||||
"display_name": "doczy-smart-chunking-U_35LsVn-py3.12",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import re
|
||||
import hashlib
|
||||
from typing import Callable
|
||||
|
||||
import src.constants.investment_values as investment_values
|
||||
@@ -458,21 +459,6 @@ def reimbursement_level(
|
||||
)
|
||||
# print(f"{datetime_str()} code_breakout_answers complete for exhibit page {exhibit_page} of {filename}...")
|
||||
|
||||
# Add unique identifiers to each row composed of filename, exhibit page, service code, and index
|
||||
for idx, row in enumerate(code_breakout_answers):
|
||||
# Clean filename for identifier (remove path and extension)
|
||||
clean_filename = filename.split("/")[-1].replace(".", "_")
|
||||
|
||||
# Get service code (or description) and shorten it for the identifier
|
||||
service_identifier = ""
|
||||
if "SERVICE_TERM" in row: # This should never be empty but just in case
|
||||
service_identifier = row["SERVICE_TERM"].replace(" ", "_")[:10]
|
||||
|
||||
# Create unique ID
|
||||
row["REIMB_ID"] = (
|
||||
f"{clean_filename}_{exhibit_page}_{service_identifier}_{idx+1:03d}"
|
||||
)
|
||||
|
||||
return code_breakout_answers
|
||||
else:
|
||||
return []
|
||||
|
||||
@@ -55,7 +55,10 @@ def postprocess(df):
|
||||
|
||||
# Convert AARETE_DERIVED_REIMB_METHOD values [AWP, ASP, WAC] to 'MedRx'
|
||||
df['AARETE_DERIVED_REIMB_METHOD'] = df['AARETE_DERIVED_REIMB_METHOD'].replace({'AWP': 'MedRx', 'ASP': 'MedRx', 'WAC': 'MedRx'})
|
||||
|
||||
|
||||
# Add reimb_id
|
||||
df = postprocessing_funcs.generate_reimb_ids(df)
|
||||
|
||||
# Standardize output column order - this should ALWAYS be the final postprocessing step
|
||||
df = postprocessing_funcs.reorder_columns(df, COLUMN_ORDER)
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import logging
|
||||
import re
|
||||
|
||||
import hashlib
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
|
||||
@@ -1176,4 +1177,61 @@ def date_postprocessing(date: str) -> str:
|
||||
|
||||
prompt = investment_prompts.date_fix_prompt(date)
|
||||
response = llm_utils.invoke_claude(prompt, config.MODEL_ID_CLAUDE35_SONNET, "date_fix")
|
||||
return extract_text_from_delimiters(response, Delimiter.PIPE)
|
||||
return extract_text_from_delimiters(response, Delimiter.PIPE)
|
||||
|
||||
def generate_reimb_ids(df: pd.DataFrame) -> pd.DataFrame:
|
||||
"""Generates REIMB_ID for each row in the DataFrame based on the FILE_NAME and other fields.
|
||||
The REIMB_ID is constructed using the following format:
|
||||
{FILE_NAME}_exh_pg_{EXHIBIT_PAGE}_{index}_{hash_value}
|
||||
|
||||
Where:
|
||||
- FILE_NAME is the name of the file (without extension).
|
||||
- EXHIBIT_PAGE is the page number of the exhibit.
|
||||
- index is the index of the row in the group.
|
||||
- hash_value is the first 8 characters of the MD5 hash of a concatenated string of relevant fields.
|
||||
The relevant fields are SERVICE_TERM, REIMB_TERM, PROGRAM, PRODUCT, NETWORK, and LOB.
|
||||
|
||||
Args:
|
||||
df (pd.DataFrame): Input DataFrame containing the columns FILE_NAME, EXHIBIT_PAGE, SERVICE_TERM, REIMB_TERM, PROGRAM, PRODUCT, NETWORK, and LOB.
|
||||
The FILE_NAME column should contain the name of the file (with or without extension).
|
||||
The EXHIBIT_PAGE column should contain the page number of the exhibit.
|
||||
|
||||
Returns:
|
||||
pd.DataFrame: DataFrame with generated REIMB_IDs for each row.
|
||||
"""
|
||||
# First sort to ensure consistent ordering
|
||||
df = df.sort_values(by=['FILE_NAME', 'EXHIBIT_PAGE']) if "EXHIBIT_PAGE" in df.columns else df.sort_values(by=['FILE_NAME'])
|
||||
|
||||
# Create a temporary copy to avoid SettingWithCopyWarning
|
||||
df_temp = df.copy()
|
||||
|
||||
# Process each file+exhibit_page group to reset counter for each exhibit page
|
||||
group_cols = ['FILE_NAME', 'EXHIBIT_PAGE'] if "EXHIBIT_PAGE" in df.columns else ['FILE_NAME']
|
||||
for group_key, indices in df.groupby(group_cols).groups.items():
|
||||
if isinstance(group_key, tuple):
|
||||
filename, exhibit_page = group_key
|
||||
exhibit_page = str(exhibit_page).zfill(3)
|
||||
else:
|
||||
filename = group_key
|
||||
exhibit_page = '000'
|
||||
clean_filename = str(filename).split("/")[-1].replace(".", "_")
|
||||
|
||||
for i, idx in enumerate(indices):
|
||||
row = df.loc[idx]
|
||||
|
||||
# Get fields to include in hash
|
||||
service_term = str(row.get('SERVICE_TERM', ''))
|
||||
reimb_term = str(row.get('REIMB_TERM', ''))
|
||||
program = str(row.get('PROGRAM', ''))
|
||||
product = str(row.get('PRODUCT', ''))
|
||||
network = str(row.get('NETWORK', ''))
|
||||
lob = str(row.get('LOB', ''))
|
||||
|
||||
# Create hash string
|
||||
hash_string = f"{clean_filename}_{service_term}_{reimb_term}_{program}_{product}_{network}_{lob}"
|
||||
hash_value = hashlib.md5(hash_string.encode()).hexdigest()[:8]
|
||||
|
||||
# Generate REIMB_ID
|
||||
df_temp.at[idx, 'REIMB_ID'] = f"{clean_filename}_exh_pg_{exhibit_page}_{i+1:03d}_{hash_value}"
|
||||
|
||||
return df_temp
|
||||
Reference in New Issue
Block a user