KrishP-12 commited on
Commit
8fa1f05
·
verified ·
1 Parent(s): 9eebc53

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +211 -0
app.py ADDED
@@ -0,0 +1,211 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import os
3
+ from PIL import Image
4
+ import pytesseract
5
+ from pdf2image import convert_from_path
6
+ from langchain_community.embeddings import HuggingFaceEmbeddings
7
+ from langchain.prompts import PromptTemplate
8
+ from langchain.chains import RetrievalQA
9
+ from langchain.memory import ConversationBufferMemory
10
+ from langchain_groq import ChatGroq
11
+ from langchain_community.vectorstores import FAISS
12
+ from langchain.text_splitter import RecursiveCharacterTextSplitter
13
+ from langchain_core.vectorstores import VectorStoreRetriever
14
+
15
+ # Initialize the Groq API Key and the model
16
+ os.environ["GROQ_API_KEY"] = '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'
17
+ # config = {'max_new_tokens': 512, 'context_length': 8000}
18
+ llm = ChatGroq(
19
+ model='llama3-70b-8192',
20
+ temperature=0.5,
21
+ max_tokens=None,
22
+ timeout=None,
23
+ max_retries=2
24
+ )
25
+
26
+ # Define OCR functions for image and PDF files
27
+ def ocr_image(image_path, language='eng+guj'):
28
+ img = Image.open(image_path)
29
+ text = pytesseract.image_to_string(img, lang=language)
30
+ return text
31
+
32
+ def ocr_pdf(pdf_path, language='eng+guj'):
33
+ images = convert_from_path(pdf_path)
34
+ all_text = ""
35
+ for img in images:
36
+ text = pytesseract.image_to_string(img, lang=language)
37
+ all_text += text + "\n"
38
+ return all_text
39
+
40
+ def ocr_file(file_path):
41
+ file_extension = os.path.splitext(file_path)[1].lower()
42
+
43
+ if file_extension == ".pdf":
44
+ text_re = ocr_pdf(file_path, language='guj+eng')
45
+ elif file_extension in [".jpg", ".jpeg", ".png", ".bmp"]:
46
+ text_re = ocr_image(file_path, language='guj+eng')
47
+ else:
48
+ raise ValueError("Unsupported file format. Supported formats are PDF, JPG, JPEG, PNG, BMP.")
49
+
50
+ return text_re
51
+
52
+ def get_text_chunks(text):
53
+ text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=100)
54
+ chunks = text_splitter.split_text(text)
55
+ return chunks
56
+
57
+ # Function to create or update the vector store
58
+ def get_vector_store(text_chunks):
59
+ embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2", model_kwargs={'device': 'cpu'}, encode_kwargs={'normalize_embeddings': True})
60
+ vector_store = FAISS.from_texts(text_chunks, embedding=embeddings)
61
+
62
+ # Ensure the directory exists before saving the vector store
63
+ os.makedirs("faiss_index", exist_ok=True)
64
+ vector_store.save_local("faiss_index")
65
+
66
+ return vector_store
67
+
68
+ # Function to process multiple files and extract vector store
69
+ def process_ocr_and_pdf_files(file_paths):
70
+ raw_text = ""
71
+ for file_path in file_paths:
72
+ raw_text += ocr_file(file_path) + "\n"
73
+ text_chunks = get_text_chunks(raw_text)
74
+ return get_vector_store(text_chunks)
75
+
76
+ # embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/paraphrase-MiniLM-L6-v2", model_kwargs={'device': 'cpu'}, encode_kwargs={'normalize_embeddings': True})
77
+ # new_vector_store = FAISS.load_local(
78
+ # "faiss_index", embeddings, allow_dangerous_deserialization=True
79
+ # )
80
+
81
+ # docs = new_vector_store.similarity_search("qux")
82
+ # Conversational chain for Q&A
83
+ def get_conversational_chain():
84
+ template = """You are an intelligent educational assistant specialized in handling queries about documents. You have been provided with OCR-processed text from the uploaded files that contains important educational information.
85
+
86
+ Core Responsibilities:
87
+ 1. Language Processing:
88
+ - Identify the language of the user's query (English or Gujarati)
89
+ - Respond in the same language as the query
90
+ - If the query is in Gujarati, ensure the response maintains proper Gujarati grammar and terminology
91
+ - For technical terms, provide both English and Gujarati versions when relevant
92
+
93
+ 2. Document Understanding:
94
+ - Analyze the OCR-processed text from the uploaded files
95
+ - Account for potential OCR errors or misinterpretations
96
+ - Focus on extracting accurate information despite possible OCR imperfections
97
+
98
+ 3. Response Guidelines:
99
+ - Provide direct, clear answers based solely on the document content
100
+ - If information is unclear due to OCR quality, mention this limitation
101
+ - For numerical data (dates, percentages, marks), double-check accuracy before responding
102
+ - If information is not found in the documents, clearly state: "This information is not present in the uploaded documents"
103
+
104
+ 4. Educational Context:
105
+ - Maintain focus on educational queries related to the document content
106
+ - For admission-related queries, emphasize important deadlines and requirements
107
+ - For scholarship information, highlight eligibility criteria and application processes
108
+ - For course-related queries, provide detailed, accurate information from the documents
109
+
110
+ 5. Response Format:
111
+ - Structure responses clearly with relevant subpoints when necessary
112
+ - For complex information, break down the answer into digestible parts
113
+ - Include relevant reference points from the documents when applicable
114
+ - Format numerical data and dates clearly
115
+
116
+ 6. Quality Control:
117
+ - Verify that responses align with the document content
118
+ - Don't make assumptions beyond the provided information
119
+ - If multiple interpretations are possible due to OCR quality, mention all possibilities
120
+ - Maintain consistency in terminology throughout the conversation
121
+
122
+ Important Rules:
123
+ - Never make up information not present in the documents
124
+ - Don't combine information from previous conversations or external knowledge
125
+ - Always indicate if certain parts of the documents are unclear due to OCR quality
126
+ - Maintain professional tone while being accessible to students and parents
127
+ - If the query is out of scope of the uploaded documents, politely redirect to relevant official sources
128
+
129
+ Context from uploaded documents:
130
+ {context}
131
+
132
+ Chat History:
133
+ {history}
134
+
135
+ Current Question: {question}
136
+ Assistant: Let me provide a clear and accurate response based on the uploaded documents...
137
+ """
138
+ embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/paraphrase-MiniLM-L6-v2", model_kwargs={'device': 'cpu'}, encode_kwargs={'normalize_embeddings': True})
139
+ new_vector_store = FAISS.load_local(
140
+ "faiss_index", embeddings, allow_dangerous_deserialization=True
141
+ )
142
+ QA_CHAIN_PROMPT = PromptTemplate(input_variables=["history", "context", "question"], template=template)
143
+ qa_chain = RetrievalQA.from_chain_type(llm, retriever=new_vector_store.as_retriever(), chain_type='stuff', verbose=True, chain_type_kwargs={"verbose": True,"prompt": QA_CHAIN_PROMPT,"memory": ConversationBufferMemory(memory_key="history",input_key="question"),})
144
+ return qa_chain
145
+
146
+
147
+ def user_input(user_question):
148
+ embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2", model_kwargs={'device': 'cpu'}, encode_kwargs={'normalize_embeddings': True})
149
+ new_db = FAISS.load_local("faiss_index", embeddings, allow_dangerous_deserialization=True)
150
+ docs = new_db.similarity_search(user_question)
151
+ chain = get_conversational_chain()
152
+ response = chain({"input_documents": docs, "query": user_question}, return_only_outputs=True)
153
+ result = response.get("result", "No result found")
154
+
155
+ # Save the question and answer to session state for history tracking
156
+ if 'conversation_history' not in st.session_state:
157
+ st.session_state.conversation_history = []
158
+
159
+ # Append new question and response to the history
160
+ st.session_state.conversation_history.append({'question': user_question, 'answer': result})
161
+
162
+ return result
163
+
164
+ # Streamlit app to upload files and interact with the Q&A system
165
+ def main():
166
+ st.title("File Upload and OCR Processing")
167
+ st.write("Upload up to 5 files (PDF, JPG, JPEG, PNG, BMP)")
168
+
169
+ uploaded_files = st.file_uploader("Choose files", type=["pdf", "jpg", "jpeg", "png", "bmp"], accept_multiple_files=True)
170
+
171
+ if len(uploaded_files) > 0:
172
+ file_paths = []
173
+
174
+ # Save uploaded files and process them
175
+ for uploaded_file in uploaded_files[:5]: # Limit to 5 files
176
+ file_path = os.path.join("temp", uploaded_file.name)
177
+ os.makedirs(os.path.dirname(file_path), exist_ok=True)
178
+ with open(file_path, "wb") as f:
179
+ f.write(uploaded_file.getbuffer())
180
+ file_paths.append(file_path)
181
+
182
+ # Process the OCR and PDF files and store the vector data
183
+ st.write("Processing files...")
184
+ vector_store = process_ocr_and_pdf_files(file_paths)
185
+ st.write("Processing completed! The vector store has been updated.")
186
+
187
+ # Ask user for a question related to the documents
188
+ user_question = st.text_input("Ask a question related to the uploaded documents:")
189
+
190
+ if user_question:
191
+ response = user_input(user_question)
192
+ st.write("Answer:", response)
193
+
194
+ # Button to display chat history
195
+
196
+ # if st.button("Show Chat History"):
197
+ # history = st.session_state.get('history', [])
198
+ # if history:
199
+ # st.write("Conversation History:")
200
+ # for idx, (q, a) in enumerate(history):
201
+ # st.write(f"Q{idx+1}: {q}")
202
+ # st.write(f"A{idx+1}: {a}")
203
+ # else:
204
+ # st.write("No conversation history.")
205
+ with st.expander('Conversation History'):
206
+ for entry in st.session_state.conversation_history:
207
+ st.info(f"Q: {entry['question']}\nA: {entry['answer']}")
208
+
209
+
210
+ if __name__ == "__main__":
211
+ main()