Greg Thompson commited on
Commit
48c823d
1 Parent(s): d7c0eb6

Improve code modularity and style and incorporate nlu into wormhole prototype

Browse files
app.py CHANGED
@@ -11,8 +11,9 @@ from mathtext.sentiment import sentiment
11
  from mathtext.text2int import text2int
12
  from pydantic import BaseModel
13
 
14
- from mathtext_fastapi.nlu import prepare_message_data_for_logging
15
- from mathtext_fastapi.conversation_manager import *
 
16
 
17
  app = FastAPI()
18
 
@@ -85,7 +86,7 @@ async def programmatic_message_manager(request: Request):
85
 
86
  @app.post("/nlu")
87
  async def evaluate_user_message_with_nlu_api(request: Request):
88
- """ Calls NLU APIs on the most recent user message from Turn.io message data and logs the message data
89
 
90
  Input
91
  - request.body: a json object of message data for the most recent user response
@@ -96,45 +97,6 @@ async def evaluate_user_message_with_nlu_api(request: Request):
96
  {'type':'sentiment', 'data': 'negative'}
97
  """
98
  data_dict = await request.json()
99
-
100
  message_data = data_dict.get('message_data', '')
101
- message_text = message_data['message_body']
102
-
103
- # Handles if a student answer is already an integer or a float (ie., 8)
104
- if type(message_text) == int or type(message_text) == float:
105
- nlu_response = {'type': 'integer', 'data': message_text, 'confidence': ''}
106
- prepare_message_data_for_logging(message_data, nlu_response)
107
- return JSONResponse(content=nlu_response)
108
-
109
- # Removes whitespace and converts str to arr to handle multiple numbers
110
- message_text_arr = re.split(", |,| ", message_text.strip())
111
-
112
- # Handle if a student answer is a string of numbers (ie., "8,9, 10")
113
- if all(ele.isdigit() for ele in message_text_arr):
114
- nlu_response = {'type': 'integer', 'data': ','.join(message_text_arr), 'confidence': ''}
115
- prepare_message_data_for_logging(message_data, nlu_response)
116
- return JSONResponse(content=nlu_response)
117
-
118
- student_response_arr = []
119
-
120
- for student_response in message_text_arr:
121
- # Checks the student answer and returns an integer
122
-
123
- int_api_resp = text2int(student_response.lower())
124
- student_response_arr.append(int_api_resp)
125
-
126
- # '32202' is text2int's error code for non-integer student answers (ie., "I don't know")
127
- # If any part of the list is 32202, sentiment analysis will run
128
- if 32202 in student_response_arr:
129
- sentiment_api_resp = sentiment(message_text)
130
- # [{'label': 'POSITIVE', 'score': 0.991188645362854}]
131
- sent_data_dict = {'type': 'sentiment', 'data': sentiment_api_resp[0]['label']}
132
- nlu_response = {'type': 'sentiment', 'data': sentiment_api_resp[0]['label'], 'confidence': sentiment_api_resp[0]['score']}
133
- else:
134
- if len(student_response_arr) > 1:
135
- nlu_response = {'type': 'integer', 'data': ','.join(str(num) for num in student_response_arr), 'confidence': ''}
136
- else:
137
- nlu_response = {'type': 'integer', 'data': student_response_arr[0], 'confidence': ''}
138
-
139
- prepare_message_data_for_logging(message_data, nlu_response)
140
  return JSONResponse(content=nlu_response)
 
11
  from mathtext.text2int import text2int
12
  from pydantic import BaseModel
13
 
14
+ from mathtext_fastapi.logging import prepare_message_data_for_logging
15
+ from mathtext_fastapi.conversation_manager import manage_conversational_response
16
+ from mathtext_fastapi.nlu import evaluate_message_with_nlu
17
 
18
  app = FastAPI()
19
 
 
86
 
87
  @app.post("/nlu")
88
  async def evaluate_user_message_with_nlu_api(request: Request):
89
+ """ Calls the nlu evaluation function to run nlu functions and returns the nlu_response to Turn.io
90
 
91
  Input
92
  - request.body: a json object of message data for the most recent user response
 
97
  {'type':'sentiment', 'data': 'negative'}
98
  """
99
  data_dict = await request.json()
 
100
  message_data = data_dict.get('message_data', '')
101
+ nlu_response = evaluate_message_with_nlu(message_data)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
  return JSONResponse(content=nlu_response)
mathtext_fastapi/conversation_manager.py CHANGED
@@ -3,6 +3,7 @@ import json
3
  import requests
4
 
5
  from dotenv import load_dotenv
 
6
 
7
  load_dotenv()
8
 
@@ -161,6 +162,9 @@ def manage_conversational_response(data_json):
161
 
162
  whatsapp_id = message_data['author_id']
163
  user_message = message_data['message_body']
 
 
 
164
 
165
  message_package = return_next_conversational_state(context_data, user_message)
166
 
 
3
  import requests
4
 
