feature: on-off-tasks
#11
by ikarasz - opened
- handler.py +14 -2
- measures/OnTaskAnalyser.py +23 -0
handler.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
| 1 |
from typing import Dict, List, Any
|
| 2 |
from measures.VocabularyAnalyser import VocabularyAnalyser
|
|
|
|
| 3 |
from scipy.special import softmax
|
| 4 |
from collections import Counter, defaultdict
|
| 5 |
import numpy as np
|
|
@@ -47,6 +48,7 @@ class Utterance:
|
|
| 47 |
self.num_math_terms = None
|
| 48 |
self.math_terms = None
|
| 49 |
self.vocabulary_terms = None
|
|
|
|
| 50 |
|
| 51 |
# moments
|
| 52 |
self.uptake = None
|
|
@@ -92,8 +94,14 @@ class Utterance:
|
|
| 92 |
'questioning': True if self.question else False,
|
| 93 |
'uptake': True if self.uptake else False,
|
| 94 |
'focusingQuestion': True if self.focusing_question else False,
|
| 95 |
-
|
|
|
|
|
|
|
|
|
|
| 96 |
},
|
|
|
|
|
|
|
|
|
|
| 97 |
'unitMeasure': self.unit_measure,
|
| 98 |
'aggregateUnitMeasure': self.aggregate_unit_measure,
|
| 99 |
'wordCount': self.word_count,
|
|
@@ -537,7 +545,11 @@ class EndpointHandler():
|
|
| 537 |
vocabulary_analyser = VocabularyAnalyser(str(glossary_path))
|
| 538 |
vocabulary_analyser.run_analysis(transcript)
|
| 539 |
del vocabulary_analyser
|
| 540 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 541 |
transcript.update_utterance_roles(uptake_speaker)
|
| 542 |
sorted_math_cloud, teacher_math_cloud, student_math_cloud = run_math_density(transcript)
|
| 543 |
transcript.calculate_aggregate_word_count()
|
|
|
|
| 1 |
from typing import Dict, List, Any
|
| 2 |
from measures.VocabularyAnalyser import VocabularyAnalyser
|
| 3 |
+
from measures.OnTaskAnalyser import OnTaskAnalyser, ON_TASK_LABEL
|
| 4 |
from scipy.special import softmax
|
| 5 |
from collections import Counter, defaultdict
|
| 6 |
import numpy as np
|
|
|
|
| 48 |
self.num_math_terms = None
|
| 49 |
self.math_terms = None
|
| 50 |
self.vocabulary_terms = None
|
| 51 |
+
self.on_task = None
|
| 52 |
|
| 53 |
# moments
|
| 54 |
self.uptake = None
|
|
|
|
| 94 |
'questioning': True if self.question else False,
|
| 95 |
'uptake': True if self.uptake else False,
|
| 96 |
'focusingQuestion': True if self.focusing_question else False,
|
| 97 |
+
# Legacy alias for onTask below. On/off-task is not a talk moment;
|
| 98 |
+
# this key is kept only so already-stored analyses and older
|
| 99 |
+
# frontends keep working, and is retired in the UI.
|
| 100 |
+
'mathWord': bool(self.on_task) and self.on_task.get('label') == ON_TASK_LABEL
|
| 101 |
},
|
| 102 |
+
# On/off-task classification: a measure in its own right, alongside
|
| 103 |
+
# vocabulary. None means not classified (teacher utterance or empty text).
|
| 104 |
+
'onTask': None if self.on_task is None else self.on_task.get('label') == ON_TASK_LABEL,
|
| 105 |
'unitMeasure': self.unit_measure,
|
| 106 |
'aggregateUnitMeasure': self.aggregate_unit_measure,
|
| 107 |
'wordCount': self.word_count,
|
|
|
|
| 545 |
vocabulary_analyser = VocabularyAnalyser(str(glossary_path))
|
| 546 |
vocabulary_analyser.run_analysis(transcript)
|
| 547 |
del vocabulary_analyser
|
| 548 |
+
|
| 549 |
+
on_task_analyser = OnTaskAnalyser()
|
| 550 |
+
on_task_analyser.run_analysis(transcript, uptake_speaker=uptake_speaker)
|
| 551 |
+
del on_task_analyser
|
| 552 |
+
|
| 553 |
transcript.update_utterance_roles(uptake_speaker)
|
| 554 |
sorted_math_cloud, teacher_math_cloud, student_math_cloud = run_math_density(transcript)
|
| 555 |
transcript.calculate_aggregate_word_count()
|
measures/OnTaskAnalyser.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from transformers import pipeline
|
| 2 |
+
|
| 3 |
+
ON_TASK_MODEL = 'edsi-umd/on-task-bert'
|
| 4 |
+
ON_TASK_LABEL = 'on_task' # from the model's config.json id2label: {"0": "off_task", "1": "on_task"}
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
class OnTaskAnalyser:
|
| 8 |
+
def __init__(self, model_path=ON_TASK_MODEL, max_length=256):
|
| 9 |
+
self.pipe = pipeline("text-classification", model=model_path,
|
| 10 |
+
truncation=True, max_length=max_length)
|
| 11 |
+
|
| 12 |
+
def predict_one(self, text: str):
|
| 13 |
+
return self.pipe(text)[0] # {'label': ..., 'score': ...}
|
| 14 |
+
|
| 15 |
+
def run_analysis(self, transcript, uptake_speaker=None):
|
| 16 |
+
"""Mutate transcript utterances by setting on_task for student utterances."""
|
| 17 |
+
for utt in transcript.utterances:
|
| 18 |
+
if uptake_speaker is not None and utt.speaker == uptake_speaker:
|
| 19 |
+
continue # model trained on student utterances only
|
| 20 |
+
if not utt.text or not utt.text.strip():
|
| 21 |
+
continue
|
| 22 |
+
utt.on_task = self.predict_one(utt.text)
|
| 23 |
+
return transcript
|