Commit
·
033e08c
1
Parent(s):
9ea114e
new main
Browse files
main.py
CHANGED
@@ -1,6 +1,19 @@
|
|
1 |
import os
|
2 |
import tempfile
|
3 |
import nltk
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
|
5 |
# Set up all cache and data directories in /tmp
|
6 |
cache_dir = tempfile.mkdtemp()
|
@@ -122,56 +135,51 @@ def compute_marks():
|
|
122 |
# Get and process answers
|
123 |
a = request.form.get('answers')
|
124 |
if not a:
|
|
|
125 |
return jsonify({"error": "No answers provided"}), 400
|
126 |
|
127 |
-
|
128 |
-
|
129 |
a = json.loads(a)
|
130 |
answers = []
|
131 |
for i in a:
|
132 |
ans = i.split('\n\n')
|
133 |
answers.append(ans)
|
134 |
-
|
135 |
|
136 |
# Process files and create data structure
|
137 |
data = {}
|
138 |
parent_folder = os.path.join(cache_dir, 'student_answers')
|
139 |
os.makedirs(parent_folder, exist_ok=True)
|
140 |
|
141 |
-
|
142 |
-
# First, save uploaded files
|
143 |
files = request.files.getlist('files[]')
|
144 |
if not files:
|
|
|
145 |
return jsonify({"error": "No files uploaded"}), 400
|
146 |
|
147 |
-
|
148 |
|
149 |
-
#
|
150 |
for file in files:
|
151 |
if file.filename.endswith(('.jpg', '.jpeg', '.png')):
|
152 |
relative_path = file.filename.replace('\\', '/')
|
153 |
path_parts = relative_path.split('/')
|
154 |
|
155 |
-
|
156 |
-
|
157 |
|
158 |
if len(path_parts) >= 2:
|
159 |
student_folder = path_parts[1]
|
160 |
file_name = path_parts[-1]
|
161 |
|
162 |
-
print(f"Student folder: {student_folder}")
|
163 |
-
print(f"File name: {file_name}")
|
164 |
-
|
165 |
-
# Create student folder
|
166 |
student_dir = os.path.join(parent_folder, student_folder)
|
167 |
os.makedirs(student_dir, exist_ok=True)
|
168 |
|
169 |
-
# Save file with original name to maintain order
|
170 |
save_path = os.path.join(student_dir, file_name)
|
171 |
file.save(save_path)
|
172 |
-
|
173 |
|
174 |
-
# Store in data structure
|
175 |
if student_folder not in data:
|
176 |
data[student_folder] = []
|
177 |
data[student_folder].append({
|
@@ -179,64 +187,32 @@ def compute_marks():
|
|
179 |
'name': os.path.splitext(file_name)[0]
|
180 |
})
|
181 |
else:
|
182 |
-
|
183 |
|
184 |
-
|
|
|
185 |
for student, images in data.items():
|
186 |
-
|
187 |
-
print("Images:")
|
188 |
for img in sorted(images, key=lambda x: x['name']):
|
189 |
-
|
190 |
|
191 |
-
#
|
192 |
-
print("\n=== Verifying File Mapping ===")
|
193 |
-
for student_folder, images in data.items():
|
194 |
-
print(f"\nChecking student folder: {student_folder}")
|
195 |
-
actual_files = os.listdir(os.path.join(parent_folder, student_folder))
|
196 |
-
mapped_files = [os.path.basename(img['path']) for img in images]
|
197 |
-
|
198 |
-
print(f"Files in directory: {actual_files}")
|
199 |
-
print(f"Files in data structure: {mapped_files}")
|
200 |
-
|
201 |
-
# Check for mismatches
|
202 |
-
missing_files = set(actual_files) - set(mapped_files)
|
203 |
-
extra_files = set(mapped_files) - set(actual_files)
|
204 |
-
|
205 |
-
if missing_files:
|
206 |
-
print(f"Warning: Files in directory but not mapped: {missing_files}")
|
207 |
-
if extra_files:
|
208 |
-
print(f"Warning: Files mapped but not in directory: {extra_files}")
|
209 |
-
|
210 |
-
# Create vectors for reference answers
|
211 |
-
sen_vec_answers = []
|
212 |
-
word_vec_answers = []
|
213 |
-
for answer_set in answers:
|
214 |
-
temp_v = []
|
215 |
-
temp_w = []
|
216 |
-
for ans in answer_set:
|
217 |
-
temp_v.append(question_vector_sentence(ans))
|
218 |
-
temp_w.append(question_vector_word(ans))
|
219 |
-
sen_vec_answers.append(temp_v)
|
220 |
-
word_vec_answers.append(temp_w)
|
221 |
-
|
222 |
-
# Calculate marks
|
223 |
results = []
|
224 |
for student_folder, images in data.items():
|
225 |
student_total = 0
|
226 |
student_count = 0
|
227 |
|
228 |
-
# Sort images by name to maintain order
|
229 |
sorted_images = sorted(images, key=lambda x: x['name'])
|
230 |
|
231 |
for idx, image_info in enumerate(sorted_images):
|
232 |
try:
|
233 |
image_path = image_info['path']
|
234 |
s_answer = extract_text_from_image(image_path)
|
235 |
-
|
236 |
-
|
237 |
|
238 |
if s_answer and idx < len(answers):
|
239 |
-
|
240 |
tf_idf_word_values, max_tfidf = create_tfidf_values(answers[idx])
|
241 |
m = marks(s_answer, sen_vec_answers[idx], word_vec_answers[idx],
|
242 |
tf_idf_word_values, max_tfidf, answers[idx])
|
@@ -246,47 +222,39 @@ def compute_marks():
|
|
246 |
mark_value = round(float(m), 2)
|
247 |
student_total += mark_value
|
248 |
student_count += 1
|
|
|
249 |
else:
|
250 |
mark_value = 0
|
|
|
251 |
|
252 |
results.append({
|
253 |
'student': student_folder,
|
254 |
'image_name': image_info['name'],
|
255 |
'marks': mark_value
|
256 |
})
|
257 |
-
print(f"Marks awarded: {mark_value}")
|
258 |
|
259 |
except Exception as e:
|
260 |
-
|
261 |
results.append({
|
262 |
'student': student_folder,
|
263 |
'image_name': image_info['name'],
|
264 |
'marks': 0
|
265 |
})
|
266 |
-
|
267 |
-
# Add average for student
|
268 |
-
if student_count > 0:
|
269 |
-
avg_mark = round(student_total / student_count, 2)
|
270 |
-
results.append({
|
271 |
-
'student': student_folder,
|
272 |
-
'image_name': 'AVERAGE',
|
273 |
-
'marks': avg_mark
|
274 |
-
})
|
275 |
|
276 |
# Sort results
|
277 |
results.sort(key=lambda x: (x['student'], x['image_name']))
|
278 |
|
279 |
-
|
280 |
for r in results:
|
281 |
-
|
282 |
|
283 |
# Clean up temporary directory
|
284 |
try:
|
285 |
import shutil
|
286 |
shutil.rmtree(parent_folder)
|
287 |
-
|
288 |
except Exception as e:
|
289 |
-
|
290 |
|
291 |
return jsonify({
|
292 |
"message": results,
|
@@ -294,7 +262,7 @@ def compute_marks():
|
|
294 |
}), 200
|
295 |
|
296 |
except Exception as e:
|
297 |
-
|
298 |
try:
|
299 |
import shutil
|
300 |
shutil.rmtree(parent_folder)
|
@@ -304,44 +272,50 @@ def compute_marks():
|
|
304 |
|
305 |
|
306 |
|
307 |
-
def marks(answer,sen_vec_answers,word_vec_answers,tf_idf_word_values, max_tfidf,correct_answers):
|
308 |
marks = 0
|
309 |
-
|
|
|
310 |
|
311 |
-
|
312 |
-
|
313 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
314 |
|
315 |
-
|
316 |
-
marks2 = similarity_model_score(sen_vec_answers,answer)
|
317 |
-
a = 0
|
318 |
-
if marks2>0.95:
|
319 |
marks += 3
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
marks3
|
327 |
-
b = 0
|
328 |
-
if marks2>0.9:
|
329 |
marks += 2
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
marks4 = llm_score(correct_answers,answer)
|
337 |
for i in range(len(marks4)):
|
338 |
marks4[i] = float(marks4[i])
|
339 |
-
|
340 |
m = max(marks4)
|
341 |
-
|
342 |
-
marks = marks/2 + m/2
|
343 |
|
344 |
-
|
|
|
|
|
|
|
|
|
|
|
345 |
|
346 |
|
347 |
|
|
|
1 |
import os
|
2 |
import tempfile
|
3 |
import nltk
|
4 |
+
import logging
|
5 |
+
import sys
|
6 |
+
|
7 |
+
# Set up logging at the start of your main.py
|
8 |
+
logging.basicConfig(
|
9 |
+
level=logging.INFO,
|
10 |
+
format='%(asctime)s - %(levelname)s - %(message)s',
|
11 |
+
handlers=[
|
12 |
+
logging.StreamHandler(sys.stdout)
|
13 |
+
]
|
14 |
+
)
|
15 |
+
|
16 |
+
logger = logging.getLogger(__name__)
|
17 |
|
18 |
# Set up all cache and data directories in /tmp
|
19 |
cache_dir = tempfile.mkdtemp()
|
|
|
135 |
# Get and process answers
|
136 |
a = request.form.get('answers')
|
137 |
if not a:
|
138 |
+
logger.error("No answers provided")
|
139 |
return jsonify({"error": "No answers provided"}), 400
|
140 |
|
141 |
+
logger.info("=== Processing Answers ===")
|
142 |
+
logger.info(f"Received answers: {a}")
|
143 |
a = json.loads(a)
|
144 |
answers = []
|
145 |
for i in a:
|
146 |
ans = i.split('\n\n')
|
147 |
answers.append(ans)
|
148 |
+
logger.info(f"Processed answers structure: {answers}")
|
149 |
|
150 |
# Process files and create data structure
|
151 |
data = {}
|
152 |
parent_folder = os.path.join(cache_dir, 'student_answers')
|
153 |
os.makedirs(parent_folder, exist_ok=True)
|
154 |
|
155 |
+
logger.info("=== Processing Uploaded Files ===")
|
|
|
156 |
files = request.files.getlist('files[]')
|
157 |
if not files:
|
158 |
+
logger.error("No files uploaded")
|
159 |
return jsonify({"error": "No files uploaded"}), 400
|
160 |
|
161 |
+
logger.info(f"Number of files received: {len(files)}")
|
162 |
|
163 |
+
# File processing with logging
|
164 |
for file in files:
|
165 |
if file.filename.endswith(('.jpg', '.jpeg', '.png')):
|
166 |
relative_path = file.filename.replace('\\', '/')
|
167 |
path_parts = relative_path.split('/')
|
168 |
|
169 |
+
logger.info(f"Processing file: {file.filename}")
|
170 |
+
logger.info(f"Path parts: {path_parts}")
|
171 |
|
172 |
if len(path_parts) >= 2:
|
173 |
student_folder = path_parts[1]
|
174 |
file_name = path_parts[-1]
|
175 |
|
|
|
|
|
|
|
|
|
176 |
student_dir = os.path.join(parent_folder, student_folder)
|
177 |
os.makedirs(student_dir, exist_ok=True)
|
178 |
|
|
|
179 |
save_path = os.path.join(student_dir, file_name)
|
180 |
file.save(save_path)
|
181 |
+
logger.info(f"Saved file: {save_path}")
|
182 |
|
|
|
183 |
if student_folder not in data:
|
184 |
data[student_folder] = []
|
185 |
data[student_folder].append({
|
|
|
187 |
'name': os.path.splitext(file_name)[0]
|
188 |
})
|
189 |
else:
|
190 |
+
logger.warning(f"File {file.filename} doesn't have expected structure")
|
191 |
|
192 |
+
# Log data structure
|
193 |
+
logger.info("=== Final Data Structure ===")
|
194 |
for student, images in data.items():
|
195 |
+
logger.info(f"Student: {student}")
|
|
|
196 |
for img in sorted(images, key=lambda x: x['name']):
|
197 |
+
logger.info(f" - {img['name']} ({img['path']})")
|
198 |
|
199 |
+
# Calculate marks with logging
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
200 |
results = []
|
201 |
for student_folder, images in data.items():
|
202 |
student_total = 0
|
203 |
student_count = 0
|
204 |
|
|
|
205 |
sorted_images = sorted(images, key=lambda x: x['name'])
|
206 |
|
207 |
for idx, image_info in enumerate(sorted_images):
|
208 |
try:
|
209 |
image_path = image_info['path']
|
210 |
s_answer = extract_text_from_image(image_path)
|
211 |
+
logger.info(f"\nProcessing {student_folder}/{image_info['name']}:")
|
212 |
+
logger.info(f"Extracted answer: {s_answer}")
|
213 |
|
214 |
if s_answer and idx < len(answers):
|
215 |
+
logger.info(f"Reference answer: {answers[idx]}")
|
216 |
tf_idf_word_values, max_tfidf = create_tfidf_values(answers[idx])
|
217 |
m = marks(s_answer, sen_vec_answers[idx], word_vec_answers[idx],
|
218 |
tf_idf_word_values, max_tfidf, answers[idx])
|
|
|
222 |
mark_value = round(float(m), 2)
|
223 |
student_total += mark_value
|
224 |
student_count += 1
|
225 |
+
logger.info(f"Marks awarded: {mark_value}")
|
226 |
else:
|
227 |
mark_value = 0
|
228 |
+
logger.warning(f"No text extracted or no reference answer for index {idx}")
|
229 |
|
230 |
results.append({
|
231 |
'student': student_folder,
|
232 |
'image_name': image_info['name'],
|
233 |
'marks': mark_value
|
234 |
})
|
|
|
235 |
|
236 |
except Exception as e:
|
237 |
+
logger.error(f"Error processing {image_path}: {str(e)}")
|
238 |
results.append({
|
239 |
'student': student_folder,
|
240 |
'image_name': image_info['name'],
|
241 |
'marks': 0
|
242 |
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
243 |
|
244 |
# Sort results
|
245 |
results.sort(key=lambda x: (x['student'], x['image_name']))
|
246 |
|
247 |
+
logger.info("\nFinal Results:")
|
248 |
for r in results:
|
249 |
+
logger.info(f"{r['student']}\t{r['image_name']}\t{r['marks']}")
|
250 |
|
251 |
# Clean up temporary directory
|
252 |
try:
|
253 |
import shutil
|
254 |
shutil.rmtree(parent_folder)
|
255 |
+
logger.info(f"Cleaned up temporary directory: {parent_folder}")
|
256 |
except Exception as e:
|
257 |
+
logger.warning(f"Warning: Could not clean up temporary directory: {e}")
|
258 |
|
259 |
return jsonify({
|
260 |
"message": results,
|
|
|
262 |
}), 200
|
263 |
|
264 |
except Exception as e:
|
265 |
+
logger.error("Error in compute_marks:", str(e))
|
266 |
try:
|
267 |
import shutil
|
268 |
shutil.rmtree(parent_folder)
|
|
|
272 |
|
273 |
|
274 |
|
275 |
+
def marks(answer, sen_vec_answers, word_vec_answers, tf_idf_word_values, max_tfidf, correct_answers):
|
276 |
marks = 0
|
277 |
+
logger.info("=== Marks Calculation ===")
|
278 |
+
logger.info(f"Processing answer: {answer[:100]}...") # Log first 100 chars
|
279 |
|
280 |
+
marks1 = tfidf_answer_score(answer, tf_idf_word_values, max_tfidf, marks=10)
|
281 |
+
logger.info(f"TFIDF Score: {marks1}")
|
282 |
+
|
283 |
+
if marks1 > 3:
|
284 |
+
marks += new_value(marks1, old_min=3, old_max=10, new_min=0, new_max=5)
|
285 |
+
logger.info(f"After TFIDF adjustment: {marks}")
|
286 |
+
|
287 |
+
if marks1 > 2:
|
288 |
+
marks2 = similarity_model_score(sen_vec_answers, answer)
|
289 |
+
logger.info(f"Sentence Similarity Score: {marks2}")
|
290 |
|
291 |
+
if marks2 > 0.95:
|
|
|
|
|
|
|
292 |
marks += 3
|
293 |
+
elif marks2 > 0.5:
|
294 |
+
marks += new_value(marks2, old_min=0.5, old_max=0.95, new_min=0, new_max=3)
|
295 |
+
|
296 |
+
marks3 = fasttext_similarity(word_vec_answers, answer)
|
297 |
+
logger.info(f"Word Similarity Score: {marks3}")
|
298 |
+
|
299 |
+
if marks3 > 0.9: # Fixed the condition to use marks3 instead of marks2
|
|
|
|
|
300 |
marks += 2
|
301 |
+
elif marks3 > 0.4:
|
302 |
+
marks += new_value(marks3, old_min=0.4, old_max=0.9, new_min=0, new_max=2)
|
303 |
+
|
304 |
+
marks4 = llm_score(correct_answers, answer)
|
305 |
+
logger.info(f"LLM Scores: {marks4}")
|
306 |
+
|
|
|
307 |
for i in range(len(marks4)):
|
308 |
marks4[i] = float(marks4[i])
|
309 |
+
|
310 |
m = max(marks4)
|
311 |
+
logger.info(f"Max LLM Score: {m}")
|
|
|
312 |
|
313 |
+
marks = marks/2 + m/2
|
314 |
+
logger.info(f"Final marks: {marks}")
|
315 |
+
else:
|
316 |
+
logger.warning("TFIDF score too low, returning 0")
|
317 |
+
|
318 |
+
return marks
|
319 |
|
320 |
|
321 |
|