import os import gradio as gr from controller import generate_questions # returns question_list (or a dict containing it) from controller import generate_answer # returns a dict with question_content, answer_content, reasoning_content from db import save_in_db # saves parsed dict into mongo MAX_QUESTIONS = 20 # ---------------- Helpers ---------------- # def _extract_question_list(result): """Safely extract question list from a controller response""" if not result: return [] if isinstance(result, dict): if "success" in result and isinstance(result.get("data"), dict): return result["data"].get("question_list", []) if "question_list" in result: return result["question_list"] or [] if "data" in result and isinstance(result["data"], list): return result["data"] if isinstance(result, list): return result return [] def _extract_qa(result, original_q): """Return a dict with question_content, answer_content, reasoning_content""" default = { "question_content": original_q, "answer_content": "No answer returned", "reasoning_content": "" } if not result: return default if isinstance(result, dict): d = result.get("data") if result.get("success") and isinstance(result.get("data"), dict) else result return { "question_content": d.get("question_content", original_q), "answer_content": d.get("answer_content", d.get("answer", "")) or "", "reasoning_content": d.get("reasoning_content", d.get("reasoning", "")) or "" } return default # ---------------- Handlers ---------------- # def generate_questions_ui(topic: str, num_questions: int): """Stream Q → A → R one by one""" result_values = [] for _ in range(MAX_QUESTIONS): result_values.extend([ "", "", "", # Q, A, R gr.update(visible=False, interactive=False), # accept gr.update(visible=False, interactive=False), # reject gr.update(visible=False) # group hidden ]) yield result_values try: qres = generate_questions(topic.strip(), int(num_questions)) except Exception as e: result_values[0] = f"Error generating questions: {e}" yield result_values return question_list = _extract_question_list(qres) if not question_list: result_values[0] = "No questions returned." yield result_values return for i, q in enumerate(question_list[:MAX_QUESTIONS]): base = i * 6 result_values[base + 0] = q result_values[base + 1] = "Generating answer..." result_values[base + 2] = "Generating reasoning..." result_values[base + 5] = gr.update(visible=True) yield result_values try: ans_res = generate_answer(q) qa = _extract_qa(ans_res, q) result_values[base + 1] = qa["answer_content"] result_values[base + 2] = qa["reasoning_content"] result_values[base + 3] = gr.update(visible=True, interactive=True) result_values[base + 4] = gr.update(visible=True, interactive=True) except Exception as e: result_values[base + 1] = f"Error: {e}" result_values[base + 2] = "" result_values[base + 4] = gr.update(visible=True, interactive=True) yield result_values yield result_values def accept_question(question, answer, reasoning): """Save in DB and hide card""" parsed = { "question_content": question, "answer_language": "Odia", "reasoning_content": reasoning, "answer_content": answer, } try: save_in_db(parsed) return ( gr.update(visible=False), # accept_btn gr.update(visible=False), # reject_btn gr.update(visible=False) # group hidden ) except Exception as e: return ( gr.update(interactive=False, value=f"Error: {e}"), gr.update(visible=True), gr.update(visible=True) ) def reject_card(): """Hide rejected card""" return gr.update(visible=False) # ---------------- UI Layout ---------------- # custom_css = """ .gradio-container { background-color: #121212 !important; color: #E0E0E0 !important; } .question-card { border: 1px solid #333; box-shadow: 0 4px 12px rgba(0,0,0,0.4); border-radius: 12px; padding: 20px !important; margin-bottom: 20px !important; background-color: #1E1E1E; transition: 0.3s ease-in-out; } .question-card:hover { transform: translateY(-3px); box-shadow: 0 6px 16px rgba(0,0,0,0.6); } textarea { background-color: #2A2A2A !important; color: #E0E0E0 !important; border: 1px solid #444 !important; border-radius: 8px !important; } button { border-radius: 8px !important; padding: 8px 12px !important; } """ with gr.Blocks(theme=gr.themes.Base(), css=custom_css) as demo: gr.Markdown("