Piyushdash94 commited on
Commit
3c66e74
Β·
verified Β·
1 Parent(s): 4c289a7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +172 -172
app.py CHANGED
@@ -3,177 +3,177 @@ import gradio as gr
3
  from controller import generate_questions # returns question_list (or a dict containing it)
4
  from controller import generate_answer # returns a dict with question_content, answer_content, reasoning_content
5
  from db import save_in_db # saves parsed dict into mongo
6
-
7
- MAX_QUESTIONS = 20
8
-
9
- # ---------------- Helpers ---------------- #
10
- def _extract_question_list(result):
11
- """Safely extract question list from a controller response"""
12
- if not result:
13
- return []
14
- if isinstance(result, dict):
15
- if "success" in result and isinstance(result.get("data"), dict):
16
- return result["data"].get("question_list", [])
17
- if "question_list" in result:
18
- return result["question_list"] or []
19
- if "data" in result and isinstance(result["data"], list):
20
- return result["data"]
21
- if isinstance(result, list):
22
- return result
23
- return []
24
-
25
- def _extract_qa(result, original_q):
26
- """Return a dict with question_content, answer_content, reasoning_content"""
27
- default = {
28
- "question_content": original_q,
29
- "answer_content": "No answer returned",
30
- "reasoning_content": ""
31
- }
32
- if not result:
33
- return default
34
- if isinstance(result, dict):
35
- d = result.get("data") if result.get("success") and isinstance(result.get("data"), dict) else result
36
- return {
37
- "question_content": d.get("question_content", original_q),
38
- "answer_content": d.get("answer_content", d.get("answer", "")) or "",
39
- "reasoning_content": d.get("reasoning_content", d.get("reasoning", "")) or ""
40
- }
41
- return default
42
-
43
- # ---------------- Handlers ---------------- #
44
- def generate_questions_ui(topic: str, num_questions: int):
45
- """Stream Q β†’ A β†’ R one by one"""
46
- result_values = []
47
- for _ in range(MAX_QUESTIONS):
48
- result_values.extend([
49
- "", "", "", # Q, A, R
50
- gr.update(visible=False, interactive=False), # accept
51
- gr.update(visible=False, interactive=False), # reject
52
- gr.update(visible=False) # group hidden
53
- ])
54
- yield result_values
55
-
56
- try:
57
- qres = generate_questions(topic.strip(), int(num_questions))
58
- except Exception as e:
59
- result_values[0] = f"Error generating questions: {e}"
60
- yield result_values
61
- return
62
-
63
- question_list = _extract_question_list(qres)
64
- if not question_list:
65
- result_values[0] = "No questions returned."
66
- yield result_values
67
- return
68
-
69
- for i, q in enumerate(question_list[:MAX_QUESTIONS]):
70
- base = i * 6
71
- result_values[base + 0] = q
72
- result_values[base + 1] = "Generating answer..."
73
- result_values[base + 2] = "Generating reasoning..."
74
- result_values[base + 5] = gr.update(visible=True)
75
- yield result_values
76
-
77
- try:
78
- ans_res = generate_answer(q)
79
- qa = _extract_qa(ans_res, q)
80
- result_values[base + 1] = qa["answer_content"]
81
- result_values[base + 2] = qa["reasoning_content"]
82
- result_values[base + 3] = gr.update(visible=True, interactive=True)
83
- result_values[base + 4] = gr.update(visible=True, interactive=True)
84
- except Exception as e:
85
- result_values[base + 1] = f"Error: {e}"
86
- result_values[base + 2] = ""
87
- result_values[base + 4] = gr.update(visible=True, interactive=True)
88
-
89
- yield result_values
90
-
91
- yield result_values
92
-
93
- def accept_question(question, answer, reasoning):
94
- """Save in DB and hide card"""
95
- parsed = {
96
- "question_content": question,
97
- "answer_language": "Odia",
98
- "reasoning_content": reasoning,
99
- "answer_content": answer,
100
- }
101
- try:
102
- save_in_db(parsed)
103
- return (
104
- gr.update(visible=False), # accept_btn
105
- gr.update(visible=False), # reject_btn
106
- gr.update(visible=False) # group hidden
107
- )
108
- except Exception as e:
109
- return (
110
- gr.update(interactive=False, value=f"Error: {e}"),
111
- gr.update(visible=True),
112
- gr.update(visible=True)
113
- )
114
-
115
- def reject_card():
116
- """Hide rejected card"""
117
- return gr.update(visible=False)
118
-
119
- # ---------------- UI Layout ---------------- #
120
- custom_css = """
121
- .gradio-container { background-color: #121212 !important; color: #E0E0E0 !important; }
122
- .question-card {
123
- border: 1px solid #333;
124
- box-shadow: 0 4px 12px rgba(0,0,0,0.4);
125
- border-radius: 12px;
126
- padding: 20px !important;
127
- margin-bottom: 20px !important;
128
- background-color: #1E1E1E;
129
- transition: 0.3s ease-in-out;
130
- }
131
- .question-card:hover {
132
- transform: translateY(-3px);
133
- box-shadow: 0 6px 16px rgba(0,0,0,0.6);
134
- }
135
- textarea { background-color: #2A2A2A !important; color: #E0E0E0 !important; border: 1px solid #444 !important; border-radius: 8px !important; }
136
- button { border-radius: 8px !important; padding: 8px 12px !important; }
137
- """
138
-
139
- with gr.Blocks(theme=gr.themes.Base(), css=custom_css) as demo:
140
- gr.Markdown("<h2 style='color:#90CAF9;'>πŸŒ™ Odia Q&A β€” Generate β†’ Answer (streaming)</h2>")
141
-
142
- with gr.Row():
143
- topic_input = gr.Textbox(label="πŸ“ Topic", placeholder="Enter a topic, e.g., 'Photosynthesis'")
144
- num_questions_input = gr.Dropdown(label="πŸ”’ Number of Questions", choices=[5, 10, 15, 20], value=5)
145
- generate_btn = gr.Button("⚑ Generate", variant="primary")
146
-
147
- output_components = []
148
- for i in range(MAX_QUESTIONS):
149
- with gr.Group(visible=False, elem_classes=["question-card"]) as output_group:
150
- with gr.Row():
151
- with gr.Column(scale=4):
152
- q_text = gr.Textbox(label="❓ Question", interactive=False)
153
- a_text = gr.Textbox(label="βœ… Answer", interactive=False)
154
- r_text = gr.Textbox(label="🧠 Reasoning", interactive=False)
155
- with gr.Column(scale=1, min_width=150):
156
- accept_btn = gr.Button("Accept", variant="primary")
157
- reject_btn = gr.Button("Reject", variant="stop")
158
-
159
- # Bind buttons
160
- accept_btn.click(
161
- fn=accept_question,
162
- inputs=[q_text, a_text, r_text], # βœ… only inputs
163
- outputs=[accept_btn, reject_btn, output_group] # βœ… update group visibility
164
- )
165
- reject_btn.click(fn=reject_card, outputs=[output_group])
166
-
167
- output_components.extend([q_text, a_text, r_text, accept_btn, reject_btn, output_group])
168
-
169
- generate_btn.click(
170
- fn=generate_questions_ui,
171
- inputs=[topic_input, num_questions_input],
172
- outputs=output_components
173
- )
174
-
175
- demo.queue()
176
-
177
  if __name__ == "__main__":
