5b88185611
[daip2-9] basic code refactor - unreferenced functions and reorganize existing files * remove unreferenced functions in ac_funcs.py * move compare_output.py * move file_counting.py * move merge_issue_regex.py * remove unreferenced functions in postprocessing_funcs.py * clean up preprocessing_funcs.py * move prerun.py * move table_analysis.py and textract_template.py to scripts * remove unreferenced functions in table_funcs.py * moved tin_pull.py to scripts * move detect_complex.py and remove merge_funcs.py * clean up dict operations and utils, mark functions in utils for destinations * removed errant import Approved-by: Katon Minhas
178 lines
5.7 KiB
Python
178 lines
5.7 KiB
Python
import json
|
|
import boto3
|
|
import pandas as pd
|
|
import numpy as np
|
|
from datetime import datetime
|
|
import os
|
|
import anthropic
|
|
import re
|
|
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
|
|
import config
|
|
import utils
|
|
|
|
# Global configuration variables
|
|
S3_REGION = "us-east-2"
|
|
BEDROCK_REGION = "us-east-1"
|
|
LLM_SELECTED = "Claude Instant"
|
|
bedrock_runtime = config.BEDROCK_RUNTIME
|
|
|
|
|
|
def find_tin_numbers(text):
|
|
# Regular expression to find sets of 9 digits with an optional dash after the first two digits
|
|
pattern = r"\b\d{2}-?\d{7}\b"
|
|
|
|
# Find all matches in the provided text
|
|
matches = re.findall(pattern, text)
|
|
|
|
return matches
|
|
|
|
|
|
def invoke_llm(context, llm_selected=LLM_SELECTED):
|
|
prompt_data = f"""
|
|
|
|
Human: Use the following pieces of context to provide a concise answer to the questions at the end. You must answer in python list format.
|
|
|
|
{context}
|
|
|
|
Question: What is the Group provider's taxpayer identification number stated in the contract? This is a 9 digit long number typically with a hyphen after the first 2 digits. Return only this 9 digit number with a hyphen after the first 2 digits. Do not elaborate or add context.
|
|
|
|
Assistant: Answer in list format: ["""
|
|
|
|
if llm_selected == "Claude 3 - Sonnet":
|
|
model_id = "anthropic.claude-3-5-sonnet-20240620-v1:0"
|
|
body = json.dumps(
|
|
{
|
|
"anthropic_version": "bedrock-2023-05-31",
|
|
"max_tokens": 4096,
|
|
"messages": [
|
|
{
|
|
"role": "user",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": anthropic.HUMAN_PROMPT
|
|
+ prompt_data
|
|
+ anthropic.AI_PROMPT,
|
|
}
|
|
],
|
|
}
|
|
],
|
|
"temperature": 0.0,
|
|
}
|
|
)
|
|
elif llm_selected in ["Claude Instant"]:
|
|
model_id = "anthropic.claude-instant-v1"
|
|
body = json.dumps(
|
|
{
|
|
"prompt": anthropic.HUMAN_PROMPT + prompt_data + anthropic.AI_PROMPT,
|
|
"max_tokens_to_sample": 2048,
|
|
"temperature": 0.0,
|
|
"top_p": 1,
|
|
"top_k": 250,
|
|
"stop_sequences": [anthropic.HUMAN_PROMPT],
|
|
}
|
|
)
|
|
else:
|
|
raise ValueError("Unsupported LLM selected")
|
|
|
|
try:
|
|
response = bedrock_runtime.invoke_model(
|
|
body=body,
|
|
modelId=model_id,
|
|
accept="application/json",
|
|
contentType="application/json",
|
|
)
|
|
response_body = json.loads(response.get("body").read())
|
|
if llm_selected == "Claude 3 - Sonnet":
|
|
response_text = response_body["content"][0]["text"]
|
|
elif llm_selected in ["Claude Instant"]:
|
|
response_text = response_body["completion"]
|
|
else:
|
|
print("Unsupported LLM selected")
|
|
except Exception as e:
|
|
print(f"Error invoking LLM: {e}")
|
|
response_text = "failed"
|
|
return response_text.strip()
|
|
|
|
|
|
def main(filename, contract_text):
|
|
print(f"Processing contract: {filename}")
|
|
try:
|
|
df = pd.DataFrame(columns=["Contract Name", "Raw value", "Final value"])
|
|
|
|
tin_number = find_tin_numbers(contract_text)
|
|
final_tin = list(set(tin_number))
|
|
|
|
if len(final_tin) != 1:
|
|
final_tin = find_tin_numbers(
|
|
invoke_llm(contract_text, llm_selected=LLM_SELECTED)
|
|
)
|
|
|
|
df["Raw value"] = [tin_number]
|
|
df["Final value"] = [final_tin]
|
|
df["Contract Name"] = [filename]
|
|
|
|
df.to_csv(f"tin_output/{filename}.csv", index=False)
|
|
except Exception as e:
|
|
print(f"Error processing contract: {e}")
|
|
|
|
|
|
# bucket = "centene-national-contracting-files"
|
|
# contract_path = "no_tins_text_files"
|
|
|
|
# s3_client = boto3.Session(aws_access_key_id=config.S3_ACCESS_KEY_ID,
|
|
# aws_secret_access_key=config.S3_SECRET_ACCESS_KEY,
|
|
# aws_session_token=config.S3_SESSION_TOKEN, region_name="us-east-2").client('s3')
|
|
|
|
# objects = s3_client.list_objects_v2(Bucket=bucket, Prefix=contract_path)
|
|
file_list = []
|
|
|
|
OUTPUT_DIRECTORY = r"tin_output/no_tins_text_files"
|
|
NUM_WORKERS = 10
|
|
BATCH_SIZE = 10
|
|
|
|
|
|
def process_file(item):
|
|
filename, contract_text = item
|
|
if filename.endswith(".txt") and not os.path.exists(
|
|
os.path.join(OUTPUT_DIRECTORY, (filename[:-3] + "csv"))
|
|
):
|
|
main(filename, contract_text)
|
|
|
|
|
|
def process_directory(input_dict):
|
|
# for item in input_dict.items():
|
|
with ThreadPoolExecutor(max_workers=NUM_WORKERS) as executor:
|
|
futures = {executor.submit(process_file, item) for item in input_dict.items()}
|
|
for future in as_completed(futures):
|
|
future.result() # This will raise an exception if the callable raised one
|
|
|
|
|
|
input_dict = utils.read_input(path="data/cnc/no_tins")
|
|
process_directory(input_dict)
|
|
|
|
individual_path = r"tin_output/no_tins_text_files"
|
|
|
|
|
|
def individual_to_dict(filename):
|
|
df = pd.read_csv(os.path.join(individual_path, filename))
|
|
df = df.dropna(axis=1, how="all")
|
|
column_names = ["Filename", "Answer", "Final Answer"]
|
|
new_column_names = column_names[: len(df.columns)] + list(
|
|
df.columns[len(column_names) :]
|
|
)
|
|
df.columns = new_column_names
|
|
df_dict = {"Filename": filename}
|
|
df_dict["Answer"] = df["Answer"].iloc[0]
|
|
df_dict["Final Answer"] = df["Final Answer"].iloc[0]
|
|
return df_dict
|
|
|
|
|
|
all_dicts = []
|
|
for filename in os.listdir(individual_path):
|
|
df_dict = individual_to_dict(filename)
|
|
all_dicts.append(df_dict)
|
|
final_df = pd.DataFrame(all_dicts)
|
|
final_df.to_csv("results.csv", index=False)
|