Ahmed12322 commited on
Commit
927fe6a
Β·
verified Β·
1 Parent(s): 4812b3d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +159 -104
app.py CHANGED
@@ -1,104 +1,159 @@
1
- import streamlit as st
2
- import faiss
3
- import numpy as np
4
- from sentence_transformers import SentenceTransformer
5
- from groq import Groq
6
- import os
7
- import pypdf
8
- from langchain.text_splitter import RecursiveCharacterTextSplitter
9
-
10
- # Set Groq API key
11
- GROQ_API_KEY = os.getenv("GROQ_API_KEY", "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")
12
- if not GROQ_API_KEY:
13
- st.error("⚠️ GROQ_API_KEY is missing! Please set it in your environment variables.")
14
- st.stop()
15
-
16
- # Load embedding model
17
- embedding_model = SentenceTransformer("all-MiniLM-L6-v2")
18
-
19
- # Set up Groq client
20
- client = Groq(api_key=GROQ_API_KEY)
21
-
22
- # Function to extract text from PDF
23
- def extract_text_from_pdf(uploaded_file):
24
- reader = pypdf.PdfReader(uploaded_file)
25
- extracted_text = [page.extract_text() for page in reader.pages if page.extract_text()]
26
- return "\n".join(extracted_text) if extracted_text else "No text could be extracted from this PDF."
27
-
28
- # Function to create text chunks
29
- def create_chunks(text, chunk_size=500, chunk_overlap=100):
30
- text_splitter = RecursiveCharacterTextSplitter(chunk_size=chunk_size, chunk_overlap=chunk_overlap)
31
- return text_splitter.split_text(text)
32
-
33
- # Function to create and save FAISS index
34
- def create_faiss_index(chunks):
35
- embeddings = embedding_model.encode(chunks, convert_to_numpy=True)
36
-
37
- # Create FAISS index
38
- dimension = embeddings.shape[1]
39
- index = faiss.IndexFlatL2(dimension)
40
- index.add(embeddings)
41
-
42
- # Save FAISS index and chunks
43
- faiss.write_index(index, "faiss_index.bin")
44
- np.save("chunks.npy", np.array(chunks, dtype=object))
45
-
46
- return index, chunks
47
-
48
- # Function to search FAISS
49
- def search_faiss(query, index, chunks, top_k=2):
50
- if index is None:
51
- return ["No database found. Please upload a PDF first."]
52
-
53
- query_embedding = embedding_model.encode([query], convert_to_numpy=True)
54
- distances, indices = index.search(query_embedding, top_k)
55
- return [chunks[i] for i in indices[0] if i < len(chunks)]
56
-
57
- # Function to query Groq
58
- def query_groq(query):
59
- chat_completion = client.chat.completions.create(
60
- messages=[{"role": "user", "content": query}],
61
- model="llama-3.3-70b-versatile",
62
- )
63
- return chat_completion.choices[0].message.content
64
-
65
- # Streamlit UI
66
- st.set_page_config(page_title="RAG Chatbot", page_icon="πŸ€–")
67
- st.title("πŸ“„ RAG-Based Chatbot with FAISS & Groq")
68
-
69
- # Upload PDF
70
- uploaded_file = st.file_uploader("πŸ“€ Upload a PDF file", type="pdf")
71
-
72
- if uploaded_file:
73
- with st.spinner("πŸ”„ Processing PDF..."):
74
- text = extract_text_from_pdf(uploaded_file)
75
- if text.strip():
76
- chunks = create_chunks(text)
77
-
78
- # Create FAISS index
79
- index, chunks = create_faiss_index(chunks)
80
-
81
- # Store in session state
82
- st.session_state["faiss_index"] = index
83
- st.session_state["chunks"] = chunks
84
-
85
- st.success("βœ… PDF processed successfully!")
86
- else:
87
- st.error("❌ No text found in the uploaded PDF.")
88
-
89
- # Load FAISS index if available
90
- index = st.session_state.get("faiss_index", None)
91
- chunks = st.session_state.get("chunks", [])
92
-
93
- # User query input
94
- user_query = st.text_input("πŸ’¬ Ask me something about the document:")
95
-
96
- if st.button("Search") and user_query:
97
- with st.spinner("πŸ”Ž Retrieving response..."):
98
- retrieved_text = search_faiss(user_query, index, chunks)
99
- if retrieved_text:
100
- response = query_groq("\n".join(retrieved_text))
101
- st.write("### πŸ€– AI Response:")
102
- st.write(response)
103
- else:
104
- st.error("⚠️ No relevant information found.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import faiss
3
+ import numpy as np
4
+ from sentence_transformers import SentenceTransformer
5
+ from groq import Groq
6
+ import os
7
+ import pypdf
8
+ from langchain.text_splitter import RecursiveCharacterTextSplitter
9
+
10
+ # Initialize session state variables
11
+ if "faiss_index" not in st.session_state:
12
+ st.session_state["faiss_index"] = None
13
+ if "chunks" not in st.session_state:
14
+ st.session_state["chunks"] = []
15
+
16
+ # Set Groq API key - Consider using st.secrets for better security
17
+ GROQ_API_KEY = os.getenv("GROQ_API_KEY") or st.secrets.get("GROQ_API_KEY", "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")
18
+ if not GROQ_API_KEY:
19
+ st.error("⚠️ GROQ_API_KEY is missing! Please set it in your environment variables or secrets.toml file.")
20
+ st.stop()
21
+
22
+ # Load embedding model with error handling
23
+ try:
24
+ embedding_model = SentenceTransformer("all-MiniLM-L6-v2")
25
+ except Exception as e:
26
+ st.error(f"❌ Failed to load embedding model: {str(e)}")
27
+ st.stop()
28
+
29
+ # Set up Groq client with error handling
30
+ try:
31
+ client = Groq(api_key=GROQ_API_KEY)
32
+ except Exception as e:
33
+ st.error(f"❌ Failed to initialize Groq client: {str(e)}")
34
+ st.stop()
35
+
36
+ # Function to extract text from PDF with error handling
37
+ def extract_text_from_pdf(uploaded_file):
38
+ try:
39
+ reader = pypdf.PdfReader(uploaded_file)
40
+ extracted_text = [page.extract_text() for page in reader.pages if page.extract_text()]
41
+ return "\n".join(extracted_text) if extracted_text else ""
42
+ except Exception as e:
43
+ st.error(f"❌ Error extracting text from PDF: {str(e)}")
44
+ return ""
45
+
46
+ # Function to create text chunks
47
+ def create_chunks(text, chunk_size=500, chunk_overlap=100):
48
+ text_splitter = RecursiveCharacterTextSplitter(
49
+ chunk_size=chunk_size,
50
+ chunk_overlap=chunk_overlap,
51
+ separators=["\n\n", "\n", " ", ""] # Added separators for better splitting
52
+ )
53
+ return text_splitter.split_text(text)
54
+
55
+ # Function to create and save FAISS index
56
+ def create_faiss_index(chunks):
57
+ try:
58
+ embeddings = embedding_model.encode(chunks, convert_to_numpy=True)
59
+
60
+ # Create FAISS index
61
+ dimension = embeddings.shape[1]
62
+ index = faiss.IndexFlatL2(dimension)
63
+ index.add(embeddings)
64
+
65
+ return index, chunks
66
+ except Exception as e:
67
+ st.error(f"❌ Error creating FAISS index: {str(e)}")
68
+ return None, []
69
+
70
+ # Function to search FAISS
71
+ def search_faiss(query, index, chunks, top_k=2):
72
+ if index is None or not chunks:
73
+ return []
74
+
75
+ try:
76
+ query_embedding = embedding_model.encode([query], convert_to_numpy=True)
77
+ distances, indices = index.search(query_embedding, top_k)
78
+ return [chunks[i] for i in indices[0] if i < len(chunks)]
79
+ except Exception as e:
80
+ st.error(f"❌ Search error: {str(e)}")
81
+ return []
82
+
83
+ # Function to query Groq with enhanced prompt
84
+ def query_groq(query, context=None):
85
+ try:
86
+ prompt = f"""Use the following context to answer the question.
87
+ If you don't know the answer, say you don't know. Don't make up answers.
88
+
89
+ Context: {context if context else 'No specific context provided'}
90
+
91
+ Question: {query}
92
+
93
+ Answer:"""
94
+
95
+ chat_completion = client.chat.completions.create(
96
+ messages=[{"role": "user", "content": prompt}],
97
+ model="llama-3-70b-8192", # Updated model name
98
+ temperature=0.3,
99
+ max_tokens=1024
100
+ )
101
+ return chat_completion.choices[0].message.content
102
+ except Exception as e:
103
+ return f"Error querying Groq: {str(e)}"
104
+
105
+ # Streamlit UI
106
+ st.set_page_config(page_title="RAG Chatbot", page_icon="πŸ€–", layout="wide")
107
+ st.title("πŸ“„ RAG-Based Chatbot with FAISS & Groq")
108
+
109
+ # Sidebar for settings
110
+ with st.sidebar:
111
+ st.header("Settings")
112
+ top_k = st.slider("Number of chunks to retrieve", 1, 5, 2)
113
+ chunk_size = st.slider("Chunk size (characters)", 200, 1000, 500)
114
+ chunk_overlap = st.slider("Chunk overlap (characters)", 0, 200, 100)
115
+
116
+ # Upload PDF
117
+ uploaded_file = st.file_uploader("πŸ“€ Upload a PDF file", type="pdf")
118
+
119
+ if uploaded_file:
120
+ with st.spinner("πŸ”„ Processing PDF..."):
121
+ text = extract_text_from_pdf(uploaded_file)
122
+ if text.strip():
123
+ chunks = create_chunks(text, chunk_size=chunk_size, chunk_overlap=chunk_overlap)
124
+
125
+ # Create FAISS index
126
+ index, chunks = create_faiss_index(chunks)
127
+
128
+ # Store in session state
129
+ st.session_state["faiss_index"] = index
130
+ st.session_state["chunks"] = chunks
131
+
132
+ st.success(f"βœ… PDF processed successfully! Created {len(chunks)} chunks.")
133
+ else:
134
+ st.error("❌ No text found in the uploaded PDF.")
135
+
136
+ # Chat interface
137
+ if "messages" not in st.session_state:
138
+ st.session_state.messages = []
139
+
140
+ # Display chat messages
141
+ for message in st.session_state.messages:
142
+ with st.chat_message(message["role"]):
143
+ st.markdown(message["content"])
144
+
145
+ # User query input
146
+ if prompt := st.chat_input("πŸ’¬ Ask me something about the document:"):
147
+ st.session_state.messages.append({"role": "user", "content": prompt})
148
+ with st.chat_message("user"):
149
+ st.markdown(prompt)
150
+
151
+ with st.spinner("πŸ”Ž Retrieving response..."):
152
+ retrieved_text = search_faiss(prompt, st.session_state["faiss_index"], st.session_state["chunks"], top_k=top_k)
153
+ context = "\n".join(retrieved_text) if retrieved_text else "No relevant context found."
154
+
155
+ response = query_groq(prompt, context)
156
+
157
+ st.session_state.messages.append({"role": "assistant", "content": response})
158
+ with st.chat_message("assistant"):
159
+ st.markdown(response)