JustusI commited on
Commit
bc49df4
·
verified ·
1 Parent(s): 1fd3254

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +184 -0
app.py ADDED
@@ -0,0 +1,184 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import os
3
+ import tempfile
4
+ import json
5
+ import random
6
+ from PyPDF2 import PdfReader
7
+ import openai
8
+
9
+ # ---------------------------
10
+ # Set up OpenAI API Key
11
+ # ---------------------------
12
+ openai.api_key = os.getenv("OPENAI_API_KEY") # Ensure this is set in your environment/Space secrets
13
+
14
+ # ---------------------------
15
+ # Helper Function: Extract text from PDF
16
+ # ---------------------------
17
+ def extract_text(uploaded_file):
18
+ pdf_reader = PdfReader(uploaded_file)
19
+ text = ""
20
+ for page in pdf_reader.pages:
21
+ text += page.extract_text()
22
+ return text
23
+
24
+ # ---------------------------
25
+ # OpenAI Helper Functions
26
+ # ---------------------------
27
+ def generate_summary_from_text(text):
28
+ prompt = f"Summarize the following document in a concise manner, highlighting the key points that a student should know:\n\n{text}"
29
+ messages = [
30
+ {"role": "system", "content": "You are an educational assistant."},
31
+ {"role": "user", "content": prompt}
32
+ ]
33
+ response = openai.ChatCompletion.create(model="gpt-4o-mini", messages=messages)
34
+ return response.choices[0].message.content.strip()
35
+
36
+ def chat_with_document(text, conversation_history, user_query):
37
+ # Append the new query to the conversation history.
38
+ messages = conversation_history + [
39
+ {"role": "user", "content": f"Document content:\n\n{text}\n\nQuestion: {user_query}"}
40
+ ]
41
+ response = openai.ChatCompletion.create(model="gpt-3.5-turbo", messages=messages)
42
+ return response.choices[0].message.content.strip()
43
+
44
+ def generate_flashcards_from_text(text, num_cards):
45
+ prompt = (
46
+ f"Generate {num_cards} flashcards based on the following document. "
47
+ "Return a Python dictionary (in valid JSON format) where each key is a flashcard question and its value is the corresponding answer. "
48
+ f"Document:\n\n{text}"
49
+ )
50
+ messages = [
51
+ {"role": "system", "content": "You are an educational assistant that creates study flashcards."},
52
+ {"role": "user", "content": prompt}
53
+ ]
54
+ response = openai.ChatCompletion.create(model="gpt-3.5-turbo", messages=messages)
55
+ output = response.choices[0].message.content.strip()
56
+ try:
57
+ # Try to parse the output as JSON and convert it into a Python dict.
58
+ flashcards = json.loads(output)
59
+ if isinstance(flashcards, dict):
60
+ return flashcards
61
+ else:
62
+ return {}
63
+ except Exception as e:
64
+ st.error(f"Error parsing flashcards: {e}")
65
+ return {}
66
+
67
+ # ---------------------------
68
+ # Sidebar: Upload and Mode Selection
69
+ # ---------------------------
70
+ st.sidebar.title("Study Companion Setup")
71
+
72
+ uploaded_pdf = st.sidebar.file_uploader("Upload your study PDF", type="pdf")
73
+ mode = st.sidebar.radio("Select Mode", ("Summary", "Chat", "Flashcards"))
74
+
75
+ # For Flashcards mode, ask how many flashcards to generate.
76
+ num_flashcards = None
77
+ if mode == "Flashcards":
78
+ num_flashcards = st.sidebar.number_input("Number of flashcards to generate:", min_value=1, max_value=20, value=5, step=1)
79
+
80
+ # ---------------------------
81
+ # Session State Initialization
82
+ # ---------------------------
83
+ if "pdf_text" not in st.session_state:
84
+ st.session_state.pdf_text = None
85
+ if "summary" not in st.session_state:
86
+ st.session_state.summary = None
87
+ if "chat_history" not in st.session_state:
88
+ st.session_state.chat_history = [{"role": "assistant", "content": "Hi, how can I help you with your study material?"}]
89
+ if "flashcards" not in st.session_state:
90
+ st.session_state.flashcards = {}
91
+ if "current_card" not in st.session_state:
92
+ st.session_state.current_card = 0
93
+ if "score" not in st.session_state:
94
+ st.session_state.score = 0
95
+ if "show_answer" not in st.session_state:
96
+ st.session_state.show_answer = False
97
+
98
+ # ---------------------------
99
+ # Process PDF Upload
100
+ # ---------------------------
101
+ if uploaded_pdf is not None:
102
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp:
103
+ tmp.write(uploaded_pdf.read())
104
+ pdf_file_path = tmp.name
105
+ # Extract the full text from the PDF and store it in session state.
106
+ st.session_state.pdf_text = extract_text(pdf_file_path)
107
+ st.sidebar.success("PDF uploaded and processed successfully!")
108
+
109
+ # ---------------------------
110
+ # Main Area: Mode-Based Display
111
+ # ---------------------------
112
+ st.title("Study Companion: PDF-based Learning")
113
+
114
+ if st.session_state.pdf_text is None:
115
+ st.info("Please upload a PDF from the sidebar to begin.")
116
+ else:
117
+ if mode == "Summary":
118
+ st.header("Summary & Key Points")
119
+ # Generate summary only once
120
+ if st.session_state.summary is None:
121
+ with st.spinner("Generating summary..."):
122
+ st.session_state.summary = generate_summary_from_text(st.session_state.pdf_text)
123
+ st.write(st.session_state.summary)
124
+
125
+ elif mode == "Chat":
126
+ st.header("Chat with Your Study Companion")
127
+ # Display chat history
128
+ for msg in st.session_state.chat_history:
129
+ st.chat_message(msg["role"]).write(msg["content"])
130
+ user_question = st.chat_input("Ask a question about the document:")
131
+ if user_question:
132
+ # Preserve current history and then update
133
+ st.session_state.chat_history.append({"role": "user", "content": user_question})
134
+ st.chat_message("user").write(user_question)
135
+ with st.spinner("Processing your question..."):
136
+ response = chat_with_document(st.session_state.pdf_text, st.session_state.chat_history, user_question)
137
+ st.session_state.chat_history.append({"role": "assistant", "content": response})
138
+ st.chat_message("assistant").write(response)
139
+
140
+ elif mode == "Flashcards":
141
+ st.header("Practice Flashcards")
142
+ # Provide a button to generate flashcards on demand.
143
+ if st.button("Generate Flashcards"):
144
+ with st.spinner("Generating flashcards..."):
145
+ flashcards = generate_flashcards_from_text(st.session_state.pdf_text, num_flashcards)
146
+ st.session_state.flashcards = flashcards
147
+ st.session_state.current_card = 0
148
+ st.session_state.score = 0
149
+ st.session_state.show_answer = False
150
+ st.success("Flashcards generated successfully!")
151
+
152
+ if not st.session_state.flashcards:
153
+ st.info("No flashcards available. Click the button above to generate flashcards.")
154
+ else:
155
+ # Loop through flashcards stored as a dictionary.
156
+ flashcards = st.session_state.flashcards
157
+ total_cards = len(flashcards)
158
+ # Check if all flashcards have been practiced.
159
+ if st.session_state.current_card >= total_cards:
160
+ st.success(f"You've completed all flashcards! Final Score: {st.session_state.score} / {total_cards}")
161
+ st.info("Restart the session or generate new flashcards from the sidebar.")
162
+ else:
163
+ # Get the current flashcard key-value pair.
164
+ current_keys = list(flashcards.keys())
165
+ current_key = current_keys[st.session_state.current_card]
166
+ current_answer = flashcards[current_key]
167
+ st.write(f"**Question:** {current_key}")
168
+ if st.button("Show Answer"):
169
+ st.session_state.show_answer = True
170
+ if st.session_state.show_answer:
171
+ st.write(f"**Answer:** {current_answer}")
172
+ col1, col2 = st.columns(2)
173
+ with col1:
174
+ if st.button("Correct"):
175
+ st.session_state.score += 1
176
+ st.success("Correct!")
177
+ with col2:
178
+ if st.button("Wrong"):
179
+ st.error("Incorrect!")
180
+ if st.button("Next Card"):
181
+ st.session_state.current_card += 1
182
+ st.session_state.show_answer = False
183
+ st.rerun()
184
+ st.write(f"**Current Score:** {st.session_state.score} / {total_cards}")