RAMYASRI-39 commited on
Commit
4d37fb2
·
verified ·
1 Parent(s): be2fc39

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +196 -198
app.py CHANGED
@@ -1,100 +1,176 @@
1
- # Importing libraries
2
- import pandas as pd
3
- import json
4
  import gradio as gr
5
  from pathlib import Path
6
- from ragatouille import RAGPretrainedModel
7
- from gradio_client import Client
8
- from tempfile import NamedTemporaryFile
9
  from sentence_transformers import CrossEncoder
10
  import numpy as np
11
  from time import perf_counter
12
- from sentence_transformers import CrossEncoder
 
 
 
 
13
 
14
- #calling functions from other files - to call the knowledge database tables (lancedb for accurate mode) for creating quiz
15
- from backend.semantic_search import table, retriever
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
  VECTOR_COLUMN_NAME = "vector"
18
  TEXT_COLUMN_NAME = "text"
19
  proj_dir = Path.cwd()
20
 
21
- # Set up logging
22
- import logging
23
- logging.basicConfig(level=logging.INFO)
24
- logger = logging.getLogger(__name__)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
26
- # Replace Mixtral client with Qwen Client
27
- client = Client("Qwen/Qwen1.5-110B-Chat-demo")
28
-
29
- def system_instructions(question_difficulty, topic, documents_str):
30
- return f"""<s> [INST] You are a great teacher and your task is to create 10 questions with 4 choices with {question_difficulty} difficulty about the topic request "{topic}" only from the below given documents, {documents_str}. Then create answers. Index in JSON format, the questions as "Q#":"" to "Q#":"", the four choices as "Q#:C1":"" to "Q#:C4":"", and the answers as "A#":"Q#:C#" to "A#":"Q#:C#". Example: 'A10':'Q10:C3' [/INST]"""
31
-
32
- # Ragatouille database for Colbert ie highly accurate mode
33
- RAG_db = gr.State()
34
- quiz_data = None
35
-
36
-
37
- #defining a function to convert json file to excel file
38
- def json_to_excel(output_json):
39
- # Initialize list for DataFrame
40
- data = []
41
- gr.Warning('Generating Shareable file link..', duration=30)
42
- for i in range(1, 11): # Assuming there are 10 questions
43
- question_key = f"Q{i}"
44
- answer_key = f"A{i}"
45
-
46
- question = output_json.get(question_key, '')
47
- correct_answer_key = output_json.get(answer_key, '')
48
- #correct_answer = correct_answer_key.split(':')[-1] if correct_answer_key else ''
49
- correct_answer = correct_answer_key.split(':')[-1].replace('C', '').strip() if correct_answer_key else ''
50
-
51
- # Extract options
52
- option_keys = [f"{question_key}:C{i}" for i in range(1, 6)]
53
- options = [output_json.get(key, '') for key in option_keys]
54
-
55
- # Add data row
56
- data.append([
57
- question, # Question Text
58
- "Multiple Choice", # Question Type
59
- options[0], # Option 1
60
- options[1], # Option 2
61
- options[2] if len(options) > 2 else '', # Option 3
62
- options[3] if len(options) > 3 else '', # Option 4
63
- options[4] if len(options) > 4 else '', # Option 5
64
- correct_answer, # Correct Answer
65
- 30, # Time in seconds
66
- '' # Image Link
67
- ])
68
-
69
- # Create DataFrame
70
- df = pd.DataFrame(data, columns=[
71
- "Question Text",
72
- "Question Type",
73
- "Option 1",
74
- "Option 2",
75
- "Option 3",
76
- "Option 4",
77
- "Option 5",
78
- "Correct Answer",
79
- "Time in seconds",
80
- "Image Link"
81
- ])
82
-
83
- temp_file = NamedTemporaryFile(delete=False, suffix=".xlsx")
84
- df.to_excel(temp_file.name, index=False)
85
- return temp_file.name
86
  # Define a colorful theme
