async def run( self, dispatcher, tracker, domain, ): logger.info("query_school") attribute = tracker.get_slot("attribute") url = "api/v2/schoolProfiles" logger.info("On Query School action") results = school_info( url, attribute, tracker, ) if results is None: dispatcher.utter_message( "Sorry, 🤔 It seems I don't have that information about your school." ) return [FollowupAction("action_bottom_top_menu")] text = resolve_message( intent="school_info", attribute=attribute, results=results, ) dispatcher.utter_message(text) return [FollowupAction("action_bottom_top_menu")]
async def run( self, dispatcher, tracker: Tracker, domain: Dict[Text, Any], ) -> List[Dict[Text, Any]]: school_id = extract_schoolid_from_tracker(tracker) logger.info("action_queryredis_csv") if not school_id: dispatcher.utter_message( "Sorry 🤔 something is wrong.Please try again later." ) return [] context = tracker.get_slot("context") try: parent_button_list = get_parent_button(school_id) except ConnectionError as e: logger.error("Connection error to redis server Error Message{e}") dispatcher.utter_message( "Sorry 🤔 something is wrong.Please try again later." ) return [] parentbuttonlabel = list(parent_button_list.keys()) parentbuttonpayload = list(parent_button_list.values()) buttons = [] if not parentbuttonlabel and not parentbuttonpayload: return [FollowupAction("action_bottom_top_menu")] # this loop generate button for parent i.e. button right after csv for button_label, button_id in zip( parentbuttonlabel, parentbuttonpayload ): payload = { "buttonid": button_id, "new_action": "action_queryredisid", } payload = json.dumps(payload) buttons.append( {"title": f"{button_label}", "payload": f"/router{payload}"} ) # find previous context before current context "schoolinfo" from csv and take contol to action_help_menu for back button help_context = help_db[help_db["context"] == context] context = help_context.prev_context_leaf.values[0] backbuttonpayload = { "buttonid": None, "context": context, "new_action": "action_help_menu", } backbuttonpayload = json.dumps(backbuttonpayload) buttons.append( {"title": "Back", "payload": f"/router{backbuttonpayload}"} ) dispatcher.utter_message(text="This is what I have", buttons=buttons) return [FollowupAction("action_listen")]
async def run( self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict[Text, Any], ) -> List[Dict[Text, Any]]: logger.info("action_init_tutorial") return [SlotSet("context", "help"), FollowupAction("action_help_menu")]
def get_parent_button(schoolId): try: logger.info("connected to redis server successfully") query = f"schoolid:{schoolId}" logger.info(f"School data is:\n{r.hgetall(query)}") return r.hgetall(query) except Exception as e: logger.exception("Error message: {e}") raise ConnectionError
def read_obj(id): try: query = f"buttonid:{id}" logger.info("connected to redis server successfully") logger.info(f"button object data is:\n{r.hgetall(query)}") return r.hgetall(query) except Exception as e: logger.exception("Error message: {e}") raise ConnectionError
def extract_url_from_tracker(tracker): events = tracker.current_state()["events"] for e in reversed(events): if e["event"] == "user": metadata = e["metadata"] try: logger.info(f"Rest Url{metadata['rest_url']} sent from frontend sucessfully.") return metadata["rest_url"] except KeyError as e: logger.error(f"Rest URL not sent from frontend ErrorMessage:{e}") return None
async def run( self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict[Text, Any], ) -> List[Dict[Text, Any]]: logger.info("On Query announcement action") url = "announcements/messages/students" if tracker.get_slot("context") == "help_class_announcements": data = { "sortBy": "", "sortOrder": "", "batchId": [], "courseId": [], "filterBy": "Class_Announcement", "page": 1, "size": 10, } else: data = { "sortBy": "", "sortOrder": "", "batchId": [], "courseId": [], "filterBy": "General_Announcement", "page": 1, "size": 10, } text = announcement_list( url, data, tracker, ) if not text: dispatcher.utter_message( "I couldn't find any announcements at the moment.Check again later. " ) return [FollowupAction("action_bottom_top_menu")] if text is None: dispatcher.utter_message( "I couldn't find any announcements. Something must be wrong.🤔 Check again later, sorry. " ) return [FollowupAction("action_bottom_top_menu")] dispatcher.utter_message(text) return [FollowupAction("action_bottom_top_menu")]
def extract_schoolid_from_tracker(tracker): events = tracker.current_state()["events"] for e in reversed(events): if e["event"] == "user": metadata = e["metadata"] try: logger.info(f"schoolid {metadata['schoolId']} sent from frontend sucessfully.") return metadata["schoolId"] except KeyError as e: logger.error(f"SchoolId not sent from frontend ErrorMessage:{e}") return None
async def run( self, dispatcher, tracker: Tracker, domain: Dict[Text, Any], ) -> List[Dict[Text, Any]]: logger.info("action_elastic_redis") last_message = tracker.latest_message.get("text") school_id = extract_schoolid_from_tracker(tracker) if not school_id: dispatcher.utter_message( "Sorry 🤔 something is wrong.Please try again later." ) return [] buttonid = search_query_fallback(last_message, school_id) if isinstance(buttonid, str): return [ SlotSet("buttonid", buttonid), FollowupAction("action_queryredisid"), ] elif isinstance(buttonid, zip): buttons = [] for objectid, label in buttonid: payload = { "buttonid": objectid, "new_action": "action_queryredisid", } payload = json.dumps(payload) buttons.append( {"title": label, "payload": f"/router{payload}",} ) payload = { "context": "School Info", "new_action": "action_help_menu", } payload = json.dumps(payload) buttons.append( {"title": "School Info", "payload": f"/router{payload}"} ) message_title = "Do you mean any of these" dispatcher.utter_message(text=message_title, buttons=buttons) return [] else: dispatcher.utter_message( "Sorry something is wrong.Please try again later." ) return [ SlotSet("new_action", "action_help_menu"), SlotSet("context", "help"), FollowupAction("action_router"), ]
async def run( self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict[Text, Any], ) -> List[Dict[Text, Any]]: logger.info("On Query Quiz action") url = "api/v2/students/quiz?" if tracker.get_slot("context") == "help_not_attempted_quiz": params = { "courseIds": "", "batchIds": "", "quizAttemptType": "NOT_ATTEMPTED", "quizType": "QUIZ", # "page": 1, # "size": 10, } elif tracker.get_slot("context") == "help_passed_quiz": params = { "courseIds": "", "batchIds": "", "quizAttemptType": "PASSED", "quizType": "QUIZ", } else: params = { "courseIds": "", "batchIds": "", "quizAttemptType": "FAILED", "quizType": "QUIZ", } text = quiz_list(url, params, tracker, tracker.get_slot("context")) if not text: # for empty lists dispatcher.utter_message( "I couldn't find any quizzes at the moment.Check again later! 🤓 " ) return [FollowupAction("action_bottom_top_menu")] if text is None: # for exception dispatcher.utter_message( "I couldn't find any quizes. Something must be wrong.🤔 Check again later, sorry." ) return [FollowupAction("action_bottom_top_menu")] dispatcher.utter_message(text) return [FollowupAction("action_bottom_top_menu")]
async def run( self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict[Text, Any], ) -> List[Dict[Text, Any]]: print("In action_intent_slot_map:") current_intent = tracker.latest_message["intent"].get("name") # context_to_set = intent_slot_dict[current_intent] logger.info("action_intent_slot_map") return [ SlotSet("context", current_intent), FollowupAction("action_help_menu"), ]
def extract_headers_from_tracker(tracker): events = tracker.current_state()["events"] for e in reversed(events): if e["event"] == "user": metadata = e["metadata"] try: headers = { key: metadata[key] for key in ["Authorization", "Origin", "idToken"] } logger.info("Header is sent from frontend successfully.") return headers except KeyError: logger.error("Header not sent from frontend") return None
def object_list(object_type, tracker): try: url = "api/v2/enrolledCourses" results = api_reader(url, tracker=tracker) logger.info(f"object list results is {results}") object_list = [] for p in results: if object_type == "courseBy": object_list.append(p[object_type][0]) else: object_list.append(p[object_type]) return object_list except Exception as e: logger.exception(f"Parsing of API resuts failed") return None
def assignment_list(context, url, params, tracker): text = "" try: res = api_reader(url, params, tracker=tracker) if not res: return res logger.info(f"The assignments list are:\n{res}") for i, p in enumerate(res["content"]): title = p["assignment"]["assignmentTitle"] logger.info(f"data is {p['assignment']}") epochtime = p["assignment"]["deadLine"] try: grade = p["assignment"]["totalGrade"] except: grade = "NOT Available" deadline = time.localtime(epochtime / 1000) deadline = datetime.fromtimestamp(mktime(deadline)) deadline = deadline + timedelta(hours=5, minutes=45) deadline = deadline.strftime("%m/%d/%Y, %H:%M") text = text + assignement_template.format( title=title, deadline=deadline, grade=grade ) if i == 4: break if context == "help_upcoming_assignments": if text: return "**The upcoming assignments are** \n\n" + text return "Currently, you have no any upcoming assignments.😀" elif context == "help_late_assignments": if text: return "**The late assignments are** \n\n" + text return "Congrats!!! you have completed all the assignments till now.😀" except Exception as e: logger.exception(f"Parsing of API resuts failed") return None
async def run( self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict[Text, Any], ) -> List[Dict[Text, Any]]: button_label = "⬆ Back to Top" button_code = "help" new_action = "action_help_menu" buttons_list = [] payload = {"context": button_code, "new_action": new_action} payload = json.dumps(payload) buttons_list.append({ "title": f"{button_label}", "payload": f"/router{payload}" }) text = "Hope that was useful 😊😊" dispatcher.utter_message(text=text, buttons=buttons_list) logger.info("action_top_menu_nlu") return [ FollowupAction("action_listen"), ]
async def run( self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict[Text, Any], ) -> List[Dict[Text, Any]]: current_context = tracker.get_slot("context") rows = db_help[db_help["context"] == current_context] prev_context = rows.loc[rows.index[0], "prev_context_leaf"] prev_action = rows.loc[rows.index[0], "prev_action_leaf"] if (current_context.lower() == "school info") or (current_context.lower() == "school_info"): button_label = ["⬅ Back to top"] button_code = ["help"] new_action = ["action_help_menu"] text = "I have not been programmed by school admin yet. Please check again soon!" else: button_label = ["⬅ Back", "⬆ Top"] button_code = [prev_context, "help"] new_action = [prev_action, "action_help_menu"] text = "What else can I help you with?" buttons_list = [] for label, code, action in zip(button_label, button_code, new_action): print("label:", label, "code:", code, "action:", action) payload = {"context": code, "new_action": action} payload = json.dumps(payload) buttons_list.append({ "title": f"{label}", "payload": f"/router{payload}" }) logger.info("action_bottom_top_menu") dispatcher.utter_message(text=text, buttons=buttons_list) return [ FollowupAction("action_listen"), ]
async def run( self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict[Text, Any], ) -> List[Dict[Text, Any]]: current_intent = tracker.latest_message["intent"].get("name") context = current_intent # school_id = extract_schoolid_from_tracker(tracker) help_context = db_help[db_help["context"] == current_intent] if help_context.empty: dispatcher.utter_message( text="I'm sorry I could not find help. 😕") return [] if help_context.action.notnull().values: next_action = help_context.action.values[0] if help_context.object_type.notnull().values: object_type = help_context["object_type"] object_type = ast.literal_eval(object_type.iloc[0])[0] else: object_type = "null" if help_context.attribute.notnull().values: attribute = help_context["attribute"] attribute = ast.literal_eval(attribute.iloc[0])[0] else: attribute = "null" logger.info("action_leaf") return [ SlotSet("context", context), SlotSet("object_type", object_type), SlotSet("attribute", attribute), FollowupAction(next_action), ]
async def run( self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict[Text, Any], ) -> List[Dict[Text, Any]]: logger.info("On Query Grade action") url = "api/v2/grades/homePage/student/semester" text = grade_list(url, tracker) if not text: dispatcher.utter_message( "I couldn't find your grades. Something must be wrong.🤔 Check again later, sorry. " ) return [FollowupAction("action_bottom_top_menu")] if text is None: dispatcher.utter_message( "🤔 I couldn't find your grades.Something must be wrong.Check again later, sorry." ) return [FollowupAction("action_bottom_top_menu")] dispatcher.utter_message(text) return [FollowupAction("action_bottom_top_menu")]
async def run( self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict[Text, Any], ) -> List[Dict[Text, Any]]: buttons_list = [] course_list = object_list("courseName", tracker) course_id = object_list("courseId", tracker) results = zip(course_list, course_id) # for running in rasax # results = zip(["computer programming"], ["5fe09439dfc567003f7afb8b"]) logger.info("list_course") for course, id in results: payload = {"course_id": id, "new_action": "open_get_data"} payload = json.dumps(payload) buttons_list.append( {"title": course, "payload": f"/router{payload}"} ) text = "Select the course:" dispatcher.utter_message(text=text, buttons=buttons_list) return []
from config_parser import env from elasticsearch import Elasticsearch from ordered_set import OrderedSet from actions.transformerclient import TransformerClient from actions.log_config import logger es_host = env["elastic"]["host"] es_port = env["elastic"]["port"] transformer_host = env["transformer"]["host"] transformer_port = env["transformer"]["port"] # es = Elasticsearch(f"{es_host}:{es_port}") es = Elasticsearch(f"{es_host}") logger.info(f"es url is {es}") t = TransformerClient(host=transformer_host, port=transformer_port) INDEXNAME = env["elastic"]["INDEXNAME"] def search_query_fallback(query, schoolId): try: query_vector = t.encode(query) logger.info("Connected to Transformer as a service server") except Exception as e: logger.error(f"Cannot connect to taas server. ErrorMessage: {e}") return None try:
async def run(self, dispatcher, tracker, domain): newaction = tracker.get_slot("new_action") logger.info("action_router") return [FollowupAction(newaction)]
async def run( self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict[Text, Any], ) -> List[Dict[Text, Any]]: context = tracker.get_slot("context") help_context = help_db[(help_db["context"] == context)] logger.info("action_help_menu") if help_context.empty: context_mapper_db = context_mapping[ (context_mapping["intent"] == context) ] context2word = context_mapper_db.entities.values if context2word: dispatcher.utter_message( text=f"Sorry, I'm not sure I've understood you correctly🤔 Do you mean '{context2word[0]}'. I don't think I have that information." ) return [] else: dispatcher.utter_message( text=f"Sorry, I'm not sure I've understood you correctly🤔 .I don't think I have that information." ) return [] if help_context.action.isnull().values: button_choices = help_context.buttons button_context = help_context["button_context"] button_choices = ast.literal_eval(button_choices.iloc[0]) button_context = ast.literal_eval(button_context.iloc[0]) if help_context.object_type.notnull().values: object_type = help_context["object_type"] object_type = ast.literal_eval(object_type.iloc[0]) else: object_type = ["null"] * len(button_context) if help_context.attribute.notnull().values: attribute = help_context["attribute"] attribute = ast.literal_eval(attribute.iloc[0]) else: attribute = ["null"] * len(button_context) buttons = [] for choice, context, obj, attrib in zip( button_choices, button_context, object_type, attribute ): payload = { "context": context, "object_type": obj, "attribute": attrib, } payload = json.dumps(payload) buttons.append( {"title": f"{choice}", "payload": f"/choose{payload}"} ) help_message = help_context.message.values[0] dispatcher.utter_message(text=help_message, buttons=buttons) return [FollowupAction("action_listen")] elif ( help_context.action.notnull().values and help_context.message.isnull().values ): next_action = help_context.action.values[0] return [ FollowupAction(next_action), ] else: help_message = help_context.message.values[0] dispatcher.utter_message(help_message) next_action = help_context.action.values[0] return [ FollowupAction(next_action), ]
async def run( self, dispatcher, tracker: Tracker, domain: Dict[Text, Any], ) -> List[Dict[Text, Any]]: logger.info("action_queryredisid") parentid = tracker.get_slot("buttonid") try: button_obj = read_obj(parentid) except ConnectionError: logger.error("Connection error to redis server Error Message{e}") dispatcher.utter_message("Sorry 🤔 something is wrong.Please try again later.") # button_obj = read_obj(parentid) # Only None when we are in parent node if not button_obj: return [ FollowupAction("action_router"), SlotSet("new_action", "action_queryredis_csv"), SlotSet("context", "School Info"), ] message_list = [] if button_obj.get("answerTypes"): answer_type = ast.literal_eval(button_obj.get("answerTypes")) for p in answer_type: if p["type"] == "text": message = p.get("text") message = random.choice(message) message_info = {"type": "text", "msg": message} message_list.append(message_info) else: message = p.get("uri") message = random.choice(message) message_info = {"type": "uri", "msg": message} message_list.append(message_info) backbutton_payload = { "buttonid": button_obj.get("parent"), "new_action": "action_queryredisid", } backbutton_payload = json.dumps(backbutton_payload) child_button_id = ast.literal_eval(button_obj.get("children")) if not child_button_id: for message in message_list: if message["type"] == "text": text = message["msg"] dispatcher.utter_message(text=text) else: attachment = message["msg"].rsplit("/", 1)[-1] buttons_list = [] logger.info(f"attachment is {attachment} ") payload = f"{message['msg']}" payload = json.dumps(payload) buttons_list.append( {"title": attachment, "payload": f"{payload}/link",} ) dispatcher.utter_message( text="Please click the following link", buttons=buttons_list, ) return [FollowupAction("action_top_menu_nlu")] buttons = [] for childid in child_button_id: button_obj = read_obj(childid) button_label = button_obj.get("label") payload = { "buttonid": childid, "new_action": "action_queryredisid", } payload = json.dumps(payload) buttons.append( {"title": f"{button_label}", "payload": f"/router{payload}"} ) buttons.append( {"title": "Back", "payload": f"/router{backbutton_payload}"} ) for message in message_list: if message["type"] == "text": text = message["msg"] dispatcher.utter_message(text) else: attachment = message["msg"].rsplit("/", 1)[-1] logger.info(f"attachment is {attachment} ") buttons_list = [] payload = f"{message['msg']}" payload = json.dumps(payload) buttons_list.append( {"title": f"{attachment}", "payload": f"{payload}/link"} ) dispatcher.utter_message( text="Please click the following link", buttons=buttons_list, ) dispatcher.utter_message(text="Select from below", buttons=buttons) return []
def search_query_fallback(query, schoolId): try: query_vector = t.encode(query) logger.info("Connected to Transformer as a service server") except Exception as e: logger.error(f"Cannot connect to taas server. ErrorMessage: {e}") return None try: script_query = { "script_score": { "query": { "bool": { "filter": [ # {"term": {"helpDeskIntent.keyword": helpDeskIntent}}, { "term": { "schoolId": schoolId } }, ] } }, "script": { "source": "cosineSimilarity(params.query_vector, doc['question_vector']) + 1.0", "params": { "query_vector": query_vector }, }, } } response = es.search( index=INDEXNAME, # name of the index body={ "size": 3, "query": script_query, "_source": { "includes": [ "question", "objectId", "helpDeskIntent", "label", ] }, }, ) logger.info("Connected to Elastic search") except Exception as e: logger.error(f"Cannot cannect to es server .ErrorMessage: {e}") return None try: if response["hits"]["max_score"] > 1.8: objectid = response["hits"]["hits"][0]["_source"]["objectId"] return objectid else: buttonids = [] labels = [] for p in response["hits"]["hits"]: buttonids.append(p["_source"]["objectId"]) labels.append(p["_source"]["label"]) buttonids = list(OrderedSet(buttonids)) labels = list(OrderedSet(labels)) return zip(buttonids, labels) except Exception as e: logger.error("ErrorMessage: {e}") return None
async def run( self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict[Text, Any], ) -> List[Dict[Text, Any]]: logger.info("query_assignments") context = tracker.get_slot("context") courseId = [] batchId = [] courseId = set(object_list( "courseId", tracker, )) batchId = set(object_list( "batchId", tracker, )) logger.info(f"course id is {courseId}") logger.info(f"bATCH id is {batchId}") url = "api/v2/assignments/students/papers?" if tracker.get_slot("context") == "help_late_assignments": params = { "filterBy": "overdue", "page": 1, "size": 10, "courseId": list(courseId), "batchId": list(batchId), "filterByGradeType": "", "keyword": "", "assignmentType": "PAPER" } else: params = { "filterBy": "notSubmitted", "page": 1, "size": 10, "courseId": list(courseId), "batchId": list(batchId), "filterByGradeType": "", "keyword": "", "assignmentType": "PAPER" } text = assignment_list(context, url, params, tracker) if not text: if tracker.get_slot("context") == "help_late_assignments": dispatcher.utter_message( "I couldn't find any late assignments at the moment. 😁") else: dispatcher.utter_message( "I couldn't find any upcoming assignments at the moment. Check again later!😊 " ) return [FollowupAction("action_bottom_top_menu")] if text is None: # for exception dispatcher.utter_message( "I couldn't find your assignments. Something must be wrong.🤔Check again later, sorry." ) return [FollowupAction("action_bottom_top_menu")] dispatcher.utter_message(text) return [FollowupAction("action_bottom_top_menu")]