Exemple #1
0
def format_response_text_with_links(text_reponse, links):
    if (len(links) == 0):
        return [{"text": text_reponse, "link": ""}]

    new_text_response = []
    matches = re.findall('((.*?)(link[0-9]+))', text_reponse)
    found_text = ""
    for match in matches:
        found_text = found_text + match[0]
        linkid = match[2]
        text_before_link = match[1]
        
        item_detail = {}
        item_detail["text"] = text_before_link
        if linkid in links.keys():
            logger("webUI").info("Link " + linkid + " after: " + text_before_link)
            item_detail["link"] = links[linkid]
            del links[linkid]
        
        new_text_response.append(item_detail)
    
    remain_text = text_reponse.replace(found_text, "").strip()
    if (remain_text != ""):
        new_text_response.append({"text": remain_text, "link": ""})
    
    logger("webUI").info(new_text_response)
    return new_text_response
def format_response(text_response):
    text_response_wo_link = text_response
    retlinks = {}

    # @description: This part is to detect and extract all links in the response (It could be returned from dialogflow or web-hook
    # @input: Text response
    # @output: dictionary of link with {link<1|2|...|n>: http address}
    logger("chat").info("4.1. Extract links from the response")
    if ("http" in text_response):
        links = re.findall(WEB_URL_REGEX, text_response)
        i = 1
        for url in links:
            if not (url.startswith('http')):
                continue
            text_response_wo_link = text_response_wo_link.replace(
                url, 'link' + str(i))
            retlinks['link' + str(i)] = url
            i = i + 1
            logger("chat").debug("     -> Detecting link " + url)

    (intro_response,
     detail_response) = separate_retro_with_detail(text_response_wo_link)
    logger("chat").info("4.2. Extract retro/introduction from response: " +
                        intro_response)

    # Split detail into list and remove the empty elements.
    # To ignore the case where empty or element with 'spaces', need to check detail_response start with '-' or not first.
    # Ignore the new line in the text, to prevent to mismatch of regular expression later in the code.
    responses = []
    formated_responses = []
    if not (detail_response == ""):
        detail_response = detail_response.replace("\n", " ")
        detail_response = detail_response.replace("<section>", "<li><section>")

        responses = filter(None, detail_response.split("<li>"))
        for response in responses:
            if response.strip() == '':
                continue
            else:
                formated_responses.append(response.strip())

    # Return: retro text, list of detail response, dictionary of links
    logger("chat").info("4.3. Format the details/list from response: ")
    logger("chat").info("     -> ".join(formated_responses))
    return (intro_response, formated_responses, retlinks)
Exemple #3
0
def receive_wav_files():
    form  = request.form
    if (request.method == 'POST'):
        # UPLOAD_FOLDER
        #print (request.form)
        split_ind = request.form['data'].find(",")

        data = request.form['data'][(split_ind + 1):]
        decodedData = base64.decodestring(data)

        filename = (request.form['fname']).replace("%3A", ":")
        #print ("The output filename is " + filename)
        #print (decodedData)
        with open(WAVS_FOLDER + "/" + filename, 'wb') as wavfile:
            wavfile.write(decodedData)

        logger("voice_input").info("The output file is " + UPLOAD_FOLDER + "/" + filename)

    return render_template('nsfnb_chat.html', form=form)
Exemple #4
0
def main_render():
    form = ChatForm(request.form)
    # ---------To clear the log each time the page is refreshed, even the same session id ----------#
    form.ssid = uuid.uuid4().hex
    if (form.ssid in form.chats.keys()):
        del form.chats[form.ssid][:]
    logger("webUI").info("You are requesting a new session by refresh: " + form.ssid)

    # ---------To keep log each time the page is refreshed but the time in bot response is lost ----------#
    logger("webUI").info("======================CHAT HISTORY======================")
    logger("webUI").info(form.chats)
    if len(form.chats.keys()) == 1:
        form.ssid = form.chats.keys()[0]
    logger("webUI").info("======================SESSION ID======================")
    logger("webUI").info(form.ssid)
    if (__DEBUG__):
        print ("Session id: " + str(form.ssid))

    retro_msg = [{"text": "Welcome! I am North-Spine Food Ordering bot."}]
    retro_details = [[{'text': 'Ordering food in canteen A (NorthSpine)', 'link': 'http://www.ntu.edu.sg/has/FnB/Pages/NorthSpine.aspx'}],
                     [{'text': 'Getting to know the location of Canteen A', 'link': 'http://maps.ntu.edu.sg/m?q=Canteen%20A&fs=m'}]
                    ]
    link = []
    singaporetz = timezone('Asia/Singapore')
    form.chats[form.ssid] = []
    form.chats[form.ssid].insert(0, {
                      #'user':  ("User: Get started"),
                      'bot': (retro_details),
                      'retro': (retro_msg),
                      'link': (link),
                      'time': datetime.now(singaporetz),
                      'id': len(form.chats[form.ssid]) + 1,
                      'feedback': ''
                      })

    return render_template('nsfnb_chat.html', form=form)
