AlirezaHSZ commited on
Commit
720b5a8
·
verified ·
1 Parent(s): 6b2c7fb

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +55 -62
app.py CHANGED
@@ -1,68 +1,65 @@
1
  import os
2
  import fitz # PyMuPDF
3
- from langchain.text_splitter import RecursiveCharacterTextSplitter
4
- from langchain_google_genai import GoogleGenerativeAIEmbeddings
5
  import streamlit as st
6
  import google.generativeai as genai
7
- from langchain.vectorstores import FAISS
8
- from langchain_google_genai import ChatGoogleGenerativeAI
9
- from langchain.chains.question_answering import load_qa_chain
10
- from langchain.prompts import PromptTemplate
11
  from dotenv import load_dotenv
12
  from google.api_core.exceptions import GoogleAPIError, InvalidArgument
13
 
 
 
 
 
 
 
14
  # Load environment variables
15
  load_dotenv()
16
  api_key = os.getenv("GOOGLE_API_KEY")
17
  genai.configure(api_key=api_key)
18
 
19
 
20
- # ---------------- PDF Extraction ----------------
21
  def get_pdf_text(pdf_docs):
22
- """Extract text from uploaded PDFs (supports Farsi + English)."""
23
  text = ""
24
  for pdf in pdf_docs:
25
- doc = fitz.open(stream=pdf.read(), filetype="pdf")
26
- for page in doc:
27
- page_text = page.get_text("text")
28
- if page_text:
29
- text += page_text + "\n"
30
  return text
31
 
32
 
33
- # ---------------- Text Chunking ----------------
34
  def get_text_chunks(text):
35
- """Split text into smaller chunks for embedding."""
36
- splitter = RecursiveCharacterTextSplitter(
37
- chunk_size=800,
38
- chunk_overlap=150,
39
- separators=["\n\n", "\n", " ", ""]
40
- )
41
- return splitter.split_text(text)
42
 
43
 
44
- # ---------------- FAISS Vector Store ----------------
45
  def get_vector_store(chunks):
46
- """Create and store FAISS index in session state."""
47
  try:
48
  embeddings = GoogleGenerativeAIEmbeddings(model="models/text-embedding-004")
49
  vector_store = FAISS.from_texts(chunks, embedding=embeddings)
50
- st.session_state.vector_store = vector_store
51
- except (GoogleAPIError, InvalidArgument):
52
- raise RuntimeError("Error processing embeddings. Please try again in a minute.")
53
 
54
 
55
- # ---------------- Conversational Chain ----------------
56
  def get_conversational_chain():
57
- """Create QA chain with custom prompt."""
58
  prompt_template = """
59
- You are a helpful assistant.
60
- Always answer in the same language as the question (Farsi or English).
61
- If the answer is not in the provided context, reply with:
62
- "پاسخ در متن موجود نیست" for Farsi OR "answer is not available in the context" for English.
 
 
 
 
 
 
63
 
64
- Context:\n {context}\n
65
- Question:\n {question}\n
66
  Answer:
67
  """
68
  try:
@@ -70,28 +67,29 @@ def get_conversational_chain():
70
  prompt = PromptTemplate(template=prompt_template, input_variables=["context", "question"])
71
  chain = load_qa_chain(llm=model, chain_type="stuff", prompt=prompt)
72
  return chain
73
- except (GoogleAPIError, InvalidArgument):
74
- raise RuntimeError("Error creating conversational chain. Please try again in a minute.")
75
 
76
 
77
- # ---------------- Chat Functions ----------------
78
  def clear_chat_history():
79
- st.session_state.messages = [
80
- {"role": "assistant", "content": "در خدمتیم"}]
81
 
82
 
 
83
  def user_input(user_question):
84
- """Handle user query and return response."""
85
  try:
86
- docs = st.session_state.vector_store.similarity_search(user_question, k=4)
 
 
87
  chain = get_conversational_chain()
88
  response = chain({"input_documents": docs, "question": user_question}, return_only_outputs=True)
89
- return response['output_text']
90
- except (GoogleAPIError, InvalidArgument):
91
- raise RuntimeError("لطفا پس از چند لحظه دوباره امتحان کنید ")
92
 
93
 
94
- # ---------------- Main App ----------------
95
  def main():
