JustusI commited on
Commit
5675df2
·
verified ·
1 Parent(s): 6f5203d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +236 -23
app.py CHANGED
@@ -12,16 +12,25 @@ from ast import literal_eval
12
  api_key = os.getenv("OPENAI_API_KEY")
13
  client = OpenAI(api_key = api_key)
14
 
 
 
15
  # ---------------------------
16
  # Helper Function: Extract text from PDF
17
  # ---------------------------
18
  def extract_text(uploaded_file):
 
 
 
 
 
 
 
19
  pdf_reader = PdfReader(uploaded_file)
20
  text = ""
21
  for page in pdf_reader.pages:
22
  page_text = page.extract_text()
23
  if page_text:
24
- text += page_text
25
  return text
26
 
27
  # ---------------------------
@@ -29,8 +38,7 @@ def extract_text(uploaded_file):
29
  # ---------------------------
30
  def generate_summary_from_text(text):
31
  prompt = (
32
- f"Summarize the following document in a concise manner, "
33
- "highlighting the key points that a student should know:\n\n{text}"
34
  )
35
  messages = [
36
  {"role": "system", "content": "You are an educational assistant."},
@@ -52,11 +60,26 @@ def chat_with_document(text, conversation_history, user_query):
52
  )
53
  return completion.choices[0].message.content.strip()
54
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  def generate_flashcards_from_text(text, num_cards):
56
  prompt = (
57
- f"Generate {num_cards} flashcards based on the following document. \n\nDocument:\n\n{text} "
58
  "Return a Python dictionary where each key is a flashcard question and its corresponding value is the answer. "
59
- #"Do not include any additional text.\n\nDocument:\n\n{text}"
60
  )
61
  messages = [
62
  {"role": "system", "content": "You are an educational assistant that creates study flashcards."},
@@ -68,7 +91,6 @@ def generate_flashcards_from_text(text, num_cards):
68
  )
69
  output = completion.choices[0].message.content.strip()
70
  try:
71
- # Use literal_eval to safely evaluate the string as a Python dictionary.
72
  flashcards = literal_eval(output)
73
  if isinstance(flashcards, dict):
74
  return flashcards
@@ -83,12 +105,16 @@ def generate_flashcards_from_text(text, num_cards):
83
  # ---------------------------
84
  st.sidebar.title("Study Companion Setup")
85
 
86
- uploaded_pdf = st.sidebar.file_uploader("Upload your study PDF", type="pdf")
87
- mode = st.sidebar.radio("Select Mode", ("Summary", "Chat", "Flashcards"))
88
 
 
 
89
  num_flashcards = None
90
- if mode == "Flashcards":
91
- num_flashcards = st.sidebar.number_input("Number of flashcards to generate:", min_value=1, max_value=20, value=5, step=1)
 
 
92
 
93
  # ---------------------------
94
  # Session State Initialization
@@ -99,6 +125,8 @@ if "summary" not in st.session_state:
99
  st.session_state.summary = None
100
  if "chat_history" not in st.session_state:
101
  st.session_state.chat_history = [{"role": "assistant", "content": "Hi, how can I help you with your study material?"}]
 
 
102
  if "flashcards" not in st.session_state:
103
  st.session_state.flashcards = {}
104
  if "current_card" not in st.session_state:
@@ -112,29 +140,23 @@ if "show_answer" not in st.session_state:
112
  # Process PDF Upload
113
  # ---------------------------
114
  if uploaded_pdf is not None:
115
- with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp:
116
- tmp.write(uploaded_pdf.read())
117
- st.session_state.pdf_file_path = tmp.name
118
  st.session_state.pdf_text = extract_text(uploaded_pdf)
119
- st.sidebar.success("PDF uploaded and processed successfully!")
 
 
 
120
 
121
  # ---------------------------
122
- # Main Area: Mode-Based Display
123
  # ---------------------------
124
  st.title("Study Companion: PDF-based Learning")
