Spaces:
Runtime error
Runtime error
File size: 7,565 Bytes
440b9c5 4177751 440b9c5 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
from fuzzywuzzy import fuzz
from mathtext_fastapi.logging import prepare_message_data_for_logging
from mathtext.sentiment import sentiment
from mathtext.text2int import text2int
from mathtext_fastapi.intent_classification import create_intent_classification_model, retrieve_intent_classification_model, predict_message_intent
import re
def build_nlu_response_object(type, data, confidence):
""" Turns nlu results into an object to send back to Turn.io
Inputs
- type: str - the type of nlu run (integer or sentiment-analysis)
- data: str/int - the student message
- confidence: - the nlu confidence score (sentiment) or '' (integer)
>>> build_nlu_response_object('integer', 8, 0)
{'type': 'integer', 'data': 8, 'confidence': 0}
>>> build_nlu_response_object('sentiment', 'POSITIVE', 0.99)
{'type': 'sentiment', 'data': 'POSITIVE', 'confidence': 0.99}
"""
return {'type': type, 'data': data, 'confidence': confidence}
# def test_for_float_or_int(message_data, message_text):
# nlu_response = {}
# if type(message_text) == int or type(message_text) == float:
# nlu_response = build_nlu_response_object('integer', message_text, '')
# prepare_message_data_for_logging(message_data, nlu_response)
# return nlu_response
def test_for_number_sequence(message_text_arr, message_data, message_text):
""" Determines if the student's message is a sequence of numbers
>>> test_for_number_sequence(['1','2','3'], {"author_id": "57787919091", "author_type": "OWNER", "contact_uuid": "df78gsdf78df", "message_body": "I am tired", "message_direction": "inbound", "message_id": "dfgha789789ag9ga", "message_inserted_at": "2023-01-10T02:37:28.487319Z", "message_updated_at": "2023-01-10T02:37:28.487319Z"}, '1, 2, 3')
{'type': 'integer', 'data': '1,2,3', 'confidence': 0}
>>> test_for_number_sequence(['a','b','c'], {"author_id": "57787919091", "author_type": "OWNER", "contact_uuid": "df78gsdf78df", "message_body": "I am tired", "message_direction": "inbound", "message_id": "dfgha789789ag9ga", "message_inserted_at": "2023-01-10T02:37:28.487319Z", "message_updated_at": "2023-01-10T02:37:28.487319Z"}, 'a, b, c')
{}
"""
nlu_response = {}
if all(ele.isdigit() for ele in message_text_arr):
nlu_response = build_nlu_response_object(
'integer',
','.join(message_text_arr),
0
)
prepare_message_data_for_logging(message_data, nlu_response)
return nlu_response
def run_text2int_on_each_list_item(message_text_arr):
""" Attempts to convert each list item to an integer
Input
- message_text_arr: list - a set of text extracted from the student message
Output
- student_response_arr: list - a set of integers (32202 for error code)
>>> run_text2int_on_each_list_item(['1','2','3'])
[1, 2, 3]
"""
student_response_arr = []
for student_response in message_text_arr:
int_api_resp = text2int(student_response.lower())
student_response_arr.append(int_api_resp)
return student_response_arr
def run_sentiment_analysis(message_text):
""" Evaluates the sentiment of a student message
>>> run_sentiment_analysis("I am tired")
[{'label': 'NEGATIVE', 'score': 0.9997807145118713}]
>>> run_sentiment_analysis("I am full of joy")
[{'label': 'POSITIVE', 'score': 0.999882698059082}]
"""
# TODO: Add intent labelling here
# TODO: Add logic to determine whether intent labeling or sentiment analysis is more appropriate (probably default to intent labeling)
return sentiment(message_text)
def run_intent_classification(message_text):
""" Process a student's message using basic fuzzy text comparison
>>> run_intent_classification("exit")
{'type': 'intent', 'data': 'exit', 'confidence': 1.0}
>>> run_intent_classification("exi")
{'type': 'intent', 'data': 'exit', 'confidence': 0.86}
>>> run_intent_classification("eas")
{'type': 'intent', 'data': '', 'confidence': 0}
>>> run_intent_classification("hard")
{'type': 'intent', 'data': '', 'confidence': 0}
>>> run_intent_classification("hardier")
{'type': 'intent', 'data': 'harder', 'confidence': 0.92}
"""
label = ''
ratio = 0
nlu_response = {'type': 'intent', 'data': label, 'confidence': ratio}
commands = [
'easier',
'exit',
'harder',
'hint',
'next',
'stop',
]
for command in commands:
ratio = fuzz.ratio(command, message_text.lower())
if ratio > 80:
nlu_response['data'] = command
nlu_response['confidence'] = ratio / 100
return nlu_response
def evaluate_message_with_nlu(message_data):
""" Process a student's message using NLU functions and send the result
>>> evaluate_message_with_nlu({"author_id": "57787919091", "author_type": "OWNER", "contact_uuid": "df78gsdf78df", "message_body": "8", "message_direction": "inbound", "message_id": "dfgha789789ag9ga", "message_inserted_at": "2023-01-10T02:37:28.487319Z", "message_updated_at": "2023-01-10T02:37:28.487319Z"})
{'type': 'integer', 'data': 8, 'confidence': 0}
>>> evaluate_message_with_nlu({"author_id": "57787919091", "author_type": "OWNER", "contact_uuid": "df78gsdf78df", "message_body": "I am tired", "message_direction": "inbound", "message_id": "dfgha789789ag9ga", "message_inserted_at": "2023-01-10T02:37:28.487319Z", "message_updated_at": "2023-01-10T02:37:28.487319Z"})
{'type': 'sentiment', 'data': 'NEGATIVE', 'confidence': 0.9997807145118713}
"""
# Keeps system working with two different inputs - full and filtered @event object
try:
message_text = message_data['message_body']
except KeyError:
message_data = {
'author_id': message_data['message']['_vnd']['v1']['chat']['owner'],
'author_type': message_data['message']['_vnd']['v1']['author']['type'],
'contact_uuid': message_data['message']['_vnd']['v1']['chat']['contact_uuid'],
'message_body': message_data['message']['text']['body'],
'message_direction': message_data['message']['_vnd']['v1']['direction'],
'message_id': message_data['message']['id'],
'message_inserted_at': message_data['message']['_vnd']['v1']['chat']['inserted_at'],
'message_updated_at': message_data['message']['_vnd']['v1']['chat']['updated_at'],
}
message_text = message_data['message_body']
# Run intent classification only for keywords
intent_api_response = run_intent_classification(message_text)
if intent_api_response['data']:
return intent_api_response
number_api_resp = text2int(message_text.lower())
if number_api_resp == 32202:
# Run intent classification with logistic regression model
predicted_label = predict_message_intent(message_text)
if predicted_label['confidence'] > 0.01:
nlu_response = predicted_label
else:
# Run sentiment analysis
sentiment_api_resp = sentiment(message_text)
nlu_response = build_nlu_response_object(
'sentiment',
sentiment_api_resp[0]['label'],
sentiment_api_resp[0]['score']
)
else:
nlu_response = build_nlu_response_object(
'integer',
number_api_resp,
0
)
prepare_message_data_for_logging(message_data, nlu_response)
return nlu_response
|