Ahmad-01 commited on
Commit
0c8f0ca
Β·
verified Β·
1 Parent(s): a95b10f

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +145 -66
src/streamlit_app.py CHANGED
@@ -25,18 +25,26 @@ client = Groq(api_key=os.environ.get("GROQ_API_KEY"))
25
  st.set_page_config(
26
  page_title="AI Study Assistant πŸ“š",
27
  page_icon="πŸŽ“",
28
- layout="wide",
29
- initial_sidebar_state="expanded"
30
  )
31
 
32
  # -----------------------------
33
  # SIDEBAR
34
  # -----------------------------
35
  st.sidebar.title("πŸ“Œ Settings")
 
36
  education_level = st.sidebar.selectbox(
37
  "Select Education Level",
38
- ["Primary School", "Middle School", "Secondary School", "High School", "Undergraduate", "Graduate"]
 
 
 
 
 
 
 
39
  )
 
40
  st.sidebar.markdown("---")
41
  st.sidebar.write("Developed by **Ahmad Bilal** | Fiverr Portfolio Demo")
42
 
@@ -47,97 +55,130 @@ st.markdown(
47
  """
48
  <div style='text-align:center; padding:10px; background-color:#f0f2f6; border-radius:10px'>
49
  <h1 style='color:#0f4c81'>πŸŽ“ AI Study Assistant</h1>
50
- <p style='font-size:18px; color:#333'>Upload your study material and ask questions. Get answers & summaries instantly!</p>
51
  </div>
52
  """,
53
  unsafe_allow_html=True
54
  )
55
 
56
  # -----------------------------
57
- # FILE UPLOADER (CENTER)
58
  # -----------------------------
59
  uploaded_files = st.file_uploader(
60
  "Upload Study Documents",
61
- type=["pdf", "docx", "txt", "csv", "xlsx"],
62
- accept_multiple_files=True,
63
- label_visibility="visible"
64
  )
65
 
 
 
66
  if uploaded_files:
67
- st.success(f"{len(uploaded_files)} file(s) uploaded successfully!")
68
- MAX_FILE_SIZE = 20 * 1024 * 1024 # 20MB
69
 
70
- valid_files = []
 
 
 
 
 
 
 
 
71
 
72
- for file in uploaded_files:
73
- if file.size > MAX_FILE_SIZE:
74
- st.error(f"{file.name} is too large. Please upload files under 20MB.")
75
- else:
76
- valid_files.append(file)
77
  # -----------------------------
78
- # FILE PROCESSING
79
  # -----------------------------
80
  def load_pdf(file):
81
  reader = PdfReader(file)
82
- text=""
83
  for page in reader.pages:
84
- text+=page.extract_text()
 
85
  return text
86
 
 
87
  def load_docx(file):
88
- doc=docx.Document(file)
89
  return "\n".join([p.text for p in doc.paragraphs])
90
 
 
91
  def load_csv(file):
92
- df=pd.read_csv(file)
93
  return df.to_string()
94
 
 
95
  def load_xlsx(file):
96
- df=pd.read_excel(file)
97
  return df.to_string()
98
 
 
99
  def load_txt(file):
100
  return file.read().decode("utf-8")
101
 
102
- raw_text = process_docs(valid_files):
103
- text=""
 
 
 
 
 
 
104
  for file in files:
105
- if file.type=="application/pdf":
106
- text+=load_pdf(file)
107
- elif file.type=="application/vnd.openxmlformats-officedocument.wordprocessingml.document":
108
- text+=load_docx(file)
109
- elif file.type=="text/csv":
110
- text+=load_csv(file)
111
- elif file.type=="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":
112
- text+=load_xlsx(file)
 
 
 
 
 
113
  else:
114
- text+=load_txt(file)
 
115
  return text
116
 
 
117
  # -----------------------------
118
  # VECTOR STORE
119
  # -----------------------------
120
  @st.cache_resource
121
  def create_vectorstore(text):
