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