2024-02-28 18:23:22 +05:30
import json
import boto3
from langchain . prompts import PromptTemplate
from langchain . embeddings . bedrock import BedrockEmbeddings
from langchain . llms . bedrock import Bedrock
from langchain_community . vectorstores import Chroma
from constants import CHROMA_SETTINGS , EMBEDDING_MODEL_NAME , PERSIST_DIRECTORY , MODEL_ID , MODEL_BASENAME , SOURCE_DIRECTORY
from langchain . chains import RetrievalQA
import streamlit as st
from streamlit_extras . add_vertical_space import add_vertical_space
import os
import pandas as pd
2024-03-13 17:23:20 +05:30
import numpy as np
2024-03-08 17:36:36 +05:30
import util
2024-03-13 17:23:20 +05:30
import anthropic
from pydantic import BaseModel
from typing import List
import re
2024-02-28 18:23:22 +05:30
2024-03-13 17:23:20 +05:30
REDIRECT_URI = ' https://doczy.aarete.com:8502 '
2024-03-18 17:27:08 +05:30
user_list = [ ' maamseek@aarete.com ' , ' smahdavian@aarete.com ' , ' ahinge@aarete.com ' , ' akadam@aarete.com ' , ' pkatariya@aarete.com '
2024-03-08 18:15:55 +05:30
, ' piragavarapu@aarete.com ' , ' umistry@aarete.com ' , ' ahutchison@aarete.com ' , ' bgrunst@aarete.com ' , ' ddimeglio@aarete.com '
2024-04-19 10:59:02 -05:00
, ' vnair@aarete.com ' , ' kminhas@aarete.com ' , ' dculotta@aarete.com ' , ' cbull@aarete.com ' , ' sclark@aarete.com ' , ' fmohiuddin@aarete.com ' , ' hupreti@aarete.com ' ]
2024-02-28 18:23:22 +05:30
2024-03-08 17:36:36 +05:30
st . set_page_config ( layout = " wide " )
2024-02-28 18:23:22 +05:30
# Sidebar contents
with st . sidebar :
st . title ( " Doczy.AI ™ " )
st . markdown (
"""
## About
This app extracts data from contracts
"""
)
add_vertical_space ( 15 )
# st.write("Doczy")
2024-04-02 14:31:43 +05:30
_ , c1 = st . columns ( [ 5 , 1 ] )
2024-03-13 17:23:20 +05:30
try :
2024-03-27 19:01:11 +05:30
util . setup_page ( REDIRECT_URI )
2024-03-13 17:23:20 +05:30
except :
2024-04-10 20:43:35 +05:30
st . write ( " SSO Failed " )
st . session_state [ ' user_info ' ] = { ' mail ' : ' maamseek@aarete.com ' , ' displayName ' : ' Mayank Aamseek ' }
2024-04-05 12:15:54 +05:30
try :
c1 . write ( f " User: ** { st . session_state . user_info [ ' displayName ' ] } ** " )
user_mail = st . session_state . user_info [ ' mail ' ]
except KeyError as e :
st . write ( " Session Expired. " )
2024-04-09 16:20:29 +05:30
st . stop ( )
2024-03-13 17:23:20 +05:30
2024-03-22 23:59:54 +05:30
try :
sf_secrets = json . loads ( get_secret ( ) )
conn = snowflake . connector . connect (
user = sf_secrets . get ( ' user ' ) ,
password = sf_secrets . get ( ' password ' ) ,
account = " aarete-doczyai " ,
role = " DEVADMIN " ,
warehouse = " DEV_XS " ,
database = " DOCZY_DEV " ,
schema = " STG "
)
cur = conn . cursor ( )
query = ' select * from " TRAINING_DATA_RAW " '
cur . execute ( query )
field_values = pd . DataFrame . from_records ( iter ( cur ) , columns = [ x [ 0 ] for x in cur . description ] )
# st.write(field_values)
field_values [ ' Document_Name ' ] = field_values [ ' DOCUMENT_NAME ' ]
# field_values['Contract ID'] = field_values['CONTRACT_TITLE']
# error('table values are incorrect')
except :
field_values = pd . read_csv ( ' contract_field_values.csv ' , encoding = ' unicode_escape ' , skipinitialspace = True )
field_values . rename ( columns = { ' (internal) Document Name ' : ' Document_Name ' } , inplace = True )
# field_values.rename(columns={'(Internal) Carveout ID': 'Contract ID'}, inplace = True)
# st.write("conn failed")
try :
query = ' select * from " PROMPT_CONFIG " '
cur . execute ( query )
fields = pd . DataFrame ( cur . fetchall ( ) )
fields . rename ( columns = { ' FIELD_DESC ' : ' Field Name ' } , inplace = True )
fields . rename ( columns = { ' PROMPT ' : ' Interrogation Question? ' } , inplace = True )
fields . rename ( columns = { ' GROUP_ID ' : ' PRIORITY ' } , inplace = True )
fields . rename ( columns = { ' FIELD_NAME ' : ' SF_DB_COL_NAME ' } , inplace = True )
fields . rename ( columns = { ' FM_MODEL_ID ' : ' llm_selected ' } , inplace = True )
error ( ' table is empty ' )
except :
fields = pd . read_csv ( ' contract_fields.csv ' , encoding = ' unicode_escape ' , skipinitialspace = True )
fields = fields . drop_duplicates ( subset = ' Field Name ' , keep = " first " ) . sort_values ( ' Field Name ' )
fields = fields [ ~ fields [ ' Field Name ' ] . isnull ( ) ]
s3_client = boto3 . client ( ' s3 ' ,
2024-04-02 19:20:12 +05:30
region_name = " us-east-2 "
2024-03-22 23:59:54 +05:30
)
bucket = ' doczy-dev-infra-textract '
2024-04-19 17:16:13 +05:30
objects = s3_client . list_objects_v2 ( Bucket = bucket , Prefix = " training-data/ " )
2024-03-22 23:59:54 +05:30
file_list = [ ]
for obj in objects [ ' Contents ' ] :
if not obj [ ' Key ' ] . endswith ( ' / ' ) :
file_list . append ( obj [ ' Key ' ] )
contract_list = sorted ( file_list )
# to be deleted later
contract_list = [ contract for contract in contract_list if contract . rsplit ( ' / ' , 1 ) [ 1 ] . replace ( ' MU ' , ' ' ) . replace ( ' _MU ' , ' ' ) . replace ( ' .txt ' , ' ' ) in list ( field_values [ ' Document_Name ' ] ) ]
2024-03-13 17:23:20 +05:30
if user_mail in user_list :
2024-03-08 17:36:36 +05:30
file_row = st . columns ( [ 0.2 , 0.7 , 0.1 ] )
with file_row [ 0 ] :
st . write ( " **Contract Name** " )
with file_row [ 1 ] :
# file_name = st.text_input("**Contract Name**", label_visibility = "collapsed")
2024-03-22 23:59:54 +05:30
file_name = st . selectbox ( ' Select a file ' , contract_list + [ ' All ' ] , label_visibility = " collapsed " )
2024-03-08 17:36:36 +05:30
# lob_row = st.columns([0.2, 0.7, 0.1])
# with lob_row[0]:
# st.write("**LOB**")
# with lob_row[1]:
# lob = st.selectbox('LOB',('Medicare', 'Medicaid'), label_visibility = "collapsed")
2024-03-13 17:23:20 +05:30
field_row = st . columns ( [ 0.2 , 0.7 , 0.1 ] )
with field_row [ 0 ] :
st . write ( " **Field Group** " )
with field_row [ 1 ] :
field_group = st . selectbox ( ' Field Group ' , ( ' Unique Key ' , ' Contract Related ' , ' Pricing Before Carveouts - I '
, ' Pricing Before Carveouts - II ' , ' Carveout Indicator, Code Type and Code #s - I '
, ' Carveout Indicator, Code Type and Code #s - II ' , ' Carveout Indicator, Code Type and Code #s - III '
, ' Optimize Carving Indic. ' , ' Carveout Method - I ' , ' Carveout Method - II ' , ' Provider '
, ' Timeline ' ) , label_visibility = " collapsed " )
2024-04-03 15:28:40 +05:30
# llm_row = st.columns([0.2, 0.7, 0.1])
# with llm_row[0]:
# st.write("**Langauge Model**")
# with llm_row[1]:
# llm_selected = st.selectbox('Langauge Model',('Claude 2', 'Claude Instant', 'Llama 2 Chat 70B'
# , 'Titan Text Express'), index=1, label_visibility = "collapsed")
llm_selected = ' Claude Instant '
2024-03-13 17:23:20 +05:30
if field_group == ' Unique Key ' :
fields = fields [ fields [ ' PRIORITY ' ] == ' A ' ]
elif field_group == ' Contract Related ' :
fields = fields [ fields [ ' PRIORITY ' ] == ' C ' ]
elif field_group == ' Pricing Before Carveouts - I ' :
fields = fields [ fields [ ' PRIORITY ' ] == ' B ' ]
fields = np . array_split ( fields , 2 ) [ 0 ]
elif field_group == ' Pricing Before Carveouts - II ' :
fields = fields [ fields [ ' PRIORITY ' ] == ' B ' ]
fields = np . array_split ( fields , 2 ) [ 1 ]
elif field_group == ' Carveout Indicator, Code Type and Code #s - I ' :
fields = fields [ fields [ ' PRIORITY ' ] == ' F ' ]
fields = np . array_split ( fields , 3 ) [ 0 ]
elif field_group == ' Carveout Indicator, Code Type and Code #s - II ' :
fields = fields [ fields [ ' PRIORITY ' ] == ' F ' ]
fields = np . array_split ( fields , 3 ) [ 1 ]
elif field_group == ' Carveout Indicator, Code Type and Code #s - III ' :
fields = fields [ fields [ ' PRIORITY ' ] == ' F ' ]
fields = np . array_split ( fields , 3 ) [ 2 ]
elif field_group == ' Carveout Methodology - I ' :
fields = fields [ fields [ ' PRIORITY ' ] == ' G ' ]
fields = np . array_split ( fields , 4 ) [ 0 ]
elif field_group == ' Carveout Methodology - II ' :
fields = fields [ fields [ ' PRIORITY ' ] == ' G ' ]
fields = np . array_split ( fields , 4 ) [ 1 ]
elif field_group == ' Carveout Method - III ' :
fields = fields [ fields [ ' PRIORITY ' ] == ' G ' ]
fields = np . array_split ( fields , 4 ) [ 2 ]
elif field_group == ' Carveout Method - IV ' :
fields = fields [ fields [ ' PRIORITY ' ] == ' G ' ]
fields = np . array_split ( fields , 4 ) [ 3 ]
elif field_group == ' Provider ' :
fields = fields [ fields [ ' PRIORITY ' ] == ' D ' ]
elif field_group == ' Timeline ' :
fields = fields [ fields [ ' PRIORITY ' ] == ' E ' ]
fields [ ' Interrogation Question? ' ] = fields [ ' Interrogation Question? ' ] . fillna ( ' ' )
field_prompt_mapping = dict ( zip ( fields [ ' Field Name ' ] , fields [ ' Interrogation Question? ' ] ) )
2024-03-08 17:36:36 +05:30
# Setup bedrock
bedrock_runtime = boto3 . client (
service_name = " bedrock-runtime " ,
region_name = " us-east-1 "
2024-02-28 18:23:22 +05:30
)
2024-03-08 17:36:36 +05:30
2024-03-13 17:23:20 +05:30
# question_list = list(field_prompt_mapping.items())
# class OutputSchema(BaseModel):
# question_list[0]: str
# question_list[1]: str
# question_list[2]: str
# question_list[3]: str
# question_list[4]: str
# question_list[5]: str
# question_list[6]: str
# question_list[7]: str
# question_list[8]: str
# question_list[9]: str
# question_list[10]: str
# question_list[11]: str
# question_list[12]: str
# question_list[13]: str
# question_list[14]: str
# question_list[15]: str
# question_list[16]: str
# question_list[17]: str
# question_list[18]: str
# question_list[19]: str
# class OutputList(BaseModel):
# answer: List[OutputSchema]
# question = '\\n'.join(question_list)
question = json . dumps ( field_prompt_mapping )
# question_with_schema = f'{question}{OutputList.schema_json()}'
question_with_schema = question
2024-03-22 23:59:54 +05:30
def run_llm ( bucket , file_name , llm_selected , field_values ) :
# with open(os.path.join(SOURCE_DIRECTORY, file_name), 'r') as infile:
# context = infile.read()
# # page_count = context.count('Start of Page No. = ')
data = s3_client . get_object ( Bucket = bucket , Key = file_name )
contents = data [ ' Body ' ] . read ( )
context = contents . decode ( " utf-8 " )
2024-03-13 17:23:20 +05:30
2024-03-22 23:59:54 +05:30
if llm_selected == " Titan Text Express " :
context = context [ : 16000 ]
prompt_data = f """ Answer the question based only on the information provided between ## and give step by step guide. You must answer in correct JSON format.
#
{ context }
#
Question: { question }
Answer: Answer in JSON format: {{
"""
parameters = {
" maxTokenCount " : 1024 ,
" stopSequences " : [ ] ,
" temperature " : 0 ,
" topP " : 0.9
}
body = json . dumps ( { " inputText " : prompt_data , " textGenerationConfig " : parameters } )
model_id = " amazon.titan-text-express-v1 " # change this to use a different version from the model provider
2024-03-08 17:36:36 +05:30
2024-03-22 23:59:54 +05:30
elif llm_selected == ' Llama 2 Chat 70B ' :
context = context [ : 6000 ]
prompt_data = f """ Answer the question based only on the information provided between ## and give step by step guide. You must answer in correct JSON format.
##
{ context }
##
Question: { question }
Answer: Answer in JSON format: {{
"""
payload = {
" prompt " : " [INST] " + prompt_data + " [/INST] " ,
" max_gen_len " : 1024 ,
" temperature " : 0.0 ,
" top_p " : 0.9
}
body = json . dumps ( payload )
model_id = " meta.llama2-70b-chat-v1 "
2024-03-08 17:36:36 +05:30
2024-03-22 23:59:54 +05:30
elif llm_selected in [ ' Claude Instant ' , ' Claude 2 ' ] :
if llm_selected == ' Claude Instant ' :
context = context [ : 150000 ]
2024-03-08 17:36:36 +05:30
2024-03-22 23:59:54 +05:30
prompt_data = f """
2024-03-08 17:36:36 +05:30
2024-03-22 23:59:54 +05:30
Human: Use the following pieces of context to provide a concise answer to the questions at the end. If you don ' t know the answer, just say that you don ' t know, don ' t try to make up an answer. You must answer in JSON format.
2024-03-08 17:36:36 +05:30
2024-03-22 23:59:54 +05:30
{ context }
2024-03-13 17:23:20 +05:30
2024-03-22 23:59:54 +05:30
Question: { question_with_schema }
2024-03-13 17:23:20 +05:30
2024-03-22 23:59:54 +05:30
Assistant: Answer in JSON format: {{
"""
body = json . dumps (
{ " prompt " : anthropic . HUMAN_PROMPT + prompt_data + anthropic . AI_PROMPT ,
" max_tokens_to_sample " : 1024 ,
" temperature " : 0.0 ,
" top_p " : 1 ,
" top_k " : 250 ,
" stop_sequences " : [ anthropic . HUMAN_PROMPT ]
} )
if llm_selected == " Claude 2 " :
model_id = " anthropic.claude-v2:1 "
else :
model_id = " anthropic.claude-instant-v1 "
2024-02-28 18:23:22 +05:30
2024-03-08 17:36:36 +05:30
2024-03-22 23:59:54 +05:30
# def claude_prompt_format(prompt: str) -> str:
# # Add headers to start and end of prompt
# return "\n\nHuman: " + prompt + "\n\nAssistant:"
2024-03-13 17:23:20 +05:30
2024-03-22 23:59:54 +05:30
# # Call Claude model
# def call_claude(prompt):
# prompt_config = {
# "prompt": claude_prompt_format(prompt),
# "max_tokens_to_sample": 4096,
# "temperature": 0.5,
# "top_k": 250,
# "top_p": 0.5,
# "stop_sequences": [],
# }
2024-03-13 17:23:20 +05:30
2024-03-22 23:59:54 +05:30
# body = json.dumps(prompt_config)
2024-03-13 17:23:20 +05:30
2024-03-22 23:59:54 +05:30
# modelId = "anthropic.claude-instant-v1"
# accept = "application/json"
# contentType = "application/json"
2024-03-13 17:23:20 +05:30
2024-03-22 23:59:54 +05:30
# response = bedrock_runtime.invoke_model(
# body=body, modelId=modelId, accept=accept, contentType=contentType
# )
# response_body = json.loads(response.get("body").read())
2024-03-13 17:23:20 +05:30
2024-03-22 23:59:54 +05:30
# results = response_body.get("completion")
# return results
2024-03-13 17:23:20 +05:30
2024-03-22 23:59:54 +05:30
# prompt = SECOND_PROMPT
# result = call_claude(prompt)
# st.write(result)
2024-03-13 17:23:20 +05:30
2024-03-22 23:59:54 +05:30
df = pd . DataFrame ( columns = [ ' Contract Name ' , ' Field Name ' , ' Snippet ' , ' Page Number ' ,
' Field Extracted Value ' , ' Imputed Value ' ] )
# field_list = list(field_prompt_mapping.keys())
# query_list = [field_prompt_mapping[x] for x in field_list]
# st.write(field_prompt_mapping)
2024-03-08 17:36:36 +05:30
2024-03-22 23:59:54 +05:30
# st.write(prompt_data)
2024-03-13 17:23:20 +05:30
2024-03-22 23:59:54 +05:30
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 == " Titan Text Express " :
response_text = response_body . get ( " results " ) [ 0 ] . get ( " outputText " )
elif llm_selected == ' Llama 2 Chat 70B ' :
response_text = response_body [ ' generation ' ]
elif llm_selected in [ ' Claude Instant ' , ' Claude 2 ' ] :
response_text = response_body [ ' completion ' ]
except :
response_text = " failed "
2024-03-13 17:23:20 +05:30
2024-03-22 23:59:54 +05:30
raw_response_text = response_text
2024-03-13 17:23:20 +05:30
response_text = response_text . strip ( )
2024-03-22 23:59:54 +05:30
2024-03-13 17:23:20 +05:30
try :
if response_text . split ( " { " , 1 ) [ 1 ] . strip ( ) [ 0 ] == ' " ' :
response_text = " { " + response_text . split ( " { " , 1 ) [ 1 ]
else :
response_text = " { " + response_text
except :
response_text = " { " + response_text
if len ( response_text . split ( " } " , 1 ) ) > 1 :
if response_text . rsplit ( " } " , 1 ) [ 0 ] . strip ( ) [ - 1 ] == ' " ' :
response_text = response_text . rsplit ( " } " , 1 ) [ 0 ] + " } "
else :
response_text = response_text . rstrip ( " , " )
response_text = response_text + " } "
try :
response_dict = json . loads ( response_text )
except :
response_dict = { " Test value " : " Failed to extract " }
# st.write(response_dict)
field_list = list ( response_dict . keys ( ) )
answer_list = list ( response_dict . values ( ) )
# st.write(answer_list)
location_list = [ context . find ( answer ) if isinstance ( answer , str ) and answer != " " else - 1 for answer in answer_list ]
snippet_list = [ ' ' . join ( context [ : location ] . split ( ' . ' ) [ - 4 : ] ) + ' ' + ' ' . join ( context [ location : ] . split ( ' . ' ) [ : 5 ]
) if location != - 1 else ' ' for location in location_list ]
page_no_list = [ " " if location == - 1 else context [ : location ] . rsplit ( " Start of Page No. = " , 1 ) [ 1 ] if len ( context [ : location ] . rsplit (
" Start of Page No. = " , 1 ) ) > 1 else context [ : location ] . rsplit ( " Start of Page No. = " , 1 ) [ 0 ] for location in location_list ]
# st.write(location_list)
page_no_list = [ re . search ( r ' \ d+ ' , page ) . group ( ) if page != " " and re . search ( r ' \ d+ ' , page ) is not None else " " for page in page_no_list ]
# response_list = [QA({"query":query}) for query in query_list]
# answer_list = [response['result'] for response in response_list]
# doc_list = [response['source_documents'] for response in response_list]
# snippet_list = [str(doc[0].page_content) for doc in doc_list]
# page_no_list = [int(str(doc[0].metadata["source"]).rsplit('_page')[1].replace('.txt',''))+1 for doc in doc_list]
2024-03-08 17:36:36 +05:30
df [ ' Field Name ' ] = field_list
df [ ' Contract Name ' ] = file_name
df [ ' Snippet ' ] = snippet_list
df [ ' Page Number ' ] = page_no_list
2024-03-13 17:23:20 +05:30
# df['Confidence Level'] = ' '
2024-03-08 17:36:36 +05:30
df [ ' Field Extracted Value ' ] = answer_list
2024-03-22 23:59:54 +05:30
df = pd . merge ( df , fields [ [ ' Field Name ' , ' SF_DB_COL_NAME ' ] ] , how = ' left ' , on = ' Field Name ' )
document_name = [ x for x in list ( field_values [ ' Document_Name ' ] ) if not pd . isna ( x ) and file_name . rsplit ( ' / ' , 1 ) [ 1 ] . replace ( ' MU ' , ' ' ) . replace (
' _MU ' , ' ' ) . replace ( ' .txt ' , ' ' ) in x ] [ 0 ]
field_values = field_values [ field_values [ ' Document_Name ' ] == document_name ] . head ( 1 ) . transpose ( ) . reset_index ( )
field_values . columns = [ ' SF_DB_COL_NAME ' , ' Actual Value ' ]
df = pd . merge ( df , field_values , how = ' left ' , on = ' SF_DB_COL_NAME ' )
df = df [ [ ' Contract Name ' , ' Field Name ' , ' SF_DB_COL_NAME ' , ' Snippet ' , ' Page Number ' , ' Field Extracted Value ' , ' Actual Value ' , ' Imputed Value ' ] ]
return df , raw_response_text
raw_response_text = ' { " Test value " : " Failed to extract " } '
if st . button ( " Show Results " ) :
if file_name == ' All ' :
df_1 = pd . DataFrame ( columns = [ ' Contract Name ' , ' Field Name ' , ' SF_DB_COL_NAME ' , ' Snippet ' , ' Page Number '
, ' Field Extracted Value ' , ' Actual Value ' , ' Imputed Value ' ] )
for contract in contract_list :
print ( contract )
df , raw_response_text = run_llm ( bucket , contract , llm_selected , field_values )
df_1 = pd . concat ( [ df_1 , df ] , ignore_index = True )
else :
df_1 , raw_response_text = run_llm ( bucket , file_name , llm_selected , field_values )
df_1 . to_csv ( ' temp2.csv ' , index = False )
2024-03-08 17:36:36 +05:30
df2 = pd . read_csv ( ' temp2.csv ' )
df2 [ ' Imputed Value ' ] = ' '
edited_df = st . data_editor ( df2 )
@st.cache_data
def convert_df ( df ) :
return df . to_csv ( index = False ) . encode ( ' utf-8 ' )
csv = convert_df ( edited_df )
buttons = st . columns ( 3 )
with buttons [ 0 ] :
2024-03-28 17:53:00 +05:30
# st.button("Save All Imputations")
2024-03-08 17:36:36 +05:30
st . download_button ( " Download Table " , csv , " file.csv " , " text/csv " , key = ' download-csv ' )
2024-03-28 17:53:00 +05:30
with buttons [ 1 ] :
# st.download_button("Download Table", csv, "file.csv", "text/csv", key='download-csv')
2024-03-29 15:36:46 +05:30
st . write ( " " )
2024-03-08 17:36:36 +05:30
with buttons [ 2 ] :
st . button ( " Kickoff Database Integration " )
2024-03-22 23:59:54 +05:30
add_vertical_space ( 20 )
st . write ( raw_response_text )
2024-03-08 17:36:36 +05:30
else :
st . write ( " Access Denied " )
2024-02-28 18:23:22 +05:30