87
- colorful_theme = gr.themes.Default(
88
- primary_hue="cyan", # Set a bright cyan as primary color
89
- secondary_hue="yellow", # Set a bright magenta as secondary color
90
- neutral_hue="purple" # Optionally set a neutral color
91
-
92
- )
93
 
94
- #gradio app creation for a user interface
95
  with gr.Blocks(title="Quiz Maker", theme=colorful_theme) as QUIZBOT:
96
-
97
-
98
  # Create a single row for the HTML and Image
99
  with gr.Row():
100
  with gr.Column(scale=2):
@@ -102,129 +178,51 @@ with gr.Blocks(title="Quiz Maker", theme=colorful_theme) as QUIZBOT:
102
  with gr.Column(scale=6):
103
  gr.HTML("""
104
  <center>
105
- <h1><span style="color: purple;">GOVERNMENT HIGH SCHOOL,SUTHUKENY</span> STUDENTS QUIZBOT</h1>
106
  <h2>Generative AI-powered Capacity building for STUDENTS</h2>
107
- <i>⚠️STUDENTS CAN CREATE QUIZ AND EVALUATE BY THEMSELVES ! ⚠️</i>
108
  </center>
109
  """)
110
-
111
-
112
 
113
-
114
- topic = gr.Textbox(label="Enter the Topic for Quiz", placeholder="Write any topic/details from 10 social CBSE")
115
 
116
  with gr.Row():
117
  difficulty_radio = gr.Radio(["easy", "average", "hard"], label="How difficult should the quiz be?")
118
- model_radio = gr.Radio(choices=[ '(ACCURATE) BGE reranker', '(HIGH ACCURATE) ColBERT'],
119
- value='(ACCURATE) BGE reranker', label="Embeddings",
120
- info="First query to ColBERT may take a little time")
121
 
122
  generate_quiz_btn = gr.Button("Generate Quiz!🚀")
