Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
@@ -24,15 +24,28 @@ def parse_transcript(file):
|
|
24 |
def extract_transcript_info(df):
|
25 |
transcript_text = df['Transcript_Text'].iloc[0] if 'Transcript_Text' in df.columns else ''
|
26 |
info = {}
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
|
|
|
|
|
|
|
|
|
|
31 |
if grade_match:
|
32 |
info['Grade_Level'] = grade_match.group(1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
courses = re.findall(r'(?i)\b([A-Z][a-zA-Z\s&/]+)\s+(\d{1,3})\b', transcript_text)
|
34 |
if courses:
|
35 |
info['Courses'] = list(set([c[0].strip() for c in courses]))
|
|
|
36 |
return info
|
37 |
|
38 |
# Learning style questions - from educationplanner.org
|
@@ -66,6 +79,7 @@ style_count_map = {0: "visual", 1: "auditory", 2: "reading/writing"}
|
|
66 |
|
67 |
def learning_style_quiz(*answers):
|
68 |
scores = {'visual': 0, 'auditory': 0, 'reading/writing': 0}
|
|
|
69 |
for i, ans in enumerate(answers):
|
70 |
if i < len(learning_style_answers):
|
71 |
options = learning_style_answers[i]
|
@@ -73,8 +87,10 @@ def learning_style_quiz(*answers):
|
|
73 |
index = options.index(ans)
|
74 |
style = style_count_map[index]
|
75 |
scores[style] += 1
|
|
|
76 |
max_score = max(scores.values())
|
77 |
best_styles = [style.capitalize() for style, score in scores.items() if score == max_score]
|
|
|
78 |
return ", ".join(best_styles)
|
79 |
|
80 |
get_to_know_categories = {
|
@@ -115,7 +131,7 @@ get_to_know_categories = {
|
|
115 |
def generate_learning_plan(info):
|
116 |
level = info.get("Grade_Level", "unknown")
|
117 |
courses = info.get("Courses", [])
|
118 |
-
gpa = info.get("GPA", "N/A")
|
119 |
return f"""
|
120 |
π **Personalized Learning Plan**
|
121 |
- Grade Level: {level}
|
@@ -138,25 +154,41 @@ Your dreams are powerful: {'; '.join(hopes) if hopes else 'You are filled with p
|
|
138 |
Believe in yourself and keep moving forward.
|
139 |
"""
|
140 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
141 |
def save_profile(file, *inputs):
|
142 |
if not file:
|
143 |
-
return "β οΈ Please upload your transcript.", False
|
|
|
144 |
quiz_answers = inputs[:len(learning_style_questions)]
|
145 |
if any(ans is None for ans in quiz_answers):
|
146 |
-
return "β οΈ Please answer all the learning style questions.", False
|
|
|
147 |
blog_checkbox = inputs[len(learning_style_questions)]
|
148 |
blog_text = inputs[len(learning_style_questions)+1]
|
149 |
category_answers = inputs[len(learning_style_questions)+2:]
|
|
|
150 |
if any(ans.strip() == "" for ans in category_answers):
|
151 |
-
return "β οΈ Please complete all 'Get to Know You' sections before saving.", False
|
|
|
152 |
if blog_checkbox and blog_text.strip() == "":
|
153 |
-
return "β οΈ You checked the blog option but didnβt write anything. Please write your mini blog or uncheck the option.", False
|
154 |
|
155 |
df = parse_transcript(file)
|
156 |
transcript_info = extract_transcript_info(df)
|
157 |
learning_type = learning_style_quiz(*quiz_answers)
|
|
|
158 |
question_texts = [q for cat in get_to_know_categories.values() for q, _ in cat]
|
159 |
responses = dict(zip(question_texts, category_answers))
|
|
|
160 |
profile = {
|
161 |
"transcript": df.to_dict(orient='records'),
|
162 |
"transcript_info": transcript_info,
|
@@ -164,28 +196,24 @@ def save_profile(file, *inputs):
|
|
164 |
"get_to_know_answers": responses,
|
165 |
"blog": blog_text if blog_checkbox else "[User chose to skip this section]"
|
166 |
}
|
|
|
167 |
summary = {
|
168 |
"Learning_Plan": generate_learning_plan(transcript_info),
|
169 |
"Style_Summary": generate_learning_style_summary(learning_type),
|
170 |
"Motivation": generate_motivation_section(responses)
|
171 |
}
|
|
|
172 |
with open("student_profile.json", "w") as f:
|
173 |
json.dump(profile, f, indent=4)
|
|
|
174 |
with open("student_summary.md", "w") as f:
|
175 |
f.write(summary["Learning_Plan"] + '\n' + summary["Style_Summary"] + '\n' + summary["Motivation"])
|
176 |
-
return f"β
Profile saved! Your learning style is: {learning_type}", True
|
177 |
|
178 |
-
|
179 |
-
updates = []
|
180 |
-
updates.append(gr.update(visible=False)) # for file upload
|
181 |
-
updates.extend([gr.update(visible=False) for _ in range(len(learning_style_questions))])
|
182 |
-
updates.append(gr.update(visible=False)) # blog checkbox
|
183 |
-
updates.append(gr.update(visible=False)) # blog text
|
184 |
-
updates.extend([gr.update(visible=False) for _ in range(sum(len(v) for v in get_to_know_categories.values()))])
|
185 |
-
return updates
|
186 |
|
187 |
with gr.Blocks() as demo:
|
188 |
gr.Markdown("## π Personalized AI Student Assistant")
|
|
|
189 |
with gr.Row():
|
190 |
file = gr.File(label="π Upload Your Transcript (.csv, .xlsx, .pdf)")
|
191 |
|
@@ -209,15 +237,12 @@ with gr.Blocks() as demo:
|
|
209 |
blog_checkbox.change(fn=lambda x: gr.update(visible=x), inputs=blog_checkbox, outputs=blog_text)
|
210 |
|
211 |
submit = gr.Button("ποΈ Save My Profile")
|
212 |
-
|
|
|
213 |
|
214 |
submit.click(fn=save_profile,
|
215 |
inputs=[file, *quiz_components, blog_checkbox, blog_text, *category_inputs],
|
216 |
-
outputs=[
|
217 |
-
|
218 |
-
submit.click(fn=hide_ui,
|
219 |
-
inputs=[],
|
220 |
-
outputs=[file, *quiz_components, blog_checkbox, blog_text, *category_inputs])
|
221 |
|
222 |
if __name__ == '__main__':
|
223 |
demo.launch()
|
|
|
24 |
def extract_transcript_info(df):
|
25 |
transcript_text = df['Transcript_Text'].iloc[0] if 'Transcript_Text' in df.columns else ''
|
26 |
info = {}
|
27 |
+
|
28 |
+
# GPA extraction
|
29 |
+
gpa_matches = re.findall(r'(weighted|unweighted)?\s*GPA[:\s-]*([0-4]\.?\d{0,2})', transcript_text, re.IGNORECASE)
|
30 |
+
for gpa_type, gpa_value in gpa_matches:
|
31 |
+
key = f"{gpa_type.strip().capitalize() if gpa_type else 'GPA'}"
|
32 |
+
info[key] = gpa_value
|
33 |
+
|
34 |
+
# Grade Level
|
35 |
+
grade_match = re.search(r'Grade:?\s*(\d{1,2})', transcript_text, re.IGNORECASE)
|
36 |
if grade_match:
|
37 |
info['Grade_Level'] = grade_match.group(1)
|
38 |
+
|
39 |
+
# Full Name
|
40 |
+
name_match = re.search(r'(Student Name|Name):?\s*([A-Z][a-z]+\s+[A-Z][a-z]+)', transcript_text)
|
41 |
+
if name_match:
|
42 |
+
info['Full_Name'] = name_match.group(2)
|
43 |
+
|
44 |
+
# Courses
|
45 |
courses = re.findall(r'(?i)\b([A-Z][a-zA-Z\s&/]+)\s+(\d{1,3})\b', transcript_text)
|
46 |
if courses:
|
47 |
info['Courses'] = list(set([c[0].strip() for c in courses]))
|
48 |
+
|
49 |
return info
|
50 |
|
51 |
# Learning style questions - from educationplanner.org
|
|
|
79 |
|
80 |
def learning_style_quiz(*answers):
|
81 |
scores = {'visual': 0, 'auditory': 0, 'reading/writing': 0}
|
82 |
+
|
83 |
for i, ans in enumerate(answers):
|
84 |
if i < len(learning_style_answers):
|
85 |
options = learning_style_answers[i]
|
|
|
87 |
index = options.index(ans)
|
88 |
style = style_count_map[index]
|
89 |
scores[style] += 1
|
90 |
+
|
91 |
max_score = max(scores.values())
|
92 |
best_styles = [style.capitalize() for style, score in scores.items() if score == max_score]
|
93 |
+
|
94 |
return ", ".join(best_styles)
|
95 |
|
96 |
get_to_know_categories = {
|
|
|
131 |
def generate_learning_plan(info):
|
132 |
level = info.get("Grade_Level", "unknown")
|
133 |
courses = info.get("Courses", [])
|
134 |
+
gpa = info.get("GPA", info.get("Unweighted", "N/A"))
|
135 |
return f"""
|
136 |
π **Personalized Learning Plan**
|
137 |
- Grade Level: {level}
|
|
|
154 |
Believe in yourself and keep moving forward.
|
155 |
"""
|
156 |
|
157 |
+
def show_basic_info():
|
158 |
+
with open("student_profile.json") as f:
|
159 |
+
profile = json.load(f)
|
160 |
+
info = profile["transcript_info"]
|
161 |
+
name = info.get("Full_Name", "Name not found")
|
162 |
+
grade = info.get("Grade_Level", "N/A")
|
163 |
+
gpa = info.get("GPA", info.get("Unweighted", "N/A"))
|
164 |
+
weighted = info.get("Weighted", "Not provided")
|
165 |
+
return f"π€ Name: {name}\nπ Grade Level: {grade}\nπ GPA: {gpa}\nπ Weighted GPA: {weighted}"
|
166 |
+
|
167 |
def save_profile(file, *inputs):
|
168 |
if not file:
|
169 |
+
return gr.Textbox.update(value="β οΈ Please upload your transcript."), gr.Textbox.update(visible=False)
|
170 |
+
|
171 |
quiz_answers = inputs[:len(learning_style_questions)]
|
172 |
if any(ans is None for ans in quiz_answers):
|
173 |
+
return gr.Textbox.update(value="β οΈ Please answer all the learning style questions."), gr.Textbox.update(visible=False)
|
174 |
+
|
175 |
blog_checkbox = inputs[len(learning_style_questions)]
|
176 |
blog_text = inputs[len(learning_style_questions)+1]
|
177 |
category_answers = inputs[len(learning_style_questions)+2:]
|
178 |
+
|
179 |
if any(ans.strip() == "" for ans in category_answers):
|
180 |
+
return gr.Textbox.update(value="β οΈ Please complete all 'Get to Know You' sections before saving."), gr.Textbox.update(visible=False)
|
181 |
+
|
182 |
if blog_checkbox and blog_text.strip() == "":
|
183 |
+
return gr.Textbox.update(value="β οΈ You checked the blog option but didnβt write anything. Please write your mini blog or uncheck the option."), gr.Textbox.update(visible=False)
|
184 |
|
185 |
df = parse_transcript(file)
|
186 |
transcript_info = extract_transcript_info(df)
|
187 |
learning_type = learning_style_quiz(*quiz_answers)
|
188 |
+
|
189 |
question_texts = [q for cat in get_to_know_categories.values() for q, _ in cat]
|
190 |
responses = dict(zip(question_texts, category_answers))
|
191 |
+
|
192 |
profile = {
|
193 |
"transcript": df.to_dict(orient='records'),
|
194 |
"transcript_info": transcript_info,
|
|
|
196 |
"get_to_know_answers": responses,
|
197 |
"blog": blog_text if blog_checkbox else "[User chose to skip this section]"
|
198 |
}
|
199 |
+
|
200 |
summary = {
|
201 |
"Learning_Plan": generate_learning_plan(transcript_info),
|
202 |
"Style_Summary": generate_learning_style_summary(learning_type),
|
203 |
"Motivation": generate_motivation_section(responses)
|
204 |
}
|
205 |
+
|
206 |
with open("student_profile.json", "w") as f:
|
207 |
json.dump(profile, f, indent=4)
|
208 |
+
|
209 |
with open("student_summary.md", "w") as f:
|
210 |
f.write(summary["Learning_Plan"] + '\n' + summary["Style_Summary"] + '\n' + summary["Motivation"])
|
|
|
211 |
|
212 |
+
return gr.Textbox.update(value="β
Profile saved!"), gr.Textbox.update(value=show_basic_info(), visible=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
213 |
|
214 |
with gr.Blocks() as demo:
|
215 |
gr.Markdown("## π Personalized AI Student Assistant")
|
216 |
+
|
217 |
with gr.Row():
|
218 |
file = gr.File(label="π Upload Your Transcript (.csv, .xlsx, .pdf)")
|
219 |
|
|
|
237 |
blog_checkbox.change(fn=lambda x: gr.update(visible=x), inputs=blog_checkbox, outputs=blog_text)
|
238 |
|
239 |
submit = gr.Button("ποΈ Save My Profile")
|
240 |
+
status_output = gr.Textbox(label="Status")
|
241 |
+
user_info_output = gr.Textbox(label="π€ Your Info", visible=False)
|
242 |
|
243 |
submit.click(fn=save_profile,
|
244 |
inputs=[file, *quiz_components, blog_checkbox, blog_text, *category_inputs],
|
245 |
+
outputs=[status_output, user_info_output])
|
|
|
|
|
|
|
|
|
246 |
|
247 |
if __name__ == '__main__':
|
248 |
demo.launch()
|