5
  from dotenv import load_dotenv
6
+ from mathtext_fastapi.nlu import evaluate_message_with_nlu
7
 
8
  load_dotenv()
9
 
 
162
 
163
  whatsapp_id = message_data['author_id']
164
  user_message = message_data['message_body']
165
+
166
+ # TODO: Need to incorporate nlu_response into wormhole by checking answers against database (spreadsheet?)
167
+ nlu_response = evaluate_message_with_nlu(message_data)
168
 
169
  message_package = return_next_conversational_state(context_data, user_message)
170
 
mathtext_fastapi/logging.py ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from datetime import datetime
3
+
4
+ from dotenv import load_dotenv
5
+ from supabase import create_client
6
+
7
+ load_dotenv()
8
+
9
+ SUPA = create_client(os.environ.get('SUPABASE_URL'), os.environ.get('SUPABASE_KEY'))
10
+
11
+
12
+ def log_message_data_through_supabase_api(table_name, log_data):
13
+ return SUPA.table(table_name).insert(log_data).execute()
14
+
15
+
16
+ def format_datetime_in_isoformat(dt):
17
+ return getattr(dt.now(), 'isoformat', lambda x: None)()
18
+
19
+
20
+ def get_or_create_supabase_entry(table_name, insert_data, check_variable=None):
21
+ """ Checks whether a project or contact exists in the database and adds if one is not found
22
+
23
+ Input:
24
+ - table_name: str- the name of the table in Supabase that is being examined
25
+ - insert_data: json - the data to insert
26
+ - check_variable: str/None - the specific field to examine for existing matches
27
+
28
+ Result
29
+ - logged_data - an object with the Supabase data
30
+
31
+ """
32
+ if table_name == 'contact':
33
+ resp = SUPA.table('contact').select("*").eq("original_contact_id", insert_data['original_contact_id']).eq("project", insert_data['project']).execute()
34
+ else:
35
+ resp = SUPA.table(table_name).select("*").eq(check_variable, insert_data[check_variable]).execute()
36
+
37
+ if len(resp.data) == 0:
38
+ logged_data = log_message_data_through_supabase_api(table_name, insert_data)
39
+ else:
40
+ logged_data = resp
41
+ return logged_data
42
+
43
+
44
+
45
+ def prepare_message_data_for_logging(message_data, nlu_response):
46
+ """ Builds the message data for each table and ensures it's logged to the database
47
+
48
+ Input:
49
+ - message_data: an object with the full message data from Turn.io/Whatsapp
50
+ """
51
+ project_data = {
52
+ 'name': "Rori",
53
+ # Autogenerated fields: id, created_at, modified_at
54
+ }
55
+ project_data_log = get_or_create_supabase_entry('project', project_data, 'name')
56
+
57
+ contact_data = {
58
+ 'project': project_data_log.data[0]['id'], # FK
59
+ 'original_contact_id': message_data['contact_uuid'],
60
+ 'urn': "",
61
+ 'language_code': "en",
62
+ 'contact_inserted_at': format_datetime_in_isoformat(datetime.now())
63
+ # Autogenerated fields: id, created_at, modified_at
64
+ }
65
+ contact_data_log = get_or_create_supabase_entry('contact', contact_data)
66
+
67
+
68
+ del message_data['author_id']
69
+
70
+ message_data = {
71
+ 'contact': contact_data_log.data[0]['id'], # FK
72
+ 'original_message_id': message_data['message_id'],
73
+ 'text': message_data['message_body'],
74
+ 'direction': message_data['message_direction'],
75
+ 'sender_type': message_data['author_type'],
76
+ 'channel_type': "whatsapp / turn.io",
77
+ 'message_inserted_at': message_data['message_inserted_at'],
78
+ 'message_modified_at': message_data['message_updated_at'],
79
+ 'message_sent_at': format_datetime_in_isoformat(datetime.now()),
80
+ 'nlu_response': nlu_response,
81
+ 'request_object': message_data
82
+ # Autogenerated fields: created_at, modified_at
83
+ }
84
+ message_data_log = log_message_data_through_supabase_api('message', message_data)
mathtext_fastapi/nlu.py CHANGED
@@ -1,84 +1,87 @@
1
- import os
2
- from datetime import datetime
3
-
4
- from dotenv import load_dotenv
5
- from supabase import create_client
6
-
7
- load_dotenv()
8
-
9
- SUPA = create_client(os.environ.get('SUPABASE_URL'), os.environ.get('SUPABASE_KEY'))
 
 
 
 
 
10
 
11
 
12
- def log_message_data_through_supabase_api(table_name, log_data):
13
- return SUPA.table(table_name).insert(log_data).execute()
 
 
 
 
14
 
15
 
16
- def format_datetime_in_isoformat(dt):
17
- return getattr(dt.now(), 'isoformat', lambda x: None)()
 
 
 
 
18
 
19
 