Exemple #5
0
def format_response_list_with_links(detail_list, links):
    logger("webUI").info(links.keys())
    new_details = []
    
    for detail in detail_list:
        m = re.match('(.*?)(link[0-9]+)', detail)
        item_detail = {}
        if bool(m):
            key = m.group(2)
            logger("webUI").info("Link index " + key + " and detail: " + detail)
            item_detail["text"] = detail.replace(key, "")
            if key in links.keys():
                item_detail["link"] = links[key]
                del links[key]
        else:
            item_detail["text"] = detail
            item_detail["link"] = ""
        
        new_details.append(item_detail)
    
    logger("webUI").info(new_details)
    return new_details
Exemple #6
0
def receive_query():
    form = ChatForm(request.form)

    # Select to use session id info (1. generated from client, or 2. returned from dialogflow|api.ai)
    if (request.form['session_id'] == ''):
        form.ssid = uuid.uuid4().hex
    else:
        form.ssid =request.form['session_id']
    # If the ssid is new, should clear the chat log - history.
    if (form.ssid not in form.chats.keys()):
        form.chats[form.ssid] = []

    last_ind = len(form.chats[form.ssid])
    if (last_ind > 0):
        logger("webUI").info("Last query, response and feedback: ")
        logger("webUI").info(form.chats[form.ssid][0])

    singaporetz = timezone('Asia/Singapore')
    user_query = ""
    timestamp_userquery = datetime.now(singaporetz)

    """
    #CHECK IF THE INPUT IS AUDIO -> CONVERT TO TEXT THEN ASSIGN TO USER_QUERY
    logger("webUI").info("UPLOAD FILE debugging - start")
    if (request.method == 'POST'):
        # check if the post request has the file part
        if 'au_file' not in request.files:
            flash('Warning: No file part')
            return redirect(request.url)
        file = request.files['au_file']
        # if user does not select file, browser also
        # submit a empty part without filename
        if file.filename == '':
            flash('Warning: No selected file')
            return redirect(request.url)

        if file and allowed_file(file.filename):
            filename = secure_filename(file.filename)
            file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))

            logger("webUI").info("UPLOAD FILE debugging - end")
            return redirect(url_for('receive_query', _external="true", _scheme="https"))
    """

    # Get information returned form dialogflow (FAQs agent)
    user_query = request.form['user_query']
    if (__DEBUG__):
        print ("1. Your query is ")
        pprint.pprint(user_query)

    if (user_query.strip() != ""):
        #(bot_response, detail_list, links, sessionid, timestamp_insgtz, intentname, params) = ask_question(user_query)
        (bot_response, detail_list, links, sessionid, timestamp_insgtz, intentname, params) = ask_question_v2(user_query)
        if (__DEBUG__):
            print ("---------------------------")
            pprint.pprint(params)
            print ("---------------------------")

        # Delete the chat history if the ssid is different.
        logger("webUI").info("Return session from api.ai: " + sessionid)
        if not (sessionid in form.recent_sessionids):
            form.recent_sessionids.append(sessionid)
            del form.chats[form.ssid][:]

        # update the form's parameters from result.
        form.intent_name = intentname
        form.intent_params = params
        form.timestamp = timestamp_insgtz

        formated_details = format_response_list_with_links(detail_list, links)
        formated_retro_response = format_response_text_with_links(bot_response, links)

        if (__DEBUG__):
            print ("2. Inserting data to forms.chats")
        #form.chats[form.ssid].insert(0, {
        #                      'user':  ["User (" + str(timestamp_userquery) + ")",  user_query],
        #                      'bot': (formated_details),
        #                      'retro': (formated_retro_response),
        #                      'link': (links.values()),
        #                      'time': form.timestamp,
        #                      'id': len(form.chats[form.ssid]) + 1,
        #                      'feedback': ''
        #                      })

        form.chats[form.ssid].append({
                              'user':  ["User (" + str(timestamp_userquery) + ")", user_query],
                              'bot': (formated_details),
                              'retro': (formated_retro_response),
                              'link': (links.values()),
                              'time': form.timestamp,
                              'id': len(form.chats[form.ssid]) + 1,
                              'feedback': '',
                              'meta': params,
                              })

        if (__DEBUG__):
            print ("3. Number of elements: " + str(len(form.chats)))

        form.similar_queries = suggest_commplete(user_query)
    return render_template('nsfnb_chat.html', form=form)