122
- splitter = RecursiveCharacterTextSplitter(chunk_size=800, chunk_overlap=100)
 
 
 
 
 
123
  chunks = splitter.split_text(text)
124
- embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
 
 
 
 
125
  vectorstore = FAISS.from_texts(chunks, embeddings)
 
126
  return vectorstore
127
 
 
128
  # -----------------------------
129
  # PROMPT BUILDER
130
  # -----------------------------
131
  def build_prompt(context, question, level):
132
- style={
133
- "Primary School":"Explain like teaching a 5 year old child using simple fun examples.",
134
- "Middle School":"Explain using easy examples.",
135
- "Secondary School":"Explain clearly using simple concepts.",
136
- "High School":"Explain with reasoning and examples.",
137
- "Undergraduate":"Explain in academic but easy language.",
138
- "Graduate":"Provide detailed academic explanation."
 
139
  }
140
- prompt=f"""
 
141
  Use the study material below to answer the question.
142
 
143
  Study Material:
@@ -149,76 +190,114 @@ Question:
149
  Explanation Style:
150
  {style[level]}
151
  """
 
152
  return prompt
153
 
 
154
  # -----------------------------
155
- # GROQ LLM CALL
156
  # -----------------------------
157
  def ask_llm(prompt):
 
158
  chat_completion = client.chat.completions.create(
159
  messages=[{"role":"user","content":prompt}],
160
  model="llama-3.3-70b-versatile"
161
  )
 
162
  return chat_completion.choices[0].message.content
163
 
 
164
  # -----------------------------
165
- # SUMMARY GENERATOR
166
  # -----------------------------
167
  def generate_summary(text):
168
- prompt=f"""
169
- Create a short and easy summary of the following material.
 
170
 
171
  {text}
172
  """
 
173
  return ask_llm(prompt)
174
 
 
175
  # -----------------------------
176
  # PDF GENERATOR
177
  # -----------------------------
178
  def create_pdf(text):
179
- temp_file=tempfile.NamedTemporaryFile(delete=False,suffix=".pdf")
180
- styles=getSampleStyleSheet()
181
- story=[Paragraph(text,styles["Normal"])]
182
- doc=SimpleDocTemplate(temp_file.name)
 
 
 
 
 
183
  doc.build(story)
 
184
  return temp_file.name
185
 
 
186
  # -----------------------------
187
- # MAIN APP LOGIC
188
  # -----------------------------
189
- if uploaded_files:
 
 
190
 
191
- raw_text=process_docs(uploaded_files)
192
- vectorstore=create_vectorstore(raw_text)
193
 
194
  st.markdown("---")
195
- st.markdown("### ❓ Ask a Question")
196
- question=st.text_input("Type your question here:")
 
 
197
 
198
  if question:
199
 
200
- # Use columns for nicer layout
201
  col1, col2 = st.columns([2,1])
202
 
203
  docs = vectorstore.similarity_search(question, k=3)
 
204
  context = "\n".join([doc.page_content for doc in docs])
 
205
  prompt = build_prompt(context, question, education_level)
 
206
  answer = ask_llm(prompt)
207
 
208
  with col1:
 
209
  st.markdown("### πŸ“– Answer")
 
210
  st.success(answer)
211
 
212
  with col2:
213
- st.markdown("### πŸ“ Generate Summary")
214
- if st.button("Create Summary & Download"):
 
 
 
215
  summary = generate_summary(context)
216
- st.markdown("#### Summary")
217
  st.info(summary)
218
- st.download_button("Download Markdown", summary, file_name="summary.md")
219
- pdf_file=create_pdf(summary)
220
- with open(pdf_file,"rb") as f:
221
- st.download_button("Download PDF", f, file_name="summary.pdf")
 
 
 
 
 
 
 
 
 
 
 
 
222
 
223
  else:
224
- st.markdown("⚠️ Please upload at least one study document to start.")
 
 
25
  st.set_page_config(
26
  page_title="AI Study Assistant πŸ“š",
27
  page_icon="πŸŽ“",
28
+ layout="wide"
 
29
  )
30
 
31
  # -----------------------------
32
  # SIDEBAR
33
  # -----------------------------
34
  st.sidebar.title("πŸ“Œ Settings")
35
+
36
  education_level = st.sidebar.selectbox(
37
  "Select Education Level",
38
+ [
39
+ "Primary School",
40
+ "Middle School",
41
+ "Secondary School",
42
+ "High School",
43
+ "Undergraduate",
44
+ "Graduate"
45
+ ]
46
  )
47
+
48
  st.sidebar.markdown("---")
49
  st.sidebar.write("Developed by **Ahmad Bilal** | Fiverr Portfolio Demo")
50
 
 
55
  """
56
  <div style='text-align:center; padding:10px; background-color:#f0f2f6; border-radius:10px'>
57
  <h1 style='color:#0f4c81'>πŸŽ“ AI Study Assistant</h1>
58
+ <p style='font-size:18px'>Upload study materials and ask questions instantly!</p>
59
  </div>
60
  """,
61
  unsafe_allow_html=True
62
  )
63
 
64
  # -----------------------------
65
+ # FILE UPLOADER
66
  # -----------------------------
67
  uploaded_files = st.file_uploader(
68
  "Upload Study Documents",
69
+ type=["pdf","docx","txt","csv","xlsx"],
70
+ accept_multiple_files=True
 
71
  )
72
 
73
+ valid_files = []
74
+
75
  if uploaded_files:
 
 
76
 
77
+ MAX_FILE_SIZE = 20 * 1024 * 1024
78
+
79
+ for file in uploaded_files:
80
+ if file.size > MAX_FILE_SIZE:
81
+ st.error(f"{file.name} is too large. Upload files under 20MB.")
82
+ else:
83
+ valid_files.append(file)
84
+
85
+ st.success(f"{len(valid_files)} file(s) ready for processing")
86
 
 
 
 
 
 
87
  # -----------------------------
88
+ # FILE LOADERS
89
  # -----------------------------
90
  def load_pdf(file):
91
  reader = PdfReader(file)
92
+ text = ""
93
  for page in reader.pages:
94
+ if page.extract_text():
95
+ text += page.extract_text()
96
  return text
97
 
98
+
99
  def load_docx(file):
100
+ doc = docx.Document(file)
101
  return "\n".join([p.text for p in doc.paragraphs])
102
 
103
+
104
  def load_csv(file):
105
+ df = pd.read_csv(file)
106
  return df.to_string()
107
 
108
+
109
  def load_xlsx(file):
110
+ df = pd.read_excel(file)
111
  return df.to_string()
112
 
113
+
114
  def load_txt(file):
115
  return file.read().decode("utf-8")
116
 
117
+
118
+ # -----------------------------
119
+ # DOCUMENT PROCESSING
120
+ # -----------------------------
121
+ def process_docs(files):
122
+
123
+ text = ""
124
+
125
  for file in files:
126
+
127
+ if file.type == "application/pdf":
128
+ text += load_pdf(file)
129
+
130
+ elif file.type == "application/vnd.openxmlformats-officedocument.wordprocessingml.document":
131
+ text += load_docx(file)
132
+
133
+ elif file.type == "text/csv":
134
+ text += load_csv(file)
135
+
136
+ elif file.type == "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":
137
+ text += load_xlsx(file)
138
+
139
  else:
140
+ text += load_txt(file)
141
+
142
  return text
143
 
144
+
145
  # -----------------------------
146
  # VECTOR STORE
147
  # -----------------------------
148
  @st.cache_resource
149
  def create_vectorstore(text):
150
+
151
+ splitter = RecursiveCharacterTextSplitter(
152
+ chunk_size=800,
153
+ chunk_overlap=100
154
+ )
155
+
156
  chunks = splitter.split_text(text)
