added better app for chat history - trialapp.py
Browse files- trialapp.py +139 -0
trialapp.py
ADDED
@@ -0,0 +1,139 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Importing libraries
|
2 |
+
import streamlit as st
|
3 |
+
from langchain.chains.history_aware_retriever import create_history_aware_retriever
|
4 |
+
from langchain.chains.retrieval import create_retrieval_chain
|
5 |
+
from langchain.chains.combine_documents import create_stuff_documents_chain
|
6 |
+
from langchain_community.vectorstores import FAISS
|
7 |
+
from langchain_community.chat_message_histories import ChatMessageHistory
|
8 |
+
from langchain_core.chat_history import BaseChatMessageHistory
|
9 |
+
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
|
10 |
+
from langchain_groq import ChatGroq
|
11 |
+
from langchain_core.runnables.history import RunnableWithMessageHistory
|
12 |
+
from langchain_huggingface import HuggingFaceEmbeddings
|
13 |
+
from langchain_text_splitters import RecursiveCharacterTextSplitter
|
14 |
+
from langchain_community.document_loaders import PyPDFLoader
|
15 |
+
import os
|
16 |
+
from dotenv import load_dotenv
|
17 |
+
|
18 |
+
# Load environment variables
|
19 |
+
load_dotenv()
|
20 |
+
|
21 |
+
# API and model settings
|
22 |
+
os.environ['HF_TOKEN'] = os.getenv('HF_TOKEN')
|
23 |
+
os.environ['GROQ_API_KEY'] = os.getenv('GROQ_API_KEY')
|
24 |
+
embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
|
25 |
+
|
26 |
+
# Streamlit app
|
27 |
+
st.title("PDFSense : PDF Question and Answering with Session Chat History")
|
28 |
+
st.write("Upload PDFs and ask questions related to the content of the PDFs.")
|
29 |
+
llm = ChatGroq(model="Gemma2-9b-It")
|
30 |
+
session_id = st.text_input("Session ID", value="common_session")
|
31 |
+
|
32 |
+
# Manage chat history
|
33 |
+
if 'store' not in st.session_state:
|
34 |
+
st.session_state.store = {}
|
35 |
+
|
36 |
+
# Upload files and document loading
|
37 |
+
uploaded_files = st.file_uploader("Drop the PDF files here", type="pdf", accept_multiple_files=True)
|
38 |
+
|
39 |
+
if uploaded_files:
|
40 |
+
documents = []
|
41 |
+
for uploaded_file in uploaded_files:
|
42 |
+
temppdf = f"./temp.pdf"
|
43 |
+
with open(temppdf, "wb") as file:
|
44 |
+
file.write(uploaded_file.getvalue())
|
45 |
+
docs = PyPDFLoader(temppdf).load()
|
46 |
+
documents.extend(docs)
|
47 |
+
|
48 |
+
# Delete the temp file as we no longer need it
|
49 |
+
if os.path.exists("./temp.pdf"):
|
50 |
+
os.remove("./temp.pdf")
|
51 |
+
|
52 |
+
# Text splitting and embedding, storing in FAISS index
|
53 |
+
text_splitter = RecursiveCharacterTextSplitter(chunk_size=5000, chunk_overlap=500)
|
54 |
+
splits = text_splitter.split_documents(documents)
|
55 |
+
faiss_index = FAISS.from_documents(splits, embeddings)
|
56 |
+
retriever = faiss_index.as_retriever()
|
57 |
+
|
58 |
+
# Prompts
|
59 |
+
context_system_prompt = (
|
60 |
+
"Given a chat history and the latest user question, "
|
61 |
+
"which might reference context in the chat history, "
|
62 |
+
"formulate a standalone question that can be understood "
|
63 |
+
"without the chat history. Do not answer the question, "
|
64 |
+
"just reformulate it if needed and otherwise return it as it is."
|
65 |
+
)
|
66 |
+
context_prompt = ChatPromptTemplate.from_messages([
|
67 |
+
("system", context_system_prompt),
|
68 |
+
MessagesPlaceholder("chat_history"),
|
69 |
+
("human", "{input}")
|
70 |
+
])
|
71 |
+
|
72 |
+
history_aware_ret = create_history_aware_retriever(llm, retriever, context_prompt)
|
73 |
+
|
74 |
+
system_prompt = (
|
75 |
+
"You are 'PDFSense', a PDF reading and answering assistant. "
|
76 |
+
"Use the following pieces of retrieved context to answer "
|
77 |
+
"the question. If you don't know the answer, say that you don't know. "
|
78 |
+
"Answer the questions nicely."
|
79 |
+
"\n\n"
|
80 |
+
"{context}"
|
81 |
+
)
|
82 |
+
|
83 |
+
prompt = ChatPromptTemplate.from_messages([
|
84 |
+
("system", system_prompt),
|
85 |
+
MessagesPlaceholder("chat_history"),
|
86 |
+
("human", "{input}")
|
87 |
+
])
|
88 |
+
|
89 |
+
# Chain for the chatbot
|
90 |
+
qa_chain = create_stuff_documents_chain(llm, prompt)
|
91 |
+
rag_chain = create_retrieval_chain(history_aware_ret, qa_chain)
|
92 |
+
|
93 |
+
# Session ID storing in chat history
|
94 |
+
def get_session_history(session: str) -> BaseChatMessageHistory:
|
95 |
+
if session_id not in st.session_state.store:
|
96 |
+
st.session_state.store[session_id] = ChatMessageHistory()
|
97 |
+
return st.session_state.store[session_id]
|
98 |
+
|
99 |
+
# RAG with history
|
100 |
+
conversation_rag = RunnableWithMessageHistory(
|
101 |
+
rag_chain,
|
102 |
+
get_session_history,
|
103 |
+
input_messages_key="input",
|
104 |
+
history_messages_key="chat_history",
|
105 |
+
output_messages_key="answer"
|
106 |
+
)
|
107 |
+
|
108 |
+
user_input = st.text_input("Enter your question")
|
109 |
+
if user_input:
|
110 |
+
session_history = get_session_history(session_id)
|
111 |
+
response = conversation_rag.invoke(
|
112 |
+
{"input": user_input},
|
113 |
+
config={
|
114 |
+
"configurable": {"session_id": session_id}
|
115 |
+
},
|
116 |
+
)
|
117 |
+
|
118 |
+
# Display the chat history
|
119 |
+
st.write("### Chat History")
|
120 |
+
for message in session_history.messages:
|
121 |
+
if isinstance(message, dict): # Handle cases where messages might be dictionaries
|
122 |
+
role = message.get("role", "user") # Default role is 'user'
|
123 |
+
content = message.get("content", "")
|
124 |
+
else:
|
125 |
+
# For LangChain message objects
|
126 |
+
role = "user" if isinstance(message, ChatMessageHistory) else "assistant"
|
127 |
+
content = message.content
|
128 |
+
|
129 |
+
if role == "user":
|
130 |
+
with st.chat_message("user"):
|
131 |
+
st.write(content)
|
132 |
+
elif role == "assistant":
|
133 |
+
with st.chat_message("assistant"):
|
134 |
+
st.write(content)
|
135 |
+
elif role == "system":
|
136 |
+
with st.chat_message("system"):
|
137 |
+
st.markdown(f"**System Message:** {content}")
|
138 |
+
|
139 |
+
#st.write("Assistant:", response['answer'])
|