125
 
126
  if st.session_state.pdf_text is None:
127
  st.info("Please upload a PDF from the sidebar to begin.")
128
  else:
129
- if mode == "Summary":
130
- st.header("Summary & Key Points")
131
- if st.session_state.summary is None:
132
- with st.spinner("Generating summary..."):
133
- st.session_state.summary = generate_summary_from_text(st.session_state.pdf_text)
134
- st.write(st.session_state.summary)
135
-
136
- elif mode == "Chat":
137
  st.header("Chat with Your Study Companion")
 
138
  for msg in st.session_state.chat_history:
139
  st.chat_message(msg["role"]).write(msg["content"])
140
  user_question = st.chat_input("Ask a question about the document:")
@@ -146,6 +168,18 @@ else:
146
  st.session_state.chat_history.append({"role": "assistant", "content": response})
147
  st.chat_message("assistant").write(response)
148
 
 
 
 
 
 
 
 
 
 
 
 
 
149
  elif mode == "Flashcards":
150
  st.header("Practice Flashcards")
151
  if st.button("Generate Flashcards"):
@@ -191,6 +225,185 @@ else:
191
 
192
 
193
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
194
  # # ---------------------------
195
  # # Helper Function: Extract text from PDF
196
  # # ---------------------------
 
12
  api_key = os.getenv("OPENAI_API_KEY")
13
  client = OpenAI(api_key = api_key)
14
 
15
+
16
+
17
  # ---------------------------
18
  # Helper Function: Extract text from PDF
19
  # ---------------------------
20
  def extract_text(uploaded_file):
21
+ # Check file size (max 10MB)
22
+ uploaded_file.seek(0, os.SEEK_END)
23
+ file_size = uploaded_file.tell()
24
+ uploaded_file.seek(0)
25
+ if file_size > 10 * 1024 * 1024:
26
+ st.error("File size exceeds 10MB limit.")
27
+ return ""
28
  pdf_reader = PdfReader(uploaded_file)
29
  text = ""
30
  for page in pdf_reader.pages:
31
  page_text = page.extract_text()
32
  if page_text:
33
+ text += page_text + "\n"
34
  return text
35
 
36
  # ---------------------------
 
38
  # ---------------------------
39
  def generate_summary_from_text(text):
40
  prompt = (
41
+ f"Summarize the following document in a concise manner, highlighting the key points that a student should know:\n\n{text}"
 
42
  )
43
  messages = [
44
  {"role": "system", "content": "You are an educational assistant."},
 
60
  )
61
  return completion.choices[0].message.content.strip()
62
 
63
+ def generate_questions_from_text(text, num_questions):
64
+ prompt = (
65
+ f"Generate up to {num_questions} study questions with answers based on the following document.\n"
66
+ "Return the output as a table with two columns: 'Question' and 'Answer'.\n\nDocument:\n\n{text}"
67
+ )
68
+ messages = [
69
+ {"role": "system", "content": "You are an educational assistant that generates study questions."},
70
+ {"role": "user", "content": prompt}
71
+ ]
72
+ completion = client.chat.completions.create(
73
+ model="gpt-4o-mini",
74
+ messages=messages
75
+ )
76
+ return completion.choices[0].message.content.strip()
77
+
78
  def generate_flashcards_from_text(text, num_cards):
79
  prompt = (
80
+ f"Generate {num_cards} flashcards based on the following document.\n\nDocument:\n\n{text}\n\n"
81
  "Return a Python dictionary where each key is a flashcard question and its corresponding value is the answer. "
82
+ "Do not include any additional text."
83
  )
84
  messages = [
85
  {"role": "system", "content": "You are an educational assistant that creates study flashcards."},
 
91
  )
92
  output = completion.choices[0].message.content.strip()
93
  try:
 
94
  flashcards = literal_eval(output)
95
  if isinstance(flashcards, dict):
96
  return flashcards
 
105
  # ---------------------------