123
- quiz_msg = gr.Textbox()
124
-
125
- question_radios = [gr.Radio(visible=False) for _ in range(10)]
126
-
127
- @generate_quiz_btn.click(inputs=[difficulty_radio, topic, model_radio], outputs=[quiz_msg] + question_radios + [gr.File(label="Download Excel")])
128
- def generate_quiz(question_difficulty, topic, cross_encoder):
129
- top_k_rank = 10
130
- documents = []
131
- gr.Warning('Generating Quiz may take 1-2 minutes. Please wait.', duration=60)
132
-
133
- if cross_encoder == '(HIGH ACCURATE) ColBERT':
134
- gr.Warning('Retrieving using ColBERT.. First-time query will take 2 minute for model to load.. please wait',duration=100)
135
- RAG = RAGPretrainedModel.from_pretrained("colbert-ir/colbertv2.0")
136
- RAG_db.value = RAG.from_index('.ragatouille/colbert/indexes/cbseclass10index')
137
- documents_full = RAG_db.value.search(topic, k=top_k_rank)
138
- documents = [item['content'] for item in documents_full]
139
-
140
- else:
141
- document_start = perf_counter()
142
- query_vec = retriever.encode(topic)
143
- doc1 = table.search(query_vec, vector_column_name=VECTOR_COLUMN_NAME).limit(top_k_rank)
144
-
145
- documents = table.search(query_vec, vector_column_name=VECTOR_COLUMN_NAME).limit(top_k_rank).to_list()
146
- documents = [doc[TEXT_COLUMN_NAME] for doc in documents]
147
-
148
- query_doc_pair = [[topic, doc] for doc in documents]
149
-
150
- # if cross_encoder == '(FAST) MiniLM-L6v2':
151
- # cross_encoder1 = CrossEncoder('cross-encoder/ms-marco-MiniLM-L-6-v2')
152
- if cross_encoder == '(ACCURATE) BGE reranker':
153
- cross_encoder1 = CrossEncoder('BAAI/bge-reranker-base')
154
-
155
- cross_scores = cross_encoder1.predict(query_doc_pair)
156
- sim_scores_argsort = list(reversed(np.argsort(cross_scores)))
157
- documents = [documents[idx] for idx in sim_scores_argsort[:top_k_rank]]
158
-
159
- #creating a text prompt to Qwen model combining the documents and system instruction
160
- formatted_prompt = system_instructions(question_difficulty, topic, '\n'.join(documents))
161
- print(' Formatted Prompt : ' ,formatted_prompt)
162
- try:
163
- response = client.predict(query=formatted_prompt, history=[], system="You are a helpful assistant.", api_name="/model_chat")
164
- response1 = response[1][0][1]
165
-
166
- # Extract JSON
167
- start_index = response1.find('{')
168
- end_index = response1.rfind('}')
169
- cleaned_response = response1[start_index:end_index + 1] if start_index != -1 and end_index != -1 else ''
170
- print('Cleaned Response :',cleaned_response)
171
- output_json = json.loads(cleaned_response)
172
- # Assign the extracted JSON to quiz_data for use in the comparison function
173
- global quiz_data
174
- quiz_data = output_json
175
- # Generate the Excel file
176
- excel_file = json_to_excel(output_json)
177
-
178
-
179
- #Create a Quiz display in app
180
- question_radio_list = []
181
- for question_num in range(1, 11):
182
- question_key = f"Q{question_num}"
183
- answer_key = f"A{question_num}"
184
-
185
- question = output_json.get(question_key)
186
- answer = output_json.get(output_json.get(answer_key))
187
-
188
- if not question or not answer:
189
- continue
190
-
191
- choice_keys = [f"{question_key}:C{i}" for i in range(1, 5)]
192
- choice_list = [output_json.get(choice_key, "Choice not found") for choice_key in choice_keys]
193
-
194
- radio = gr.Radio(choices=choice_list, label=question, visible=True, interactive=True)
195
- question_radio_list.append(radio)
196
-
197
- return ['Quiz Generated!'] + question_radio_list + [excel_file]
198
-
199
- except json.JSONDecodeError as e:
200
- print(f"Failed to decode JSON: {e}")
201
-
202
- check_button = gr.Button("Check Score")
203
- score_textbox = gr.Markdown()
204
-
205
- @check_button.click(inputs=question_radios, outputs=score_textbox)
206
- def compare_answers(*user_answers):
207
- user_answer_list = list(user_answers)
208
- answers_list = []
209
-
210
- for question_num in range(1, 20):
211
- answer_key = f"A{question_num}"
212
- answer = quiz_data.get(quiz_data.get(answer_key))
213
- if not answer:
214
- break
215
- answers_list.append(answer)
216
-
217
- score = sum(1 for item in user_answer_list if item in answers_list)
218
-
219
- if score > 7:
220
- message = f"### Excellent! You got {score} out of 10!"
221
- elif score > 5:
222
- message = f"### Good! You got {score} out of 10!"
223
- else:
224
- message = f"### You got {score} out of 10! Don't worry. You can prepare well and try better next time!"
225
-
226
- return message
227
-
228
- QUIZBOT.queue()
229
- QUIZBOT.launch(debug=True)
230
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import gradio as gr
2
  from pathlib import Path
 
 
 
3
  from sentence_transformers import CrossEncoder
4
  import numpy as np
5
  from time import perf_counter
6
+ from pydantic import BaseModel, Field
7
+ from phi.agent import Agent
8
+ from phi.model.groq import Groq
9
+ import os
10
+ import logging
11
 