def unauthorized():
    logger().error(ConstStr.unauthorized_access)
    return make_response(jsonify({"error": ConstStr.unauthorized_access}), 403)
    def post(self):
        args = self.reqparse.parse_args()
        # 1. Check if the session id is new or old - meaning the different person or timeout
        if (__DEBUG__):
            print("Receiving request from facebook-dialogflow")
            pprint.pprint(args)
            print("Finished receiving from facebook-dialogflow")

        ########################################
        # Process the information from api.ai
        ########################################
        # 1. Check if the session id is new or old - meaning the different person or timeout
        sessionId = args["responseId"]
        logger("webhookInterface").info("Current session id is " + sessionId)
        if (__DEBUG__):
            print("Current session id is " + sessionId)

        result = dict(args["queryResult"])

        # 2. Output context, should save in backend for future processing
        intent_name_confident_score = (result["intentDetectionConfidence"])
        function_name_from_intent = ""
        context_user_id = sessionId
        parameters = {}

        if ("intent" in result.keys()):
            function_name_from_intent = str(result["intent"]["displayName"])
            parameters = dict(result["parameters"])

            if ('outputContexts' in result.keys()):
                context_user_id = get_user_id(result["outputContexts"])
                if (__DEBUG__):
                    pprint.pprint(result['outputContexts'])
                    print("Finished processing user id ")
                    pprint.pprint(context_user_id)

            logger("webhookInterface").debug(type(parameters))
            if (len(parameters.values()) > 0):
                logger("webhookInterface").debug(parameters.values()[0])
            logger("webhookInterface").info("--------------------------")
            logger("webhookInterface").info(parameters.values())
            logger("webhookInterface").info("--------------------------")

            # 3. Original query, provide more information, maybe contain the info that api.ai doesn't recognize
            reslt_query = str(result["queryText"])
            logger("webhookInterface").info("Resolved query is " + reslt_query)

            # 4. Action associated with the query (checking map, database, etc.)
            #reslt_action = str(result["action"])

            # 5. Get the intent name, call the function named as intent to get the result
            logger("webhookInterface").info("Call the function " +
                                            function_name_from_intent + "(" +
                                            str(parameters.values()) + ")")
            if (__DEBUG__):
                print("Call the function " + function_name_from_intent + "(" +
                      str(parameters.values()) + ")")
            webhookResponses = {"text": ConstStr.unknown_input_str1}

            if function_name_from_intent in methods:
                func_params = parameters.values()
                func_params.append(context_user_id)
                if (__DEBUG__):
                    print("Parameters pass to the function: ")
                    pprint.pprint(func_params)
                webhookResponses = methods[function_name_from_intent](
                    func_params)  # + argument list of course
            else:
                if ("smalltalk" in function_name_from_intent):
                    logger("webhookInterface").info("No need webhook")
                else:
                    raise Exception("Method %s not implemented" %
                                    function_name_from_intent)

            # 6. Return the result: Form the result conform with the request.
            if webhookResponses == None:
                logger("webhookInterface").info(
                    "There is no response from webhook")
                return {
                    "fulfillmentText": webhookResponses,
                    "fulfillmentMessages": [{
                        "text": {
                            "text": [webhookResponses]
                        }
                    }],
                    "source": "webhookInterface",
                    "payload": {},
                    "outputContexts": [],
                    "followupEventInput": {}
                }
            else:
                logger("webhookInterface").info("Response from webhook is: ")
                if (__DEBUG__):
                    pprint.pprint(webhookResponses)
                    print("Return format")

                fullReps = format_dialogflow_text(webhookResponses['text'])
                if ('quickReplies' in webhookResponses.keys()):
                    fullReps = fullReps + format_dialogflow_qR(
                        webhookResponses['quickReplies'])
                if ('cards' in webhookResponses.keys()):
                    fullReps = fullReps + format_dialogflow_cards(
                        webhookResponses['cards'])

                if (__DEBUG__):
                    pprint.pprint(fullReps)

                if (type(webhookResponses) == type({})):
                    return {
                        "fulfillmentText": webhookResponses['text'][0],
                        "fulfillmentMessages": fullReps,
                        "source": "webhookInterface",
                        "payload": {},
                        "outputContexts": [],
                        "followupEventInput": {}
                    }
                else:
                    return {
                        "fulfillmentText":
                        webhookResponses,
                        "fulfillmentMessages": [{
                            "text": {
                                "text": [webhookResponses]
                            }
                        }],
                        "source":
                        "webhookInterface",
                        "payload": {},
                        "outputContexts": [],
                        "followupEventInput": {}
                    }
