Oviya commited on
Commit
ce7ee25
·
1 Parent(s): da3d474

add generateQuestion

Browse files
generateQuestion - Cleared.py ADDED
@@ -0,0 +1,458 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, jsonify, send_file, abort, make_response, request
2
+ from flask_cors import CORS
3
+ from moviepy.editor import VideoFileClip
4
+ from google.cloud import speech
5
+ import os
6
+ print(f"GOOGLE_APPLICATION_CREDENTIALS: {os.getenv('GOOGLE_APPLICATION_CREDENTIALS')}")
7
+ import io
8
+ import uuid
9
+ import requests
10
+ from pydub import AudioSegment
11
+ import ffmpeg
12
+ import re
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+ app = Flask(__name__)
23
+ CORS(app)
24
+ # CORS(app, resources={r"/*": {"origins": "*"}})
25
+
26
+ @app.route('/')
27
+ def home():
28
+ return "Welcome to the Flask app! The server is running."
29
+
30
+
31
+
32
+ # API configuration for AI-based question generation
33
+ COHERE_API_KEY = 'WjnDKknACe0zxHvczdo7q4vwF4WAXn2429hcPHIB'
34
+ COHERE_API_URL = 'https://api.cohere.ai/v1/generate'
35
+
36
+ # Google Cloud Speech-to-Text Configuration
37
+ speech_client = speech.SpeechClient()
38
+
39
+
40
+
41
+
42
+
43
+
44
+
45
+
46
+ def validate_topic(topic):
47
+
48
+ validation_prompt = f"""
49
+ You are an AI grammar expert. Your task is to determine if a given topic is related to **English grammar** or not.
50
+
51
+ **Input:** "{topic}"
52
+
53
+ ### **Rules:**
54
+ - If the input is **in the form of a question** (e.g., it asks for an explanation or definition), return `"ask grammar topics"`, even if the topic is related to grammar.
55
+ - If the topic is **related to English grammar concepts** such as **parts of speech**, **verb tenses**, **sentence structure**, etc., return `"Grammar"`.
56
+ - If the topic is **not related to grammar**, such as general knowledge, science, math, history, or topics from other fields, return `"Not Grammar"`.
57
+ - Your response must be based purely on whether the topic relates to grammar, and **not** based on specific words, phrases, or examples.
58
+
59
+ **Your response must be exactly either "Grammar", "Not Grammar", or "ask grammar topics". No extra text.**
60
+ """
61
+
62
+
63
+
64
+
65
+
66
+ headers = {
67
+ 'Authorization': f'Bearer {COHERE_API_KEY}',
68
+ 'Content-Type': 'application/json'
69
+ }
70
+
71
+ payload = {
72
+ 'model': 'command-r-08-2024',
73
+ 'prompt': validation_prompt,
74
+ 'max_tokens': 5 # Minimal token usage for classification
75
+ }
76
+
77
+ try:
78
+ response = requests.post(COHERE_API_URL, json=payload, headers=headers)
79
+ validation_result = response.json().get('generations', [{}])[0].get('text', '').strip()
80
+
81
+ # Ensure the response is strictly "Grammar" or "Not Grammar"
82
+ if validation_result not in ["Grammar", "Not Grammar"]:
83
+ return "Not Grammar" # Fallback to avoid incorrect responses
84
+
85
+ return validation_result
86
+
87
+ except Exception as e:
88
+ return f"Error: {str(e)}"
89
+
90
+
91
+ @app.route('/generate-questions', methods=['POST'])
92
+ def generate_questions_test():
93
+ try:
94
+ data = request.get_json()
95
+ topic = data.get('topic', '').strip() # Default to "grammar" if no topic is provided
96
+ # levels = data.get('levels', ['basic', 'medium', 'hard'])
97
+
98
+
99
+ validation_result = validate_topic(topic)
100
+
101
+ if validation_result != "Grammar":
102
+ return jsonify({"message": "Please enter a valid **grammar topic**, not a general word or unrelated question."}), 400
103
+
104
+
105
+ difficulty = data.get('difficulty', 'basic')
106
+
107
+
108
+ # Debugging output
109
+ print(f"Generating {difficulty} questions for topic: {topic}")
110
+
111
+
112
+
113
+ if difficulty == 'basic':
114
+ prompt = f"""
115
+ Generate five **completely new and unique** very basic-level fill-in-the-blank grammar questions **every time** on the topic '{topic}'.
116
+
117
+ ### Rules:
118
+ - **Each question must have a different theme**, ensuring variety.
119
+ - **Do not repeat** themes from previous generations.
120
+ - Use **different sentence structures**, avoiding predictable patterns.
121
+ - **Avoid long words or abstract concepts**
122
+ - **Focus on the topic '{topic}'**, and ensure the blank is the key part of speech.
123
+ - Each question should contain **one blank represented by '_______'**, with the correct answer provided in parentheses at the end.
124
+ - The vocabulary should be **simple and suitable for beginners**.
125
+ - Ensure that the questions are **always new and distinct**, avoiding previously used themes.
126
+
127
+ Do not include any explanations or instructions in the response—only the five unique questions.
128
+ """
129
+
130
+ elif difficulty == 'elementary':
131
+ prompt = f"""
132
+ Generate five **completely new and unique** elementary-level fill-in-the-blank grammar questions **every time** on the topic '{topic}'.
133
+
134
+ ### Rules:
135
+ - The questions should be **slightly more challenging than basic-level questions**, incorporating **a wider range of sentence structures and vocabulary**.
136
+ - **Each question must have a different theme**, ensuring variety.
137
+ - **Use varied sentence structures**, making them slightly more complex than basic-level questions.
138
+ - **Ensure that the vocabulary is still simple but slightly broader** than basic-level questions.
139
+ - **Focus on the topic '{topic}'**, and ensure the blank is the key part of speech.
140
+ - Each question should contain **one blank represented by '_______'**, with the correct answer provided in parentheses at the end.
141
+ - Ensure that the questions are **always new and distinct**, avoiding previously used themes.
142
+
143
+ Do not include any explanations or instructions in the response—only the five unique questions.
144
+ """
145
+
146
+ elif difficulty == 'pre-intermediate':
147
+ prompt = f"""
148
+ Generate five **completely new and unique** pre-intermediate-level fill-in-the-blank grammar questions **every time** on the topic '{topic}'.
149
+
150
+ ### Rules:
151
+ - The questions should be **more challenging than elementary-level questions**, incorporating **more varied sentence structures and an expanded vocabulary**.
152
+ - **Each question must have a different theme**, ensuring variety.
153
+ - **Ensure that the vocabulary is broader than elementary-level**, while keeping it understandable for learners.
154
+ - **Sentences should be longer and more descriptive** but still clear.
155
+ - **Focus on the topic '{topic}'**, and ensure the blank is the key part of speech.
156
+ - Each question should contain **one blank represented by '_______'**, with the correct answer provided in parentheses at the end.
157
+ - Ensure that the questions are **always new and distinct**, avoiding previously used themes.
158
+
159
+ Do not include any explanations or instructions in the response—only the five unique questions.
160
+ """
161
+
162
+ elif difficulty == 'intermediate':
163
+ prompt = f"""
164
+ Generate five **completely new and unique** intermediate-level fill-in-the-blank grammar questions **every time** on the topic '{topic}'.
165
+
166
+ ### Rules:
167
+ - The questions should be **more complex than pre-intermediate-level questions**, incorporating **a wider range of vocabulary and sentence structures**.
168
+ - **Each question must have a different theme**, ensuring variety.
169
+ - **Ensure that the vocabulary is more advanced than pre-intermediate-level** while keeping it natural for learners.
170
+ - **Sentences should be longer and include more detail**, improving reading comprehension.
171
+ - **Focus on the topic '{topic}'**, and ensure the blank is the key part of speech.
172
+ - Each question should contain **one blank represented by '_______'**, with the correct answer provided in parentheses at the end.
173
+ - Ensure that the questions are **always new and distinct**, avoiding previously used themes.
174
+
175
+ Do not include any explanations or instructions in the response—only the five unique questions.
176
+ """
177
+
178
+ elif difficulty == 'upper-intermediate':
179
+ prompt = f"""
180
+ Generate five **completely new and unique** upper-intermediate-level fill-in-the-blank grammar questions **every time** on the topic '{topic}'.
181
+
182
+ ### Rules:
183
+ - The questions should be **more complex than intermediate-level questions**, incorporating **more advanced sentence structures and vocabulary**.
184
+ - **Each question must have a different theme**, ensuring variety.
185
+ - **Ensure that the vocabulary is more refined and diverse** but still understandable for upper-intermediate learners.
186
+ - **Sentences should be longer and may introduce more nuanced contexts**, requiring a deeper understanding.
187
+ - **Focus on the topic '{topic}'**, and ensure the blank is the key part of speech.
188
+ - Each question should contain **one blank represented by '_______'**, with the correct answer provided in parentheses at the end.
189
+ - Ensure that the questions are **always new and distinct**, avoiding previously used themes.
190
+
191
+ Do not include any explanations or instructions in the response—only the five unique questions.
192
+ """
193
+
194
+ elif difficulty == 'advanced':
195
+ prompt = f"""
196
+ Generate five **completely new and unique** advanced-level (C1) fill-in-the-blank grammar questions **every time** on the topic '{topic}'.
197
+
198
+ ### Rules:
199
+ - The questions should be **more challenging than upper-intermediate (B2) level**, requiring a deep understanding of grammar, context, and vocabulary.
200
+ - **Ensure varied and sophisticated vocabulary**, avoiding basic words.
201
+ - **Each question should require nuanced comprehension**, testing knowledge of advanced grammar patterns.
202
+ - **The blank must be the key part of the sentence** (not an obvious answer).
203
+ - Each question should contain **one blank represented by '_______'**, with the correct answer provided in parentheses at the end.
204
+ - Ensure that the questions are **always new and distinct**, avoiding repetition of themes.
205
+
206
+ Do not include any explanations or instructions in the response—only the five unique questions.
207
+ """
208
+
209
+ elif difficulty == 'hard':
210
+ prompt = f"""
211
+ Generate five **completely new and unique** hard-level (C2) fill-in-the-blank grammar questions **every time** on the topic '{topic}'.
212
+
213
+ ### Rules:
214
+ - The questions should be **more challenging than advanced(C1) level**, requiring a deep understanding of grammar, context, and vocabulary.
215
+ - **Ensure varied and sophisticated vocabulary**, avoiding basic words.
216
+ - **Each question should require nuanced comprehension**, testing knowledge of advanced grammar patterns.
217
+ - **The blank must be the key part of the sentence** (not an obvious answer).
218
+ - Each question should contain **one blank represented by '_______'**, with the correct answer provided in parentheses at the end.
219
+ - Ensure that the questions are **always new and distinct**, avoiding repetition of themes.
220
+
221
+ Do not include any explanations or instructions in the response—only the five unique questions.
222
+ """
223
+
224
+ else:
225
+ return jsonify({"error": "Invalid difficulty level"}), 400
226
+
227
+ headers = {
228
+ 'Authorization': f'Bearer {COHERE_API_KEY}',
229
+ 'Content-Type': 'application/json'
230
+ }
231
+
232
+ payload = {
233
+ 'model': 'command-r-08-2024', # Ensure you're using the right model
234
+ 'prompt': prompt,
235
+ 'max_tokens': 1000 # Increase the token limit if needed
236
+ }
237
+
238
+ # Make the API request
239
+ response = requests.post(COHERE_API_URL, json=payload, headers=headers)
240
+
241
+ # Log the full response for debugging
242
+ print("Response status code:", response.status_code)
243
+ print("Response content:", response.text)
244
+
245
+ if response.status_code == 200:
246
+ return jsonify(response.json()) # Return the response from Cohere API
247
+ else:
248
+ return jsonify({"error": "Failed to fetch questions", "details": response.text}), 500
249
+ except Exception as e:
250
+ return jsonify({"error": str(e)}), 500
251
+
252
+ # Endpoint to validate answers
253
+ @app.route('/validate-answer', methods=['POST'])
254
+ def validate_answer():
255
+ try:
256
+ # Get the data from the request
257
+ data = request.get_json()
258
+ topic = data.get('topic', '') # Get the topic
259
+ question = data.get('question', '')
260
+ user_answer = data.get('user_answer', '')
261
+
262
+ # Validate if the required fields are present
263
+ if not question or not user_answer or not topic:
264
+ return jsonify({'error': 'Topic, question, and user answer are required'}), 400
265
+
266
+ # Construct the prompt for Cohere API
267
+ prompt = f"""
268
+ You are a highly knowledgeable grammar assistant. Validate whether the user's answer to the following question is correct or not based on {topic}. If the answer is incorrect, provide a helpful hint.
269
+
270
+ Topic: {topic}
271
+ Question: "{question}"
272
+ User's Answer: "{user_answer}"
273
+
274
+ Is the answer correct? If not, please explain why and give a hint.
275
+ """
276
+
277
+ # Headers and payload for the Cohere API request
278
+ headers = {
279
+ 'Authorization': f'Bearer {COHERE_API_KEY}',
280
+ 'Content-Type': 'application/json'
281
+ }
282
+
283
+ payload = {
284
+ 'model': 'command-r-08-2024', # Use your model name here
285
+ 'prompt': prompt,
286
+ 'max_tokens': 100,
287
+ 'temperature': 0.7
288
+ }
289
+
290
+ # Make the API call to Cohere
291
+ response = requests.post(COHERE_API_URL, headers=headers, json=payload)
292
+
293
+ # Debugging: Log response status and body
294
+ print(f"Status Code: {response.status_code}")
295
+ print(f"Response Body: {response.text}")
296
+
297
+ # Check if the request was successful
298
+ if response.status_code == 200:
299
+ data = response.json()
300
+ return jsonify(data)
301
+ else:
302
+ return jsonify({'error': 'Failed to fetch data from Cohere API'}), 500
303
+
304
+ except Exception as e:
305
+ return jsonify({'error': str(e)}), 500
306
+
307
+
308
+
309
+ # // for validating Multiple answer:
310
+
311
+ # Function to validate an individual answer using Cohere API
312
+ def validate_answer_with_ai(topic, question, user_answer):
313
+ try:
314
+ # Construct the prompt for Cohere API
315
+ prompt = f"""
316
+ You are a highly knowledgeable grammar assistant. Validate whether the user's answer to the following question is correct or not based on {topic}. If the answer is incorrect, provide a helpful hint.
317
+
318
+ Topic: {topic}
319
+ Question: "{question}"
320
+ User's Answer: "{user_answer}"
321
+
322
+ Is the answer correct? If not, please explain why and give a hint.
323
+ """
324
+
325
+ # Headers for the API request
326
+ headers = {
327
+ 'Authorization': f'Bearer {COHERE_API_KEY}',
328
+ 'Content-Type': 'application/json'
329
+ }
330
+
331
+ # Construct the payload for Cohere API request
332
+ payload = {
333
+ 'model': 'command-r-08-2024', # You can use a different model depending on your needs
334
+ 'prompt': prompt,
335
+ 'max_tokens': 200,
336
+ 'temperature': 0.7,
337
+ 'stop_sequences': ['\n']
338
+ }
339
+
340
+ # Make the POST request to the Cohere API
341
+ response = requests.post('https://api.cohere.ai/v1/generate', headers=headers, json=payload)
342
+
343
+ if response.status_code == 200:
344
+ result = response.json()
345
+ # Extract and return the relevant part of the response
346
+ validation_response = result['generations'][0]['text'].strip()
347
+ return validation_response
348
+ else:
349
+ return f"Error: {response.status_code} - {response.text}"
350
+
351
+ except Exception as e:
352
+ return f"An error occurred: {str(e)}"
353
+
354
+
355
+
356
+
357
+ # Endpoint to validate multiple answers at once
358
+ @app.route('/validate-all-answers', methods=['POST'])
359
+ def validate_all_answers():
360
+ try:
361
+ # Get the list of questions and answers from the request body
362
+ data = request.get_json()
363
+ questions = data.get('questions', [])
364
+
365
+ if not questions:
366
+ return jsonify({'error': 'No questions provided'}), 400
367
+
368
+ validation_results = []
369
+
370
+ # Iterate over the list of questions and validate each answer
371
+ for item in questions:
372
+ topic = item.get('topic', '')
373
+ question = item.get('question', '')
374
+ user_answer = item.get('user_answer', '')
375
+
376
+ if not topic or not question or not user_answer:
377
+ validation_results.append({
378
+ 'question': question,
379
+ 'error': 'Missing required fields (topic, question, or answer).'
380
+ })
381
+ continue
382
+
383
+ # Validate the answer with the Cohere API
384
+ validation_response = validate_answer_with_ai(topic, question, user_answer)
385
+
386
+ # If the answer is incorrect, generate a hint
387
+ hint = None
388
+ if "incorrect" in validation_response.lower() or "not correct" in validation_response.lower():
389
+ # Generate the hint for the incorrect answer
390
+ hint = generate_hint(topic, question, user_answer)
391
+
392
+ validation_results.append({
393
+ 'question': question,
394
+ 'user_answer': user_answer,
395
+ 'validation_response': validation_response,
396
+ 'hint': hint # Add hint to the result
397
+ })
398
+
399
+ return jsonify({'results': validation_results})
400
+
401
+ except Exception as e:
402
+ return jsonify({'error': str(e)}), 500
403
+
404
+
405
+
406
+ def generate_hint(topic, question, user_answer):
407
+ try:
408
+ # Construct the prompt for Cohere API to generate a hint for incorrect answers
409
+ prompt = f"""
410
+ You are a highly skilled grammar assistant. Your task is to generate a helpful hint for the user to improve their answer based on the following question.
411
+
412
+ Topic: {topic}
413
+ Question: "{question}"
414
+ User's Answer: "{user_answer}"
415
+
416
+ If the user's answer is incorrect, provide a specific, actionable hint to help the user correct their answer.
417
+ The hint should include:
418
+ - Explanation of the error made by the user.
419
+ - A hint on the correct grammatical structure or word form.
420
+ - A hint on how to structure the sentence correctly **without revealing the exact answer**.
421
+
422
+ Please make sure the hint is **clear** and **helpful** for the user, **without revealing the correct answer**.
423
+ """
424
+
425
+ headers = {
426
+ 'Authorization': f'Bearer {COHERE_API_KEY}',
427
+ 'Content-Type': 'application/json'
428
+ }
429
+
430
+ payload = {
431
+ 'model': 'command-r-08-2024', # Replace with the model you're using
432
+ 'prompt': prompt,
433
+ 'max_tokens': 250, # Adjust token size as needed
434
+ 'temperature': 0.7, # Use temperature to control creativity
435
+ }
436
+
437
+ # Make the POST request to Cohere API
438
+ response = requests.post(COHERE_API_URL, headers=headers, json=payload)
439
+
440
+ if response.status_code == 200:
441
+ result = response.json()
442
+ # Extract and return the relevant hint from the response
443
+ hint = result['generations'][0]['text'].strip()
444
+ return hint
445
+ else:
446
+ return f"Error: {response.status_code} - {response.text}"
447
+
448
+ except Exception as e:
449
+ return f"An error occurred: {str(e)}"
450
+
451
+
452
+
453
+
454
+
455
+
456
+ if __name__ == '__main__':
457
+ # app.run(debug=True)
458
+ app.run(host='0.0.0.0', port=5012, debug=True)
generateQuestion - Copy.py ADDED
@@ -0,0 +1,1271 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, jsonify, send_file, abort, make_response, request
2
+ from flask_cors import CORS
3
+ from moviepy.editor import VideoFileClip
4
+ from google.cloud import speech
5
+ import os
6
+ print(f"GOOGLE_APPLICATION_CREDENTIALS: {os.getenv('GOOGLE_APPLICATION_CREDENTIALS')}")
7
+ import io
8
+ import uuid
9
+ import requests
10
+ from pydub import AudioSegment
11
+ import ffmpeg
12
+ import re
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+ app = Flask(__name__)
23
+ CORS(app)
24
+ # CORS(app, resources={r"/*": {"origins": "*"}})
25
+
26
+ @app.route('/')
27
+ def home():
28
+ return "Welcome to the Flask app! The server is running."
29
+
30
+ # Directories for video, audio, and transcripts
31
+ VIDEO_FOLDER = 'static/videos'
32
+ AUDIO_FOLDER = 'static/audio'
33
+ TRANSCRIPT_FOLDER = 'static/transcripts'
34
+
35
+ # Ensure directories exist
36
+ os.makedirs(VIDEO_FOLDER, exist_ok=True)
37
+ os.makedirs(AUDIO_FOLDER, exist_ok=True)
38
+ os.makedirs(TRANSCRIPT_FOLDER, exist_ok=True)
39
+
40
+ # API configuration for AI-based question generation
41
+ COHERE_API_KEY = 'WjnDKknACe0zxHvczdo7q4vwF4WAXn2429hcPHIB'
42
+ COHERE_API_URL = 'https://api.cohere.ai/v1/generate'
43
+
44
+ # Google Cloud Speech-to-Text Configuration
45
+ speech_client = speech.SpeechClient()
46
+
47
+ # Predefined video metadata
48
+ # VIDEOS = [
49
+ # {
50
+ # "id": "1",
51
+ # "title": "Introduction to AI",
52
+ # "filename": "ai_intro.mp4"
53
+ # },
54
+ # {
55
+ # "id": "2",
56
+ # "title": "Machine Learning Basics",
57
+ # "filename": "ml_basics.mp4"
58
+ # }
59
+ # ]
60
+
61
+
62
+
63
+ @app.route('/videos', methods=['GET'])
64
+ def list_videos():
65
+ """
66
+ List available videos for users to watch.
67
+ """
68
+ return jsonify(VIDEOS), 200
69
+
70
+ @app.route('/videos/<filename>')
71
+ def serve_video(filename):
72
+ """
73
+ Serve a video file to the user.
74
+ """
75
+ video_path = os.path.join(VIDEO_FOLDER, filename)
76
+ if not os.path.exists(video_path):
77
+ print(f"Video file not found: {filename}")
78
+ abort(404)
79
+
80
+ mime_type = 'video/mp4'
81
+ print(f"Serving video: {filename}, MIME type: {mime_type}")
82
+ return send_file(video_path, mimetype=mime_type)
83
+
84
+
85
+ # Convert video to audio
86
+ def convert_video_to_audio(video_path, audio_path):
87
+ try:
88
+ # Using moviepy to extract audio from video
89
+ video = VideoFileClip(video_path)
90
+ video.audio.write_audiofile(audio_path, codec='mp3')
91
+ return audio_path
92
+ except Exception as e:
93
+ print(f"Error converting video to audio: {str(e)}")
94
+ return None
95
+
96
+ # Re-encode MP3 to ensure proper format
97
+ def reencode_mp3(input_audio_path, output_audio_path):
98
+ try:
99
+ # Using pydub to convert and re-encode MP3 (ensuring correct encoding)
100
+ audio = AudioSegment.from_mp3(input_audio_path)
101
+ audio.export(output_audio_path, format="mp3", codec="libmp3lame", parameters=["-q:a", "0"])
102
+ return output_audio_path
103
+ except Exception as e:
104
+ print(f"Error re-encoding MP3: {str(e)}")
105
+ return None
106
+ # Helper function to convert audio to the proper MP3 encoding if necessary
107
+ def convert_audio_to_mp3(input_file_path, output_file_path):
108
+ """
109
+ Converts the audio file to a valid MP3 format with proper encoding.
110
+ """
111
+ try:
112
+ ffmpeg.input(input_file_path).output(output_file_path, acodec='libmp3lame', audio_bitrate='128k').run()
113
+ return True
114
+ except Exception as e:
115
+ print(f"Error during audio conversion: {e}")
116
+ return False
117
+
118
+
119
+ # Function to compress audio dynamically
120
+ def compress_audio(input_file_path, output_file_path, target_bitrate="128k"):
121
+ audio = AudioSegment.from_file(input_file_path)
122
+ audio.export(output_file_path, format="mp3", bitrate=target_bitrate)
123
+ return output_file_path
124
+
125
+
126
+ @app.route('/upload-video', methods=['POST'])
127
+ def upload_video():
128
+ print("Received upload request.")
129
+
130
+ if 'video' not in request.files:
131
+ print("No video file provided in the request.")
132
+ return jsonify({'error': 'No video file provided'}), 400
133
+
134
+ video = request.files['video']
135
+ if video.filename == '':
136
+ print("Empty filename detected.")
137
+ return jsonify({'error': 'No selected file'}), 400
138
+
139
+ try:
140
+ filename = str(uuid.uuid4()) + ".mp4"
141
+ video_path = os.path.join(VIDEO_FOLDER, filename)
142
+
143
+ print(f"Saving video: {filename}")
144
+ video.save(video_path)
145
+
146
+ print(f"Video saved successfully at {video_path}")
147
+ return jsonify({'message': 'Video uploaded successfully!', 'filename': filename}), 200
148
+
149
+ except Exception as e:
150
+ print(f"Error saving video: {str(e)}")
151
+ return jsonify({'error': 'Failed to save video'}), 500
152
+
153
+
154
+
155
+
156
+ @app.route('/generate-questions-dynamicvideo', methods=['POST'])
157
+ def generate_questions():
158
+ try:
159
+ # Expecting a JSON request body with video filename
160
+ data = request.json
161
+ video_filename = data.get('filename')
162
+
163
+ if not video_filename:
164
+ print("Error: No filename provided in request.")
165
+ return jsonify({"error": "Filename is required"}), 400
166
+
167
+ video_path = os.path.join(VIDEO_FOLDER, video_filename)
168
+ if not os.path.exists(video_path):
169
+ print(f"Error: Video file {video_filename} not found at {video_path}")
170
+ return jsonify({"error": "Video file not found"}), 404
171
+
172
+ print(f"Processing video: {video_filename}")
173
+
174
+ # Convert video to audio
175
+ audio_filename = f"{uuid.uuid4()}.mp3"
176
+ audio_path = os.path.join(AUDIO_FOLDER, audio_filename)
177
+
178
+ # Convert video to audio
179
+ if not convert_video_to_audio(video_path, audio_path):
180
+ print("Error: Video to audio conversion failed.")
181
+ return jsonify({"error": "Failed to convert video to audio"}), 500
182
+
183
+ # Transcribe audio using Google Cloud Speech-to-Text
184
+ with open(audio_path, 'rb') as audio_file:
185
+ audio_content = audio_file.read()
186
+
187
+ audio = speech.RecognitionAudio(content=audio_content)
188
+ config = speech.RecognitionConfig(
189
+ encoding=speech.RecognitionConfig.AudioEncoding.MP3,
190
+ sample_rate_hertz=16000,
191
+ language_code="en-US",
192
+ )
193
+
194
+ response = speech_client.recognize(config=config, audio=audio)
195
+ transcripts = [result.alternatives[0].transcript for result in response.results]
196
+
197
+ if not transcripts:
198
+ print("Error: No transcription results found.")
199
+ return jsonify({"error": "No transcription results found"}), 500
200
+
201
+ transcription_text = " ".join(transcripts)
202
+ print(f"Transcription successful: {transcription_text[:200]}...") # Print first 200 chars
203
+
204
+
205
+
206
+ cohere_payload = {
207
+ "model": "command-r-08-2024",
208
+ "prompt": f"Generate exactly three multiple-choice questions based on this text:\n{transcription_text}\n"
209
+ f"Each question should start with a number followed by a period (e.g., 1.) and should have four options labeled A., B., C., and D. After the options, indicate the correct answer with 'Correct answer: <option letter>' (e.g., Correct answer: A).\n"
210
+ f"Please make sure to generate exactly four options per question, and only three questions in total.",
211
+ "max_tokens": 300,
212
+ "temperature": 0.9, # Optional: Control randomness in the responses
213
+ }
214
+
215
+ headers = {"Authorization": f"Bearer {COHERE_API_KEY}"}
216
+
217
+ cohere_response = requests.post(COHERE_API_URL, json=cohere_payload, headers=headers)
218
+
219
+ if cohere_response.status_code != 200:
220
+ print(f"Error: Cohere API response failed: {cohere_response.text}")
221
+ return jsonify({"error": "Failed to generate questions"}), 500
222
+
223
+ questions = cohere_response.json().get("generations", [])
224
+ if not questions:
225
+ print("Error: No questions generated from Cohere API.")
226
+ return jsonify({"error": "No questions generated"}), 500
227
+
228
+ # Extract raw text and parse questions
229
+ raw_text = questions[0]["text"]
230
+ structured_questions = parse_questions(raw_text)
231
+
232
+ return jsonify({"questions": structured_questions}), 200
233
+
234
+ except Exception as e:
235
+ print(f"Critical Error: {e}")
236
+ return jsonify({"error": "An error occurred while generating questions"}), 500
237
+
238
+
239
+ # @app.route('/generate-questions/<video_id>', methods=['GET'])
240
+ # def generate_questions_videos(video_id):
241
+ # try:
242
+ # # Step 1: Get video metadata
243
+ # video = next((v for v in VIDEOS if v["id"] == video_id), None)
244
+ # if not video:
245
+ # return jsonify({"error": "Video not found"}), 404
246
+
247
+ # video_path = os.path.join(VIDEO_FOLDER, video["filename"])
248
+
249
+ # # Step 2: Convert video to audio
250
+ # audio_filename = f"{uuid.uuid4()}.mp3"
251
+ # audio_path = os.path.join(AUDIO_FOLDER, audio_filename)
252
+ # video_clip = VideoFileClip(video_path)
253
+ # video_clip.audio.write_audiofile(audio_path)
254
+
255
+ # # Step 3: Transcribe the audio file using Google Cloud Speech-to-Text
256
+ # with open(audio_path, 'rb') as audio_file:
257
+ # audio_content = audio_file.read()
258
+
259
+ # audio = speech.RecognitionAudio(content=audio_content)
260
+ # config = speech.RecognitionConfig(
261
+ # encoding=speech.RecognitionConfig.AudioEncoding.MP3,
262
+ # sample_rate_hertz=16000,
263
+ # language_code="en-US",
264
+ # )
265
+
266
+ # response = speech_client.recognize(config=config, audio=audio)
267
+ # transcripts = [result.alternatives[0].transcript for result in response.results]
268
+
269
+ # if not transcripts:
270
+ # return jsonify({"error": "No transcription results found"}), 500
271
+
272
+ # transcription_text = " ".join(transcripts)
273
+
274
+ # cohere_payload = {
275
+ # "model": "command-r-08-2024",
276
+ # "prompt": f"Generate exactly three multiple-choice questions based on this text:\n{transcription_text}\n"
277
+ # f"Each question should start with a number followed by a period (e.g., 1.) and should have four options labeled A., B., C., and D. After the options, indicate the correct answer with 'Correct answer: <option letter>' (e.g., Correct answer: A).\n"
278
+ # f"Please make sure to generate exactly four options per question, and only three questions in total.",
279
+ # "max_tokens": 300,
280
+ # "temperature": 0.9, # Optional: Control randomness in the responses
281
+ # }
282
+
283
+
284
+ # headers = {"Authorization": f"Bearer {COHERE_API_KEY}"}
285
+
286
+ # # Step 5: Make the API request to Cohere
287
+ # cohere_response = requests.post(COHERE_API_URL, json=cohere_payload, headers=headers)
288
+
289
+ # if cohere_response.status_code != 200:
290
+ # print(f"Cohere API error: {cohere_response.text}")
291
+ # return jsonify({"error": "Failed to generate questions"}), 500
292
+
293
+ # # Parse the response for questions
294
+ # questions = cohere_response.json().get("generations", [])
295
+ # if not questions:
296
+ # return jsonify({"error": "No questions generated"}), 500
297
+
298
+ # # Extract raw text and parse it
299
+ # raw_text = questions[0]["text"]
300
+ # structured_questions = parse_questions(raw_text)
301
+ # print("Raw AI Model Response:", raw_text)
302
+
303
+ # # Return the structured questions
304
+ # return jsonify({"questions": structured_questions}), 200
305
+
306
+ # except Exception as e:
307
+ # print(f"Error during question generation: {e}")
308
+ # return jsonify({"error": "An error occurred while generating questions"}), 500
309
+
310
+
311
+
312
+ def parse_questions(response_text):
313
+ # Split the text into individual question blocks
314
+ question_blocks = response_text.split("\n\n")
315
+ questions = []
316
+
317
+ # Process each question block
318
+ for block in question_blocks:
319
+ print("\nProcessing Block:", block) # Debug: Log each question block
320
+
321
+ # Split the block into lines
322
+ lines = block.strip().split("\n")
323
+ print("Split Lines:", lines) # Debug: Log split lines of the block
324
+
325
+ # Ensure the block contains a question
326
+ if len(lines) < 2:
327
+ print("Skipping Invalid Block") # Debug: Log invalid blocks
328
+ continue
329
+
330
+ # Extract the question text
331
+ question_line = lines[0]
332
+ question_text = question_line.split(". ", 1)[1] if ". " in question_line else question_line
333
+ print("Question Text:", question_text) # Debug: Log extracted question text
334
+
335
+ # Extract the options and find the correct answer
336
+ options = []
337
+ correct_answer_letter = None
338
+ for line in lines[1:]:
339
+ line = line.strip()
340
+ match = re.match(r"^(?:[a-dA-D][).]?\s)?(.+)$", line) # Regex to handle `a)`, `A.`, etc.
341
+ if match:
342
+ option_text = match.group(1).strip()
343
+ # Check if this line contains the correct answer
344
+ if option_text.startswith("Correct answer:"):
345
+ correct_answer_letter = option_text.split(":")[-1].strip()
346
+ else:
347
+ options.append(option_text)
348
+ print("Extracted Options:", options) # Debug: Log extracted options
349
+ print("Correct Answer Letter:", correct_answer_letter) # Debug: Log the correct answer letter
350
+
351
+ # Map the correct answer text
352
+ correct_answer_text = ""
353
+ if correct_answer_letter:
354
+ option_index = ord(correct_answer_letter.upper()) - ord('A') # Convert 'A' to index 0, 'B' to index 1, etc.
355
+ if 0 <= option_index < len(options):
356
+ correct_answer_text = options[option_index]
357
+ print("Mapped Correct Answer Text:", correct_answer_text) # Debug: Log mapped answer
358
+
359
+ # Append the parsed question to the list
360
+ questions.append({
361
+ "question": question_text,
362
+ "options": options,
363
+ "answer": correct_answer_text # Use the full answer text
364
+ })
365
+
366
+ print("\nFinal Questions:", questions) # Debug: Log final parsed questions
367
+ return questions
368
+
369
+
370
+ # @app.route('/generate-writing-topics', methods=['POST'])
371
+ # def generate_writing_topics():
372
+ # """
373
+ # Generate writing topics based on the user's grade level and difficulty level.
374
+ # """
375
+ # try:
376
+ # # Extract grade level and difficulty level from the POST request
377
+ # data = request.json
378
+ # grade_level = data.get("grade_level", "lower").lower() # Default to 'lower' if not provided
379
+ # difficulty = data.get("difficulty", "basic").lower() # Default to 'basic' if not provided
380
+
381
+ # # Validate grade level
382
+ # valid_levels = {"lower", "middle", "upper"}
383
+ # if grade_level not in valid_levels:
384
+ # return jsonify({"error": f"Invalid grade level. Choose from: {', '.join(valid_levels)}"}), 400
385
+
386
+ # # Validate difficulty level
387
+ # valid_difficulties = {"basic", "medium", "hard"}
388
+ # if difficulty not in valid_difficulties:
389
+ # return jsonify({"error": f"Invalid difficulty level. Choose from: {', '.join(valid_difficulties)}"}), 400
390
+
391
+ # # Define a prompt based on the grade level and difficulty level
392
+ # # Define a prompt based on the grade level and difficulty level
393
+ # if difficulty == "basic":
394
+ # # prompt = (
395
+ # # f"Generate one simple and short writing topic suitable for a {grade_level}-grade student. "
396
+ # # f"The topic should be one sentence, easy to understand, and fun to write about. "
397
+ # # f"Focus on familiar and relatable themes like family, school, or favorite activities."
398
+ # # )
399
+
400
+ # prompt = (
401
+ # f"Generate one unique and imaginative writing topic suitable for a {grade_level}-grade student. "
402
+ # f"The topic should be short, easy to understand, and fun to write about. "
403
+ # f"Ensure the topic explores new and diverse themes, avoiding repetition of previous ideas. "
404
+ # f"Focus on creativity, variety, and age-appropriate fun."
405
+ # )
406
+ # elif difficulty == "medium":
407
+ # prompt = (
408
+ # f"Generate one creative writing topic suitable for a {grade_level}-grade student. "
409
+ # f"The topic should encourage imagination and exploration while still being age-appropriate. "
410
+ # f"Include themes like adventures, problem-solving, or hypothetical scenarios."
411
+ # )
412
+ # elif difficulty == "hard":
413
+ # prompt = (
414
+ # f"Generate one challenging and thought-provoking writing topic suitable for a {grade_level}-grade student. "
415
+ # f"The topic should require critical thinking, creativity, or self-reflection. "
416
+ # f"Include themes like ethical dilemmas, futuristic ideas, or personal experiences."
417
+ # )
418
+
419
+ # # Call Cohere API to generate topics
420
+ # payload = {
421
+ # "model": "command-r-08-2024",
422
+ # "prompt": prompt,
423
+ # "max_tokens": 150,
424
+ # "temperature": 0.9
425
+ # }
426
+ # headers = {"Authorization": f"Bearer {COHERE_API_KEY}"}
427
+ # response = requests.post(COHERE_API_URL, json=payload, headers=headers)
428
+
429
+ # if response.status_code != 200:
430
+ # return jsonify({"error": "Failed to generate topics"}), 500
431
+
432
+ # # Extract the generated text
433
+ # raw_text = response.json().get("generations", [])[0].get("text", "")
434
+ # topics = [topic.strip() for topic in raw_text.split("\n") if topic.strip()]
435
+
436
+ # # Return the generated topics
437
+ # return jsonify({"topics": topics}), 200
438
+
439
+ # except Exception as e:
440
+ # print(f"Error generating writing topics: {e}")
441
+ # return jsonify({"error": "An error occurred while generating topics"}), 500
442
+
443
+
444
+ generated_topics = set()
445
+
446
+
447
+ @app.route('/generate-writing-topics', methods=['POST'])
448
+ def generate_writing_topics():
449
+ """
450
+ Generate writing topics based on the user's grade level.
451
+ """
452
+ try:
453
+ # Extract grade level from the POST request
454
+ data = request.json
455
+ grade_level = data.get("grade_level", "lower").lower() # Default to 'lower' if not provided
456
+
457
+ # Validate grade level
458
+ valid_levels = {"lower", "middle", "upper"}
459
+ if grade_level not in valid_levels:
460
+ return jsonify({"error": f"Invalid grade level. Choose from: {', '.join(valid_levels)}"}), 400
461
+
462
+ # Define a prompt based on the grade level
463
+ if grade_level == "lower":
464
+ prompt = (
465
+ "Generate one simple and short writing topic suitable for a lower-grade student. "
466
+ "The topic should be one sentence, easy to understand, and fun to write about. "
467
+ "Focus on familiar and relatable themes like family, school, or favorite activities."
468
+ )
469
+ elif grade_level == "middle":
470
+ prompt = (
471
+ "Generate one creative writing topic suitable for a middle-grade student. "
472
+ "The topic should encourage imagination and exploration while still being age-appropriate. "
473
+ "Include themes like adventures, problem-solving, or hypothetical scenarios."
474
+ )
475
+ elif grade_level == "upper":
476
+ prompt = (
477
+ "Generate one challenging and thought-provoking writing topic suitable for an upper-grade student. "
478
+ "The topic should require critical thinking, creativity, or self-reflection. "
479
+ "Include themes like ethical dilemmas, futuristic ideas, or personal experiences."
480
+ )
481
+
482
+ # Call Cohere API to generate topics
483
+ payload = {
484
+ "model": "command-r-08-2024",
485
+ "prompt": prompt,
486
+ "max_tokens": 150,
487
+ "temperature": 0.9
488
+ }
489
+ headers = {"Authorization": f"Bearer {COHERE_API_KEY}"}
490
+ response = requests.post(COHERE_API_URL, json=payload, headers=headers)
491
+
492
+ if response.status_code != 200:
493
+ return jsonify({"error": "Failed to generate topics"}), 500
494
+
495
+ # Extract the generated text
496
+ raw_text = response.json().get("generations", [])[0].get("text", "")
497
+ topics = [topic.strip() for topic in raw_text.split("\n") if topic.strip()]
498
+
499
+ # Return the generated topics
500
+ return jsonify({"topics": topics}), 200
501
+
502
+ except Exception as e:
503
+ print(f"Error generating writing topics: {e}")
504
+ return jsonify({"error": "An error occurred while generating topics"}), 500
505
+
506
+
507
+
508
+
509
+
510
+
511
+
512
+
513
+
514
+
515
+
516
+
517
+
518
+
519
+
520
+
521
+
522
+
523
+ @app.route('/validate-response', methods=['POST'])
524
+ def validate_response():
525
+ """
526
+ Validate user response against the provided topic using AI.
527
+ """
528
+ try:
529
+ # Extract user input and topic from the request
530
+ data = request.json
531
+ topic = data.get("topic")
532
+ response = data.get("response")
533
+
534
+ if not topic or not response:
535
+ return jsonify({"error": "Both 'topic' and 'response' fields are required."}), 400
536
+
537
+ # Define a prompt for validation
538
+ # prompt = (
539
+ # f"You are an English teacher. Evaluate if the following response matches the given topic. "
540
+ # f"Topic: '{topic}'. Response: '{response}'. "
541
+ # f"Provide feedback on relevance, grammar, and clarity. If the response is unrelated, suggest improvements to align it with the topic."
542
+ # )
543
+
544
+ prompt = (
545
+ f"You are a writing teacher. Evaluate the sentence formation, grammar, and overall writing quality of the following response. "
546
+ f"Provide constructive feedback highlighting any errors in grammar, spelling, punctuation, and sentence structure. "
547
+ f"If the response is well-written, acknowledge its strengths. "
548
+ f"Topic: '{topic}'. Response: '{response}'."
549
+ )
550
+
551
+
552
+ # Call Cohere API for validation
553
+ payload = {
554
+ "model": "command-r-08-2024",
555
+ "prompt": prompt,
556
+ "max_tokens": 500,
557
+ "temperature": 0.7
558
+ }
559
+ headers = {"Authorization": f"Bearer {COHERE_API_KEY}"}
560
+ api_response = requests.post(COHERE_API_URL, json=payload, headers=headers)
561
+
562
+ if api_response.status_code != 200:
563
+ return jsonify({"error": "Failed to validate response"}), 500
564
+
565
+ # Extract AI feedback
566
+ feedback = api_response.json().get("generations", [])[0].get("text", "")
567
+
568
+ return jsonify({"feedback": feedback}), 200
569
+
570
+ except Exception as e:
571
+ print(f"Error validating response: {e}")
572
+ return jsonify({"error": "An error occurred while validating the response."}), 500
573
+
574
+ # Pronounciation
575
+
576
+ @app.route('/validate-pronounce', methods=['POST'])
577
+ def validate():
578
+ # Get the word and audio from the request
579
+ target_word = request.form['word']
580
+ audio_file = request.files['audio']
581
+
582
+ # Save the audio file temporarily
583
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as tmp_file:
584
+ audio_path = tmp_file.name
585
+ audio_file.save(audio_path)
586
+
587
+ # Transcribe the audio and validate the pronunciation
588
+ transcribed_word = transcribe_audio(audio_path)
589
+ os.remove(audio_path) # Clean up the temporary file
590
+
591
+ if not transcribed_word:
592
+ return jsonify({
593
+ "success": False,
594
+ "message": "Could not understand the pronunciation."
595
+ })
596
+
597
+ is_correct, message = validate_pronunciation(target_word, transcribed_word)
598
+ return jsonify({
599
+ "success": is_correct,
600
+ "message": message,
601
+ "transcribed_word": transcribed_word
602
+ })
603
+
604
+
605
+ @app.route('/teach', methods=['GET'])
606
+ def teach():
607
+ # Get the word to teach
608
+ word = request.args.get('word', default='', type=str)
609
+ if not word:
610
+ return jsonify({"success": False, "message": "No word provided."})
611
+
612
+ # Teach the pronunciation details
613
+ syllables = get_syllables(word)
614
+ silent_letters = detect_silent_letters(word)
615
+
616
+ return jsonify({
617
+ "success": True,
618
+ "syllables": syllables,
619
+ "silent_letters": silent_letters
620
+ })
621
+
622
+
623
+ # # Endpoint to explain grammar topics
624
+ # @app.route('/explain-grammar', methods=['POST'])
625
+ # def explain_grammar():
626
+ # try:
627
+ # data = request.get_json()
628
+ # topic = data.get('topic', '')
629
+ # detail = data.get('detail', '').lower() # Capture 'detail' from the user # Default to 'short' if not specified
630
+
631
+
632
+ # if not topic:
633
+ # return jsonify({'error': 'Topic is required'}), 400
634
+
635
+
636
+ # # Check if the user is asking for more details
637
+ # if any(keyword in detail for keyword in ['detailed', 'more explanation', 'in detail']):
638
+ # # Construct the prompt for detailed explanation
639
+ # prompt = f"""
640
+ # You are a highly skilled grammar assistant. Your responsibility is to provide explanations only for grammar-related topics.
641
+ # If the user submits a request that does not relate to grammar, respond with: "Please send a grammar-related question."
642
+
643
+ # Your response should be detailed and focused on grammar concepts.
644
+
645
+ # Please explain the following topic in detail: {topic}
646
+
647
+ # 1. Provide a **clear explanation** of the grammar concept.
648
+ # 2. Include **examples** to demonstrate the proper usage of the concept in context.
649
+ # 3. List **key rules** or important points related to the topic.
650
+ # 4. Provide **additional clarifications** or related information as necessary to give a thorough understanding.
651
+
652
+ # If the submitted topic does not belong to the domain of grammar (for example, topics related to non-grammar subjects), respond with: "Please send a grammar-related question."
653
+ # """
654
+ # else:
655
+ # # Construct the prompt for concise explanation
656
+ # prompt = f"""
657
+ # You are a highly skilled grammar assistant. Your responsibility is to provide explanations only for grammar-related topics.
658
+ # If the user submits a request that does not relate to grammar, respond with: "Please send a grammar-related question."
659
+
660
+ # Your response should be clear, concise, and focused solely on grammar concepts.
661
+
662
+ # Please explain the following topic in brief: {topic}
663
+
664
+ # 1. Provide a **brief explanation** of the grammar concept.
665
+ # 2. Include at least **one example** to demonstrate the proper usage of the concept.
666
+ # 3. List **key rules** or important points related to the topic.
667
+
668
+ # If the submitted topic does not belong to the domain of grammar (for example, topics related to non-grammar subjects), respond with: "Please send a grammar-related question."
669
+ # """
670
+
671
+
672
+ # # Make the API call to Cohere
673
+ # headers = {
674
+ # 'Authorization': f'Bearer {COHERE_API_KEY}',
675
+ # 'Content-Type': 'application/json'
676
+ # }
677
+
678
+ # payload = {
679
+ # 'model': 'command-r-08-2024', # Use your Cohere model here
680
+ # 'prompt': prompt,
681
+ # 'max_tokens': 300
682
+ # }
683
+
684
+ # response = requests.post(COHERE_API_URL, headers=headers, json=payload)
685
+
686
+ # if response.status_code == 200:
687
+ # data = response.json()
688
+ # return jsonify(data)
689
+ # else:
690
+ # return jsonify({'error': 'Failed to fetch data from Cohere API'}), 500
691
+
692
+ # except Exception as e:
693
+ # return jsonify({'error': str(e)}), 500
694
+
695
+
696
+ # Dictionary to store user conversations
697
+ user_sessions = {}
698
+ # Endpoint to explain grammar topics
699
+ @app.route('/explain-grammar', methods=['POST'])
700
+ def explain_grammar():
701
+ try:
702
+ data = request.get_json()
703
+ print("Received Data:", data)
704
+ topic = data.get('topic', '').strip()
705
+ session_id = data.get('session_id', str(uuid.uuid4())) # Use provided session_id or create a new one
706
+
707
+ if not topic:
708
+ return jsonify({'error': 'Topic is required'}), 400
709
+
710
+ # Retrieve previous conversation history
711
+ conversation_history = user_sessions.get(session_id, [])
712
+
713
+ # Keep the last 10 messages to maintain better context (adjustable)
714
+ if len(conversation_history) > 10:
715
+ conversation_history = conversation_history[-10:]
716
+
717
+ # Generate a more **adaptive** prompt
718
+ context = "\n".join(conversation_history) if conversation_history else ""
719
+
720
+ prompt = f"""
721
+ You are a highly skilled grammar assistant. Your job is to maintain a **dynamic conversation** and respond intelligently based on user input, If the user asks something **unrelated to grammar**, respond with: "Please send a grammar-related question..
722
+
723
+ - Your answers must always **relate to the conversation history** and **extend naturally** based on what was previously asked.
724
+ - Your answers must be **concise, clear, and to the point**
725
+ - If the user asks for **examples**, explanations, or clarifications, **automatically infer** which topic they are referring to.
726
+ - If the user's question is **vague**, determine the most **logical continuation** based on prior questions.
727
+ - If the user asks something **unrelated to grammar**, respond with: "Please send a grammar-related question."
728
+
729
+ **Conversation so far:**
730
+ {context}
731
+
732
+ **User's new question:** {topic}
733
+ Please provide a **coherent and relevant answer** that continues the conversation naturally.
734
+ """
735
+
736
+ # Make the API call to Cohere
737
+ headers = {
738
+ 'Authorization': f'Bearer {COHERE_API_KEY}',
739
+ 'Content-Type': 'application/json'
740
+ }
741
+
742
+ payload = {
743
+ 'model': 'command-r-08-2024',
744
+ 'prompt': prompt,
745
+ 'max_tokens': 1000 # Increased to allow better explanations
746
+ }
747
+
748
+ response = requests.post(COHERE_API_URL, headers=headers, json=payload)
749
+
750
+ if response.status_code == 200:
751
+ ai_response = response.json().get('generations', [{}])[0].get('text', '').strip()
752
+
753
+ # Store conversation history to maintain context
754
+ conversation_history.append(f"User: {topic}\nAI: {ai_response}")
755
+ user_sessions[session_id] = conversation_history # Update session history
756
+
757
+ return jsonify({'response': ai_response, 'session_id': session_id})
758
+ else:
759
+ return jsonify({'error': 'Failed to fetch data from Cohere API'}), 500
760
+
761
+ except Exception as e:
762
+ return jsonify({'error': str(e)}), 500
763
+
764
+
765
+
766
+ @app.route('/suggest-grammar-questions', methods=['POST'])
767
+ def suggest_grammar_questions():
768
+ try:
769
+ data = request.get_json()
770
+ user_input = data.get('input', '').strip() # User's partial input (e.g., "What is v")
771
+
772
+ if not user_input:
773
+ return jsonify({'error': 'Input is required'}), 400
774
+
775
+
776
+
777
+ prompt = f"""
778
+ You are a grammar expert. Given the user's input "{user_input}", generate **3 natural grammar-related questions** that people might ask.
779
+
780
+ - The user's input is a **partial or full grammar-related query**.
781
+ - AI must **infer the most likely grammar topic** based on the input.
782
+ - AI must **ensure all suggestions are strictly related to English grammar**.
783
+ - **If the input is incomplete, intelligently complete it** with the most likely grammar concept.
784
+ - Ensure all **questions are fully formed and relevant**.
785
+
786
+ **User input:** "{user_input}"
787
+ Provide exactly 3 well-structured, grammar-related questions:
788
+ """
789
+
790
+ # Call Cohere API
791
+ headers = {
792
+ 'Authorization': f'Bearer {COHERE_API_KEY}',
793
+ 'Content-Type': 'application/json'
794
+ }
795
+
796
+ payload = {
797
+ 'model': 'command-r-08-2024',
798
+ 'prompt': prompt,
799
+ 'max_tokens': 100, # Only short responses needed
800
+ 'temperature': 0.9, # Some randomness for variety
801
+ 'frequency_penalty': 0.8, # Reduce repeated words
802
+ 'presence_penalty': 0.8 # Encourage diverse questions
803
+ }
804
+
805
+ response = requests.post(COHERE_API_URL, headers=headers, json=payload)
806
+
807
+ if response.status_code == 200:
808
+ suggestions = response.json().get('generations', [{}])[0].get('text', '').strip().split("\n")
809
+ return jsonify({'suggestions': suggestions})
810
+ else:
811
+ return jsonify({'error': 'Failed to fetch suggestions', 'details': response.text}), 500
812
+
813
+ except Exception as e:
814
+ return jsonify({'error': str(e)}), 500
815
+
816
+
817
+ def validate_topic(topic):
818
+
819
+
820
+
821
+ # # validation_prompt = f"""
822
+ # # You are an AI grammar expert. Your task is to determine if a given topic is related to **English grammar** or not.
823
+
824
+ # # **Input:** "{topic}"
825
+
826
+ # # ### **Rules:**
827
+ # # - If the topic is related to **English grammar concepts**, such as sentence structure, parts of speech, verb tenses, or any other grammatical structures, return `"Grammar"`.
828
+ # # - If the topic is **in the form of a question** (e.g., "What is...", "How does..."), return `"Not Grammar"`.
829
+ # # - If the topic is **not related to grammar**, such as general knowledge, science, math, history, or topics from other fields, return `"Not Grammar"`.
830
+ # # - Your response must be based purely on whether the topic relates to grammar, and **not** based on specific words, phrases, or examples.
831
+
832
+ # # **Your response must be exactly either "Grammar" or "Not Grammar". No extra text.**
833
+ # # """
834
+
835
+
836
+ validation_prompt = f"""
837
+ You are an AI grammar expert. Your task is to determine if a given topic is related to **English grammar** or not.
838
+
839
+ **Input:** "{topic}"
840
+
841
+ ### **Rules:**
842
+ - If the input is **in the form of a question** (e.g., it asks for an explanation or definition), return `"ask grammar topics"`, even if the topic is related to grammar.
843
+ - If the topic is **related to English grammar concepts** such as **parts of speech**, **verb tenses**, **sentence structure**, etc., return `"Grammar"`.
844
+ - If the topic is **not related to grammar**, such as general knowledge, science, math, history, or topics from other fields, return `"Not Grammar"`.
845
+ - Your response must be based purely on whether the topic relates to grammar, and **not** based on specific words, phrases, or examples.
846
+
847
+ **Your response must be exactly either "Grammar", "Not Grammar", or "ask grammar topics". No extra text.**
848
+ """
849
+
850
+
851
+
852
+
853
+
854
+ headers = {
855
+ 'Authorization': f'Bearer {COHERE_API_KEY}',
856
+ 'Content-Type': 'application/json'
857
+ }
858
+
859
+ payload = {
860
+ 'model': 'command-r-08-2024',
861
+ 'prompt': validation_prompt,
862
+ 'max_tokens': 5 # Minimal token usage for classification
863
+ }
864
+
865
+ try:
866
+ response = requests.post(COHERE_API_URL, json=payload, headers=headers)
867
+ validation_result = response.json().get('generations', [{}])[0].get('text', '').strip()
868
+
869
+ # Ensure the response is strictly "Grammar" or "Not Grammar"
870
+ if validation_result not in ["Grammar", "Not Grammar"]:
871
+ return "Not Grammar" # Fallback to avoid incorrect responses
872
+
873
+ return validation_result
874
+
875
+ except Exception as e:
876
+ return f"Error: {str(e)}"
877
+
878
+
879
+ @app.route('/generate-questions', methods=['POST'])
880
+ def generate_questions_test():
881
+ try:
882
+ data = request.get_json()
883
+ topic = data.get('topic', '').strip() # Default to "grammar" if no topic is provided
884
+ # levels = data.get('levels', ['basic', 'medium', 'hard'])
885
+
886
+
887
+ validation_result = validate_topic(topic)
888
+
889
+ if validation_result != "Grammar":
890
+ return jsonify({"message": "Please enter a valid **grammar topic**, not a general word or unrelated question."}), 400
891
+
892
+
893
+ difficulty = data.get('difficulty', 'basic')
894
+
895
+ # # Validate if the topic is grammar-related using an AI-based classification prompt
896
+ # validation_prompt = f"""
897
+ # You are a grammar assistant. Your job is to determine whether the following topic is related to English grammar:
898
+ # Topic: {topic}
899
+ # If the topic is related to grammar, respond with "Grammar".
900
+ # If the topic is not related to grammar, respond with "Not Grammar".
901
+ # """
902
+
903
+ # headers = {
904
+ # 'Authorization': f'Bearer {COHERE_API_KEY}',
905
+ # 'Content-Type': 'application/json'
906
+ # }
907
+
908
+ # validation_payload = {
909
+ # 'model': 'command-r-08-2024',
910
+ # 'prompt': validation_prompt,
911
+ # 'max_tokens': 10 # Minimal token usage for classification
912
+ # }
913
+
914
+ # validation_response = requests.post(COHERE_API_URL, json=validation_payload, headers=headers)
915
+ # validation_result = validation_response.json().get('generations', [{}])[0].get('text', '').strip()
916
+
917
+ # if validation_result != "Grammar":
918
+ # return jsonify({"message": "Please ask a grammar-related question."}), 400
919
+
920
+
921
+ # Debugging output
922
+ print(f"Generating {difficulty} questions for topic: {topic}")
923
+
924
+
925
+
926
+ if difficulty == 'basic':
927
+ prompt = f"""
928
+ Generate five **completely new and unique** very basic-level fill-in-the-blank grammar questions **every time** on the topic '{topic}'.
929
+
930
+ ### Rules:
931
+ - **Each question must have a different theme**, ensuring variety.
932
+ - **Do not repeat** themes from previous generations.
933
+ - Use **different sentence structures**, avoiding predictable patterns.
934
+ - **Avoid long words or abstract concepts**
935
+ - **Focus on the topic '{topic}'**, and ensure the blank is the key part of speech.
936
+ - Each question should contain **one blank represented by '_______'**, with the correct answer provided in parentheses at the end.
937
+ - The vocabulary should be **simple and suitable for beginners**.
938
+ - Ensure that the questions are **always new and distinct**, avoiding previously used themes.
939
+
940
+ Do not include any explanations or instructions in the response—only the five unique questions.
941
+ """
942
+
943
+ elif difficulty == 'elementary':
944
+ prompt = f"""
945
+ Generate five **completely new and unique** elementary-level fill-in-the-blank grammar questions **every time** on the topic '{topic}'.
946
+
947
+ ### Rules:
948
+ - The questions should be **slightly more challenging than basic-level questions**, incorporating **a wider range of sentence structures and vocabulary**.
949
+ - **Each question must have a different theme**, ensuring variety.
950
+ - **Use varied sentence structures**, making them slightly more complex than basic-level questions.
951
+ - **Ensure that the vocabulary is still simple but slightly broader** than basic-level questions.
952
+ - **Focus on the topic '{topic}'**, and ensure the blank is the key part of speech.
953
+ - Each question should contain **one blank represented by '_______'**, with the correct answer provided in parentheses at the end.
954
+ - Ensure that the questions are **always new and distinct**, avoiding previously used themes.
955
+
956
+ Do not include any explanations or instructions in the response—only the five unique questions.
957
+ """
958
+
959
+ elif difficulty == 'pre-intermediate':
960
+ prompt = f"""
961
+ Generate five **completely new and unique** pre-intermediate-level fill-in-the-blank grammar questions **every time** on the topic '{topic}'.
962
+
963
+ ### Rules:
964
+ - The questions should be **more challenging than elementary-level questions**, incorporating **more varied sentence structures and an expanded vocabulary**.
965
+ - **Each question must have a different theme**, ensuring variety.
966
+ - **Ensure that the vocabulary is broader than elementary-level**, while keeping it understandable for learners.
967
+ - **Sentences should be longer and more descriptive** but still clear.
968
+ - **Focus on the topic '{topic}'**, and ensure the blank is the key part of speech.
969
+ - Each question should contain **one blank represented by '_______'**, with the correct answer provided in parentheses at the end.
970
+ - Ensure that the questions are **always new and distinct**, avoiding previously used themes.
971
+
972
+ Do not include any explanations or instructions in the response—only the five unique questions.
973
+ """
974
+
975
+ elif difficulty == 'intermediate':
976
+ prompt = f"""
977
+ Generate five **completely new and unique** intermediate-level fill-in-the-blank grammar questions **every time** on the topic '{topic}'.
978
+
979
+ ### Rules:
980
+ - The questions should be **more complex than pre-intermediate-level questions**, incorporating **a wider range of vocabulary and sentence structures**.
981
+ - **Each question must have a different theme**, ensuring variety.
982
+ - **Ensure that the vocabulary is more advanced than pre-intermediate-level** while keeping it natural for learners.
983
+ - **Sentences should be longer and include more detail**, improving reading comprehension.
984
+ - **Focus on the topic '{topic}'**, and ensure the blank is the key part of speech.
985
+ - Each question should contain **one blank represented by '_______'**, with the correct answer provided in parentheses at the end.
986
+ - Ensure that the questions are **always new and distinct**, avoiding previously used themes.
987
+
988
+ Do not include any explanations or instructions in the response—only the five unique questions.
989
+ """
990
+
991
+ elif difficulty == 'upper-intermediate':
992
+ prompt = f"""
993
+ Generate five **completely new and unique** upper-intermediate-level fill-in-the-blank grammar questions **every time** on the topic '{topic}'.
994
+
995
+ ### Rules:
996
+ - The questions should be **more complex than intermediate-level questions**, incorporating **more advanced sentence structures and vocabulary**.
997
+ - **Each question must have a different theme**, ensuring variety.
998
+ - **Ensure that the vocabulary is more refined and diverse** but still understandable for upper-intermediate learners.
999
+ - **Sentences should be longer and may introduce more nuanced contexts**, requiring a deeper understanding.
1000
+ - **Focus on the topic '{topic}'**, and ensure the blank is the key part of speech.
1001
+ - Each question should contain **one blank represented by '_______'**, with the correct answer provided in parentheses at the end.
1002
+ - Ensure that the questions are **always new and distinct**, avoiding previously used themes.
1003
+
1004
+ Do not include any explanations or instructions in the response—only the five unique questions.
1005
+ """
1006
+
1007
+ elif difficulty == 'advanced':
1008
+ prompt = f"""
1009
+ Generate five **completely new and unique** advanced-level (C1) fill-in-the-blank grammar questions **every time** on the topic '{topic}'.
1010
+
1011
+ ### Rules:
1012
+ - The questions should be **more challenging than upper-intermediate (B2) level**, requiring a deep understanding of grammar, context, and vocabulary.
1013
+ - **Ensure varied and sophisticated vocabulary**, avoiding basic words.
1014
+ - **Each question should require nuanced comprehension**, testing knowledge of advanced grammar patterns.
1015
+ - **The blank must be the key part of the sentence** (not an obvious answer).
1016
+ - Each question should contain **one blank represented by '_______'**, with the correct answer provided in parentheses at the end.
1017
+ - Ensure that the questions are **always new and distinct**, avoiding repetition of themes.
1018
+
1019
+ Do not include any explanations or instructions in the response—only the five unique questions.
1020
+ """
1021
+
1022
+ elif difficulty == 'hard':
1023
+ prompt = f"""
1024
+ Generate five **completely new and unique** hard-level (C2) fill-in-the-blank grammar questions **every time** on the topic '{topic}'.
1025
+
1026
+ ### Rules:
1027
+ - The questions should be **more challenging than advanced(C1) level**, requiring a deep understanding of grammar, context, and vocabulary.
1028
+ - **Ensure varied and sophisticated vocabulary**, avoiding basic words.
1029
+ - **Each question should require nuanced comprehension**, testing knowledge of advanced grammar patterns.
1030
+ - **The blank must be the key part of the sentence** (not an obvious answer).
1031
+ - Each question should contain **one blank represented by '_______'**, with the correct answer provided in parentheses at the end.
1032
+ - Ensure that the questions are **always new and distinct**, avoiding repetition of themes.
1033
+
1034
+ Do not include any explanations or instructions in the response—only the five unique questions.
1035
+ """
1036
+
1037
+ else:
1038
+ return jsonify({"error": "Invalid difficulty level"}), 400
1039
+
1040
+ headers = {
1041
+ 'Authorization': f'Bearer {COHERE_API_KEY}',
1042
+ 'Content-Type': 'application/json'
1043
+ }
1044
+
1045
+ payload = {
1046
+ 'model': 'command-r-08-2024', # Ensure you're using the right model
1047
+ 'prompt': prompt,
1048
+ 'max_tokens': 1000 # Increase the token limit if needed
1049
+ }
1050
+
1051
+ # Make the API request
1052
+ response = requests.post(COHERE_API_URL, json=payload, headers=headers)
1053
+
1054
+ # Log the full response for debugging
1055
+ print("Response status code:", response.status_code)
1056
+ print("Response content:", response.text)
1057
+
1058
+ if response.status_code == 200:
1059
+ return jsonify(response.json()) # Return the response from Cohere API
1060
+ else:
1061
+ return jsonify({"error": "Failed to fetch questions", "details": response.text}), 500
1062
+ except Exception as e:
1063
+ return jsonify({"error": str(e)}), 500
1064
+
1065
+ # Endpoint to validate answers
1066
+ @app.route('/validate-answer', methods=['POST'])
1067
+ def validate_answer():
1068
+ try:
1069
+ # Get the data from the request
1070
+ data = request.get_json()
1071
+ topic = data.get('topic', '') # Get the topic
1072
+ question = data.get('question', '')
1073
+ user_answer = data.get('user_answer', '')
1074
+
1075
+ # Validate if the required fields are present
1076
+ if not question or not user_answer or not topic:
1077
+ return jsonify({'error': 'Topic, question, and user answer are required'}), 400
1078
+
1079
+ # Construct the prompt for Cohere API
1080
+ prompt = f"""
1081
+ You are a highly knowledgeable grammar assistant. Validate whether the user's answer to the following question is correct or not based on {topic}. If the answer is incorrect, provide a helpful hint.
1082
+
1083
+ Topic: {topic}
1084
+ Question: "{question}"
1085
+ User's Answer: "{user_answer}"
1086
+
1087
+ Is the answer correct? If not, please explain why and give a hint.
1088
+ """
1089
+
1090
+ # Headers and payload for the Cohere API request
1091
+ headers = {
1092
+ 'Authorization': f'Bearer {COHERE_API_KEY}',
1093
+ 'Content-Type': 'application/json'
1094
+ }
1095
+
1096
+ payload = {
1097
+ 'model': 'command-r-08-2024', # Use your model name here
1098
+ 'prompt': prompt,
1099
+ 'max_tokens': 100,
1100
+ 'temperature': 0.7
1101
+ }
1102
+
1103
+ # Make the API call to Cohere
1104
+ response = requests.post(COHERE_API_URL, headers=headers, json=payload)
1105
+
1106
+ # Debugging: Log response status and body
1107
+ print(f"Status Code: {response.status_code}")
1108
+ print(f"Response Body: {response.text}")
1109
+
1110
+ # Check if the request was successful
1111
+ if response.status_code == 200:
1112
+ data = response.json()
1113
+ return jsonify(data)
1114
+ else:
1115
+ return jsonify({'error': 'Failed to fetch data from Cohere API'}), 500
1116
+
1117
+ except Exception as e:
1118
+ return jsonify({'error': str(e)}), 500
1119
+
1120
+
1121
+
1122
+ # // for validating Multiple answer:
1123
+
1124
+ # Function to validate an individual answer using Cohere API
1125
+ def validate_answer_with_ai(topic, question, user_answer):
1126
+ try:
1127
+ # Construct the prompt for Cohere API
1128
+ prompt = f"""
1129
+ You are a highly knowledgeable grammar assistant. Validate whether the user's answer to the following question is correct or not based on {topic}. If the answer is incorrect, provide a helpful hint.
1130
+
1131
+ Topic: {topic}
1132
+ Question: "{question}"
1133
+ User's Answer: "{user_answer}"
1134
+
1135
+ Is the answer correct? If not, please explain why and give a hint.
1136
+ """
1137
+
1138
+ # Headers for the API request
1139
+ headers = {
1140
+ 'Authorization': f'Bearer {COHERE_API_KEY}',
1141
+ 'Content-Type': 'application/json'
1142
+ }
1143
+
1144
+ # Construct the payload for Cohere API request
1145
+ payload = {
1146
+ 'model': 'command-r-08-2024', # You can use a different model depending on your needs
1147
+ 'prompt': prompt,
1148
+ 'max_tokens': 200,
1149
+ 'temperature': 0.7,
1150
+ 'stop_sequences': ['\n']
1151
+ }
1152
+
1153
+ # Make the POST request to the Cohere API
1154
+ response = requests.post('https://api.cohere.ai/v1/generate', headers=headers, json=payload)
1155
+
1156
+ if response.status_code == 200:
1157
+ result = response.json()
1158
+ # Extract and return the relevant part of the response
1159
+ validation_response = result['generations'][0]['text'].strip()
1160
+ return validation_response
1161
+ else:
1162
+ return f"Error: {response.status_code} - {response.text}"
1163
+
1164
+ except Exception as e:
1165
+ return f"An error occurred: {str(e)}"
1166
+
1167
+
1168
+
1169
+
1170
+ # Endpoint to validate multiple answers at once
1171
+ @app.route('/validate-all-answers', methods=['POST'])
1172
+ def validate_all_answers():
1173
+ try:
1174
+ # Get the list of questions and answers from the request body
1175
+ data = request.get_json()
1176
+ questions = data.get('questions', [])
1177
+
1178
+ if not questions:
1179
+ return jsonify({'error': 'No questions provided'}), 400
1180
+
1181
+ validation_results = []
1182
+
1183
+ # Iterate over the list of questions and validate each answer
1184
+ for item in questions:
1185
+ topic = item.get('topic', '')
1186
+ question = item.get('question', '')
1187
+ user_answer = item.get('user_answer', '')
1188
+
1189
+ if not topic or not question or not user_answer:
1190
+ validation_results.append({
1191
+ 'question': question,
1192
+ 'error': 'Missing required fields (topic, question, or answer).'
1193
+ })
1194
+ continue
1195
+
1196
+ # Validate the answer with the Cohere API
1197
+ validation_response = validate_answer_with_ai(topic, question, user_answer)
1198
+
1199
+ # If the answer is incorrect, generate a hint
1200
+ hint = None
1201
+ if "incorrect" in validation_response.lower() or "not correct" in validation_response.lower():
1202
+ # Generate the hint for the incorrect answer
1203
+ hint = generate_hint(topic, question, user_answer)
1204
+
1205
+ validation_results.append({
1206
+ 'question': question,
1207
+ 'user_answer': user_answer,
1208
+ 'validation_response': validation_response,
1209
+ 'hint': hint # Add hint to the result
1210
+ })
1211
+
1212
+ return jsonify({'results': validation_results})
1213
+
1214
+ except Exception as e:
1215
+ return jsonify({'error': str(e)}), 500
1216
+
1217
+
1218
+
1219
+ def generate_hint(topic, question, user_answer):
1220
+ try:
1221
+ # Construct the prompt for Cohere API to generate a hint for incorrect answers
1222
+ prompt = f"""
1223
+ You are a highly skilled grammar assistant. Your task is to generate a helpful hint for the user to improve their answer based on the following question.
1224
+
1225
+ Topic: {topic}
1226
+ Question: "{question}"
1227
+ User's Answer: "{user_answer}"
1228
+
1229
+ If the user's answer is incorrect, provide a specific, actionable hint to help the user correct their answer.
1230
+ The hint should include:
1231
+ - Explanation of the error made by the user.
1232
+ - A hint on the correct grammatical structure or word form.
1233
+ - A hint on how to structure the sentence correctly **without revealing the exact answer**.
1234
+
1235
+ Please make sure the hint is **clear** and **helpful** for the user, **without revealing the correct answer**.
1236
+ """
1237
+
1238
+ headers = {
1239
+ 'Authorization': f'Bearer {COHERE_API_KEY}',
1240
+ 'Content-Type': 'application/json'
1241
+ }
1242
+
1243
+ payload = {
1244
+ 'model': 'command-r-08-2024', # Replace with the model you're using
1245
+ 'prompt': prompt,
1246
+ 'max_tokens': 250, # Adjust token size as needed
1247
+ 'temperature': 0.7, # Use temperature to control creativity
1248
+ }
1249
+
1250
+ # Make the POST request to Cohere API
1251
+ response = requests.post(COHERE_API_URL, headers=headers, json=payload)
1252
+
1253
+ if response.status_code == 200:
1254
+ result = response.json()
1255
+ # Extract and return the relevant hint from the response
1256
+ hint = result['generations'][0]['text'].strip()
1257
+ return hint
1258
+ else:
1259
+ return f"Error: {response.status_code} - {response.text}"
1260
+
1261
+ except Exception as e:
1262
+ return f"An error occurred: {str(e)}"
1263
+
1264
+
1265
+
1266
+
1267
+
1268
+
1269
+ if __name__ == '__main__':
1270
+ # app.run(debug=True)
1271
+ app.run(host='0.0.0.0', port=5012, debug=True)
generateQuestion.py ADDED
@@ -0,0 +1,492 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # from flask import Flask, Blueprint, jsonify, send_file, abort, make_response, request
2
+ from flask import Flask, Blueprint, jsonify, send_file, abort, make_response, request, current_app
3
+
4
+ from flask_cors import CORS
5
+ from moviepy.editor import VideoFileClip
6
+ from google.cloud import speech
7
+ import os
8
+ print(f"GOOGLE_APPLICATION_CREDENTIALS: {os.getenv('GOOGLE_APPLICATION_CREDENTIALS')}")
9
+ import io
10
+ import uuid
11
+ import requests
12
+ from pydub import AudioSegment
13
+ import ffmpeg
14
+ import re
15
+
16
+
17
+
18
+
19
+ questions_bp = Blueprint("questions", __name__)
20
+
21
+
22
+
23
+
24
+
25
+ app = Flask(__name__)
26
+ CORS(app)
27
+ # CORS(app, resources={r"/*": {"origins": "*"}})
28
+
29
+ @app.route('/')
30
+ def home():
31
+ return "Welcome to the Flask app! The server is running."
32
+
33
+ # read from env as a fallback (works for local .env and HF Secrets)
34
+ COHERE_API_KEY = os.getenv("COHERE_API_KEY", "")
35
+
36
+ def _cohere_headers():
37
+ """
38
+ Prefer a key set on the Flask app (e.g., in verification.py: app.config["COHERE_API_KEY"]),
39
+ otherwise fall back to the environment variable COHERE_API_KEY.
40
+ """
41
+ api_key = current_app.config.get("COHERE_API_KEY") or COHERE_API_KEY
42
+ if not api_key:
43
+ return None
44
+ return {
45
+ "Authorization": f"Bearer {api_key}",
46
+ "Content-Type": "application/json",
47
+ }
48
+
49
+ # API configuration for AI-based question generation
50
+ # COHERE_API_KEY = 'WjnDKknACe0zxHvczdo7q4vwF4WAXn2429hcPHIB'
51
+ COHERE_API_URL = 'https://api.cohere.ai/v1/generate'
52
+
53
+ # Google Cloud Speech-to-Text Configuration
54
+ speech_client = speech.SpeechClient()
55
+
56
+
57
+
58
+
59
+
60
+
61
+
62
+
63
+ def validate_topic(topic):
64
+
65
+ validation_prompt = f"""
66
+ You are an AI grammar expert. Your task is to determine if a given topic is related to **English grammar** or not.
67
+
68
+ **Input:** "{topic}"
69
+
70
+ ### **Rules:**
71
+ - If the input is **in the form of a question** (e.g., it asks for an explanation or definition), return `"ask grammar topics"`, even if the topic is related to grammar.
72
+ - If the topic is **related to English grammar concepts** such as **parts of speech**, **verb tenses**, **sentence structure**, etc., return `"Grammar"`.
73
+ - If the topic is **not related to grammar**, such as general knowledge, science, math, history, or topics from other fields, return `"Not Grammar"`.
74
+ - Your response must be based purely on whether the topic relates to grammar, and **not** based on specific words, phrases, or examples.
75
+
76
+ **Your response must be exactly either "Grammar", "Not Grammar", or "ask grammar topics". No extra text.**
77
+ """
78
+
79
+
80
+
81
+
82
+
83
+ # headers = {
84
+ # 'Authorization': f'Bearer {COHERE_API_KEY}',
85
+ # 'Content-Type': 'application/json'
86
+ # }
87
+ headers = _cohere_headers()
88
+ if not headers:
89
+ return "Error: COHERE_API_KEY not set"
90
+
91
+ payload = {
92
+ 'model': 'command-r-08-2024',
93
+ 'prompt': validation_prompt,
94
+ 'max_tokens': 5 # Minimal token usage for classification
95
+ }
96
+
97
+ try:
98
+ response = requests.post(COHERE_API_URL, json=payload, headers=headers)
99
+ validation_result = response.json().get('generations', [{}])[0].get('text', '').strip()
100
+
101
+ # Ensure the response is strictly "Grammar" or "Not Grammar"
102
+ if validation_result not in ["Grammar", "Not Grammar"]:
103
+ return "Not Grammar" # Fallback to avoid incorrect responses
104
+
105
+ return validation_result
106
+
107
+ except Exception as e:
108
+ return f"Error: {str(e)}"
109
+
110
+ @questions_bp.post('/generate-questions')
111
+ # @app.route('/generate-questions', methods=['POST'])
112
+ def generate_questions_test():
113
+ try:
114
+ data = request.get_json()
115
+ topic = data.get('topic', '').strip() # Default to "grammar" if no topic is provided
116
+ # levels = data.get('levels', ['basic', 'medium', 'hard'])
117
+
118
+
119
+ validation_result = validate_topic(topic)
120
+
121
+ if validation_result != "Grammar":
122
+ return jsonify({"message": "Please enter a valid **grammar topic**, not a general word or unrelated question."}), 400
123
+
124
+
125
+ difficulty = data.get('difficulty', 'basic')
126
+
127
+
128
+ # Debugging output
129
+ print(f"Generating {difficulty} questions for topic: {topic}")
130
+
131
+
132
+
133
+ if difficulty == 'basic':
134
+ prompt = f"""
135
+ Generate five **completely new and unique** very basic-level fill-in-the-blank grammar questions **every time** on the topic '{topic}'.
136
+
137
+ ### Rules:
138
+ - **Each question must have a different theme**, ensuring variety.
139
+ - **Do not repeat** themes from previous generations.
140
+ - Use **different sentence structures**, avoiding predictable patterns.
141
+ - **Avoid long words or abstract concepts**
142
+ - **Focus on the topic '{topic}'**, and ensure the blank is the key part of speech.
143
+ - Each question should contain **one blank represented by '_______'**, with the correct answer provided in parentheses at the end.
144
+ - The vocabulary should be **simple and suitable for beginners**.
145
+ - Ensure that the questions are **always new and distinct**, avoiding previously used themes.
146
+
147
+ Do not include any explanations or instructions in the response—only the five unique questions.
148
+ """
149
+
150
+ elif difficulty == 'elementary':
151
+ prompt = f"""
152
+ Generate five **completely new and unique** elementary-level fill-in-the-blank grammar questions **every time** on the topic '{topic}'.
153
+
154
+ ### Rules:
155
+ - The questions should be **slightly more challenging than basic-level questions**, incorporating **a wider range of sentence structures and vocabulary**.
156
+ - **Each question must have a different theme**, ensuring variety.
157
+ - **Use varied sentence structures**, making them slightly more complex than basic-level questions.
158
+ - **Ensure that the vocabulary is still simple but slightly broader** than basic-level questions.
159
+ - **Focus on the topic '{topic}'**, and ensure the blank is the key part of speech.
160
+ - Each question should contain **one blank represented by '_______'**, with the correct answer provided in parentheses at the end.
161
+ - Ensure that the questions are **always new and distinct**, avoiding previously used themes.
162
+
163
+ Do not include any explanations or instructions in the response—only the five unique questions.
164
+ """
165
+
166
+ elif difficulty == 'pre-intermediate':
167
+ prompt = f"""
168
+ Generate five **completely new and unique** pre-intermediate-level fill-in-the-blank grammar questions **every time** on the topic '{topic}'.
169
+
170
+ ### Rules:
171
+ - The questions should be **more challenging than elementary-level questions**, incorporating **more varied sentence structures and an expanded vocabulary**.
172
+ - **Each question must have a different theme**, ensuring variety.
173
+ - **Ensure that the vocabulary is broader than elementary-level**, while keeping it understandable for learners.
174
+ - **Sentences should be longer and more descriptive** but still clear.
175
+ - **Focus on the topic '{topic}'**, and ensure the blank is the key part of speech.
176
+ - Each question should contain **one blank represented by '_______'**, with the correct answer provided in parentheses at the end.
177
+ - Ensure that the questions are **always new and distinct**, avoiding previously used themes.
178
+
179
+ Do not include any explanations or instructions in the response—only the five unique questions.
180
+ """
181
+
182
+ elif difficulty == 'intermediate':
183
+ prompt = f"""
184
+ Generate five **completely new and unique** intermediate-level fill-in-the-blank grammar questions **every time** on the topic '{topic}'.
185
+
186
+ ### Rules:
187
+ - The questions should be **more complex than pre-intermediate-level questions**, incorporating **a wider range of vocabulary and sentence structures**.
188
+ - **Each question must have a different theme**, ensuring variety.
189
+ - **Ensure that the vocabulary is more advanced than pre-intermediate-level** while keeping it natural for learners.
190
+ - **Sentences should be longer and include more detail**, improving reading comprehension.
191
+ - **Focus on the topic '{topic}'**, and ensure the blank is the key part of speech.
192
+ - Each question should contain **one blank represented by '_______'**, with the correct answer provided in parentheses at the end.
193
+ - Ensure that the questions are **always new and distinct**, avoiding previously used themes.
194
+
195
+ Do not include any explanations or instructions in the response—only the five unique questions.
196
+ """
197
+
198
+ elif difficulty == 'upper-intermediate':
199
+ prompt = f"""
200
+ Generate five **completely new and unique** upper-intermediate-level fill-in-the-blank grammar questions **every time** on the topic '{topic}'.
201
+
202
+ ### Rules:
203
+ - The questions should be **more complex than intermediate-level questions**, incorporating **more advanced sentence structures and vocabulary**.
204
+ - **Each question must have a different theme**, ensuring variety.
205
+ - **Ensure that the vocabulary is more refined and diverse** but still understandable for upper-intermediate learners.
206
+ - **Sentences should be longer and may introduce more nuanced contexts**, requiring a deeper understanding.
207
+ - **Focus on the topic '{topic}'**, and ensure the blank is the key part of speech.
208
+ - Each question should contain **one blank represented by '_______'**, with the correct answer provided in parentheses at the end.
209
+ - Ensure that the questions are **always new and distinct**, avoiding previously used themes.
210
+
211
+ Do not include any explanations or instructions in the response—only the five unique questions.
212
+ """
213
+
214
+ elif difficulty == 'advanced':
215
+ prompt = f"""
216
+ Generate five **completely new and unique** advanced-level (C1) fill-in-the-blank grammar questions **every time** on the topic '{topic}'.
217
+
218
+ ### Rules:
219
+ - The questions should be **more challenging than upper-intermediate (B2) level**, requiring a deep understanding of grammar, context, and vocabulary.
220
+ - **Ensure varied and sophisticated vocabulary**, avoiding basic words.
221
+ - **Each question should require nuanced comprehension**, testing knowledge of advanced grammar patterns.
222
+ - **The blank must be the key part of the sentence** (not an obvious answer).
223
+ - Each question should contain **one blank represented by '_______'**, with the correct answer provided in parentheses at the end.
224
+ - Ensure that the questions are **always new and distinct**, avoiding repetition of themes.
225
+
226
+ Do not include any explanations or instructions in the response—only the five unique questions.
227
+ """
228
+
229
+ elif difficulty == 'hard':
230
+ prompt = f"""
231
+ Generate five **completely new and unique** hard-level (C2) fill-in-the-blank grammar questions **every time** on the topic '{topic}'.
232
+
233
+ ### Rules:
234
+ - The questions should be **more challenging than advanced(C1) level**, requiring a deep understanding of grammar, context, and vocabulary.
235
+ - **Ensure varied and sophisticated vocabulary**, avoiding basic words.
236
+ - **Each question should require nuanced comprehension**, testing knowledge of advanced grammar patterns.
237
+ - **The blank must be the key part of the sentence** (not an obvious answer).
238
+ - Each question should contain **one blank represented by '_______'**, with the correct answer provided in parentheses at the end.
239
+ - Ensure that the questions are **always new and distinct**, avoiding repetition of themes.
240
+
241
+ Do not include any explanations or instructions in the response—only the five unique questions.
242
+ """
243
+
244
+ else:
245
+ return jsonify({"error": "Invalid difficulty level"}), 400
246
+
247
+ # headers = {
248
+ # 'Authorization': f'Bearer {COHERE_API_KEY}',
249
+ # 'Content-Type': 'application/json'
250
+ # }
251
+ headers = _cohere_headers()
252
+ if not headers:
253
+ return jsonify({"error": "COHERE_API_KEY not set on the server"}), 500
254
+
255
+ payload = {
256
+ 'model': 'command-r-08-2024', # Ensure you're using the right model
257
+ 'prompt': prompt,
258
+ 'max_tokens': 1000 # Increase the token limit if needed
259
+ }
260
+
261
+ # Make the API request
262
+ response = requests.post(COHERE_API_URL, json=payload, headers=headers)
263
+
264
+ # Log the full response for debugging
265
+ print("Response status code:", response.status_code)
266
+ print("Response content:", response.text)
267
+
268
+ if response.status_code == 200:
269
+ return jsonify(response.json()) # Return the response from Cohere API
270
+ else:
271
+ return jsonify({"error": "Failed to fetch questions", "details": response.text}), 500
272
+ except Exception as e:
273
+ return jsonify({"error": str(e)}), 500
274
+
275
+ # Endpoint to validate answers
276
+ @questions_bp.post('/validate-answer')
277
+ # @app.route('/validate-answer', methods=['POST'])
278
+ def validate_answer():
279
+ try:
280
+ # Get the data from the request
281
+ data = request.get_json()
282
+ topic = data.get('topic', '') # Get the topic
283
+ question = data.get('question', '')
284
+ user_answer = data.get('user_answer', '')
285
+
286
+ # Validate if the required fields are present
287
+ if not question or not user_answer or not topic:
288
+ return jsonify({'error': 'Topic, question, and user answer are required'}), 400
289
+
290
+ # Construct the prompt for Cohere API
291
+ prompt = f"""
292
+ You are a highly knowledgeable grammar assistant. Validate whether the user's answer to the following question is correct or not based on {topic}. If the answer is incorrect, provide a helpful hint.
293
+
294
+ Topic: {topic}
295
+ Question: "{question}"
296
+ User's Answer: "{user_answer}"
297
+
298
+ Is the answer correct? If not, please explain why and give a hint.
299
+ """
300
+
301
+ # Headers and payload for the Cohere API request
302
+ # headers = {
303
+ # 'Authorization': f'Bearer {COHERE_API_KEY}',
304
+ # 'Content-Type': 'application/json'
305
+ # }
306
+
307
+ headers = _cohere_headers()
308
+ if not headers:
309
+ return jsonify({"error": "COHERE_API_KEY not set on the server"}), 500
310
+
311
+ payload = {
312
+ 'model': 'command-r-08-2024', # Use your model name here
313
+ 'prompt': prompt,
314
+ 'max_tokens': 100,
315
+ 'temperature': 0.7
316
+ }
317
+
318
+ # Make the API call to Cohere
319
+ response = requests.post(COHERE_API_URL, headers=headers, json=payload)
320
+
321
+ # Debugging: Log response status and body
322
+ print(f"Status Code: {response.status_code}")
323
+ print(f"Response Body: {response.text}")
324
+
325
+ # Check if the request was successful
326
+ if response.status_code == 200:
327
+ data = response.json()
328
+ return jsonify(data)
329
+ else:
330
+ return jsonify({'error': 'Failed to fetch data from Cohere API'}), 500
331
+
332
+ except Exception as e:
333
+ return jsonify({'error': str(e)}), 500
334
+
335
+
336
+
337
+ # // for validating Multiple answer:
338
+
339
+ # Function to validate an individual answer using Cohere API
340
+ def validate_answer_with_ai(topic, question, user_answer):
341
+ try:
342
+ # Construct the prompt for Cohere API
343
+ prompt = f"""
344
+ You are a highly knowledgeable grammar assistant. Validate whether the user's answer to the following question is correct or not based on {topic}. If the answer is incorrect, provide a helpful hint.
345
+
346
+ Topic: {topic}
347
+ Question: "{question}"
348
+ User's Answer: "{user_answer}"
349
+
350
+ Is the answer correct? If not, please explain why and give a hint.
351
+ """
352
+
353
+ # Headers for the API request
354
+ # headers = {
355
+ # 'Authorization': f'Bearer {COHERE_API_KEY}',
356
+ # 'Content-Type': 'application/json'
357
+ # }
358
+
359
+ headers = _cohere_headers()
360
+ if not headers:
361
+ return "Error: COHERE_API_KEY not set"
362
+
363
+ # Construct the payload for Cohere API request
364
+ payload = {
365
+ 'model': 'command-r-08-2024', # You can use a different model depending on your needs
366
+ 'prompt': prompt,
367
+ 'max_tokens': 200,
368
+ 'temperature': 0.7,
369
+ 'stop_sequences': ['\n']
370
+ }
371
+
372
+ # Make the POST request to the Cohere API
373
+ response = requests.post('https://api.cohere.ai/v1/generate', headers=headers, json=payload)
374
+
375
+ if response.status_code == 200:
376
+ result = response.json()
377
+ # Extract and return the relevant part of the response
378
+ validation_response = result['generations'][0]['text'].strip()
379
+ return validation_response
380
+ else:
381
+ return f"Error: {response.status_code} - {response.text}"
382
+
383
+ except Exception as e:
384
+ return f"An error occurred: {str(e)}"
385
+
386
+
387
+
388
+ @questions_bp.post('/validate-all-answers')
389
+ # Endpoint to validate multiple answers at once
390
+ # @app.route('/validate-all-answers', methods=['POST'])
391
+ def validate_all_answers():
392
+ try:
393
+ # Get the list of questions and answers from the request body
394
+ data = request.get_json()
395
+ questions = data.get('questions', [])
396
+
397
+ if not questions:
398
+ return jsonify({'error': 'No questions provided'}), 400
399
+
400
+ validation_results = []
401
+
402
+ # Iterate over the list of questions and validate each answer
403
+ for item in questions:
404
+ topic = item.get('topic', '')
405
+ question = item.get('question', '')
406
+ user_answer = item.get('user_answer', '')
407
+
408
+ if not topic or not question or not user_answer:
409
+ validation_results.append({
410
+ 'question': question,
411
+ 'error': 'Missing required fields (topic, question, or answer).'
412
+ })
413
+ continue
414
+
415
+ # Validate the answer with the Cohere API
416
+ validation_response = validate_answer_with_ai(topic, question, user_answer)
417
+
418
+ # If the answer is incorrect, generate a hint
419
+ hint = None
420
+ if "incorrect" in validation_response.lower() or "not correct" in validation_response.lower():
421
+ # Generate the hint for the incorrect answer
422
+ hint = generate_hint(topic, question, user_answer)
423
+
424
+ validation_results.append({
425
+ 'question': question,
426
+ 'user_answer': user_answer,
427
+ 'validation_response': validation_response,
428
+ 'hint': hint # Add hint to the result
429
+ })
430
+
431
+ return jsonify({'results': validation_results})
432
+
433
+ except Exception as e:
434
+ return jsonify({'error': str(e)}), 500
435
+
436
+
437
+
438
+ def generate_hint(topic, question, user_answer):
439
+ try:
440
+ # Construct the prompt for Cohere API to generate a hint for incorrect answers
441
+ prompt = f"""
442
+ You are a highly skilled grammar assistant. Your task is to generate a helpful hint for the user to improve their answer based on the following question.
443
+
444
+ Topic: {topic}
445
+ Question: "{question}"
446
+ User's Answer: "{user_answer}"
447
+
448
+ If the user's answer is incorrect, provide a specific, actionable hint to help the user correct their answer.
449
+ The hint should include:
450
+ - Explanation of the error made by the user.
451
+ - A hint on the correct grammatical structure or word form.
452
+ - A hint on how to structure the sentence correctly **without revealing the exact answer**.
453
+
454
+ Please make sure the hint is **clear** and **helpful** for the user, **without revealing the correct answer**.
455
+ """
456
+
457
+ # headers = {
458
+ # 'Authorization': f'Bearer {COHERE_API_KEY}',
459
+ # 'Content-Type': 'application/json'
460
+ # }
461
+
462
+ headers = _cohere_headers()
463
+ if not headers:
464
+ return "Error: COHERE_API_KEY not set"
465
+
466
+ payload = {
467
+ 'model': 'command-r-08-2024', # Replace with the model you're using
468
+ 'prompt': prompt,
469
+ 'max_tokens': 250, # Adjust token size as needed
470
+ 'temperature': 0.7, # Use temperature to control creativity
471
+ }
472
+
473
+ # Make the POST request to Cohere API
474
+ response = requests.post(COHERE_API_URL, headers=headers, json=payload)
475
+
476
+ if response.status_code == 200:
477
+ result = response.json()
478
+ # Extract and return the relevant hint from the response
479
+ hint = result['generations'][0]['text'].strip()
480
+ return hint
481
+ else:
482
+ return f"Error: {response.status_code} - {response.text}"
483
+
484
+ except Exception as e:
485
+ return f"An error occurred: {str(e)}"
486
+
487
+
488
+ if __name__ == '__main__':
489
+ # app.run(debug=True)
490
+ app.register_blueprint(questions_bp, url_prefix='') # expose /explain-grammar locally
491
+ app.run(host='0.0.0.0', port=5012, debug=True)
492
+
verification.py CHANGED
@@ -305,8 +305,10 @@ def check_auth(username):
305
  # Register Blueprint: grammar (and later media) lives in testmovie.py
306
  # ------------------------------------------------------------------------------
307
  from chat import movie_bp # ensure testmovie.py defines movie_bp = Blueprint(...)
 
308
  app.register_blueprint(movie_bp, url_prefix="/media")
309
-
 
310
  # ------------------------------------------------------------------------------
311
  # Local run (Gunicorn will import `verification:app` on Spaces)
312
  # ------------------------------------------------------------------------------
 
305
  # Register Blueprint: grammar (and later media) lives in testmovie.py
306
  # ------------------------------------------------------------------------------
307
  from chat import movie_bp # ensure testmovie.py defines movie_bp = Blueprint(...)
308
+ from generateQuestion import questions_bp
309
  app.register_blueprint(movie_bp, url_prefix="/media")
310
+ app.register_blueprint(questions_bp, url_prefix="/media")
311
+ # app.register_blueprint(questions_bp, url_prefix="/media") # <-- add this
312
  # ------------------------------------------------------------------------------
313
  # Local run (Gunicorn will import `verification:app` on Spaces)
314
  # ------------------------------------------------------------------------------