12
+ # Set up logging
13
+ logging.basicConfig(level=logging.INFO)
14
+ logger = logging.getLogger(__name__)
15
+
16
+ # API Key setup
17
+ api_key = os.getenv("GROQ_API_KEY")
18
+ if not api_key:
19
+ gr.Warning("GROQ_API_KEY not found. Set it in 'Repository secrets'.")
20
+ logger.error("GROQ_API_KEY not found.")
21
+ else:
22
+ os.environ["GROQ_API_KEY"] = api_key
23
+
24
+ # Pydantic Model for Quiz Structure
25
+ class QuizItem(BaseModel):
26
+ question: str = Field(..., description="The quiz question")
27
+ choices: list[str] = Field(..., description="List of 4 multiple-choice options")
28
+ correct_answer: str = Field(..., description="The correct choice (e.g., 'C1')")
29
+
30
+ class QuizOutput(BaseModel):
31
+ items: list[QuizItem] = Field(..., description="List of 10 quiz items")
32
+
33
+ # Initialize Agents
34
+ groq_agent = Agent(model=Groq(model="llama3-70b-8192", api_key=api_key), markdown=True)
35
+
36
+ quiz_generator = Agent(
37
+ name="Quiz Generator",
38
+ role="Generates structured quiz questions and answers",
39
+ instructions=[
40
+ "Create 10 questions with 4 choices each based on the provided topic and documents.",
41
+ "Use the specified difficulty level (easy, average, hard) to adjust question complexity.",
42
+ "Ensure questions are derived only from the provided documents.",
43
+ "Return the output in a structured format using the QuizOutput Pydantic model.",
44
+ "Each question should have a unique correct answer from the choices (labeled C1, C2, C3, C4)."
45
+ ],
46
+ model=Groq(id="llama3-70b-8192", api_key=api_key),
47
+ response_model=QuizOutput,
48
+ markdown=True
49
+ )
50
 
51
  VECTOR_COLUMN_NAME = "vector"
52
  TEXT_COLUMN_NAME = "text"
53
  proj_dir = Path.cwd()
54
 
