Download file_study_guide_panel.py from ankban/CommTutor: direct link, hf CLI and curl.
- Browser
- Download file 6.1 kB
-
https://huggingface.co/spaces/ankban/CommTutor/resolve/main/file_study_guide_panel.py
- Command line
-
hf download hf://spaces/ankban/CommTutor/file_study_guide_panel.py
-
curl -L -o file_study_guide_panel.py https://huggingface.co/spaces/ankban/CommTutor/resolve/main/file_study_guide_panel.py
6.1 kB
| import gradio as gr | |
| import json | |
| from file_utils import extract_text_from_file, call_llm, save_study_guide, fetch_study_guides | |
| def file_study_guide_dashboard(nickname_input): | |
| with gr.Column() as panel: | |
| file_input = gr.File(label="π€ Upload a File", file_types=[".pdf", ".txt", ".md", ".pptx"]) | |
| save_btn = gr.Button("πΎ Save Guide") | |
| guide_dropdown = gr.Dropdown(label="π Your Saved Guides", choices=[]) | |
| section_output = gr.Column() | |
| file_text_state = gr.State("") | |
| guide_state = gr.State([]) | |
| def sample_section(): | |
| return render_sections([{ | |
| "section_title": "Sample Section", | |
| "overview": "This is a short summary of the topic.", | |
| "explanation": "This is a detailed explanation to show how learning content will look.", | |
| "quiz": [ | |
| {"question": "What is 2+2?", "options": ["1", "2", "3", "4"], "answer": "4"}, | |
| {"question": "Sample Q2?", "options": ["A", "B", "C", "D"], "answer": "B"}, | |
| {"question": "Sample Q3?", "options": ["A", "B", "C", "D"], "answer": "C"}, | |
| {"question": "Sample Q4?", "options": ["A", "B", "C", "D"], "answer": "D"}, | |
| {"question": "Sample Q5?", "options": ["A", "B", "C", "D"], "answer": "A"} | |
| ] | |
| }]) | |
| # Move this after render_sections is defined | |
| pass | |
| def generate_study_guide(file): | |
| if file is None: | |
| return [gr.Markdown("β No file uploaded.")], "", [] | |
| text = extract_text_from_file(file) | |
| prompt = f""" | |
| You are an AI tutor. Divide the following content into 5β6 logical sections. | |
| For each section: | |
| - Provide a 2β3 line summary (overview) | |
| - Write a detailed explanation of the topic | |
| - Create 5 multiple choice questions (MCQs), each with: | |
| - A question | |
| - 4 options | |
| - 1 correct answer | |
| Return as JSON in this format: | |
| [ | |
| {{ | |
| "section_title": "...", | |
| "overview": "...", | |
| "explanation": "...", | |
| "quiz": [ | |
| {{"question": "...", "options": ["A", "B", "C", "D"], "answer": "B"}}, | |
| ... | |
| ] | |
| }}, | |
| ... | |
| ] | |
| Text: | |
| {text} | |
| """ | |
| response = call_llm(prompt) | |
| try: | |
| guide = json.loads(response) | |
| section_output.children = render_sections(guide) | |
| return text, guide | |
| except: | |
| section_output.children = [gr.Markdown("β Failed to parse structured study guide.")] | |
| return text, [] | |
| def render_sections(guide_data): | |
| blocks = [] | |
| for i, sec in enumerate(guide_data): | |
| blocks.append(render_section(i + 1, sec)) | |
| return blocks | |
| def render_section(index, sec): | |
| block = gr.Column() | |
| with block: | |
| gr.Markdown(f"## π Section {index}: {sec['section_title']}") | |
| gr.Markdown(f"**Overview:** {sec['overview']}") | |
| gr.Markdown(f"**Explanation:**\n\n{sec['explanation']}") | |
| gr.Markdown("### π§ Quiz") | |
| question_area = gr.Column() | |
| def make_question_ui(q_idx): | |
| q = sec['quiz'][q_idx] | |
| q_box = gr.Markdown(f"**Q{q_idx+1}.** {q['question']}") | |
| q_radio = gr.Radio(q['options'], label="Choose an answer") | |
| def grade(choice): | |
| correct = q['answer'] | |
| return "β Correct!" if choice == correct else f"β Correct: {correct}" | |
| q_radio.change(fn=grade, inputs=[q_radio], outputs=[feedback_box]) | |
| return [q_box, q_radio] | |
| feedback_box = gr.Textbox(label="Answer Feedback", interactive=False) | |
| question_area.children = make_question_ui(0) | |
| with gr.Row(): | |
| for i in range(5): | |
| gr.Button(str(i + 1), size="sm").click(fn=lambda idx=i: make_question_ui(idx), inputs=[], outputs=question_area) | |
| return block | |
| def save_to_user(nickname, filename, guide): | |
| if not guide or not filename: | |
| return | |
| save_study_guide(nickname, filename.name, json.dumps(guide)) | |
| def load_user_guides(user): | |
| guides = fetch_study_guides(user) | |
| return [f"{g.filename} ({g.timestamp})" for g in guides] | |
| # Initialize with sample content after all functions are defined | |
| section_output.children = render_sections([{ | |
| "section_title": "Sample Section", | |
| "overview": "This is a short summary of the topic.", | |
| "explanation": "This is a detailed explanation to show how learning content will look.", | |
| "quiz": [ | |
| {"question": "What is 2+2?", "options": ["1", "2", "3", "4"], "answer": "4"}, | |
| {"question": "Sample Q2?", "options": ["A", "B", "C", "D"], "answer": "B"}, | |
| {"question": "Sample Q3?", "options": ["A", "B", "C", "D"], "answer": "C"}, | |
| {"question": "Sample Q4?", "options": ["A", "B", "C", "D"], "answer": "D"}, | |
| {"question": "Sample Q5?", "options": ["A", "B", "C", "D"], "answer": "A"} | |
| ] | |
| }]) | |
| def show_saved_guide(user, label): | |
| guides = fetch_study_guides(user) | |
| for g in guides: | |
| if label.startswith(g.filename): | |
| section_output.children = render_sections(json.loads(g.guide)) | |
| return | |
| section_output.children = [gr.Markdown("β Guide not found.")] | |
| file_input.change(fn=generate_study_guide, inputs=[file_input], outputs=[file_text_state, guide_state]) | |
| save_btn.click(fn=save_to_user, inputs=[nickname_input, file_input, guide_state], outputs=[]) | |
| nickname_input.change(fn=load_user_guides, inputs=[nickname_input], outputs=[guide_dropdown]) | |
| guide_dropdown.change(fn=show_saved_guide, inputs=[nickname_input, guide_dropdown], outputs=[]) | |
| return panel |