96
  st.set_page_config(
97
  page_title="Chatbot",
@@ -99,7 +97,7 @@ def main():
99
  initial_sidebar_state="expanded"
100
  )
101
 
102
- # Custom CSS for better design
103
  st.markdown(
104
  """
105
  <style>
@@ -117,7 +115,6 @@ def main():
117
  unsafe_allow_html=True
118
  )
119
 
120
- # Initialize session state variables
121
  if "uploaded" not in st.session_state:
122
  st.session_state.uploaded = False
123
 
@@ -128,12 +125,12 @@ def main():
128
  if st.button("تایید"):
129
  if pdf_docs:
130
  try:
131
- st.info("در حال پردازش")
132
  raw_text = get_pdf_text(pdf_docs)
133
  text_chunks = get_text_chunks(raw_text)
134
  get_vector_store(text_chunks)
135
  st.session_state.uploaded = True
136
- st.success("پردازش موفق")
137
  except RuntimeError as e:
138
  st.error(str(e))
139
  else:
@@ -141,40 +138,36 @@ def main():
141
  else:
142
  # Chat Page
143
  st.title("Assistant ready ...")
144
- st.write("میتونین سوالتونو بپرسین")
145
 
146
- # Add a "Return" button to go back to the upload page
147
  if st.button("بازگشت به صفحه آپلود"):
148
- st.session_state.uploaded = False
149
- st.session_state.messages = [{"role": "assistant", "content": "در خدمتیم"}]
150
  st.rerun()
151
 
152
  st.button('حذف مکالمه', on_click=clear_chat_history)
153
 
154
- # Initialize chat history
155
  if "messages" not in st.session_state:
156
- st.session_state.messages = [
157
- {"role": "assistant", "content": "در خدمتیم"}]
158
 
159
- # Display chat messages
160
  for message in st.session_state.messages:
161
  with st.chat_message(message["role"]):
162
  st.write(message["content"])
163
 
164
- # Chat input
165
  if prompt := st.chat_input():
166
  st.session_state.messages.append({"role": "user", "content": prompt})
167
  with st.chat_message("user"):
168
  st.write(prompt)
169
 
170
- # Generate bot response
171
  if st.session_state.messages[-1]["role"] != "assistant":
172
  try:
173
  with st.chat_message("assistant"):
174
  response = user_input(prompt)
175
- st.write(response)
176
- message = {"role": "assistant", "content": response}
177
- st.session_state.messages.append(message)
 
178
  except RuntimeError as e:
179
  st.error(str(e))
180
 
 
1
  import os
2
  import fitz # PyMuPDF
 
 
3
  import streamlit as st
4
  import google.generativeai as genai
 
 
 
 
5
  from dotenv import load_dotenv
6
  from google.api_core.exceptions import GoogleAPIError, InvalidArgument
7
 
8
+ from langchain.text_splitter import RecursiveCharacterTextSplitter
9
+ from langchain_google_genai import GoogleGenerativeAIEmbeddings, ChatGoogleGenerativeAI
10
+ from langchain_community.vectorstores import FAISS
11
+ from langchain.chains.question_answering import load_qa_chain
12
+ from langchain.prompts import PromptTemplate
13
+
14
  # Load environment variables
15
  load_dotenv()
16
  api_key = os.getenv("GOOGLE_API_KEY")
17
  genai.configure(api_key=api_key)
18
 
19
 
20
+ # Function to read all PDF files (Farsi + English)
21
  def get_pdf_text(pdf_docs):
 
22
  text = ""
23
  for pdf in pdf_docs:
24
+ with fitz.open(stream=pdf.read(), filetype="pdf") as doc:
25
+ for page in doc:
26
+ page_text = page.get_text("text")
27
+ if page_text:
28
+ text += page_text + "\n"
29
  return text
30
 
31
 
32
+ # Function to split text into chunks
33
  def get_text_chunks(text):
34
+ splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
35
+ chunks = splitter.split_text(text)
36
+ return chunks
 
 
 
 
37
 
38
 
39
+ # Function to get embeddings for each chunk and save to vector store
40
  def get_vector_store(chunks):
 
41
  try:
42
  embeddings = GoogleGenerativeAIEmbeddings(model="models/text-embedding-004")
43
  vector_store = FAISS.from_texts(chunks, embedding=embeddings)
44
+ vector_store.save_local("faiss_index")
45
+ except Exception as e:
46
+ raise RuntimeError(f"Error creating vector store: {e}")
47
 
48
 
49
+ # Function to get conversational chain
50
  def get_conversational_chain():
 
51
  prompt_template = """
52
+ You are a helpful assistant. Do NOT reveal your identity (Gemini) or the company (Google).
53
+ Answer the question as detailed as possible using ONLY the provided context.
54
+ If the answer is not in the context, say: "answer is not available in the context".
55
+ Do not make up answers.
56
+
57
+ Context:
58
+ {context}
59
+
60
+ Question:
61
+ {question}
62
 
 
 
63
  Answer:
64
  """
65
  try:
 
67
  prompt = PromptTemplate(template=prompt_template, input_variables=["context", "question"])
68
  chain = load_qa_chain(llm=model, chain_type="stuff", prompt=prompt)
69
  return chain
70
+ except Exception as e:
71
+ raise RuntimeError(f"Error creating conversational chain: {e}")
72
 
73
 
74
+ # Function to clear chat history
75
  def clear_chat_history():
76
+ st.session_state.messages = [{"role": "assistant", "content": "در خدمتیم"}]
 
77
 
78
 
79
+ # ✅ Function to handle user input
80
  def user_input(user_question):
 
81
  try:
82
+ embeddings = GoogleGenerativeAIEmbeddings(model="models/text-embedding-004")
83
+ new_db = FAISS.load_local("faiss_index", embeddings, allow_dangerous_deserialization=True)
84
+ docs = new_db.similarity_search(user_question, k=4)
85
  chain = get_conversational_chain()
86
  response = chain({"input_documents": docs, "question": user_question}, return_only_outputs=True)
87
+ return response
88
+ except Exception as e:
89
+ raise RuntimeError(f"Error while answering: {e}")
90
 
91
 
92
+ # Main function to run the Streamlit app
93
  def main():
94
  st.set_page_config(
95
  page_title="Chatbot",
 
97
  initial_sidebar_state="expanded"
98
  )
99
 
100
+ # Dark theme styling
101
  st.markdown(
102
  """
103
  <style>
 
115
  unsafe_allow_html=True
116
  )