106
  st.sidebar.title("Study Companion Setup")
107
 
108
+ uploaded_pdf = st.sidebar.file_uploader("Upload your study PDF (max 10MB)", type="pdf")
109
+ mode = st.sidebar.radio("Select Mode", ("Chat", "Test Your Knowledge", "Flashcards"))
110
 
111
+ # For Test Your Knowledge and Flashcards modes, allow number input.
112
+ num_questions = None
113
  num_flashcards = None
114
+ if mode == "Test Your Knowledge":
115
+ num_questions = st.sidebar.number_input("Number of questions to generate (max 50):", min_value=1, max_value=50, value=10, step=1)
116
+ elif mode == "Flashcards":
117
+ num_flashcards = st.sidebar.number_input("Number of flashcards to generate (max 5):", min_value=1, max_value=5, value=3, step=1)
118
 
119
  # ---------------------------
120
  # Session State Initialization
 
125
  st.session_state.summary = None
126
  if "chat_history" not in st.session_state:
127
  st.session_state.chat_history = [{"role": "assistant", "content": "Hi, how can I help you with your study material?"}]
128
+ if "questions_table" not in st.session_state:
129
+ st.session_state.questions_table = None
130
  if "flashcards" not in st.session_state:
131
  st.session_state.flashcards = {}
132
  if "current_card" not in st.session_state:
 
140
  # Process PDF Upload
141
  # ---------------------------
142
  if uploaded_pdf is not None:
 
 
 
143
  st.session_state.pdf_text = extract_text(uploaded_pdf)
144
+ if st.session_state.pdf_text:
145
+ st.sidebar.success("PDF uploaded and processed successfully!")
146
+ else:
147
+ st.sidebar.error("Failed to extract text. Please check your PDF file.")
148
 
149
  # ---------------------------
150
+ # Main Area: Mode-Based Display (all functions via side menu)
151
  # ---------------------------
152
  st.title("Study Companion: PDF-based Learning")
153
 
154
  if st.session_state.pdf_text is None:
155
  st.info("Please upload a PDF from the sidebar to begin.")
156
  else:
157
+ if mode == "Chat":
 
 
 
 
 
 
 
158
  st.header("Chat with Your Study Companion")
159
+ # Display persistent chat history
160
  for msg in st.session_state.chat_history:
161
  st.chat_message(msg["role"]).write(msg["content"])
162
  user_question = st.chat_input("Ask a question about the document:")
 
168
  st.session_state.chat_history.append({"role": "assistant", "content": response})
169
  st.chat_message("assistant").write(response)
170
 
171
+ elif mode == "Test Your Knowledge":
172
+ st.header("Test Your Knowledge")
173
+ if num_questions is None:
174
+ st.info("Please specify the number of questions in the sidebar.")
175
+ else:
176
+ with st.spinner("Generating questions..."):
177
+ questions_output = generate_questions_from_text(st.session_state.pdf_text, num_questions)
178
+ # Assume the output is a table in markdown format
179
+ st.markdown("### Generated Questions")
180
+ st.markdown(questions_output)
181
+ # Optionally, you can parse the table and display it with st.table if it's in a CSV-like format.
182
+
183
  elif mode == "Flashcards":
184
  st.header("Practice Flashcards")
185
  if st.button("Generate Flashcards"):
 
225
 
226
 
227
 