def ask_question_v2(input_query):
    global session_id

    # Initiate the Dialogflow agent
    logger("chat").info("Receiving input query" + input_query)
    ai = apiai.ApiAI(CLIENT_ACCESS_TOKEN)
    request = ai.text_request()
    request.lang = 'en'  # optional, default value equal 'en'
    request.session_id = session_id
    request.query = input_query.replace("\"", "'")
    request.resetContexts = is_reset_context_request(input_query)

    logger("chat").info("Request sent to YakunFood Agent")
    logger("chat").info(request)

    # Get the response from dialogflow agent
    response = request.getresponse()
    responsestr = response.read().decode('utf-8')
    response_obj = json.loads(responsestr)
    logger("chat").info("Receiving response from api.ai agent" + responsestr)

    text_response = response_obj["result"]["fulfillment"]["speech"]
    logger("chat").info("Response to display in webpage: " + text_response)

    return_session_id = response_obj["sessionId"]
    rich_messages = {"text": [], "quickreplies": [], "cards": []}

    detail_msgs = response_obj["result"]["fulfillment"]["messages"]
    for resp_message in detail_msgs:
        msg_type = (resp_message['type'])
        if (msg_type == 0):
            rich_messages["text"] = rich_messages[
                "text"] + format_text_on_website(resp_message)
            if (__DEBUG__):
                print("Format of text on website:")
                pprint.pprint(rich_messages["text"])
        elif (msg_type == 1):
            # Processing the button/card
            rich_messages["cards"] = rich_messages[
                "cards"] + format_cards_on_website(resp_message)
            if (__DEBUG__):
                print("Format of cards on website:")
                pprint.pprint(rich_messages["cards"])
        elif (msg_type == 2):
            # Processing the quickReplies
            rich_messages["quickreplies"] = rich_messages[
                "quickreplies"] + format_quickreplies_on_website(resp_message)
            if (__DEBUG__):
                print("Format of quickreplies on website:")
                pprint.pprint(rich_messages["quickreplies"])
        else:
            # Processing the carousell?
            pass

    # PROCESS THE RESPONSE - FORMAT
    (intro_response, detail_responses, links) = format_response(text_response)
    intent_name = ""
    if ("intentName" in (response_obj["result"]["metadata"]).keys()):
        # In case there is no intent name: using smalltalk or other pre-built agents from dialogflow| api.ai| google
        intent_name = response_obj["result"]["metadata"]["intentName"]
        if (intent_name == "Default Fallback Intent"):
            # If the agent cannot recognize the intent, we will suggest user topics of their queries.
            intro_response = "You can ask me something related to ordering food and beverage in Canteen A (North Spine, NTU, Singapore)."
            detail_responses = []

    # If no intent name (small talk or prebuilt agents), using the action name instead.
    actionname = response_obj["result"]["action"]
    if (intent_name == ""):
        intent_name = actionname

    # Return the parameters, this is for debugging.
    parameters = dict(response_obj["result"]["parameters"])
    response_timestamp = response_obj["timestamp"]

    # Convert time zone
    singaporetz = timezone('Asia/Singapore')
    timestamp_insgtz = convert_my_iso_8601(response_timestamp, singaporetz)

    return (intro_response, detail_responses, links, return_session_id,
            timestamp_insgtz, intent_name, rich_messages)