55
+ # Calling functions from backend (assuming they exist)
56
+ from backend.semantic_search import table, retriever
57
+
58
+ def generate_quiz_data(question_difficulty, topic, documents_str):
59
+ prompt = f"""Generate a quiz with {question_difficulty} difficulty on topic '{topic}' using only the following documents:\n{documents_str}"""
60
+ try:
61
+ response = quiz_generator.run(prompt)
62
+ return response.content
63
+ except Exception as e:
64
+ logger.error(f"Failed to generate quiz: {e}")
65
+ return None
66
+
67
+ def retrieve_and_generate_quiz(question_difficulty, topic):
68
+ gr.Warning('Generating quiz may take 1-2 minutes. Please wait.', duration=60)
69
+ top_k_rank = 10
70
+ documents = []
71
+
72
+ document_start = perf_counter()
73
+ query_vec = retriever.encode(topic)
74
+ documents = [doc[TEXT_COLUMN_NAME] for doc in table.search(query_vec, vector_column_name=VECTOR_COLUMN_NAME).limit(top_k_rank).to_list()]
75
+
76
+ # Apply BGE reranker
77
+ cross_encoder = CrossEncoder('BAAI/bge-reranker-base')
78
+ query_doc_pair = [[topic, doc] for doc in documents]
79
+ cross_scores = cross_encoder.predict(query_doc_pair)
80
+ sim_scores_argsort = list(reversed(np.argsort(cross_scores)))
81
+ documents = [documents[idx] for idx in sim_scores_argsort[:top_k_rank]]
82
+
83
+ documents_str = '\n'.join(documents)
84
+ quiz_data = generate_quiz_data(question_difficulty, topic, documents_str)
85
+ return quiz_data
86
+
87
+ def update_quiz_components(quiz_data):
88
+ if not quiz_data or not quiz_data.items:
89
+ return [gr.update(visible=False) for _ in range(10)] + [gr.update(value="Error: Failed to generate quiz.", visible=True)]
90
+
91
+ radio_updates = []
92
+ for i, item in enumerate(quiz_data.items[:10]):
93
+ choices = item.choices
94
+ radio_update = gr.update(visible=True, choices=choices, label=item.question, value=None)
95
+ radio_updates.append(radio_update)
96
+ return radio_updates + [gr.update(value="Please select answers and click 'Check Score'.", visible=True)]
97
+
98
+ # FIXED FUNCTION: Changed parameter signature to accept all arguments positionally
99
+ def collect_answers_and_calculate(*all_inputs):
100
+ print(f"Total inputs received: {len(all_inputs)}") # Debug print
101
+
102
+ # The last input is quiz_data, the first 10 are radio values
103
+ radio_values = all_inputs[:10] # First 10 inputs are radio button values
104
+ quiz_data = all_inputs[10] # Last input is quiz_data
105
+
106
+ print(f"Received radio_values: {radio_values}") # Debug print
107
+ print(f"Received quiz_data: {quiz_data}") # Debug print
108
+
109
+ # Calculate score by comparing user answers with correct answers
110
+ score = 0
111
+ answered_questions = 0
112
+
113
+ for i, (user_answer, quiz_item) in enumerate(zip(radio_values, quiz_data.items[:10])):
114
+ if user_answer is not None: # Only count if user answered
115
+ answered_questions += 1
116
+
117
+ # Convert correct answer code (e.g., 'C3') to actual choice text
118
+ correct_answer_index = int(quiz_item.correct_answer[1]) - 1 # 'C3' -> index 2
119
+ correct_answer_text = quiz_item.choices[correct_answer_index]
120
+
121
+ print(f"Q{i+1}: User='{user_answer}' vs Correct='{correct_answer_text}'") # Debug
122
+
123
+ if user_answer == correct_answer_text:
124
+ score += 1
125
+
126
+ print(f"Calculated score: {score}/{answered_questions}") # Debug print
127
+
128
+ # Create colorful HTML message
129
+ if answered_questions == 0:
130
+ html_message = """
131
+ <div style="text-align: center; padding: 20px; border-radius: 10px; background: linear-gradient(135deg, #ff6b6b, #ee5a24);">
132
+ <h2 style="color: white; margin: 0;">⚠️ Please answer at least one question!</h2>
133
+ </div>
134
+ """
135
+ elif score == answered_questions:
136
+ html_message = f"""
137
+ <div style="text-align: center; padding: 20px; border-radius: 10px; background: linear-gradient(135deg, #00d2d3, #54a0ff); box-shadow: 0 4px 15px rgba(0,0,0,0.2);">
138
+ <h1 style="color: white; margin: 0; text-shadow: 2px 2px 4px rgba(0,0,0,0.3);">🏆 PERFECT SCORE! 🏆</h1>
139
+ <h2 style="color: #fff3cd; margin: 10px 0;">You got {score} out of {answered_questions} correct!</h2>
140
+ <p style="color: white; font-size: 18px; margin: 0;">Outstanding performance! 🌟</p>
141
+ </div>
142
+ """
143
+ elif score > answered_questions * 0.7:
144
+ html_message = f"""
145
+ <div style="text-align: center; padding: 20px; border-radius: 10px; background: linear-gradient(135deg, #2ed573, #7bed9f); box-shadow: 0 4px 15px rgba(0,0,0,0.2);">
146
+ <h1 style="color: white; margin: 0; text-shadow: 2px 2px 4px rgba(0,0,0,0.3);">🎉 EXCELLENT! 🎉</h1>
147
+ <h2 style="color: #fff3cd; margin: 10px 0;">You got {score} out of {answered_questions} correct!</h2>
148
+ <p style="color: white; font-size: 18px; margin: 0;">Great job! Keep it up! 💪</p>
149
+ </div>
150
+ """
151
+ elif score > answered_questions * 0.5:
152
+ html_message = f"""
153
+ <div style="text-align: center; padding: 20px; border-radius: 10px; background: linear-gradient(135deg, #ffa726, #ffcc02); box-shadow: 0 4px 15px rgba(0,0,0,0.2);">
154
+ <h1 style="color: white; margin: 0; text-shadow: 2px 2px 4px rgba(0,0,0,0.3);">👍 GOOD JOB! 👍</h1>
155
+ <h2 style="color: #fff3cd; margin: 10px 0;">You got {score} out of {answered_questions} correct!</h2>
156
+ <p style="color: white; font-size: 18px; margin: 0;">Well done! Room for improvement! 📚</p>
157
+ </div>
158
+ """
159
+ else:
160
+ html_message = f"""
161
+ <div style="text-align: center; padding: 20px; border-radius: 10px; background: linear-gradient(135deg, #ff7675, #fd79a8); box-shadow: 0 4px 15px rgba(0,0,0,0.2);">
162
+ <h1 style="color: white; margin: 0; text-shadow: 2px 2px 4px rgba(0,0,0,0.3);">💪 KEEP TRYING! 💪</h1>
163
+ <h2 style="color: #fff3cd; margin: 10px 0;">You got {score} out of {answered_questions} correct!</h2>
164
+ <p style="color: white; font-size: 18px; margin: 0;">Don't worry! Practice makes perfect! 📖✨</p>
165
+ </div>
166
+ """
167
+
168
+ return html_message
169
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
  # Define a colorful theme