157
+
158
+ embeddings = HuggingFaceEmbeddings(
159
+ model_name="sentence-transformers/all-MiniLM-L6-v2"
160
+ )
161
+
162
  vectorstore = FAISS.from_texts(chunks, embeddings)
163
+
164
  return vectorstore
165
 
166
+
167
  # -----------------------------
168
  # PROMPT BUILDER
169
  # -----------------------------
170
  def build_prompt(context, question, level):
171
+
172
+ style = {
173
+ "Primary School": "Explain like teaching a 5 year old using fun examples.",
174
+ "Middle School": "Explain with easy examples.",
175
+ "Secondary School": "Explain clearly using simple ideas.",
176
+ "High School": "Explain with reasoning and examples.",
177
+ "Undergraduate": "Explain in academic but clear language.",
178
+ "Graduate": "Provide detailed academic explanation."
179
  }
180
+
181
+ prompt = f"""
182
  Use the study material below to answer the question.
183
 
184
  Study Material:
 
190
  Explanation Style:
191
  {style[level]}
192
  """
193
+
194
  return prompt
195
 
196
+
197
  # -----------------------------
198
+ # GROQ LLM
199
  # -----------------------------
200
  def ask_llm(prompt):
201
+
202
  chat_completion = client.chat.completions.create(
203
  messages=[{"role":"user","content":prompt}],
204
  model="llama-3.3-70b-versatile"
205
  )
206
+
207
  return chat_completion.choices[0].message.content
208
 
209
+
210
  # -----------------------------
211
+ # SUMMARY
212
  # -----------------------------
213
  def generate_summary(text):
214
+
215
+ prompt = f"""
216
+ Create a short and simple summary of this study material.
217
 
218
  {text}
219
  """
220
+
221
  return ask_llm(prompt)
222
 
223
+
224
  # -----------------------------
225
  # PDF GENERATOR
226
  # -----------------------------
227
  def create_pdf(text):
228
+
229
+ temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".pdf")
230
+
231
+ styles = getSampleStyleSheet()
232
+
233
+ story = [Paragraph(text, styles["Normal"])]
234
+
235
+ doc = SimpleDocTemplate(temp_file.name)
236
+
237
  doc.build(story)
238
+
239
  return temp_file.name
240
 
241
+
242
  # -----------------------------
243
+ # MAIN LOGIC
244
  # -----------------------------
245
+ if valid_files:
246
+
247
+ raw_text = process_docs(valid_files)
248
 
249
+ vectorstore = create_vectorstore(raw_text)
 
250
 
251
  st.markdown("---")
252
+
253
+ st.subheader("❓ Ask a Question")
254
+
255
+ question = st.text_input("Type your question")
256
 
257
  if question:
258
 
 
259
  col1, col2 = st.columns([2,1])
260
 
261
  docs = vectorstore.similarity_search(question, k=3)
262
+
263
  context = "\n".join([doc.page_content for doc in docs])
264
+
265
  prompt = build_prompt(context, question, education_level)
266
+
267
  answer = ask_llm(prompt)
268
 
269
  with col1:
270
+
271
  st.markdown("### πŸ“– Answer")
272
+
273
  st.success(answer)
274
 
275
  with col2:
276
+
277
+ st.markdown("### πŸ“ Summary")
278
+
279
+ if st.button("Generate Summary"):
280
+
281
  summary = generate_summary(context)
282
+
283
  st.info(summary)
284
+
285
+ st.download_button(
286
+ "Download Markdown",
287
+ summary,
288
+ file_name="summary.md"
289
+ )
290
+
291
+ pdf_file = create_pdf(summary)
292
+
293
+ with open(pdf_file, "rb") as f:
294
+
295
+ st.download_button(
296
+ "Download PDF",
297
+ f,
298
+ file_name="summary.pdf"
299
+ )
300
 
301
  else:
302
+
303
+ st.info("πŸ“‚ Upload at least one study document to start.")