178
  port = int(os.getenv("UI_PORT", "7860"))
179
- demo.launch(server_name="0.0.0.0", server_port=port, share=True)
 
3
  from controller import generate_questions # returns question_list (or a dict containing it)
4
  from controller import generate_answer # returns a dict with question_content, answer_content, reasoning_content
5
  from db import save_in_db # saves parsed dict into mongo
6
+
7
+ MAX_QUESTIONS = 20
8
+
9
+ # ---------------- Helpers ---------------- #
10
+ def _extract_question_list(result):
11
+ """Safely extract question list from a controller response"""
12
+ if not result:
13
+ return []
14
+ if isinstance(result, dict):
15
+ if "success" in result and isinstance(result.get("data"), dict):
16
+ return result["data"].get("question_list", [])
17
+ if "question_list" in result:
18
+ return result["question_list"] or []
19
+ if "data" in result and isinstance(result["data"], list):
20
+ return result["data"]
21
+ if isinstance(result, list):
22
+ return result
23
+ return []
24
+
25
+ def _extract_qa(result, original_q):
26
+ """Return a dict with question_content, answer_content, reasoning_content"""
27
+ default = {
28
+ "question_content": original_q,
29
+ "answer_content": "No answer returned",
30
+ "reasoning_content": ""
31
+ }
32
+ if not result:
33
+ return default
34
+ if isinstance(result, dict):
35
+ d = result.get("data") if result.get("success") and isinstance(result.get("data"), dict) else result
36
+ return {
37
+ "question_content": d.get("question_content", original_q),
38
+ "answer_content": d.get("answer_content", d.get("answer", "")) or "",
39
+ "reasoning_content": d.get("reasoning_content", d.get("reasoning", "")) or ""
40
+ }
41
+ return default
42
+
43
+ # ---------------- Handlers ---------------- #
44
+ def generate_questions_ui(topic: str, num_questions: int):
45
+ """Stream Q β†’ A β†’ R one by one"""
46
+ result_values = []
47
+ for _ in range(MAX_QUESTIONS):
48
+ result_values.extend([
49
+ "", "", "", # Q, A, R
50
+ gr.update(visible=False, interactive=False), # accept
51
+ gr.update(visible=False, interactive=False), # reject
52
+ gr.update(visible=False) # group hidden
53
+ ])
54
+ yield result_values
55
+
56
+ try:
57
+ qres = generate_questions(topic.strip(), int(num_questions))
58
+ except Exception as e:
59
+ result_values[0] = f"Error generating questions: {e}"
60
+ yield result_values
61
+ return
62
+
63
+ question_list = _extract_question_list(qres)
64
+ if not question_list:
65
+ result_values[0] = "No questions returned."
66
+ yield result_values
67
+ return
68
+
69
+ for i, q in enumerate(question_list[:MAX_QUESTIONS]):
70
+ base = i * 6
71
+ result_values[base + 0] = q
72
+ result_values[base + 1] = "Generating answer..."
73
+ result_values[base + 2] = "Generating reasoning..."
74
+ result_values[base + 5] = gr.update(visible=True)
75
+ yield result_values
76
+
77
+ try:
78
+ ans_res = generate_answer(q)
79
+ qa = _extract_qa(ans_res, q)
80
+ result_values[base + 1] = qa["answer_content"]
81
+ result_values[base + 2] = qa["reasoning_content"]
82
+ result_values[base + 3] = gr.update(visible=True, interactive=True)
83
+ result_values[base + 4] = gr.update(visible=True, interactive=True)
84
+ except Exception as e:
85
+ result_values[base + 1] = f"Error: {e}"
86
+ result_values[base + 2] = ""
87
+ result_values[base + 4] = gr.update(visible=True, interactive=True)
88
+
89
+ yield result_values
90
+
91
+ yield result_values
92
+
93
+ def accept_question(question, answer, reasoning):
94
+ """Save in DB and hide card"""
95
+ parsed = {
96
+ "question_content": question,
97
+ "answer_language": "Odia",
98
+ "reasoning_content": reasoning,
99
+ "answer_content": answer,
100
+ }
101
+ try:
102
+ save_in_db(parsed)
103
+ return (
104
+ gr.update(visible=False), # accept_btn
105
+ gr.update(visible=False), # reject_btn
106
+ gr.update(visible=False) # group hidden
107
+ )
108
+ except Exception as e:
109
+ return (
110
+ gr.update(interactive=False, value=f"Error: {e}"),
111
+ gr.update(visible=True),
112
+ gr.update(visible=True)
113
+ )
114
+
115
+ def reject_card():
116
+ """Hide rejected card"""
117
+ return gr.update(visible=False)
118
+
119
+ # ---------------- UI Layout ---------------- #
120
+ custom_css = """
121
+ .gradio-container { background-color: #121212 !important; color: #E0E0E0 !important; }
122
+ .question-card {
123
+ border: 1px solid #333;
124
+ box-shadow: 0 4px 12px rgba(0,0,0,0.4);
125
+ border-radius: 12px;
126
+ padding: 20px !important;
127
+ margin-bottom: 20px !important;
128
+ background-color: #1E1E1E;
129
+ transition: 0.3s ease-in-out;
130
+ }
131
+ .question-card:hover {
132
+ transform: translateY(-3px);
133
+ box-shadow: 0 6px 16px rgba(0,0,0,0.6);
134
+ }
135
+ textarea { background-color: #2A2A2A !important; color: #E0E0E0 !important; border: 1px solid #444 !important; border-radius: 8px !important; }
136
+ button { border-radius: 8px !important; padding: 8px 12px !important; }
137
+ """
138
+
139
+ with gr.Blocks(theme=gr.themes.Base(), css=custom_css) as demo:
140
+ gr.Markdown("<h2 style='color:#90CAF9;'>πŸŒ™ Odia Q&A β€” Generate β†’ Answer (streaming)</h2>")
141
+
142
+ with gr.Row():
143
+ topic_input = gr.Textbox(label="πŸ“ Topic", placeholder="Enter a topic, e.g., 'Photosynthesis'")
144
+ num_questions_input = gr.Dropdown(label="πŸ”’ Number of Questions", choices=[5, 10, 15, 20], value=5)
145
+ generate_btn = gr.Button("⚑ Generate", variant="primary")
146
+
147
+ output_components = []
148
+ for i in range(MAX_QUESTIONS):
149
+ with gr.Group(visible=False, elem_classes=["question-card"]) as output_group:
150
+ with gr.Row():
151
+ with gr.Column(scale=4):
152
+ q_text = gr.Textbox(label="❓ Question", interactive=False)
153
+ a_text = gr.Textbox(label="βœ… Answer", interactive=False)
154
+ r_text = gr.Textbox(label="🧠 Reasoning", interactive=False)
155
+ with gr.Column(scale=1, min_width=150):
156
+ accept_btn = gr.Button("Accept", variant="primary")
157
+ reject_btn = gr.Button("Reject", variant="stop")
158
+
159
+ # Bind buttons
160
+ accept_btn.click(
161
+ fn=accept_question,
162
+ inputs=[q_text, a_text, r_text], # βœ… only inputs
163
+ outputs=[accept_btn, reject_btn, output_group] # βœ… update group visibility
164
+ )
165
+ reject_btn.click(fn=reject_card, outputs=[output_group])
166
+
167
+ output_components.extend([q_text, a_text, r_text, accept_btn, reject_btn, output_group])
168
+
169
+ generate_btn.click(
170
+ fn=generate_questions_ui,
171
+ inputs=[topic_input, num_questions_input],
172
+ outputs=output_components
173
+ )
174
+
175
+ demo.queue()
176
+
177
  if __name__ == "__main__":
178
  port = int(os.getenv("UI_PORT", "7860"))
179
+ demo.launch(server_name="0.0.0.0", server_port=int(os.getenv("PORT", "7860")), share=False)