228
+ # # ---------------------------
229
+ # # Helper Function: Extract text from PDF
230
+ # # ---------------------------
231
+ # def extract_text(uploaded_file):
232
+ # pdf_reader = PdfReader(uploaded_file)
233
+ # text = ""
234
+ # for page in pdf_reader.pages:
235
+ # page_text = page.extract_text()
236
+ # if page_text:
237
+ # text += page_text
238
+ # return text
239
+
240
+ # # ---------------------------
241
+ # # OpenAI Response Functions (using new style)
242
+ # # ---------------------------
243
+ # def generate_summary_from_text(text):
244
+ # prompt = (
245
+ # f"Summarize the following document in a concise manner, "
246
+ # "highlighting the key points that a student should know:\n\n{text}"
247
+ # )
248
+ # messages = [
249
+ # {"role": "system", "content": "You are an educational assistant."},
250
+ # {"role": "user", "content": prompt}
251
+ # ]
252
+ # completion = client.chat.completions.create(
253
+ # model="gpt-4o-mini",
254
+ # messages=messages
255
+ # )
256
+ # return completion.choices[0].message.content.strip()
257
+
258
+ # def chat_with_document(text, conversation_history, user_query):
259
+ # messages = conversation_history + [
260
+ # {"role": "user", "content": f"Based on the following document:\n\n{text}\n\nQuestion: {user_query}"}
261
+ # ]
262
+ # completion = client.chat.completions.create(
263
+ # model="gpt-4o-mini",
264
+ # messages=messages
265
+ # )
266
+ # return completion.choices[0].message.content.strip()
267
+
268
+ # def generate_flashcards_from_text(text, num_cards):
269
+ # prompt = (
270
+ # f"Generate {num_cards} flashcards based on the following document. \n\nDocument:\n\n{text} "
271
+ # "Return a Python dictionary where each key is a flashcard question and its corresponding value is the answer. "
272
+ # #"Do not include any additional text.\n\nDocument:\n\n{text}"
273
+ # )
274
+ # messages = [
275
+ # {"role": "system", "content": "You are an educational assistant that creates study flashcards."},
276
+ # {"role": "user", "content": prompt}
277
+ # ]
278
+ # completion = client.chat.completions.create(
279
+ # model="gpt-4o-mini",
280
+ # messages=messages
281
+ # )
282
+ # output = completion.choices[0].message.content.strip()
283
+ # try:
284
+ # # Use literal_eval to safely evaluate the string as a Python dictionary.
285
+ # flashcards = literal_eval(output)
286
+ # if isinstance(flashcards, dict):
287
+ # return flashcards
288
+ # else:
289
+ # return {}
290
+ # except Exception as e:
291
+ # st.error(f"Error parsing flashcards: {e}")
292
+ # return {}
293
+
294
+ # # ---------------------------
295
+ # # Sidebar: File Upload & Mode Selection
296
+ # # ---------------------------
297
+ # st.sidebar.title("Study Companion Setup")
298
+
299
+ # uploaded_pdf = st.sidebar.file_uploader("Upload your study PDF", type="pdf")
300
+ # mode = st.sidebar.radio("Select Mode", ("Summary", "Chat", "Flashcards"))
301
+
302
+ # num_flashcards = None
303
+ # if mode == "Flashcards":
304
+ # num_flashcards = st.sidebar.number_input("Number of flashcards to generate:", min_value=1, max_value=20, value=5, step=1)
305
+
306
+ # # ---------------------------
307
+ # # Session State Initialization
308
+ # # ---------------------------
309
+ # if "pdf_text" not in st.session_state:
310
+ # st.session_state.pdf_text = None
311
+ # if "summary" not in st.session_state:
312
+ # st.session_state.summary = None
313
+ # if "chat_history" not in st.session_state:
314
+ # st.session_state.chat_history = [{"role": "assistant", "content": "Hi, how can I help you with your study material?"}]
315
+ # if "flashcards" not in st.session_state:
316
+ # st.session_state.flashcards = {}
317
+ # if "current_card" not in st.session_state:
318
+ # st.session_state.current_card = 0
319
+ # if "score" not in st.session_state:
320
+ # st.session_state.score = 0
321
+ # if "show_answer" not in st.session_state:
322
+ # st.session_state.show_answer = False
323
+
324
+ # # ---------------------------
325
+ # # Process PDF Upload
326
+ # # ---------------------------
327
+ # if uploaded_pdf is not None:
328
+ # with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp:
329
+ # tmp.write(uploaded_pdf.read())
330
+ # st.session_state.pdf_file_path = tmp.name
331
+ # st.session_state.pdf_text = extract_text(uploaded_pdf)
332
+ # st.sidebar.success("PDF uploaded and processed successfully!")
333
+
334
+ # # ---------------------------
335
+ # # Main Area: Mode-Based Display
336
+ # # ---------------------------
337
+ # st.title("Study Companion: PDF-based Learning")
338
+
339
+ # if st.session_state.pdf_text is None:
340
+ # st.info("Please upload a PDF from the sidebar to begin.")
341
+ # else:
342
+ # if mode == "Summary":
343
+ # st.header("Summary & Key Points")
344
+ # if st.session_state.summary is None:
345
+ # with st.spinner("Generating summary..."):
346
+ # st.session_state.summary = generate_summary_from_text(st.session_state.pdf_text)
347
+ # st.write(st.session_state.summary)
348
+
349
+ # elif mode == "Chat":
350
+ # st.header("Chat with Your Study Companion")
351
+ # for msg in st.session_state.chat_history:
352
+ # st.chat_message(msg["role"]).write(msg["content"])
353
+ # user_question = st.chat_input("Ask a question about the document:")
354
+ # if user_question:
355
+ # st.session_state.chat_history.append({"role": "user", "content": user_question})
356
+ # st.chat_message("user").write(user_question)
357
+ # with st.spinner("Processing your question..."):
358
+ # response = chat_with_document(st.session_state.pdf_text, st.session_state.chat_history, user_question)
359
+ # st.session_state.chat_history.append({"role": "assistant", "content": response})
360
+ # st.chat_message("assistant").write(response)
361
+
362
+ # elif mode == "Flashcards":
363
+ # st.header("Practice Flashcards")
364
+ # if st.button("Generate Flashcards"):
365
+ # with st.spinner("Generating flashcards..."):
366
+ # flashcards = generate_flashcards_from_text(st.session_state.pdf_text, num_flashcards)
367
+ # st.session_state.flashcards = flashcards
368
+ # st.session_state.current_card = 0
369
+ # st.session_state.score = 0
370
+ # st.session_state.show_answer = False
371
+ # st.success("Flashcards generated successfully!")
372
+
373
+ # if not st.session_state.flashcards:
374
+ # st.info("No flashcards available. Click the button above to generate flashcards.")
375
+ # else:
376
+ # total_cards = len(st.session_state.flashcards)
377
+ # if st.session_state.current_card >= total_cards:
378
+ # st.success(f"You've completed all flashcards! Final Score: {st.session_state.score} / {total_cards}")
379
+ # st.info("Restart the session or generate new flashcards from the sidebar.")
380
+ # else:
381
+ # flashcards = st.session_state.flashcards
382
+ # current_keys = list(flashcards.keys())
383
+ # current_question = current_keys[st.session_state.current_card]
384
+ # current_answer = flashcards[current_question]
385
+ # st.write(f"**Question:** {current_question}")
386
+ # if st.button("Show Answer"):
387
+ # st.session_state.show_answer = True
388
+ # if st.session_state.show_answer:
389
+ # st.write(f"**Answer:** {current_answer}")
390
+ # col1, col2 = st.columns(2)
391
+ # with col1:
392
+ # if st.button("Correct"):
393
+ # st.session_state.score += 1
394
+ # st.success("Correct!")
395
+ # with col2:
396
+ # if st.button("Wrong"):
397
+ # st.error("Incorrect!")
398
+ # if st.button("Next Card"):
399
+ # st.session_state.current_card += 1
400
+ # st.session_state.show_answer = False
401
+ # st.rerun()
402
+ # st.write(f"**Current Score:** {st.session_state.score} / {total_cards}")
403
+
404
+
405
+
406
+
407
  # # ---------------------------
408
  # # Helper Function: Extract text from PDF
409
  # # ---------------------------