20
- def get_or_create_supabase_entry(table_name, insert_data, check_variable=None):
21
- """ Checks whether a project or contact exists in the database and adds if one is not found
22
 
23
- Input:
24
- - table_name: str- the name of the table in Supabase that is being examined
25
- - insert_data: json - the data to insert
26
- - check_variable: str/None - the specific field to examine for existing matches
27
 
28
- Result
29
- - logged_data - an object with the Supabase data
30
-
31
  """
32
- if table_name == 'contact':
33
- resp = SUPA.table('contact').select("*").eq("original_contact_id", insert_data['original_contact_id']).eq("project", insert_data['project']).execute()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  else:
35
- resp = SUPA.table(table_name).select("*").eq(check_variable, insert_data[check_variable]).execute()
36
-
37
- if len(resp.data) == 0:
38
- logged_data = log_message_data_through_supabase_api(table_name, insert_data)
39
- else:
40
- logged_data = resp
41
- return logged_data
42
 
 
 
43
 
44
 
45
- def prepare_message_data_for_logging(message_data, nlu_response):
46
- """ Builds the message data for each table and ensures it's logged to the database
47
-
48
- Input:
49
- - message_data: an object with the full message data from Turn.io/Whatsapp
50
- """
51
- project_data = {
52
- 'name': "Rori",
53
- # Autogenerated fields: id, created_at, modified_at
54
- }
55
- project_data_log = get_or_create_supabase_entry('project', project_data, 'name')
56
-
57
- contact_data = {
58
- 'project': project_data_log.data[0]['id'], # FK
59
- 'original_contact_id': message_data['contact_uuid'],
60
- 'urn': "",
61
- 'language_code': "en",
62
- 'contact_inserted_at': format_datetime_in_isoformat(datetime.now())
63
- # Autogenerated fields: id, created_at, modified_at
64
- }
65
- contact_data_log = get_or_create_supabase_entry('contact', contact_data)
66
-
67
-
68
- del message_data['author_id']
69
-
70
- message_data = {
71
- 'contact': contact_data_log.data[0]['id'], # FK
72
- 'original_message_id': message_data['message_id'],
73
- 'text': message_data['message_body'],
74
- 'direction': message_data['message_direction'],
75
- 'sender_type': message_data['author_type'],
76
- 'channel_type': "whatsapp / turn.io",
77
- 'message_inserted_at': message_data['message_inserted_at'],
78
- 'message_modified_at': message_data['message_updated_at'],
79
- 'message_sent_at': format_datetime_in_isoformat(datetime.now()),
80
- 'nlu_response': nlu_response,
81
- 'request_object': message_data
82
- # Autogenerated fields: created_at, modified_at
83
- }
84
- message_data_log = log_message_data_through_supabase_api('message', message_data)
 
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
+
7
+ def build_nlu_response_object(type, data, confidence):
8
+ """ Builds a json object from the result of nlu functions 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. Integer is ''. Sentiment analysis is a float
13
+ """
14
+ return {'type': type, 'data': data, 'confidence': confidence}
15
 
16
 
17
+ def test_for_float_or_int(message_data, message_text):
18
+ nlu_response = {}
19
+ if type(message_text) == int or type(message_text) == float:
20
+ nlu_response = build_nlu_response_object('integer', message_text, '')
21
+ prepare_message_data_for_logging(message_data, nlu_response)
22
+ return nlu_response
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('integer', ','.join(message_text_arr), '')
29
+ prepare_message_data_for_logging(message_data, nlu_response)
30
+ return nlu_response
31
 
32
 
33
+ def run_text2int_on_each_list_item(message_text_arr):
34
+ """ Checks each item in an array to see if it can be converted to an integer
35
 
36
+ Input
37
+ - message_text_arr: list - a set of text extracted from the student message
 
 
38
 
39
+ Output
40
+ - student_response_arr: list - a set of integers derived from the nlu function
 
41
  """
42
+ student_response_arr = []
43
+ for student_response in message_text_arr:
44
+ int_api_resp = text2int(student_response.lower())
45
+ student_response_arr.append(int_api_resp)
46
+ return student_response_arr
47
+
48
+
49
+ def run_sentiment_analysis(message_text):
50
+ # TODO: Add intent labelling here
51
+ # TODO: Add logic to determine whether intent labeling or sentiment analysis is more appropriate (probably default to intent labeling)
52
+ return sentiment(message_text)
53
+
54
+
55
+ def evaluate_message_with_nlu(message_data):
56
+ message_text = message_data['message_body']
57
+ message_text_arr = re.split(", |,| ", message_text.strip())
58
+
59
+ # TODO: Replace this with appropriate utility function (is_int, is_float, render_int_or_float)
60
+ nlu_response = test_for_float_or_int(message_data, message_text)
61
+ if len(nlu_response) > 0:
62
+ return nlu_response
63
+
64
+ # TODO: Replace this with appropriate utility function
65
+ nlu_response = test_for_number_sequence(message_text_arr, message_data, message_text)
66
+ if len(nlu_response) > 0:
67
+ return nlu_response
68
+
69
+ student_response_arr = run_text2int_on_each_list_item(message_text_arr)
70
+
71
+ # '32202' is text2int's error code for non-integer student answers (ie., "I don't know")
72
+ # If any part of the list is 32202, sentiment analysis will run
73
+ # TODO: Need to replace this with logic that recognizes multiple intents (Maybe 36 = "sentiment analysis" & "integer")
74
+ student_response_arr = run_text2int_on_each_list_item(message_text_arr)
75
+ if 32202 in student_response_arr:
76
+ sentiment_api_resp = sentiment(message_text)
77
+ nlu_response = build_nlu_response_object('sentiment', sentiment_api_resp[0]['label'], sentiment_api_resp[0]['score'])
78
  else:
79
+ if len(student_response_arr) > 1:
80
+ nlu_response = build_nlu_response_object('integer', ','.join(str(num) for num in student_response_arr), '' )
81
+ else:
82
+ nlu_response = build_nlu_response_object('integer', student_response_arr[0], '')
 
 
 
83
 
84
+ prepare_message_data_for_logging(message_data, nlu_response)
85
+ return nlu_response
86
 
87
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
scripts/make_request.py CHANGED
@@ -1,144 +1,147 @@
 
1
  import requests
2
 
3
- # request = requests.post(url=
4
- # 'https://tangibleai-mathtext-fastapi.hf.space/sentiment-analysis',
5
- # json={"content": "I reject it"}).json()
6
-
7
- # print(request)
8
-
9
- # request = requests.post(url=
10
- # 'https://tangibleai-mathtext-fastapi.hf.space/text2int',
11
- # json={"content": "seven thousand nine hundred fifty seven"}
12
- # ).json()
13
-
14
- # print(request)
15
-
16
-
17
- # # json = {
18
- # # 'message': {
19
- # # '_vnd': {
20
- # # 'v1': {
21
- # # 'author': {
22
- # # 'id': 57787919091,
23
- # # 'name': 'GT',
24
- # # 'type': 'OWNER'
25
- # # },
26
- # # 'card_uuid': None,
27
- # # 'chat': {
28
- # # 'assigned_to': {
29
- # # 'id': 'jhk151kl-hj42-3752-3hjk-h4jk6hjkk2',
30
- # # 'name': 'Greg Thompson',
31
- # # 'type': 'OPERATOR'
32
- # # },
33
- # # 'contact_uuid': 'j43hk26-2hjl-43jk-hnk2-k4ljl46j0ds09',
34
- # # 'inserted_at': '2022-07-05T04:00:34.033522Z',
35
- # # 'owner': '+57787919091',
36
- # # 'permalink': 'https://app.turn.io/c/4kl209sd0-a7b8-2hj3-8563-3hu4a89b32',
37
- # # 'state': 'OPEN',
38
- # # 'state_reason': 'Re-opened by inbound message.',
39
- # # 'unread_count': 19,
40
- # # 'updated_at': '2023-01-10T02:37:28.487319Z',
41
- # # 'uuid': '4kl209sd0-a7b8-2hj3-8563-3hu4a89b32'
42
- # # },
43
- # # 'direction': 'inbound',
44
- # # 'faq_uuid': None,
45
- # # 'in_reply_to': None,
46
- # # 'inserted_at': '2023-01-10T02:37:28.477940Z',
47
- # # 'labels': [{
48
- # # 'confidence': 0.506479332,
49
- # # 'metadata': {
50
- # # 'nlu': {
51
- # # 'confidence': 0.506479332,
52
- # # 'intent': 'question',
53
- # # 'model_name': 'nlu-general-spacy-ngrams-20191014'
54
- # # }
55
- # # },
56
- # # 'uuid': 'ha7890s2k-hjk2-2476-s8d9-fh9779a8a9ds',
57
- # # 'value': 'Unclassified'
58
- # # }],
59
- # # 'last_status': None,
60
- # # 'last_status_timestamp': None,
61
- # # 'on_fallback_channel': False,
62
- # # 'rendered_content': None,
63
- # # 'uuid': 's8df79zhws-h89s-hj23-7s8d-thb248d9bh2qn'
64
- # # }
65
- # # },
66
- # # 'from': 57787919091,
67
- # # 'id': 'hsjkthzZGehkzs09sijWA3',
68
- # # 'text': {'body': 'eight'},
69
- # # 'timestamp': 1673318248,
70
- # # 'type': 'text'
71
- # # },
72
- # # 'type': 'message'
73
- # # }
74
-
75
- # json = b'{"message_data": {"message":{"_vnd":{"v1":{"author":{"id":57787919091,"name":"GT","type":"OWNER"},"card_uuid":null,"chat":{"assigned_to":{"id":"jhk151kl-hj42-3752-3hjk-h4jk6hjkk2","name":"Greg Thompson","type":"OPERATOR"},"contact_uuid":"j43hk26-2hjl-43jk-hnk2-k4ljl46j0ds09","inserted_at":"2022-07-05T04:00:34.033522Z","owner":"+57787919091","permalink":"https://app.turn.io/c/4kl209sd0-a7b8-2hj3-8563-3hu4a89b32","state":"OPEN","state_reason":"Re-opened by inbound message.","unread_count":14,"updated_at":"2023-01-10T02:37:28.487319Z","uuid":"4kl209sd0-a7b8-2hj3-8563-3hu4a89b32"},"direction":"inbound","faq_uuid":null,"in_reply_to":null,"inserted_at":"2023-01-10T02:37:28.477940Z","labels":[{"confidence":0.506479332,"metadata":{"nlu":{"confidence":0.506479332,"intent":"question","model_name":"nlu-general-spacy-ngrams-20191014"}},"uuid":"ha7890s2k-hjk2-2476-s8d9-fh9779a8a9ds","value":"Unclassified"}],"last_status":null,"last_status_timestamp":null,"on_fallback_channel":false,"rendered_content":null,"uuid":"s8df79zhws-h89s-hj23-7s8d-thb248d9bh2qn"}},"from":57787919091,"id":"hsjkthzZGehkzs09sijWA3","text":{"body":"eight"},"timestamp":1673318248,"type":"text"},"type":"message"}}\n'
76
-
77
- # # eight > 8
78
- # request = requests.post(url=
79
- # 'http://localhost:7860/nlu',
80
- # data=json
81
- # ).json()
82
- # print(request)
83
-
84
- # json2 = b'{"message_data": {"message":{"_vnd":{"v1":{"author":{"id":57787919091,"name":"GT","type":"OWNER"},"card_uuid":null,"chat":{"assigned_to":{"id":"jhk151kl-hj42-3752-3hjk-h4jk6hjkk2","name":"Greg Thompson","type":"OPERATOR"},"contact_uuid":"j43hk26-2hjl-43jk-hnk2-k4ljl46j0ds09","inserted_at":"2022-07-05T04:00:34.033522Z","owner":"+57787919091","permalink":"https://app.turn.io/c/4kl209sd0-a7b8-2hj3-8563-3hu4a89b32","state":"OPEN","state_reason":"Re-opened by inbound message.","unread_count":14,"updated_at":"2023-01-10T02:37:28.487319Z","uuid":"4kl209sd0-a7b8-2hj3-8563-3hu4a89b32"},"direction":"inbound","faq_uuid":null,"in_reply_to":null,"inserted_at":"2023-01-10T02:37:28.477940Z","labels":[{"confidence":0.506479332,"metadata":{"nlu":{"confidence":0.506479332,"intent":"question","model_name":"nlu-general-spacy-ngrams-20191014"}},"uuid":"ha7890s2k-hjk2-2476-s8d9-fh9779a8a9ds","value":"Unclassified"}],"last_status":null,"last_status_timestamp":null,"on_fallback_channel":false,"rendered_content":null,"uuid":"s8df79zhws-h89s-hj23-7s8d-thb248d9bh2qn"}},"from":57787919091,"id":"hsjkthzZGehkzs09sijWA3","text":{"body":"eight, nine, ten"},"timestamp":1673318248,"type":"text"},"type":"message"}}\n'
85
-
86
- # # "eight, nine, ten" > 8,9,10
87
- # request = requests.post(url=
88
- # 'http://localhost:7860/nlu',
89
- # data=json2
90
- # ).json()
91
-
92
- # print(request)
93
-
94
-
95
- # json = b'{"message_data": {"message":{"_vnd":{"v1":{"author":{"id":57787919091,"name":"GT","type":"OWNER"},"card_uuid":null,"chat":{"assigned_to":{"id":"jhk151kl-hj42-3752-3hjk-h4jk6hjkk2","name":"Greg Thompson","type":"OPERATOR"},"contact_uuid":"j43hk26-2hjl-43jk-hnk2-k4ljl46j0ds09","inserted_at":"2022-07-05T04:00:34.033522Z","owner":"+57787919091","permalink":"https://app.turn.io/c/4kl209sd0-a7b8-2hj3-8563-3hu4a89b32","state":"OPEN","state_reason":"Re-opened by inbound message.","unread_count":14,"updated_at":"2023-01-10T02:37:28.487319Z","uuid":"4kl209sd0-a7b8-2hj3-8563-3hu4a89b32"},"direction":"inbound","faq_uuid":null,"in_reply_to":null,"inserted_at":"2023-01-10T02:37:28.477940Z","labels":[{"confidence":0.506479332,"metadata":{"nlu":{"confidence":0.506479332,"intent":"question","model_name":"nlu-general-spacy-ngrams-20191014"}},"uuid":"ha7890s2k-hjk2-2476-s8d9-fh9779a8a9ds","value":"Unclassified"}],"last_status":null,"last_status_timestamp":null,"on_fallback_channel":false,"rendered_content":null,"uuid":"s8df79zhws-h89s-hj23-7s8d-thb248d9bh2qn"}},"from":57787919091,"id":"hsjkthzZGehkzs09sijWA3","text":{"body":8},"timestamp":1673318248,"type":"text"},"type":"message"}}\n'
96
-
97
- # # 8 > 8
98
- # request = requests.post(url=
99
- # 'http://localhost:7860/nlu',
100
- # data=json
101
- # ).json()
102
-
103
- # print(request)
104
-
105
- # json = b'{"message_data": {"message":{"_vnd":{"v1":{"author":{"id":57787919091,"name":"GT","type":"OWNER"},"card_uuid":null,"chat":{"assigned_to":{"id":"jhk151kl-hj42-3752-3hjk-h4jk6hjkk2","name":"Greg Thompson","type":"OPERATOR"},"contact_uuid":"j43hk26-2hjl-43jk-hnk2-k4ljl46j0ds09","inserted_at":"2022-07-05T04:00:34.033522Z","owner":"+57787919091","permalink":"https://app.turn.io/c/4kl209sd0-a7b8-2hj3-8563-3hu4a89b32","state":"OPEN","state_reason":"Re-opened by inbound message.","unread_count":14,"updated_at":"2023-01-10T02:37:28.487319Z","uuid":"4kl209sd0-a7b8-2hj3-8563-3hu4a89b32"},"direction":"inbound","faq_uuid":null,"in_reply_to":null,"inserted_at":"2023-01-10T02:37:28.477940Z","labels":[{"confidence":0.506479332,"metadata":{"nlu":{"confidence":0.506479332,"intent":"question","model_name":"nlu-general-spacy-ngrams-20191014"}},"uuid":"ha7890s2k-hjk2-2476-s8d9-fh9779a8a9ds","value":"Unclassified"}],"last_status":null,"last_status_timestamp":null,"on_fallback_channel":false,"rendered_content":null,"uuid":"s8df79zhws-h89s-hj23-7s8d-thb248d9bh2qn"}},"from":57787919091,"id":"hsjkthzZGehkzs09sijWA3","text":{"body":"8, 9, 10"},"timestamp":1673318248,"type":"text"},"type":"message"}}\n'
106
-
107
- # # "8, 9, 10" > "8,9,10"
108
- # request = requests.post(url=
109
- # 'http://localhost:7860/nlu',
110
- # data=json
111
- # ).json()
112
-
113
- # print(request)
114
-
115
- # json = b'{"message_data": {"message":{"_vnd":{"v1":{"author":{"id":57787919091,"name":"GT","type":"OWNER"},"card_uuid":null,"chat":{"assigned_to":{"id":"jhk151kl-hj42-3752-3hjk-h4jk6hjkk2","name":"Greg Thompson","type":"OPERATOR"},"contact_uuid":"j43hk26-2hjl-43jk-hnk2-k4ljl46j0ds09","inserted_at":"2022-07-05T04:00:34.033522Z","owner":"+57787919091","permalink":"https://app.turn.io/c/4kl209sd0-a7b8-2hj3-8563-3hu4a89b32","state":"OPEN","state_reason":"Re-opened by inbound message.","unread_count":14,"updated_at":"2023-01-10T02:37:28.487319Z","uuid":"4kl209sd0-a7b8-2hj3-8563-3hu4a89b32"},"direction":"inbound","faq_uuid":null,"in_reply_to":null,"inserted_at":"2023-01-10T02:37:28.477940Z","labels":[{"confidence":0.506479332,"metadata":{"nlu":{"confidence":0.506479332,"intent":"question","model_name":"nlu-general-spacy-ngrams-20191014"}},"uuid":"ha7890s2k-hjk2-2476-s8d9-fh9779a8a9ds","value":"Unclassified"}],"last_status":null,"last_status_timestamp":null,"on_fallback_channel":false,"rendered_content":null,"uuid":"s8df79zhws-h89s-hj23-7s8d-thb248d9bh2qn"}},"from":57787919091,"id":"hsjkthzZGehkzs09sijWA3","text":{"body":"I dont know"},"timestamp":1673318248,"type":"text"},"type":"message"}}\n'
116
-
117
- # # "8, 9, 10" > "8,9,10"
118
- # request = requests.post(url=
119
- # 'http://localhost:7860/nlu',
120
- # data=json
121
- # ).json()
122
-
123
- # print(request)
124
-
125
- # json = b'{"message_data": {"message":{"_vnd":{"v1":{"author":{"id":57787919091,"name":"GT","type":"OWNER"},"card_uuid":null,"chat":{"assigned_to":{"id":"jhk151kl-hj42-3752-3hjk-h4jk6hjkk2","name":"Greg Thompson","type":"OPERATOR"},"contact_uuid":"j43hk26-2hjl-43jk-hnk2-k4ljl46j0ds09","inserted_at":"2022-07-05T04:00:34.033522Z","owner":"+57787919091","permalink":"https://app.turn.io/c/4kl209sd0-a7b8-2hj3-8563-3hu4a89b32","state":"OPEN","state_reason":"Re-opened by inbound message.","unread_count":14,"updated_at":"2023-01-10T02:37:28.487319Z","uuid":"4kl209sd0-a7b8-2hj3-8563-3hu4a89b32"},"direction":"inbound","faq_uuid":null,"in_reply_to":null,"inserted_at":"2023-01-10T02:37:28.477940Z","labels":[{"confidence":0.506479332,"metadata":{"nlu":{"confidence":0.506479332,"intent":"question","model_name":"nlu-general-spacy-ngrams-20191014"}},"uuid":"ha7890s2k-hjk2-2476-s8d9-fh9779a8a9ds","value":"Unclassified"}],"last_status":null,"last_status_timestamp":null,"on_fallback_channel":false,"rendered_content":null,"uuid":"s8df79zhws-h89s-hj23-7s8d-thb248d9bh2qn"}},"from":57787919091,"id":"hsjkthzZGehkzs09sijWA3","text":{"body":"Today is a wonderful day"},"timestamp":1673318248,"type":"text"},"type":"message"}}\n'
126
-
127
- # # "8, 9, 10" > "8,9,10"
128
- # request = requests.post(url=
129
- # 'http://localhost:7860/nlu',
130
- # data=json
131
- # ).json()
132
-
133
- # print(request)
134
-
135
-
136
- json = b'{"context": "hi", "message_data": {"message":{"_vnd":{"v1":{"author":{"id":57787919091,"name":"GT","type":"OWNER"},"card_uuid":null,"chat":{"assigned_to":{"id":"jhk151kl-hj42-3752-3hjk-h4jk6hjkk2","name":"Greg Thompson","type":"OPERATOR"},"contact_uuid":"j43hk26-2hjl-43jk-hnk2-k4ljl46j0ds09","inserted_at":"2022-07-05T04:00:34.033522Z","owner":"+57787919091","permalink":"https://app.turn.io/c/4kl209sd0-a7b8-2hj3-8563-3hu4a89b32","state":"OPEN","state_reason":"Re-opened by inbound message.","unread_count":14,"updated_at":"2023-01-10T02:37:28.487319Z","uuid":"4kl209sd0-a7b8-2hj3-8563-3hu4a89b32"},"direction":"inbound","faq_uuid":null,"in_reply_to":null,"inserted_at":"2023-01-10T02:37:28.477940Z","labels":[{"confidence":0.506479332,"metadata":{"nlu":{"confidence":0.506479332,"intent":"question","model_name":"nlu-general-spacy-ngrams-20191014"}},"uuid":"ha7890s2k-hjk2-2476-s8d9-fh9779a8a9ds","value":"Unclassified"}],"last_status":null,"last_status_timestamp":null,"on_fallback_channel":false,"rendered_content":null,"uuid":"s8df79zhws-h89s-hj23-7s8d-thb248d9bh2qn"}},"from":57787919091,"id":"hsjkthzZGehkzs09sijWA3","text":{"body":"Today is a wonderful day"},"timestamp":1673318248,"type":"text"},"type":"message"}}\n'
137
-
138
-
139
-
140
- request = requests.post(url=
141
- 'http://localhost:7860/manager',
142
- data=json
143
- ).json()
144
- print(request)
 
 
 