117
 
 
118
  if "uploaded" not in st.session_state:
119
  st.session_state.uploaded = False
120
 
 
125
  if st.button("تایید"):
126
  if pdf_docs:
127
  try:
128
+ st.info("در حال پردازش ...")
129
  raw_text = get_pdf_text(pdf_docs)
130
  text_chunks = get_text_chunks(raw_text)
131
  get_vector_store(text_chunks)
132
  st.session_state.uploaded = True
133
+ st.success("پردازش موفق شد ✅")
134
  except RuntimeError as e:
135
  st.error(str(e))
136
  else:
 
138
  else:
139
  # Chat Page
140
  st.title("Assistant ready ...")
141
+ st.write("میتونین سوالتونو بپرسین 👇")
142
 
 
143
  if st.button("بازگشت به صفحه آپلود"):
144
+ st.session_state.uploaded = False
145
+ clear_chat_history()
146
  st.rerun()
147
 
148
  st.button('حذف مکالمه', on_click=clear_chat_history)
149
 
 
150
  if "messages" not in st.session_state:
151
+ st.session_state.messages = [{"role": "assistant", "content": "در خدمتیم"}]
 
152
 
153
+ # Show history
154
  for message in st.session_state.messages:
155
  with st.chat_message(message["role"]):
156
  st.write(message["content"])
157
 
 
158
  if prompt := st.chat_input():
159
  st.session_state.messages.append({"role": "user", "content": prompt})
160
  with st.chat_message("user"):
161
  st.write(prompt)
162
 
 
163
  if st.session_state.messages[-1]["role"] != "assistant":
164
  try:
165
  with st.chat_message("assistant"):
166
  response = user_input(prompt)
167
+ if response:
168
+ full_response = response['output_text']
169
+ st.write(full_response)
170
+ st.session_state.messages.append({"role": "assistant", "content": full_response})
171
  except RuntimeError as e:
172
  st.error(str(e))
173