171
+ colorful_theme = gr.themes.Default(primary_hue="cyan", secondary_hue="yellow", neutral_hue="purple")
 
 
 
 
 
172
 
 
173
  with gr.Blocks(title="Quiz Maker", theme=colorful_theme) as QUIZBOT:
 
 
174
  # Create a single row for the HTML and Image
175
  with gr.Row():
176
  with gr.Column(scale=2):
 
178
  with gr.Column(scale=6):
179
  gr.HTML("""
180
  <center>
181
+ <h1><span style="color: purple;">GOVERNMENT HIGH SCHOOL,SUTHUKENY</span> STUDENTS QUIZBOT </h1>
182
  <h2>Generative AI-powered Capacity building for STUDENTS</h2>
183
+ <i>⚠️ Students can create quiz from any topic from 10th Science and evaluate themselves! ⚠️</i>
184
  </center>
185
  """)
 
 
186
 
187
+ topic = gr.Textbox(label="Enter the Topic for Quiz", placeholder="Write any CHAPTER NAME")
 
188
 
189
  with gr.Row():
190
  difficulty_radio = gr.Radio(["easy", "average", "hard"], label="How difficult should the quiz be?")
191
+ model_radio = gr.Radio(choices=['(ACCURATE) BGE reranker'], value='(ACCURATE) BGE reranker', label="Embeddings")
 
 
192
 
193
  generate_quiz_btn = gr.Button("Generate Quiz!🚀")
194
+ quiz_msg = gr.Textbox(label="Status", interactive=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
195
 
196
+ # Pre-defined radio buttons for 10 questions
197
+ question_radios = [gr.Radio(visible=False, label="", choices=[""], value=None) for _ in range(10)]
198
+ quiz_data_state = gr.State(value=None)
199
+ check_score_btn = gr.Button("Check Score", variant="primary", size="lg")
200
+
201
+ # HTML output for colorful score display at bottom
202
+ score_output = gr.HTML(visible=False, label="Your Results")
203
+
204
+ # Register the click event for Generate Quiz without @ decorator
205
+ generate_quiz_btn.click(
206
+ fn=retrieve_and_generate_quiz,
207
+ inputs=[difficulty_radio, topic],
208
+ outputs=[quiz_data_state]
209
+ ).then(
210
+ fn=update_quiz_components,
211
+ inputs=[quiz_data_state],
212
+ outputs=question_radios + [quiz_msg]
213
+ )
214
+
215
+ # FIXED: Register the click event for Check Score with correct input handling
216
+ check_score_btn.click(
217
+ fn=collect_answers_and_calculate,
218
+ inputs=question_radios + [quiz_data_state], # This creates a list of 11 inputs
219
+ outputs=[score_output],
220
+ api_name="check_score"
221
+ ).then(
222
+ fn=lambda: gr.update(visible=True), # Make score output visible after calculation
223
+ inputs=[],
224
+ outputs=[score_output]
225
+ )
226
+
227
+ if __name__ == "__main__":
228
+ QUIZBOT.queue().launch(server_name="0.0.0.0", server_port=7860)# import gradio as gr