1
+ import json
2
  import requests
3
 
4
+
5
+ def add_message_text_to_sample_object(message_text):
6
+ """
7
+ Builds a sample request object using an example of a student answer
8
+
9
+ Input
10
+ - message_text: str - an example of user input to test
11
+
12
+ Example Input
13
+ "test message"
14
+
15
+ Output
16
+ - b_string: json b-string - an object simulating what Turn.io sends to the API endpoint using the message_text
17
+
18
+ Example Output
19
+ b'{"context": "hi", "message_data": {"author_id": "+57787919091", "author_type": "OWNER", "contact_uuid": "j43hk26-2hjl-43jk-hnk2-k4ljl46j0ds09", "message_body": "test message", "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"}}'
20
+
21
+ """
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":"start-conversation", "bot_message":"", "user_message":"{message_text}"' + '}'
24
+
25
+ json_string = '{' + f'"context_data": {context_data}, "message_data": {message_data}' + '}'
26
+ b_string = json_string.encode("utf-8")
27
+
28
+ return b_string
29
+
30
+
31
+ def run_simulated_request(endpoint, sample_answer, context = None):
32
+ print(f"Case: {sample_answer}")
33
+ b_string = add_message_text_to_sample_object(sample_answer)
34
+
35
+ if endpoint == 'sentiment-analysis' or endpoint == 'text2int':
36
+ request = requests.post(url=
37
+ f'http://localhost:7860/{endpoint}',
38
+ json={'content': sample_answer}
39
+ ).json()
40
+ else:
41
+ request = requests.post(url=
42
+ f'http://localhost:7860/{endpoint}',
43
+ data=b_string
44
+ ).json()
45
+
46
+ print(request)
47
+
48
+ run_simulated_request('sentiment-analysis', 'I reject it')
49
+ run_simulated_request('text2int', 'seven thousand nine hundred fifty seven')
50
+ run_simulated_request('nlu', 'test message')
51
+ run_simulated_request('nlu', 'eight')
52
+ run_simulated_request('nlu', 'eight, nine, ten')
53
+ run_simulated_request('nlu', '8, 9, 10')
54
+ run_simulated_request('nlu', '8')
55
+ run_simulated_request('nlu', "I don't know")
56
+ run_simulated_request('nlu', 'Today is a wonderful day')
57
+ run_simulated_request('nlu', 'IDK 5?')
58
+ run_simulated_request('manager', '')
59
+ run_simulated_request('manager', 'add')
60
+ run_simulated_request('manager', 'subtract')
61
+ run_simulated_request('manager', 'exit')
62
+
63
+
64
+ # Example of simplified object received from Turn.io stacks
65
+ # This is a contrived example to show the structure, not an actual state
66
+ # NOTE: This is actually a bstring, not a dict
67
+ simplified_json = {
68
+ "context": {
69
+ "user":"+57787919091",
70
+ "state":"answer-addition-problem",
71
+ "bot_message":"What is 2+2?",
72
+ "user_message":"eight",
73
+ "type": "ask"
74
+ },
75
+ "message_data": {
76
+ "author_id": "+57787919091",
77
+ "author_type": "OWNER",
78
+ "contact_uuid": "j43hk26-2hjl-43jk-hnk2-k4ljl46j0ds09",
79
+ "message_body": "eight",
80
+ "message_direction": "inbound",
81
+ "message_id": "4kl209sd0-a7b8-2hj3-8563-3hu4a89b32",
82
+ "message_inserted_at": "2023-01-10T02:37:28.477940Z",
83
+ "message_updated_at": "2023-01-10T02:37:28.487319Z"
84
+ }
85
+ }
86
+
87
+
88
+
89
+ # Full example of event data from Turn.io
90
+ # simplified_json is built from this in Turn.io
91
+ # full_json = {
92
+ # 'message': {
93
+ # '_vnd': {
94
+ # 'v1': {
95
+ # 'author': {
96
+ # 'id': 57787919091,
97
+ # 'name': 'GT',
98
+ # 'type': 'OWNER'
99
+ # },
100
+ # 'card_uuid': None,
101
+ # 'chat': {
102
+ # 'assigned_to': {
103
+ # 'id': 'jhk151kl-hj42-3752-3hjk-h4jk6hjkk2',
104
+ # 'name': 'Greg Thompson',
105
+ # 'type': 'OPERATOR'
106
+ # },
107
+ # 'contact_uuid': 'j43hk26-2hjl-43jk-hnk2-k4ljl46j0ds09',
108
+ # 'inserted_at': '2022-07-05T04:00:34.033522Z',
109
+ # 'owner': '+57787919091',
110
+ # 'permalink': 'https://app.turn.io/c/4kl209sd0-a7b8-2hj3-8563-3hu4a89b32',
111
+ # 'state': 'OPEN',
112
+ # 'state_reason': 'Re-opened by inbound message.',
113
+ # 'unread_count': 19,
114
+ # 'updated_at': '2023-01-10T02:37:28.487319Z',
115
+ # 'uuid': '4kl209sd0-a7b8-2hj3-8563-3hu4a89b32'
116
+ # },
117
+ # 'direction': 'inbound',
118
+ # 'faq_uuid': None,
119
+ # 'in_reply_to': None,
120
+ # 'inserted_at': '2023-01-10T02:37:28.477940Z',
121
+ # 'labels': [{
122
+ # 'confidence': 0.506479332,
123
+ # 'metadata': {
124
+ # 'nlu': {
125
+ # 'confidence': 0.506479332,
126
+ # 'intent': 'question',
127
+ # 'model_name': 'nlu-general-spacy-ngrams-20191014'
128
+ # }
129
+ # },
130
+ # 'uuid': 'ha7890s2k-hjk2-2476-s8d9-fh9779a8a9ds',
131
+ # 'value': 'Unclassified'
132
+ # }],
133
+ # 'last_status': None,
134
+ # 'last_status_timestamp': None,
135
+ # 'on_fallback_channel': False,
136
+ # 'rendered_content': None,
137
+ # 'uuid': 's8df79zhws-h89s-hj23-7s8d-thb248d9bh2qn'
138
+ # }
139
+ # },
140
+ # 'from': 57787919091,
141
+ # 'id': 'hsjkthzZGehkzs09sijWA3',
142
+ # 'text': {'body': 'eight'},
143
+ # 'timestamp': 1673318248,
144
+ # 'type': 'text'
145
+ # },
146
+ # 'type': 'message'
147
+ # }