Merged in feature/training-content (pull request #14)

Feature/training content
This commit is contained in:
carlos.mesquita
2024-08-19 15:57:09 +00:00
committed by Tiago Ribeiro

View File

@@ -1,3 +1,4 @@
import json
from datetime import datetime from datetime import datetime
from logging import getLogger from logging import getLogger
@@ -42,6 +43,7 @@ class TrainingContentService:
**weak_areas **weak_areas
} }
doc_ref = self._db.collection('training').add(training_doc) doc_ref = self._db.collection('training').add(training_doc)
return { return {
"id": doc_ref[1].id "id": doc_ref[1].id
} }
@@ -70,7 +72,6 @@ class TrainingContentService:
tips = {"tips": []} tips = {"tips": []}
for query in queries: for query in queries:
print(f"{query.category} {query.text}")
if query.category == "words": if query.category == "words":
tips["tips"].extend( tips["tips"].extend(
self._training_content_module.query_knowledge_base(query.text, "word_link") self._training_content_module.query_knowledge_base(query.text, "word_link")
@@ -104,7 +105,8 @@ class TrainingContentService:
' with sentence structure and punctuation.", the "queries" field is where you will write queries ' ' with sentence structure and punctuation.", the "queries" field is where you will write queries '
'for tips that will be displayed to the student, the category attribute is a collection of ' 'for tips that will be displayed to the student, the category attribute is a collection of '
'embeddings and the text will be the text used to query the knowledge base. The categories are ' 'embeddings and the text will be the text used to query the knowledge base. The categories are '
f'the following [{", ".join(self.TOOLS)}].' f'the following [{", ".join(self.TOOLS)}]. The exam data will be a json where the key of the field '
'"exams" is the exam id, an exam can be composed of multiple modules or single modules.'
) )
}, },
{ {
@@ -150,42 +152,66 @@ class TrainingContentService:
def _sort_out_solutions(self, stats): def _sort_out_solutions(self, stats):
grouped_stats = {} grouped_stats = {}
for stat in stats: for stat in stats:
exam_id = stat["exam"] session_key = f'{str(stat["date"])}-{stat["user"]}'
module = stat["module"] module = stat["module"]
if module not in grouped_stats: exam_id = stat["exam"]
grouped_stats[module] = {}
if exam_id not in grouped_stats[module]: if session_key not in grouped_stats:
grouped_stats[module][exam_id] = [] grouped_stats[session_key] = {}
grouped_stats[module][exam_id].append(stat) if module not in grouped_stats[session_key]:
grouped_stats[session_key][module] = {
"stats": [],
"exam_id": exam_id
}
grouped_stats[session_key][module]["stats"].append(stat)
exercises = {} exercises = {}
exam_map = {} exam_map = {}
for module, exams in grouped_stats.items(): for session_key, modules in grouped_stats.items():
exercises[module] = {} exercises[session_key] = {}
for exam_id, stat_group in exams.items(): for module, module_stats in modules.items():
exam = self._get_doc_by_id(module, exam_id) exercises[session_key][module] = {}
exercises[module][exam_id] = {"date": None, "exercises": [], "score": None}
exam_id = module_stats["exam_id"]
if exam_id not in exercises[session_key][module]:
exercises[session_key][module][exam_id] = {"date": None, "exercises": []}
exam_total_questions = 0 exam_total_questions = 0
exam_total_correct = 0 exam_total_correct = 0
for stat in stat_group:
for stat in module_stats["stats"]:
exam_total_questions += stat["score"]["total"] exam_total_questions += stat["score"]["total"]
exam_total_correct += stat["score"]["correct"] exam_total_correct += stat["score"]["correct"]
exercises[module][exam_id]["date"] = stat["date"] exercises[session_key][module][exam_id]["date"] = stat["date"]
if exam_id not in exam_map: if session_key not in exam_map:
exam_map[exam_id] = {"stat_ids": [], "score": 0} exam_map[session_key] = {"stat_ids": [], "score": 0}
exam_map[exam_id]["stat_ids"].append(stat["id"]) exam_map[session_key]["stat_ids"].append(stat["id"])
exam = self._get_doc_by_id(module, exam_id)
if module == "listening": if module == "listening":
exercises[module][exam_id]["exercises"].extend(self._get_listening_solutions(stat, exam)) exercises[session_key][module][exam_id]["exercises"].extend(
if module == "reading": self._get_listening_solutions(stat, exam))
exercises[module][exam_id]["exercises"].extend(self._get_reading_solutions(stat, exam)) elif module == "reading":
if module == "writing": exercises[session_key][module][exam_id]["exercises"].extend(
exercises[module][exam_id]["exercises"].extend(self._get_writing_prompts_and_answers(stat, exam)) self._get_reading_solutions(stat, exam))
elif module == "writing":
exercises[session_key][module][exam_id]["exercises"].extend(
self._get_writing_prompts_and_answers(stat, exam)
)
elif module == "speaking":
exercises[session_key][module][exam_id]["exercises"].extend(
self._get_speaking_solutions(stat, exam)
)
elif module == "level": # same structure as listening
exercises[session_key][module][exam_id]["exercises"].extend(
self._get_listening_solutions(stat, exam)
)
exam_map[exam_id]["score"] = round((exam_total_correct / exam_total_questions) * 100) exam_map[session_key]["score"] = round((exam_total_correct / exam_total_questions) * 100)
exam_map[exam_id]["module"] = module exam_map[session_key]["module"] = module
return exercises, exam_map
return {"exams": exercises}, exam_map
def _get_writing_prompts_and_answers(self, stat, exam): def _get_writing_prompts_and_answers(self, stat, exam):
result = [] result = []
@@ -224,7 +250,7 @@ class TrainingContentService:
"solution": exercise["solutions"], "solution": exercise["solutions"],
"answer": stat["solutions"] "answer": stat["solutions"]
}) })
if stat["type"] == "multipleChoice": elif stat["type"] == "multipleChoice":
result.append({ result.append({
"question": exercise["prompt"], "question": exercise["prompt"],
"exercise": exercise["questions"], "exercise": exercise["questions"],
@@ -234,6 +260,35 @@ class TrainingContentService:
self._logger.warning(f"Malformed stat object: {str(e)}") self._logger.warning(f"Malformed stat object: {str(e)}")
return result return result
def _get_speaking_solutions(self, stat, exam):
result = {}
try:
result = {
"comments": {
key: value['comment'] for key, value in stat['solutions'][0]['evaluation']['task_response'].items()}
,
"exercises": {}
}
for exercise in exam["exercises"]:
if exercise["id"] == stat["exercise"]:
if stat["type"] == "interactiveSpeaking":
for i in range(len(exercise["prompts"])):
result["exercises"][f"exercise_{i+1}"] = {
"question": exercise["prompts"][i]["text"]
}
for i in range(len(exercise["prompts"])):
answer = stat['solutions'][0]["evaluation"].get(f'transcript_{i+1}', '')
result["exercises"][f"exercise_{i+1}"]["answer"] = answer
elif stat["type"] == "speaking":
result["exercises"]["exercise_1"] = {
"question": exercise["text"],
"answer": stat['solutions'][0]["evaluation"].get(f'transcript', '')
}
except KeyError as e:
self._logger.warning(f"Malformed stat object: {str(e)}")
return [result]
def _get_reading_solutions(self, stat, exam): def _get_reading_solutions(self, stat, exam):
result = [] result = []
try: try:
@@ -258,8 +313,13 @@ class TrainingContentService:
"solutions": exercise["solutions"], "solutions": exercise["solutions"],
"answer": stat["solutions"] "answer": stat["solutions"]
}) })
else: elif stat["type"] == "trueFalse":
# match_sentences result.append({
"text": text,
"questions": exercise["questions"],
"answer": stat["solutions"]
})
elif stat["type"] == "matchSentences":
result.append({ result.append({
"text": text, "text": text,
"question": exercise["prompt"], "question": exercise["prompt"],