Spaces:
Build error
Build error
Merge branch 'feature-wormhole' into 'vlad'
Browse files- README.md +1 -1
- app.py +45 -3
- mathtext_fastapi/curriculum_mapper.py +183 -0
- mathtext_fastapi/data/Rori_Framework_v1.xlsx +0 -0
- mathtext_fastapi/data/curriculum_framework_for_tests.xlsx +0 -0
- mathtext_fastapi/data/intent_classification_model.joblib +3 -0
- mathtext_fastapi/data/labeled_data.csv +144 -0
- mathtext_fastapi/data/text2int_results.csv +104 -91
- mathtext_fastapi/global_state_manager.py +23 -0
- mathtext_fastapi/intent_classification.py +52 -0
- mathtext_fastapi/nlu.py +96 -15
- mathtext_fastapi/v2_conversation_manager.py +257 -0
- requirements.txt +10 -7
- scripts/make_request.py +23 -15
README.md
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
---
|
2 |
-
title: Mathtext
|
3 |
emoji: 🐨
|
4 |
colorFrom: blue
|
5 |
colorTo: red
|
|
|
1 |
---
|
2 |
+
title: Mathtext Wormhole
|
3 |
emoji: 🐨
|
4 |
colorFrom: blue
|
5 |
colorTo: red
|
app.py
CHANGED
@@ -15,7 +15,9 @@ from pydantic import BaseModel
|
|
15 |
|
16 |
from mathtext_fastapi.logging import prepare_message_data_for_logging
|
17 |
from mathtext_fastapi.conversation_manager import manage_conversation_response
|
|
|
18 |
from mathtext_fastapi.nlu import evaluate_message_with_nlu
|
|
|
19 |
|
20 |
app = FastAPI()
|
21 |
|
@@ -53,7 +55,7 @@ def text2int_ep(content: Text = None):
|
|
53 |
return JSONResponse(content=content)
|
54 |
|
55 |
|
56 |
-
@app.post("/manager")
|
57 |
async def programmatic_message_manager(request: Request):
|
58 |
"""
|
59 |
Calls conversation management function to determine the next state
|
@@ -86,6 +88,46 @@ async def programmatic_message_manager(request: Request):
|
|
86 |
return JSONResponse(context)
|
87 |
|
88 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
89 |
@app.post("/nlu")
|
90 |
async def evaluate_user_message_with_nlu_api(request: Request):
|
91 |
""" Calls nlu evaluation and returns the nlu_response
|
@@ -95,8 +137,8 @@ async def evaluate_user_message_with_nlu_api(request: Request):
|
|
95 |
|
96 |
Output
|
97 |
- int_data_dict or sent_data_dict: dict - the type of NLU run and result
|
98 |
-
{'type':'integer', 'data': '8'}
|
99 |
-
{'type':'sentiment', 'data': 'negative'}
|
100 |
"""
|
101 |
data_dict = await request.json()
|
102 |
message_data = data_dict.get('message_data', '')
|
|
|
15 |
|
16 |
from mathtext_fastapi.logging import prepare_message_data_for_logging
|
17 |
from mathtext_fastapi.conversation_manager import manage_conversation_response
|
18 |
+
from mathtext_fastapi.v2_conversation_manager import manage_conversation_response
|
19 |
from mathtext_fastapi.nlu import evaluate_message_with_nlu
|
20 |
+
from mathtext_fastapi.nlu import run_intent_classification
|
21 |
|
22 |
app = FastAPI()
|
23 |
|
|
|
55 |
return JSONResponse(content=content)
|
56 |
|
57 |
|
58 |
+
@app.post("/v1/manager")
|
59 |
async def programmatic_message_manager(request: Request):
|
60 |
"""
|
61 |
Calls conversation management function to determine the next state
|
|
|
88 |
return JSONResponse(context)
|
89 |
|
90 |
|
91 |
+
@app.post("/v2/manager")
|
92 |
+
async def programmatic_message_manager(request: Request):
|
93 |
+
"""
|
94 |
+
Calls conversation management function to determine the next state
|
95 |
+
|
96 |
+
Input
|
97 |
+
request.body: dict - message data for the most recent user response
|
98 |
+
{
|
99 |
+
"author_id": "+47897891",
|
100 |
+
"contact_uuid": "j43hk26-2hjl-43jk-hnk2-k4ljl46j0ds09",
|
101 |
+
"author_type": "OWNER",
|
102 |
+
"message_body": "a test message",
|
103 |
+
"message_direction": "inbound",
|
104 |
+
"message_id": "ABJAK64jlk3-agjkl2QHFAFH",
|
105 |
+
"message_inserted_at": "2022-07-05T04:00:34.03352Z",
|
106 |
+
"message_updated_at": "2023-02-14T03:54:19.342950Z",
|
107 |
+
}
|
108 |
+
|
109 |
+
Output
|
110 |
+
context: dict - the information for the current state
|
111 |
+
{
|
112 |
+
"user": "47897891",
|
113 |
+
"state": "welcome-message-state",
|
114 |
+
"bot_message": "Welcome to Rori!",
|
115 |
+
"user_message": "",
|
116 |
+
"type": "ask"
|
117 |
+
}
|
118 |
+
"""
|
119 |
+
data_dict = await request.json()
|
120 |
+
context = manage_conversation_response(data_dict)
|
121 |
+
return JSONResponse(context)
|
122 |
+
|
123 |
+
|
124 |
+
@app.post("/intent-classification")
|
125 |
+
def intent_classification_ep(content: Text = None):
|
126 |
+
ml_response = run_intent_classification(content.content)
|
127 |
+
content = {"message": ml_response}
|
128 |
+
return JSONResponse(content=content)
|
129 |
+
|
130 |
+
|
131 |
@app.post("/nlu")
|
132 |
async def evaluate_user_message_with_nlu_api(request: Request):
|
133 |
""" Calls nlu evaluation and returns the nlu_response
|
|
|
137 |
|
138 |
Output
|
139 |
- int_data_dict or sent_data_dict: dict - the type of NLU run and result
|
140 |
+
{'type':'integer', 'data': '8', 'confidence': 0}
|
141 |
+
{'type':'sentiment', 'data': 'negative', 'confidence': 0.99}
|
142 |
"""
|
143 |
data_dict = await request.json()
|
144 |
message_data = data_dict.get('message_data', '')
|
mathtext_fastapi/curriculum_mapper.py
ADDED
@@ -0,0 +1,183 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import numpy as np
|
2 |
+
import pandas as pd
|
3 |
+
import re
|
4 |
+
|
5 |
+
from pathlib import Path
|
6 |
+
|
7 |
+
|
8 |
+
def read_and_preprocess_spreadsheet(file_name):
|
9 |
+
""" Creates a pandas dataframe from the curriculum overview spreadsheet """
|
10 |
+
DATA_DIR = Path(__file__).parent.parent / "mathtext_fastapi" / "data" / file_name
|
11 |
+
script_df = pd.read_excel(DATA_DIR, engine='openpyxl')
|
12 |
+
# Ensures the grade level columns are integers instead of floats
|
13 |
+
script_df.columns = script_df.columns[:2].tolist() + script_df.columns[2:11].astype(int).astype(str).tolist() + script_df.columns[11:].tolist()
|
14 |
+
script_df.fillna('', inplace=True)
|
15 |
+
return script_df
|
16 |
+
|
17 |
+
|
18 |
+
def extract_skill_code(skill):
|
19 |
+
""" Looks within a curricular skill description for its descriptive code
|
20 |
+
|
21 |
+
Input
|
22 |
+
- skill: str - a brief description of a curricular skill
|
23 |
+
|
24 |
+
>>> extract_skill_code('A3.3.4 - Solve inequalities')
|
25 |
+
'A3.3.4'
|
26 |
+
>>> extract_skill_code('A3.3.2 - Graph linear equations, and identify the x- and y-intercepts or the slope of a line')
|
27 |
+
'A3.3.2'
|
28 |
+
"""
|
29 |
+
pattern = r'[A-Z][0-9]\.\d+\.\d+'
|
30 |
+
result = re.search(pattern, skill)
|
31 |
+
return result.group()
|
32 |
+
|
33 |
+
|
34 |
+
def build_horizontal_transitions(script_df):
|
35 |
+
""" Build a list of transitional relationships within a curricular skill
|
36 |
+
|
37 |
+
Inputs
|
38 |
+
- script_df: pandas dataframe - an overview of the curriculum skills by grade level
|
39 |
+
|
40 |
+
Output
|
41 |
+
- horizontal_transitions: array of arrays - transition data with label, from state, and to state
|
42 |
+
|
43 |
+
>>> script_df = read_and_preprocess_spreadsheet('curriculum_framework_for_tests.xlsx')
|
44 |
+
>>> build_horizontal_transitions(script_df)
|
45 |
+
[['right', 'N1.1.1_G1', 'N1.1.1_G2'], ['right', 'N1.1.1_G2', 'N1.1.1_G3'], ['right', 'N1.1.1_G3', 'N1.1.1_G4'], ['right', 'N1.1.1_G4', 'N1.1.1_G5'], ['right', 'N1.1.1_G5', 'N1.1.1_G6'], ['left', 'N1.1.1_G6', 'N1.1.1_G5'], ['left', 'N1.1.1_G5', 'N1.1.1_G4'], ['left', 'N1.1.1_G4', 'N1.1.1_G3'], ['left', 'N1.1.1_G3', 'N1.1.1_G2'], ['left', 'N1.1.1_G2', 'N1.1.1_G1'], ['right', 'N1.1.2_G1', 'N1.1.2_G2'], ['right', 'N1.1.2_G2', 'N1.1.2_G3'], ['right', 'N1.1.2_G3', 'N1.1.2_G4'], ['right', 'N1.1.2_G4', 'N1.1.2_G5'], ['right', 'N1.1.2_G5', 'N1.1.2_G6'], ['left', 'N1.1.2_G6', 'N1.1.2_G5'], ['left', 'N1.1.2_G5', 'N1.1.2_G4'], ['left', 'N1.1.2_G4', 'N1.1.2_G3'], ['left', 'N1.1.2_G3', 'N1.1.2_G2'], ['left', 'N1.1.2_G2', 'N1.1.2_G1']]
|
46 |
+
"""
|
47 |
+
horizontal_transitions = []
|
48 |
+
for index, row in script_df.iterrows():
|
49 |
+
skill_code = extract_skill_code(row['Knowledge or Skill'])
|
50 |
+
|
51 |
+
rightward_matches = []
|
52 |
+
for i in range(9):
|
53 |
+
# Grade column
|
54 |
+
current_grade = i+1
|
55 |
+
if row[current_grade].lower().strip() == 'x':
|
56 |
+
rightward_matches.append(i)
|
57 |
+
|
58 |
+
for match in rightward_matches:
|
59 |
+
if rightward_matches[-1] != match:
|
60 |
+
horizontal_transitions.append([
|
61 |
+
"right",
|
62 |
+
f"{skill_code}_G{match}",
|
63 |
+
f"{skill_code}_G{match+1}"
|
64 |
+
])
|
65 |
+
|
66 |
+
leftward_matches = []
|
67 |
+
for i in reversed(range(9)):
|
68 |
+
current_grade = i
|
69 |
+
if row[current_grade].lower().strip() == 'x':
|
70 |
+
leftward_matches.append(i)
|
71 |
+
|
72 |
+
for match in leftward_matches:
|
73 |
+
if leftward_matches[0] != match:
|
74 |
+
horizontal_transitions.append([
|
75 |
+
"left",
|
76 |
+
f"{skill_code}_G{match}",
|
77 |
+
f"{skill_code}_G{match-1}"
|
78 |
+
])
|
79 |
+
|
80 |
+
return horizontal_transitions
|
81 |
+
|
82 |
+
|
83 |
+
def gather_all_vertical_matches(script_df):
|
84 |
+
""" Build a list of transitional relationships within a grade level across skills
|
85 |
+
|
86 |
+
Inputs
|
87 |
+
- script_df: pandas dataframe - an overview of the curriculum skills by grade level
|
88 |
+
|
89 |
+
Output
|
90 |
+
- all_matches: array of arrays - represents skills at each grade level
|
91 |
+
|
92 |
+
>>> script_df = read_and_preprocess_spreadsheet('curriculum_framework_for_tests.xlsx')
|
93 |
+
>>> gather_all_vertical_matches(script_df)
|
94 |
+
[['N1.1.1', '1'], ['N1.1.2', '1'], ['N1.1.1', '2'], ['N1.1.2', '2'], ['N1.1.1', '3'], ['N1.1.2', '3'], ['N1.1.1', '4'], ['N1.1.2', '4'], ['N1.1.1', '5'], ['N1.1.2', '5'], ['N1.1.1', '6'], ['N1.1.2', '6']]
|
95 |
+
"""
|
96 |
+
all_matches = []
|
97 |
+
columns = ['1', '2', '3', '4', '5', '6', '7', '8', '9']
|
98 |
+
|
99 |
+
for column in columns:
|
100 |
+
for index, value in script_df[column].iteritems():
|
101 |
+
row_num = index + 1
|
102 |
+
if value == 'x':
|
103 |
+
# Extract skill code
|
104 |
+
skill_code = extract_skill_code(
|
105 |
+
script_df['Knowledge or Skill'][row_num-1]
|
106 |
+
)
|
107 |
+
|
108 |
+
all_matches.append([skill_code, column])
|
109 |
+
return all_matches
|
110 |
+
|
111 |
+
|
112 |
+
def build_vertical_transitions(script_df):
|
113 |
+
""" Build a list of transitional relationships within a grade level across skills
|
114 |
+
|
115 |
+
Inputs
|
116 |
+
- script_df: pandas dataframe - an overview of the curriculum skills by grade level
|
117 |
+
|
118 |
+
Output
|
119 |
+
- vertical_transitions: array of arrays - transition data with label, from state, and to state
|
120 |
+
|
121 |
+
>>> script_df = read_and_preprocess_spreadsheet('curriculum_framework_for_tests.xlsx')
|
122 |
+
>>> build_vertical_transitions(script_df)
|
123 |
+
[['down', 'N1.1.1_G1', 'N1.1.2_G1'], ['down', 'N1.1.2_G1', 'N1.1.1_G1'], ['down', 'N1.1.1_G2', 'N1.1.2_G2'], ['down', 'N1.1.2_G2', 'N1.1.1_G2'], ['down', 'N1.1.1_G3', 'N1.1.2_G3'], ['down', 'N1.1.2_G3', 'N1.1.1_G3'], ['down', 'N1.1.1_G4', 'N1.1.2_G4'], ['down', 'N1.1.2_G4', 'N1.1.1_G4'], ['down', 'N1.1.1_G5', 'N1.1.2_G5'], ['down', 'N1.1.2_G5', 'N1.1.1_G5'], ['down', 'N1.1.1_G6', 'N1.1.2_G6'], ['up', 'N1.1.2_G6', 'N1.1.1_G6'], ['up', 'N1.1.1_G6', 'N1.1.2_G6'], ['up', 'N1.1.2_G5', 'N1.1.1_G5'], ['up', 'N1.1.1_G5', 'N1.1.2_G5'], ['up', 'N1.1.2_G4', 'N1.1.1_G4'], ['up', 'N1.1.1_G4', 'N1.1.2_G4'], ['up', 'N1.1.2_G3', 'N1.1.1_G3'], ['up', 'N1.1.1_G3', 'N1.1.2_G3'], ['up', 'N1.1.2_G2', 'N1.1.1_G2'], ['up', 'N1.1.1_G2', 'N1.1.2_G2'], ['up', 'N1.1.2_G1', 'N1.1.1_G1']]
|
124 |
+
"""
|
125 |
+
vertical_transitions = []
|
126 |
+
|
127 |
+
all_matches = gather_all_vertical_matches(script_df)
|
128 |
+
|
129 |
+
# Downward
|
130 |
+
for index, match in enumerate(all_matches):
|
131 |
+
skill = match[0]
|
132 |
+
row_num = match[1]
|
133 |
+
if all_matches[-1] != match:
|
134 |
+
vertical_transitions.append([
|
135 |
+
"down",
|
136 |
+
f"{skill}_G{row_num}",
|
137 |
+
f"{all_matches[index+1][0]}_G{row_num}"
|
138 |
+
])
|
139 |
+
|
140 |
+
# Upward
|
141 |
+
for index, match in reversed(list(enumerate(all_matches))):
|
142 |
+
skill = match[0]
|
143 |
+
row_num = match[1]
|
144 |
+
if all_matches[0] != match:
|
145 |
+
vertical_transitions.append([
|
146 |
+
"up",
|
147 |
+
f"{skill}_G{row_num}",
|
148 |
+
f"{all_matches[index-1][0]}_G{row_num}"
|
149 |
+
])
|
150 |
+
|
151 |
+
return vertical_transitions
|
152 |
+
|
153 |
+
|
154 |
+
def build_all_states(all_transitions):
|
155 |
+
""" Creates an array with all state labels for the curriculum
|
156 |
+
|
157 |
+
Input
|
158 |
+
- all_transitions: list of lists - all possible up, down, left, or right transitions in curriculum
|
159 |
+
|
160 |
+
Output
|
161 |
+
- all_states: list - a collection of state labels (skill code and grade number)
|
162 |
+
|
163 |
+
>>> all_transitions = [['right', 'N1.1.1_G1', 'N1.1.1_G2'], ['right', 'N1.1.1_G2', 'N1.1.1_G3'], ['right', 'N1.1.1_G3', 'N1.1.1_G4'], ['right', 'N1.1.1_G4', 'N1.1.1_G5'], ['right', 'N1.1.1_G5', 'N1.1.1_G6'], ['left', 'N1.1.1_G6', 'N1.1.1_G5'], ['left', 'N1.1.1_G5', 'N1.1.1_G4'], ['left', 'N1.1.1_G4', 'N1.1.1_G3'], ['left', 'N1.1.1_G3', 'N1.1.1_G2'], ['left', 'N1.1.1_G2', 'N1.1.1_G1'], ['right', 'N1.1.2_G1', 'N1.1.2_G2'], ['right', 'N1.1.2_G2', 'N1.1.2_G3'], ['right', 'N1.1.2_G3', 'N1.1.2_G4'], ['right', 'N1.1.2_G4', 'N1.1.2_G5'], ['right', 'N1.1.2_G5', 'N1.1.2_G6'], ['left', 'N1.1.2_G6', 'N1.1.2_G5'], ['left', 'N1.1.2_G5', 'N1.1.2_G4'], ['left', 'N1.1.2_G4', 'N1.1.2_G3'], ['left', 'N1.1.2_G3', 'N1.1.2_G2'], ['left', 'N1.1.2_G2', 'N1.1.2_G1'], ['down', 'N1.1.1_G1', 'N1.1.2_G1'], ['down', 'N1.1.2_G1', 'N1.1.1_G1'], ['down', 'N1.1.1_G2', 'N1.1.2_G2'], ['down', 'N1.1.2_G2', 'N1.1.1_G2'], ['down', 'N1.1.1_G3', 'N1.1.2_G3'], ['down', 'N1.1.2_G3', 'N1.1.1_G3'], ['down', 'N1.1.1_G4', 'N1.1.2_G4'], ['down', 'N1.1.2_G4', 'N1.1.1_G4'], ['down', 'N1.1.1_G5', 'N1.1.2_G5'], ['down', 'N1.1.2_G5', 'N1.1.1_G5'], ['down', 'N1.1.1_G6', 'N1.1.2_G6'], ['up', 'N1.1.2_G6', 'N1.1.1_G6'], ['up', 'N1.1.1_G6', 'N1.1.2_G6'], ['up', 'N1.1.2_G5', 'N1.1.1_G5'], ['up', 'N1.1.1_G5', 'N1.1.2_G5'], ['up', 'N1.1.2_G4', 'N1.1.1_G4'], ['up', 'N1.1.1_G4', 'N1.1.2_G4'], ['up', 'N1.1.2_G3', 'N1.1.1_G3'], ['up', 'N1.1.1_G3', 'N1.1.2_G3'], ['up', 'N1.1.2_G2', 'N1.1.1_G2'], ['up', 'N1.1.1_G2', 'N1.1.2_G2'], ['up', 'N1.1.2_G1', 'N1.1.1_G1']]
|
164 |
+
>>> build_all_states(all_transitions)
|
165 |
+
['N1.1.1_G1', 'N1.1.1_G2', 'N1.1.1_G3', 'N1.1.1_G4', 'N1.1.1_G5', 'N1.1.1_G6', 'N1.1.2_G1', 'N1.1.2_G2', 'N1.1.2_G3', 'N1.1.2_G4', 'N1.1.2_G5', 'N1.1.2_G6']
|
166 |
+
"""
|
167 |
+
all_states = []
|
168 |
+
for transition in all_transitions:
|
169 |
+
for index, state in enumerate(transition):
|
170 |
+
if index == 0:
|
171 |
+
continue
|
172 |
+
if state not in all_states:
|
173 |
+
all_states.append(state)
|
174 |
+
return all_states
|
175 |
+
|
176 |
+
|
177 |
+
def build_curriculum_logic():
|
178 |
+
script_df = read_and_preprocess_spreadsheet('Rori_Framework_v1.xlsx')
|
179 |
+
horizontal_transitions = build_horizontal_transitions(script_df)
|
180 |
+
vertical_transitions = build_vertical_transitions(script_df)
|
181 |
+
all_transitions = horizontal_transitions + vertical_transitions
|
182 |
+
all_states = build_all_states(all_transitions)
|
183 |
+
return all_states, all_transitions
|
mathtext_fastapi/data/Rori_Framework_v1.xlsx
ADDED
Binary file (420 kB). View file
|
|
mathtext_fastapi/data/curriculum_framework_for_tests.xlsx
ADDED
Binary file (510 kB). View file
|
|
mathtext_fastapi/data/intent_classification_model.joblib
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:ea4954368c3b95673167ce347f2962b5508c4af295b6af58b6c11b3c1075b42e
|
3 |
+
size 127903
|
mathtext_fastapi/data/labeled_data.csv
ADDED
@@ -0,0 +1,144 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Utterance,Label
|
2 |
+
skip this,skip
|
3 |
+
this is stupid,skip
|
4 |
+
this is stupid,harder
|
5 |
+
this is stupid,feedback
|
6 |
+
I'm done,exit
|
7 |
+
quit,exit
|
8 |
+
I don't know,hint
|
9 |
+
help,hint
|
10 |
+
can I do something else?,main menu
|
11 |
+
what's going on,rapport
|
12 |
+
what's going on,main menu
|
13 |
+
tell me a joke,rapport
|
14 |
+
tell me a joke,main menu
|
15 |
+
Sorry I don't understand,do not know
|
16 |
+
Ten thousand,number
|
17 |
+
1.234,number
|
18 |
+
"10,000",number
|
19 |
+
"123, 456",numbers
|
20 |
+
"11, 12, 13",numbers
|
21 |
+
"100, 200, 300",numbers
|
22 |
+
"100, 200",numbers
|
23 |
+
Stop for a minute,wait
|
24 |
+
Bye bye,exit
|
25 |
+
Good night,exit
|
26 |
+
Am done,exit
|
27 |
+
Yes,yes
|
28 |
+
Help,help
|
29 |
+
Idiot,harder
|
30 |
+
Stop,exit
|
31 |
+
I don't get it,hint
|
32 |
+
Math,main menu
|
33 |
+
Math,math topic
|
34 |
+
Tomorrow let do math,wait
|
35 |
+
Later,wait
|
36 |
+
Pls i will continue pls,skip
|
37 |
+
Rori tell me now,help
|
38 |
+
harder,skip
|
39 |
+
Stop for now i wont to go to School,exit
|
40 |
+
Next,next
|
41 |
+
Okay,okay
|
42 |
+
Great,affirmation
|
43 |
+
Give me for example,example
|
44 |
+
No I want to learn algebraic expressions,algebra
|
45 |
+
Hi rori,greeting
|
46 |
+
*help*,help
|
47 |
+
*Next*,next
|
48 |
+
Okay nice,okay
|
49 |
+
I don't know it,hint
|
50 |
+
Nex,next
|
51 |
+
I need a help,hint
|
52 |
+
Please can I ask your any math questions?,faq
|
53 |
+
The answer is 1,answer
|
54 |
+
The answer is 1,number
|
55 |
+
But 0.8 is also same as . 8 so I was actually right,I'm right
|
56 |
+
What is the number system?,faq
|
57 |
+
Ok thanks,thanks
|
58 |
+
I'm going to school now,exit
|
59 |
+
Let's move to another topic,main menu
|
60 |
+
"Ummanni saba
|
61 |
+
Kebena bara kana galmi keenya inni guddaan bilisummaa qofa #Gabrummaan_ammaan booda_gaha namni hundi bakka jiru irraa kutatee ka,ee jira obboleewwan goototni keenya jiran haqa Kebenaaf jechaa jiru Guraandhala 29 booda walabummaa keenya labsina Dhugaa qabna Ni injifanna *** . Naannoo giddu galeessa Itoophiyaatti #Kebenaan aanaa addaati Kun murtoo ummata Kebenaa hundaati",spam
|
62 |
+
Yes it,yes
|
63 |
+
U type fast,too fast
|
64 |
+
I mean your typing is fast,too fast
|
65 |
+
Why do u type so fast,too fast
|
66 |
+
Ur typing is fast,too fast
|
67 |
+
Can we go to a real work,harder
|
68 |
+
I know all this,harder
|
69 |
+
Answer this,preamble
|
70 |
+
Am tired,exit
|
71 |
+
This is not what I asked for,main menu
|
72 |
+
Bye,exit
|
73 |
+
😱😱😂😂😂😡😰😰😰😒,spam
|
74 |
+
Gbxbxbcbcbbcbchcbchc,spam
|
75 |
+
I want to solve math,math topic
|
76 |
+
Pleas let start with the fraction,fractions topic
|
77 |
+
Okey,okay
|
78 |
+
i need substraction,subtraction topic
|
79 |
+
Can you please stop with me,exit
|
80 |
+
Another one,next
|
81 |
+
Harder or easy,main menu
|
82 |
+
Hard or easier,main menu
|
83 |
+
Jump topic,menu
|
84 |
+
Got it,okay
|
85 |
+
I didn't understand,don't know
|
86 |
+
Don't understand,don't know
|
87 |
+
Excuse me pls,hint
|
88 |
+
Let stop for today,exit
|
89 |
+
Help and stop asking me stupid questions,
|
90 |
+
Ykay,okay
|
91 |
+
Not interested in solving this,menu
|
92 |
+
Stpo,exit
|
93 |
+
Hiiiiiii,greeting
|
94 |
+
Hi rori,greeting
|
95 |
+
I've done this things before,harder
|
96 |
+
Which number my phone number,
|
97 |
+
Unit,main menu
|
98 |
+
No ide,don't know
|
99 |
+
No ide,hint
|
100 |
+
No idea,don't know
|
101 |
+
🙈🤩😇🙏,spam
|
102 |
+
Thank u,thanks
|
103 |
+
Do you know programming,faq
|
104 |
+
Delete my number,unsubscribe
|
105 |
+
See u,exit
|
106 |
+
Can I go for break ??,wait
|
107 |
+
I wanna fuck,profanity
|
108 |
+
Enough of this nw,exit
|
109 |
+
Can we move to equations,equations
|
110 |
+
Do you know you are an idiot,insult
|
111 |
+
3 digit number,number
|
112 |
+
3 digit number,answer
|
113 |
+
Three digit number,confident answer
|
114 |
+
Three digit number,number
|
115 |
+
Good evening Rori,greeting
|
116 |
+
89 Next,answer
|
117 |
+
89 Next,number
|
118 |
+
3 digit number,answer
|
119 |
+
Three digit number,answer
|
120 |
+
This is too simple,harder
|
121 |
+
Am not a kid,harder
|
122 |
+
Hey Miss Roribcan you ask me some question from Secondary 2,greeting
|
123 |
+
Hey Miss Roribcan you ask me some question from Secondary 2,faq
|
124 |
+
Hey Miss Roribcan you ask me some question from Secondary 2,main menu
|
125 |
+
don't know,hint
|
126 |
+
don't know,easier
|
127 |
+
𝑴𝒂𝒕𝒉,math
|
128 |
+
Rori can you help me to gat value,
|
129 |
+
I called but u are not picking up,
|
130 |
+
0.3 answer,answer
|
131 |
+
Sorry rori was101,answer
|
132 |
+
Y is it 6,answer
|
133 |
+
Y is it 6,number
|
134 |
+
0.3 answer,number
|
135 |
+
Why 0.5,more explanation
|
136 |
+
Why 0.5,number
|
137 |
+
6\nNext,Next
|
138 |
+
How is the answer is 11,more explanation
|
139 |
+
How comes we have 11,more explanation
|
140 |
+
Yes 6,answer
|
141 |
+
Yes 6,number
|
142 |
+
6\nNext,number
|
143 |
+
How is the answer is 11,number
|
144 |
+
How comes we have 11,number
|
mathtext_fastapi/data/text2int_results.csv
CHANGED
@@ -1,92 +1,105 @@
|
|
1 |
input,output,text2int,score
|
2 |
-
notanumber,32202,32202,True
|
3 |
-
this is not a number,32202,32202,True
|
4 |
-
fourteen,14,14,True
|
5 |
-
forteen,14,14,True
|
6 |
-
one thousand four hundred ninety two,1492,1492,True
|
7 |
-
one thousand ninety two,1092,1092,True
|
8 |
-
Fourteen Hundred Ninety-Two,1492,1492,True
|
9 |
-
Fourteen Hundred,1400,1400,True
|
10 |
-
Ninety nine,99,99,True
|
11 |
-
fifteen thousand five hundred-sixty,15560,15560,True
|
12 |
-
three hundred fifty,350,350,True
|
13 |
-
one nine eight five,1985,1985,True
|
14 |
-
nineteen eighty-five,1985,1605,False
|
15 |
-
oh one,1,1,True
|
16 |
-
six oh 1,601,601,True
|
17 |
-
sex,6,6,True
|
18 |
-
six,6,6,True
|
19 |
-
eight oh,80,8,False
|
20 |
-
eighty,80,80,True
|
21 |
-
ate,8,1,False
|
22 |
-
double eight,88,
|
23 |
-
eight three seven five three O nine,8375309,
|
24 |
-
eight three seven five three oh nine,8375309,8375309,True
|
25 |
-
eight three seven five three zero nine,8375309,8375309,True
|
26 |
-
eight three seven five three oh ni-ee-ine,8375309,
|
27 |
-
two eight,28,16,False
|
28 |
-
seven oh eleven,7011,77,False
|
29 |
-
seven elevens,77,77,True
|
30 |
-
seven eleven,711,77,False
|
31 |
-
ninety nine oh five,9905,149,False
|
32 |
-
seven 0 seven 0 seven 0 seven,7070707,7070707,True
|
33 |
-
123 hundred,123000,223,False
|
34 |
-
5 o 5,505,
|
35 |
-
15 o 5,1505,
|
36 |
-
15-o 5,1505,
|
37 |
-
15 o-5,1505,
|
38 |
-
911-thousand,911000,911000,True
|
39 |
-
twenty-two twenty-two,2222,44,False
|
40 |
-
twenty-two twenty-twos,484,44,False
|
41 |
-
four eighty four,484,404,False
|
42 |
-
four eighties,320,72,False
|
43 |
-
four eighties and nine nineties,1130,243,False
|
44 |
-
ninety nine hundred and seventy seven,9977,276,False
|
45 |
-
seven thousands,7000,7000,True
|
46 |
-
2 hundreds,200,200,True
|
47 |
-
99 thousands and one,99001,99001,True
|
48 |
-
"forty-five thousand, seven hundred and nine",45709,1161,False
|
49 |
-
eighty eight hundred eighty,8880,268,False
|
50 |
-
a hundred hundred,10000,
|
51 |
-
a hundred thousand,100000,
|
52 |
-
a hundred million,100000000,
|
53 |
-
nineteen ninety nine,1999,1809,False
|
54 |
-
forteen twenty seven,1427,307,False
|
55 |
-
seventeen-thousand and seventy two,17072,17072,True
|
56 |
-
two hundred and nine,209,209,True
|
57 |
-
two thousand ten,2010,2010,True
|
58 |
-
two thousand and ten,2010,2010,True
|
59 |
-
twelve million,12000000,12000000,True
|
60 |
-
8 billion,8000000000,8000000000,True
|
61 |
-
twenty ten,2010,2010,True
|
62 |
-
thirty-two hundred,3200,3200,True
|
63 |
-
nine,9,9,True
|
64 |
-
forty two,42,42,True
|
65 |
-
1 2 three,123,123,True
|
66 |
-
fourtean,14,14,True
|
67 |
-
one tousand four hundred ninty two,1492,1492,True
|
68 |
-
Furteen Hundrd Ninety-Too,1492,1492,True
|
69 |
-
forrteen,14,14,True
|
70 |
-
sevnteen-thosand and seventy two,17072,17072,True
|
71 |
-
ninety nine hundred ad seventy seven,9977,
|
72 |
-
seven thusands,7000,7000,True
|
73 |
-
2 hunreds,200,200,True
|
74 |
-
99 tousands and one,99001,99001,True
|
75 |
-
eighty ate hundred eighty,8880,261,False
|
76 |
-
fourteen Hundred,1400,1400,True
|
77 |
-
8 Bilion,8000000000,8000000,False
|
78 |
-
one million three thousand one,1003001,1003001,True
|
79 |
-
four million nine thousand seven,4009007,4009007,True
|
80 |
-
two million five hundred thousand,2500000,2001500,False
|
81 |
-
two tousand ten,2010,2010,True
|
82 |
-
two thousand teen,2010,2007,False
|
83 |
-
tvelve milion,12000000,12000000,True
|
84 |
-
tventy ten,2010,2010,True
|
85 |
-
tirty-twoo hunred,3200,3200,True
|
86 |
-
sevn thoosands,7000,7000,True
|
87 |
-
five,5,5,True
|
88 |
-
ten,10,10,True
|
89 |
-
one two three and ten,12310,51,False
|
90 |
-
ONE MILLion three hunded and fiv,1000305,1000305,True
|
91 |
-
"50,500 and six",50506,50506,True
|
92 |
-
one_million_and_five,1000005,1000005,True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
input,output,text2int,score
|
2 |
+
notanumber,32202.0,32202.0,True
|
3 |
+
this is not a number,32202.0,32202.0,True
|
4 |
+
fourteen,14.0,14.0,True
|
5 |
+
forteen,14.0,14.0,True
|
6 |
+
one thousand four hundred ninety two,1492.0,1492.0,True
|
7 |
+
one thousand ninety two,1092.0,1092.0,True
|
8 |
+
Fourteen Hundred Ninety-Two,1492.0,1492.0,True
|
9 |
+
Fourteen Hundred,1400.0,1400.0,True
|
10 |
+
Ninety nine,99.0,99.0,True
|
11 |
+
fifteen thousand five hundred-sixty,15560.0,15560.0,True
|
12 |
+
three hundred fifty,350.0,350.0,True
|
13 |
+
one nine eight five,1985.0,1985.0,True
|
14 |
+
nineteen eighty-five,1985.0,1605.0,False
|
15 |
+
oh one,1.0,1.0,True
|
16 |
+
six oh 1,601.0,601.0,True
|
17 |
+
sex,6.0,6.0,True
|
18 |
+
six,6.0,6.0,True
|
19 |
+
eight oh,80.0,8.0,False
|
20 |
+
eighty,80.0,80.0,True
|
21 |
+
ate,8.0,1.0,False
|
22 |
+
double eight,88.0,8.0,False
|
23 |
+
eight three seven five three O nine,8375309.0,8375319.0,False
|
24 |
+
eight three seven five three oh nine,8375309.0,8375309.0,True
|
25 |
+
eight three seven five three zero nine,8375309.0,8375309.0,True
|
26 |
+
eight three seven five three oh ni-ee-ine,8375309.0,837530111.0,False
|
27 |
+
two eight,28.0,16.0,False
|
28 |
+
seven oh eleven,7011.0,77.0,False
|
29 |
+
seven elevens,77.0,77.0,True
|
30 |
+
seven eleven,711.0,77.0,False
|
31 |
+
ninety nine oh five,9905.0,149.0,False
|
32 |
+
seven 0 seven 0 seven 0 seven,7070707.0,7070707.0,True
|
33 |
+
123 hundred,123000.0,223.0,False
|
34 |
+
5 o 5,505.0,515.0,False
|
35 |
+
15 o 5,1505.0,21.0,False
|
36 |
+
15-o 5,1505.0,21.0,False
|
37 |
+
15 o-5,1505.0,21.0,False
|
38 |
+
911-thousand,911000.0,911000.0,True
|
39 |
+
twenty-two twenty-two,2222.0,44.0,False
|
40 |
+
twenty-two twenty-twos,484.0,44.0,False
|
41 |
+
four eighty four,484.0,404.0,False
|
42 |
+
four eighties,320.0,72.0,False
|
43 |
+
four eighties and nine nineties,1130.0,243.0,False
|
44 |
+
ninety nine hundred and seventy seven,9977.0,276.0,False
|
45 |
+
seven thousands,7000.0,7000.0,True
|
46 |
+
2 hundreds,200.0,200.0,True
|
47 |
+
99 thousands and one,99001.0,99001.0,True
|
48 |
+
"forty-five thousand, seven hundred and nine",45709.0,1161.0,False
|
49 |
+
eighty eight hundred eighty,8880.0,268.0,False
|
50 |
+
a hundred hundred,10000.0,100.0,False
|
51 |
+
a hundred thousand,100000.0,100.0,False
|
52 |
+
a hundred million,100000000.0,100.0,False
|
53 |
+
nineteen ninety nine,1999.0,1809.0,False
|
54 |
+
forteen twenty seven,1427.0,307.0,False
|
55 |
+
seventeen-thousand and seventy two,17072.0,17072.0,True
|
56 |
+
two hundred and nine,209.0,209.0,True
|
57 |
+
two thousand ten,2010.0,2010.0,True
|
58 |
+
two thousand and ten,2010.0,2010.0,True
|
59 |
+
twelve million,12000000.0,12000000.0,True
|
60 |
+
8 billion,8000000000.0,8000000000.0,True
|
61 |
+
twenty ten,2010.0,2010.0,True
|
62 |
+
thirty-two hundred,3200.0,3200.0,True
|
63 |
+
nine,9.0,9.0,True
|
64 |
+
forty two,42.0,42.0,True
|
65 |
+
1 2 three,123.0,123.0,True
|
66 |
+
fourtean,14.0,14.0,True
|
67 |
+
one tousand four hundred ninty two,1492.0,1492.0,True
|
68 |
+
Furteen Hundrd Ninety-Too,1492.0,1492.0,True
|
69 |
+
forrteen,14.0,14.0,True
|
70 |
+
sevnteen-thosand and seventy two,17072.0,17072.0,True
|
71 |
+
ninety nine hundred ad seventy seven,9977.0,90.0,False
|
72 |
+
seven thusands,7000.0,7000.0,True
|
73 |
+
2 hunreds,200.0,200.0,True
|
74 |
+
99 tousands and one,99001.0,99001.0,True
|
75 |
+
eighty ate hundred eighty,8880.0,261.0,False
|
76 |
+
fourteen Hundred,1400.0,1400.0,True
|
77 |
+
8 Bilion,8000000000.0,8000000.0,False
|
78 |
+
one million three thousand one,1003001.0,1003001.0,True
|
79 |
+
four million nine thousand seven,4009007.0,4009007.0,True
|
80 |
+
two million five hundred thousand,2500000.0,2001500.0,False
|
81 |
+
two tousand ten,2010.0,2010.0,True
|
82 |
+
two thousand teen,2010.0,2007.0,False
|
83 |
+
tvelve milion,12000000.0,12000000.0,True
|
84 |
+
tventy ten,2010.0,2010.0,True
|
85 |
+
tirty-twoo hunred,3200.0,3200.0,True
|
86 |
+
sevn thoosands,7000.0,7000.0,True
|
87 |
+
five,5.0,5.0,True
|
88 |
+
ten,10.0,10.0,True
|
89 |
+
one two three and ten,12310.0,51.0,False
|
90 |
+
ONE MILLion three hunded and fiv,1000305.0,1000305.0,True
|
91 |
+
"50,500 and six",50506.0,50506.0,True
|
92 |
+
one_million_and_five,1000005.0,1000005.0,True
|
93 |
+
2.0,2.0,2.0,True
|
94 |
+
4.5,4.5,4.5,True
|
95 |
+
12345.001,12345.001,12345.001,True
|
96 |
+
7..0,7.0,7.0,True
|
97 |
+
0.06,0.06,0.06,True
|
98 |
+
"0,25",0.25,25.0,False
|
99 |
+
o.45,0.45,32202.0,False
|
100 |
+
0.1.2,0.12,32202.0,False
|
101 |
+
0.00009,9e-05,9e-05,True
|
102 |
+
0.01.,0.01,0.01,True
|
103 |
+
I don't know 8,8.0,8.0,True
|
104 |
+
"You're wrong it's not 20, it's 45",45.0,20.0,False
|
105 |
+
I don't understand why it's 19,19.0,19.0,True
|
mathtext_fastapi/global_state_manager.py
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from transitions import Machine
|
2 |
+
from mathtext_fastapi.curriculum_mapper import build_curriculum_logic
|
3 |
+
|
4 |
+
all_states, all_transitions = build_curriculum_logic()
|
5 |
+
|
6 |
+
class GlobalStateManager(object):
|
7 |
+
states = all_states
|
8 |
+
|
9 |
+
transitions = all_transitions
|
10 |
+
|
11 |
+
def __init__(
|
12 |
+
self,
|
13 |
+
initial_state='N1.1.1_G1',
|
14 |
+
):
|
15 |
+
self.machine = Machine(
|
16 |
+
model=self,
|
17 |
+
states=GlobalStateManager.states,
|
18 |
+
transitions=GlobalStateManager.transitions,
|
19 |
+
initial=initial_state
|
20 |
+
)
|
21 |
+
|
22 |
+
|
23 |
+
curriculum = GlobalStateManager()
|
mathtext_fastapi/intent_classification.py
ADDED
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import numpy as np
|
2 |
+
import pandas as pd
|
3 |
+
|
4 |
+
from pathlib import Path
|
5 |
+
from sentence_transformers import SentenceTransformer
|
6 |
+
from sklearn.linear_model import LogisticRegression
|
7 |
+
from joblib import dump, load
|
8 |
+
|
9 |
+
def pickle_model(model):
|
10 |
+
DATA_DIR = Path(__file__).parent.parent / "mathtext_fastapi" / "data" / "intent_classification_model.joblib"
|
11 |
+
dump(model, DATA_DIR)
|
12 |
+
|
13 |
+
|
14 |
+
def create_intent_classification_model():
|
15 |
+
encoder = SentenceTransformer('all-MiniLM-L6-v2')
|
16 |
+
# path = list(Path.cwd().glob('*.csv'))
|
17 |
+
DATA_DIR = Path(__file__).parent.parent / "mathtext_fastapi" / "data" / "labeled_data.csv"
|
18 |
+
|
19 |
+
print("DATA_DIR")
|
20 |
+
print(f"{DATA_DIR}")
|
21 |
+
|
22 |
+
with open(f"{DATA_DIR}",'r', newline='', encoding='utf-8') as f:
|
23 |
+
df = pd.read_csv(f)
|
24 |
+
df = df[df.columns[:2]]
|
25 |
+
df = df.dropna()
|
26 |
+
X_explore = np.array([list(encoder.encode(x)) for x in df['Utterance']])
|
27 |
+
X = np.array([list(encoder.encode(x)) for x in df['Utterance']])
|
28 |
+
y = df['Label']
|
29 |
+
model = LogisticRegression(class_weight='balanced')
|
30 |
+
model.fit(X, y, sample_weight=None)
|
31 |
+
|
32 |
+
print("MODEL")
|
33 |
+
print(model)
|
34 |
+
|
35 |
+
pickle_model(model)
|
36 |
+
|
37 |
+
|
38 |
+
def retrieve_intent_classification_model():
|
39 |
+
DATA_DIR = Path(__file__).parent.parent / "mathtext_fastapi" / "data" / "intent_classification_model.joblib"
|
40 |
+
model = load(DATA_DIR)
|
41 |
+
return model
|
42 |
+
|
43 |
+
|
44 |
+
def predict_message_intent(message):
|
45 |
+
encoder = SentenceTransformer('all-MiniLM-L6-v2')
|
46 |
+
model = retrieve_intent_classification_model()
|
47 |
+
tokenized_utterance = np.array([list(encoder.encode(message))])
|
48 |
+
predicted_label = model.predict(tokenized_utterance)
|
49 |
+
predicted_probabilities = model.predict_proba(tokenized_utterance)
|
50 |
+
confidence_score = predicted_probabilities.max()
|
51 |
+
|
52 |
+
return {"type": "intent", "data": predicted_label[0], "confidence": confidence_score}
|
mathtext_fastapi/nlu.py
CHANGED
@@ -1,6 +1,8 @@
|
|
|
|
1 |
from mathtext_fastapi.logging import prepare_message_data_for_logging
|
2 |
from mathtext.sentiment import sentiment
|
3 |
from mathtext.text2int import text2int
|
|
|
4 |
import re
|
5 |
|
6 |
|
@@ -8,27 +10,41 @@ def build_nlu_response_object(type, data, confidence):
|
|
8 |
""" Turns nlu results into an object to send back to Turn.io
|
9 |
Inputs
|
10 |
- type: str - the type of nlu run (integer or sentiment-analysis)
|
11 |
-
- data: str - the student message
|
12 |
- confidence: - the nlu confidence score (sentiment) or '' (integer)
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
"""
|
14 |
return {'type': type, 'data': data, 'confidence': confidence}
|
15 |
|
16 |
|
17 |
-
def test_for_float_or_int(message_data, message_text):
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
|
24 |
|
25 |
def test_for_number_sequence(message_text_arr, message_data, message_text):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
nlu_response = {}
|
27 |
if all(ele.isdigit() for ele in message_text_arr):
|
28 |
nlu_response = build_nlu_response_object(
|
29 |
'integer',
|
30 |
','.join(message_text_arr),
|
31 |
-
|
32 |
)
|
33 |
prepare_message_data_for_logging(message_data, nlu_response)
|
34 |
return nlu_response
|
@@ -42,6 +58,9 @@ def run_text2int_on_each_list_item(message_text_arr):
|
|
42 |
|
43 |
Output
|
44 |
- student_response_arr: list - a set of integers (32202 for error code)
|
|
|
|
|
|
|
45 |
"""
|
46 |
student_response_arr = []
|
47 |
for student_response in message_text_arr:
|
@@ -51,12 +70,63 @@ def run_text2int_on_each_list_item(message_text_arr):
|
|
51 |
|
52 |
|
53 |
def run_sentiment_analysis(message_text):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
54 |
# TODO: Add intent labelling here
|
55 |
# TODO: Add logic to determine whether intent labeling or sentiment analysis is more appropriate (probably default to intent labeling)
|
56 |
return sentiment(message_text)
|
57 |
|
58 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
def evaluate_message_with_nlu(message_data):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
60 |
# Keeps system working with two different inputs - full and filtered @event object
|
61 |
try:
|
62 |
message_text = message_data['message_body']
|
@@ -73,20 +143,31 @@ def evaluate_message_with_nlu(message_data):
|
|
73 |
}
|
74 |
message_text = message_data['message_body']
|
75 |
|
|
|
|
|
|
|
|
|
|
|
76 |
number_api_resp = text2int(message_text.lower())
|
77 |
|
78 |
if number_api_resp == 32202:
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
85 |
else:
|
86 |
nlu_response = build_nlu_response_object(
|
87 |
'integer',
|
88 |
number_api_resp,
|
89 |
-
|
90 |
)
|
91 |
|
92 |
prepare_message_data_for_logging(message_data, nlu_response)
|
|
|
1 |
+
from fuzzywuzzy import fuzz
|
2 |
from mathtext_fastapi.logging import prepare_message_data_for_logging
|
3 |
from mathtext.sentiment import sentiment
|
4 |
from mathtext.text2int import text2int
|
5 |
+
from mathtext_fastapi.intent_classification import create_intent_classification_model, retrieve_intent_classification_model, predict_message_intent
|
6 |
import re
|
7 |
|
8 |
|
|
|
10 |
""" Turns nlu results into an object to send back to Turn.io
|
11 |
Inputs
|
12 |
- type: str - the type of nlu run (integer or sentiment-analysis)
|
13 |
+
- data: str/int - the student message
|
14 |
- confidence: - the nlu confidence score (sentiment) or '' (integer)
|
15 |
+
|
16 |
+
>>> build_nlu_response_object('integer', 8, 0)
|
17 |
+
{'type': 'integer', 'data': 8, 'confidence': 0}
|
18 |
+
|
19 |
+
>>> build_nlu_response_object('sentiment', 'POSITIVE', 0.99)
|
20 |
+
{'type': 'sentiment', 'data': 'POSITIVE', 'confidence': 0.99}
|
21 |
"""
|
22 |
return {'type': type, 'data': data, 'confidence': confidence}
|
23 |
|
24 |
|
25 |
+
# def test_for_float_or_int(message_data, message_text):
|
26 |
+
# nlu_response = {}
|
27 |
+
# if type(message_text) == int or type(message_text) == float:
|
28 |
+
# nlu_response = build_nlu_response_object('integer', message_text, '')
|
29 |
+
# prepare_message_data_for_logging(message_data, nlu_response)
|
30 |
+
# return nlu_response
|
31 |
|
32 |
|
33 |
def test_for_number_sequence(message_text_arr, message_data, message_text):
|
34 |
+
""" Determines if the student's message is a sequence of numbers
|
35 |
+
|
36 |
+
>>> 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')
|
37 |
+
{'type': 'integer', 'data': '1,2,3', 'confidence': 0}
|
38 |
+
|
39 |
+
>>> 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')
|
40 |
+
{}
|
41 |
+
"""
|
42 |
nlu_response = {}
|
43 |
if all(ele.isdigit() for ele in message_text_arr):
|
44 |
nlu_response = build_nlu_response_object(
|
45 |
'integer',
|
46 |
','.join(message_text_arr),
|
47 |
+
0
|
48 |
)
|
49 |
prepare_message_data_for_logging(message_data, nlu_response)
|
50 |
return nlu_response
|
|
|
58 |
|
59 |
Output
|
60 |
- student_response_arr: list - a set of integers (32202 for error code)
|
61 |
+
|
62 |
+
>>> run_text2int_on_each_list_item(['1','2','3'])
|
63 |
+
[1, 2, 3]
|
64 |
"""
|
65 |
student_response_arr = []
|
66 |
for student_response in message_text_arr:
|
|
|
70 |
|
71 |
|
72 |
def run_sentiment_analysis(message_text):
|
73 |
+
""" Evaluates the sentiment of a student message
|
74 |
+
|
75 |
+
>>> run_sentiment_analysis("I am tired")
|
76 |
+
[{'label': 'NEGATIVE', 'score': 0.9997807145118713}]
|
77 |
+
|
78 |
+
>>> run_sentiment_analysis("I am full of joy")
|
79 |
+
[{'label': 'POSITIVE', 'score': 0.999882698059082}]
|
80 |
+
"""
|
81 |
# TODO: Add intent labelling here
|
82 |
# TODO: Add logic to determine whether intent labeling or sentiment analysis is more appropriate (probably default to intent labeling)
|
83 |
return sentiment(message_text)
|
84 |
|
85 |
|
86 |
+
def run_intent_classification(message_text):
|
87 |
+
""" Process a student's message using basic fuzzy text comparison
|
88 |
+
|
89 |
+
>>> run_intent_classification("exit")
|
90 |
+
{'type': 'intent', 'data': 'exit', 'confidence': 1.0}
|
91 |
+
>>> run_intent_classification("exi")
|
92 |
+
{'type': 'intent', 'data': 'exit', 'confidence': 0.86}
|
93 |
+
>>> run_intent_classification("eas")
|
94 |
+
{'type': 'intent', 'data': '', 'confidence': 0}
|
95 |
+
>>> run_intent_classification("hard")
|
96 |
+
{'type': 'intent', 'data': '', 'confidence': 0}
|
97 |
+
>>> run_intent_classification("hardier")
|
98 |
+
{'type': 'intent', 'data': 'harder', 'confidence': 0.92}
|
99 |
+
"""
|
100 |
+
label = ''
|
101 |
+
ratio = 0
|
102 |
+
nlu_response = {'type': 'intent', 'data': label, 'confidence': ratio}
|
103 |
+
commands = [
|
104 |
+
'easier',
|
105 |
+
'exit',
|
106 |
+
'harder',
|
107 |
+
'hint',
|
108 |
+
'next',
|
109 |
+
'stop',
|
110 |
+
]
|
111 |
+
|
112 |
+
for command in commands:
|
113 |
+
ratio = fuzz.ratio(command, message_text.lower())
|
114 |
+
if ratio > 80:
|
115 |
+
nlu_response['data'] = command
|
116 |
+
nlu_response['confidence'] = ratio / 100
|
117 |
+
|
118 |
+
return nlu_response
|
119 |
+
|
120 |
+
|
121 |
def evaluate_message_with_nlu(message_data):
|
122 |
+
""" Process a student's message using NLU functions and send the result
|
123 |
+
|
124 |
+
>>> 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"})
|
125 |
+
{'type': 'integer', 'data': 8, 'confidence': 0}
|
126 |
+
|
127 |
+
>>> 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"})
|
128 |
+
{'type': 'sentiment', 'data': 'NEGATIVE', 'confidence': 0.9997807145118713}
|
129 |
+
"""
|
130 |
# Keeps system working with two different inputs - full and filtered @event object
|
131 |
try:
|
132 |
message_text = message_data['message_body']
|
|
|
143 |
}
|
144 |
message_text = message_data['message_body']
|
145 |
|
146 |
+
# Run intent classification only for keywords
|
147 |
+
intent_api_response = run_intent_classification(message_text)
|
148 |
+
if intent_api_response['data']:
|
149 |
+
return intent_api_response
|
150 |
+
|
151 |
number_api_resp = text2int(message_text.lower())
|
152 |
|
153 |
if number_api_resp == 32202:
|
154 |
+
# Run intent classification with logistic regression model
|
155 |
+
predicted_label = predict_message_intent(message_text)
|
156 |
+
if predicted_label['confidence'] > 0.01:
|
157 |
+
nlu_response = predicted_label
|
158 |
+
else:
|
159 |
+
# Run sentiment analysis
|
160 |
+
sentiment_api_resp = sentiment(message_text)
|
161 |
+
nlu_response = build_nlu_response_object(
|
162 |
+
'sentiment',
|
163 |
+
sentiment_api_resp[0]['label'],
|
164 |
+
sentiment_api_resp[0]['score']
|
165 |
+
)
|
166 |
else:
|
167 |
nlu_response = build_nlu_response_object(
|
168 |
'integer',
|
169 |
number_api_resp,
|
170 |
+
0
|
171 |
)
|
172 |
|
173 |
prepare_message_data_for_logging(message_data, nlu_response)
|
mathtext_fastapi/v2_conversation_manager.py
ADDED
@@ -0,0 +1,257 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import base64
|
2 |
+
import copy
|
3 |
+
import dill
|
4 |
+
import os
|
5 |
+
import json
|
6 |
+
import jsonpickle
|
7 |
+
import pickle
|
8 |
+
import random
|
9 |
+
import requests
|
10 |
+
import mathtext_fastapi.global_state_manager as gsm
|
11 |
+
|
12 |
+
from dotenv import load_dotenv
|
13 |
+
from mathtext_fastapi.nlu import evaluate_message_with_nlu
|
14 |
+
from mathtext_fastapi.math_quiz_fsm import MathQuizFSM
|
15 |
+
from mathtext_fastapi.math_subtraction_fsm import MathSubtractionFSM
|
16 |
+
from supabase import create_client
|
17 |
+
from transitions import Machine
|
18 |
+
|
19 |
+
from scripts.quiz.generators import start_interactive_math
|
20 |
+
from scripts.quiz.hints import generate_hint
|
21 |
+
|
22 |
+
load_dotenv()
|
23 |
+
|
24 |
+
SUPA = create_client(
|
25 |
+
os.environ.get('SUPABASE_URL'),
|
26 |
+
os.environ.get('SUPABASE_KEY')
|
27 |
+
)
|
28 |
+
|
29 |
+
|
30 |
+
def pickle_and_encode_state_machine(state_machine):
|
31 |
+
dump = pickle.dumps(state_machine)
|
32 |
+
dump_encoded = base64.b64encode(dump).decode('utf-8')
|
33 |
+
return dump_encoded
|
34 |
+
|
35 |
+
|
36 |
+
def manage_math_quiz_fsm(user_message, contact_uuid, type):
|
37 |
+
fsm_check = SUPA.table('state_machines').select("*").eq(
|
38 |
+
"contact_uuid",
|
39 |
+
contact_uuid
|
40 |
+
).execute()
|
41 |
+
|
42 |
+
# This doesn't allow for when one FSM is present and the other is empty
|
43 |
+
"""
|
44 |
+
1
|
45 |
+
data=[] count=None
|
46 |
+
|
47 |
+
2
|
48 |
+
data=[{'id': 29, 'contact_uuid': 'j43hk26-2hjl-43jk-hnk2-k4ljl46j0ds09', 'addition3': None, 'subtraction': None, 'addition':
|
49 |
+
|
50 |
+
- but problem is there is no subtraction , but it's assuming there's a subtration
|
51 |
+
|
52 |
+
Cases
|
53 |
+
- make a completely new record
|
54 |
+
- update an existing record with an existing FSM
|
55 |
+
- update an existing record without an existing FSM
|
56 |
+
"""
|
57 |
+
print("MATH QUIZ FSM ACTIVITY")
|
58 |
+
print("user_message")
|
59 |
+
print(user_message)
|
60 |
+
# Make a completely new entry
|
61 |
+
if fsm_check.data == []:
|
62 |
+
if type == 'addition':
|
63 |
+
math_quiz_state_machine = MathQuizFSM()
|
64 |
+
else:
|
65 |
+
math_quiz_state_machine = MathSubtractionFSM()
|
66 |
+
messages = [math_quiz_state_machine.response_text]
|
67 |
+
dump_encoded = pickle_and_encode_state_machine(math_quiz_state_machine)
|
68 |
+
|
69 |
+
SUPA.table('state_machines').insert({
|
70 |
+
'contact_uuid': contact_uuid,
|
71 |
+
f'{type}': dump_encoded
|
72 |
+
}).execute()
|
73 |
+
# Update an existing record with a new state machine
|
74 |
+
elif not fsm_check.data[0][type]:
|
75 |
+
if type == 'addition':
|
76 |
+
math_quiz_state_machine = MathQuizFSM()
|
77 |
+
else:
|
78 |
+
math_quiz_state_machine = MathSubtractionFSM()
|
79 |
+
messages = [math_quiz_state_machine.response_text]
|
80 |
+
dump_encoded = pickle_and_encode_state_machine(math_quiz_state_machine)
|
81 |
+
|
82 |
+
SUPA.table('state_machines').update({
|
83 |
+
f'{type}': dump_encoded
|
84 |
+
}).eq(
|
85 |
+
"contact_uuid", contact_uuid
|
86 |
+
).execute()
|
87 |
+
# Update an existing record with an existing state machine
|
88 |
+
elif fsm_check.data[0][type]:
|
89 |
+
undump_encoded = base64.b64decode(
|
90 |
+
fsm_check.data[0][type].encode('utf-8')
|
91 |
+
)
|
92 |
+
math_quiz_state_machine = pickle.loads(undump_encoded)
|
93 |
+
|
94 |
+
math_quiz_state_machine.student_answer = user_message
|
95 |
+
math_quiz_state_machine.correct_answer = str(math_quiz_state_machine.correct_answer)
|
96 |
+
messages = math_quiz_state_machine.validate_answer()
|
97 |
+
dump_encoded = pickle_and_encode_state_machine(math_quiz_state_machine)
|
98 |
+
SUPA.table('state_machines').update({
|
99 |
+
f'{type}': dump_encoded
|
100 |
+
}).eq(
|
101 |
+
"contact_uuid", contact_uuid
|
102 |
+
).execute()
|
103 |
+
return messages
|
104 |
+
|
105 |
+
|
106 |
+
def retrieve_microlesson_content(context_data, user_message, microlesson, contact_uuid):
|
107 |
+
if context_data['local_state'] == 'addition-question-sequence' or \
|
108 |
+
user_message == 'add' or \
|
109 |
+
microlesson == 'addition':
|
110 |
+
messages = manage_math_quiz_fsm(user_message, contact_uuid, 'addition')
|
111 |
+
|
112 |
+
if user_message == 'exit':
|
113 |
+
state_label = 'exit'
|
114 |
+
else:
|
115 |
+
state_label = 'addition-question-sequence'
|
116 |
+
|
117 |
+
input_prompt = messages.pop()
|
118 |
+
message_package = {
|
119 |
+
'messages': messages,
|
120 |
+
'input_prompt': input_prompt,
|
121 |
+
'state': state_label
|
122 |
+
}
|
123 |
+
elif context_data['local_state'] == 'subtraction-question-sequence' or \
|
124 |
+
user_message == 'subtract' or \
|
125 |
+
microlesson == 'subtraction':
|
126 |
+
messages = manage_math_quiz_fsm(user_message, contact_uuid, 'subtraction')
|
127 |
+
|
128 |
+
if user_message == 'exit':
|
129 |
+
state_label = 'exit'
|
130 |
+
else:
|
131 |
+
state_label = 'subtraction-question-sequence'
|
132 |
+
|
133 |
+
input_prompt = messages.pop()
|
134 |
+
|
135 |
+
message_package = {
|
136 |
+
'messages': messages,
|
137 |
+
'input_prompt': input_prompt,
|
138 |
+
'state': state_label
|
139 |
+
}
|
140 |
+
print("MICROLESSON CONTENT RESPONSE")
|
141 |
+
print(message_package)
|
142 |
+
return message_package
|
143 |
+
|
144 |
+
|
145 |
+
curriculum_lookup_table = {
|
146 |
+
'N1.1.1_G1': 'addition',
|
147 |
+
'N1.1.1_G2': 'subtraction'
|
148 |
+
}
|
149 |
+
|
150 |
+
|
151 |
+
def lookup_local_state(next_state):
|
152 |
+
microlesson = curriculum_lookup_table[next_state]
|
153 |
+
return microlesson
|
154 |
+
|
155 |
+
|
156 |
+
def create_text_message(message_text, whatsapp_id):
|
157 |
+
""" Fills a template with input values to send a text message to Whatsapp
|
158 |
+
|
159 |
+
Inputs
|
160 |
+
- message_text: str - the content that the message should display
|
161 |
+
- whatsapp_id: str - the message recipient's phone number
|
162 |
+
|
163 |
+
Outputs
|
164 |
+
- message_data: dict - a preformatted template filled with inputs
|
165 |
+
"""
|
166 |
+
message_data = {
|
167 |
+
"preview_url": False,
|
168 |
+
"recipient_type": "individual",
|
169 |
+
"to": whatsapp_id,
|
170 |
+
"type": "text",
|
171 |
+
"text": {
|
172 |
+
"body": message_text
|
173 |
+
}
|
174 |
+
}
|
175 |
+
return message_data
|
176 |
+
|
177 |
+
|
178 |
+
def manage_conversation_response(data_json):
|
179 |
+
""" Calls functions necessary to determine message and context data """
|
180 |
+
print("V2 ENDPOINT")
|
181 |
+
|
182 |
+
user_message = ''
|
183 |
+
# whatsapp_id = data_json['author_id']
|
184 |
+
message_data = data_json['message_data']
|
185 |
+
context_data = data_json['context_data']
|
186 |
+
whatsapp_id = message_data['author_id']
|
187 |
+
print("MESSAGE DATA")
|
188 |
+
print(message_data)
|
189 |
+
print("CONTEXT DATA")
|
190 |
+
print(context_data)
|
191 |
+
print("=================")
|
192 |
+
|
193 |
+
# nlu_response = evaluate_message_with_nlu(message_data)
|
194 |
+
|
195 |
+
# context_data = {
|
196 |
+
# 'contact_uuid': 'abcdefg',
|
197 |
+
# 'current_state': 'N1.1.1_G2',
|
198 |
+
# 'user_message': '1',
|
199 |
+
# 'local_state': ''
|
200 |
+
# }
|
201 |
+
print("STEP 1")
|
202 |
+
print(data_json)
|
203 |
+
if not context_data['current_state']:
|
204 |
+
context_data['current_state'] = 'N1.1.1_G1'
|
205 |
+
|
206 |
+
curriculum_copy = copy.deepcopy(gsm.curriculum)
|
207 |
+
|
208 |
+
print("STEP 2")
|
209 |
+
if context_data['user_message'] == 'easier':
|
210 |
+
curriculum_copy.left()
|
211 |
+
next_state = curriculum_copy.state
|
212 |
+
elif context_data['user_message'] == 'harder':
|
213 |
+
curriculum_copy.right()
|
214 |
+
next_state = curriculum_copy.state
|
215 |
+
else:
|
216 |
+
next_state = context_data['current_state']
|
217 |
+
|
218 |
+
print("STEP 3")
|
219 |
+
microlesson = lookup_local_state(next_state)
|
220 |
+
|
221 |
+
print("microlesson")
|
222 |
+
print(microlesson)
|
223 |
+
|
224 |
+
microlesson_content = retrieve_microlesson_content(context_data, context_data['user_message'], microlesson, context_data['contact_uuid'])
|
225 |
+
|
226 |
+
headers = {
|
227 |
+
'Authorization': f"Bearer {os.environ.get('TURN_AUTHENTICATION_TOKEN')}",
|
228 |
+
'Content-Type': 'application/json'
|
229 |
+
}
|
230 |
+
|
231 |
+
# Send all messages for the current state before a user input prompt (text/button input request)
|
232 |
+
for message in microlesson_content['messages']:
|
233 |
+
data = create_text_message(message, whatsapp_id)
|
234 |
+
|
235 |
+
print("data")
|
236 |
+
print(data)
|
237 |
+
|
238 |
+
r = requests.post(
|
239 |
+
f'https://whatsapp.turn.io/v1/messages',
|
240 |
+
data=json.dumps(data),
|
241 |
+
headers=headers
|
242 |
+
)
|
243 |
+
|
244 |
+
print("STEP 4")
|
245 |
+
# combine microlesson content and context_data object
|
246 |
+
|
247 |
+
updated_context = {
|
248 |
+
"context": {
|
249 |
+
"contact_id": whatsapp_id,
|
250 |
+
"contact_uuid": context_data['contact_uuid'],
|
251 |
+
"state": microlesson_content['state'],
|
252 |
+
"bot_message": microlesson_content['input_prompt'],
|
253 |
+
"user_message": user_message,
|
254 |
+
"type": 'ask'
|
255 |
+
}
|
256 |
+
}
|
257 |
+
return updated_context
|
requirements.txt
CHANGED
@@ -1,12 +1,15 @@
|
|
1 |
dill
|
2 |
-
en-core-web-sm @ https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-3.4.1/en_core_web_sm-3.4.1-py3-none-any.whl
|
|
|
3 |
jsonpickle
|
4 |
-
git+
|
5 |
-
|
6 |
-
|
7 |
-
pydantic
|
8 |
-
|
9 |
-
|
|
|
|
|
10 |
supabase
|
11 |
transitions
|
12 |
uvicorn
|
|
|
1 |
dill
|
2 |
+
en-core-web-sm @ https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-3.4.1/en_core_web_sm-3.4.1-py3-none-any.whl
|
3 |
+
fuzzywuzzy
|
4 |
jsonpickle
|
5 |
+
mathtext @ git+https://gitlab.com/tangibleai/community/mathtext@main
|
6 |
+
fastapi==0.74.*
|
7 |
+
openpyxl
|
8 |
+
pydantic==1.10.*
|
9 |
+
python-Levenshtein
|
10 |
+
requests==2.27.*
|
11 |
+
sentencepiece==0.1.*
|
12 |
+
sentence-transformers
|
13 |
supabase
|
14 |
transitions
|
15 |
uvicorn
|
scripts/make_request.py
CHANGED
@@ -22,7 +22,11 @@ def add_message_text_to_sample_object(message_text):
|
|
22 |
message_data = '{' + f'"author_id": "+57787919091", "author_type": "OWNER", "contact_uuid": "j43hk26-2hjl-43jk-hnk2-k4ljl46j0ds09", "message_body": "{message_text}", "message_direction": "inbound", "message_id": "4kl209sd0-a7b8-2hj3-8563-3hu4a89b32", "message_inserted_at": "2023-01-10T02:37:28.477940Z", "message_updated_at": "2023-01-10T02:37:28.487319Z"' + '}'
|
23 |
# context_data = '{' + '"user":"", "state":"addition-question-sequence", "bot_message":"", "user_message":"{message_text}"' + '}'
|
24 |
|
25 |
-
|
|
|
|
|
|
|
|
|
26 |
|
27 |
# context_data = '{' + '"user":"", "state":"addition-question-sequence", "bot_message":"", "user_message":"{message_text}","text": "What is 2+3?","question_numbers": [4,3],"right_answer": 7,"number_correct": 2, "number_incorrect": 0, "hints_used": 0, "level": "easy"' + '}'
|
28 |
|
@@ -44,7 +48,7 @@ def run_simulated_request(endpoint, sample_answer, context=None):
|
|
44 |
print(f"Case: {sample_answer}")
|
45 |
b_string = add_message_text_to_sample_object(sample_answer)
|
46 |
|
47 |
-
if endpoint == 'sentiment-analysis' or endpoint == 'text2int':
|
48 |
request = requests.post(
|
49 |
url=f'http://localhost:7860/{endpoint}',
|
50 |
json={'content': sample_answer}
|
@@ -58,21 +62,25 @@ def run_simulated_request(endpoint, sample_answer, context=None):
|
|
58 |
print(request)
|
59 |
|
60 |
|
|
|
|
|
61 |
# run_simulated_request('sentiment-analysis', 'I reject it')
|
62 |
# run_simulated_request('text2int', 'seven thousand nine hundred fifty seven')
|
63 |
-
run_simulated_request('nlu', 'test message')
|
64 |
-
run_simulated_request('nlu', 'eight')
|
65 |
-
run_simulated_request('nlu', 'is it 8')
|
66 |
-
run_simulated_request('nlu', 'can I know how its 0.5')
|
67 |
-
run_simulated_request('nlu', 'eight, nine, ten')
|
68 |
-
run_simulated_request('nlu', '8, 9, 10')
|
69 |
-
run_simulated_request('nlu', '8')
|
70 |
-
run_simulated_request('nlu', "I don't know")
|
71 |
-
run_simulated_request('nlu', "I don't know eight")
|
72 |
-
run_simulated_request('nlu', "I don't 9")
|
73 |
-
run_simulated_request('nlu', "0.2")
|
74 |
-
run_simulated_request('nlu', 'Today is a wonderful day')
|
75 |
-
run_simulated_request('nlu', 'IDK 5?')
|
|
|
|
|
76 |
# run_simulated_request('manager', '')
|
77 |
# run_simulated_request('manager', 'add')
|
78 |
# run_simulated_request('manager', 'subtract')
|
|
|
22 |
message_data = '{' + f'"author_id": "+57787919091", "author_type": "OWNER", "contact_uuid": "j43hk26-2hjl-43jk-hnk2-k4ljl46j0ds09", "message_body": "{message_text}", "message_direction": "inbound", "message_id": "4kl209sd0-a7b8-2hj3-8563-3hu4a89b32", "message_inserted_at": "2023-01-10T02:37:28.477940Z", "message_updated_at": "2023-01-10T02:37:28.487319Z"' + '}'
|
23 |
# context_data = '{' + '"user":"", "state":"addition-question-sequence", "bot_message":"", "user_message":"{message_text}"' + '}'
|
24 |
|
25 |
+
# V1
|
26 |
+
# context_data = '{' + '"user":"", "state":"start-conversation", "bot_message":"", "user_message":"{message_text}"' + '}'
|
27 |
+
|
28 |
+
#V2
|
29 |
+
context_data = '{' + '"contact_uuid": "j43hk26-2hjl-43jk-hnk2-k4ljl46j0ds09", "current_state":"", "local_state": "", "user_message":""' + '}'
|
30 |
|
31 |
# context_data = '{' + '"user":"", "state":"addition-question-sequence", "bot_message":"", "user_message":"{message_text}","text": "What is 2+3?","question_numbers": [4,3],"right_answer": 7,"number_correct": 2, "number_incorrect": 0, "hints_used": 0, "level": "easy"' + '}'
|
32 |
|
|
|
48 |
print(f"Case: {sample_answer}")
|
49 |
b_string = add_message_text_to_sample_object(sample_answer)
|
50 |
|
51 |
+
if endpoint == 'sentiment-analysis' or endpoint == 'text2int' or endpoint =='intent-classification':
|
52 |
request = requests.post(
|
53 |
url=f'http://localhost:7860/{endpoint}',
|
54 |
json={'content': sample_answer}
|
|
|
62 |
print(request)
|
63 |
|
64 |
|
65 |
+
# run_simulated_request('intent-classification', 'exit')
|
66 |
+
# run_simulated_request('intent-classification', "I'm not sure")
|
67 |
# run_simulated_request('sentiment-analysis', 'I reject it')
|
68 |
# run_simulated_request('text2int', 'seven thousand nine hundred fifty seven')
|
69 |
+
# run_simulated_request('nlu', 'test message')
|
70 |
+
# run_simulated_request('nlu', 'eight')
|
71 |
+
# run_simulated_request('nlu', 'is it 8')
|
72 |
+
# run_simulated_request('nlu', 'can I know how its 0.5')
|
73 |
+
# run_simulated_request('nlu', 'eight, nine, ten')
|
74 |
+
# run_simulated_request('nlu', '8, 9, 10')
|
75 |
+
# run_simulated_request('nlu', '8')
|
76 |
+
# run_simulated_request('nlu', "I don't know")
|
77 |
+
# run_simulated_request('nlu', "I don't know eight")
|
78 |
+
# run_simulated_request('nlu', "I don't 9")
|
79 |
+
# run_simulated_request('nlu', "0.2")
|
80 |
+
# run_simulated_request('nlu', 'Today is a wonderful day')
|
81 |
+
# run_simulated_request('nlu', 'IDK 5?')
|
82 |
+
run_simulated_request('v2/manager', '')
|
83 |
+
run_simulated_request('v2/manager', '5')
|
84 |
# run_simulated_request('manager', '')
|
85 |
# run_simulated_request('manager', 'add')
|
86 |
# run_simulated_request('manager', 'subtract')
|