Выполнить сценарий python в фоновом режиме, при этом ответ диалогового окна отправляется обратно (Python Flask) - PullRequest
0 голосов
/ 07 мая 2020
app = Flask(__name__)
av=""
time=""
action=""

def again():
    ...

@app.route('/')
def index():
    return 'Hello World!'

def results():
    global action
    req = request.get_json(force=True)
    action = req.get('queryResult').get('action')
    if(action=="get_address"):
        global av
        global time
        av=req.get('queryResult').get('parameters').get('location').get('city')
        threade=threading.Thread(target=again())
        threade.start()

        textv="Thanks! Please enter your name now."
        return {'fulfillmentText': textv}
    else:
        textv="Time: " + time
        return {'fulfillmentText': textv}


# create a route for webhook
@app.route('/webhook', methods=['GET', 'POST'])
def webhook():
    # return response
    return make_response(jsonify(results()))

# run the app
if __name__ == '__main__':
   app.run()

Итак, это сценарий python для моего бэкэнда для Dialogflow Agent. У агента следующая структура разговора:

Привет-> Пожалуйста, введите адрес-> Пожалуйста, введите имя (чтобы тратить время) -> [и затем будет указано время в пути]

Итак, этот агент в основном дает время в пути между введенным адресом и фиксированным адресом (с использованием скрипта в again()). Также обратите внимание, что я зря трачу время, поскольку, если я напрямую попытаюсь вывести время в пути после адреса, агент Dialogflow сообщает, что крайний срок превышен . Чтобы преодолеть это, я попытался использовать потоки, чтобы время в пути вычислялось в фоновом режиме, а тем временем ответ возвращается в диалог, он запрашивает имя пользователя, а затем выводит время в пути.

Но проблема в том, что DialogFlow по-прежнему сообщает «Превышен крайний срок» (на «Введите свой адрес» ). И я подозреваю, что причина в том, что хотя сценарий python возвращает веб-перехватчик, но диалоговый поток не показывает результат, пока сценарий python не перестанет выполняться. Итак, как мне это преодолеть?

Подводя итог, я хочу, чтобы запрос был возвращен (get_address действие), а время в пути вычисляется (с использованием again()) и возвращается в следующем запрос.

Итак, как было предложено, я удалил return {'fulfillmentText': textv} из if() части функции results() и заменил ее на return {'followupEventInput': 'IN_PROGRESS'}, но все же там написано DEADLINE_EXCEEDED. Как я сказал ранее, проблема, похоже, заключается в ie том факте, что функция results() вообще не возвращается.

Ответы [ 2 ]

2 голосов
/ 07 мая 2020

Я сам прикинул. Проблема заключалась в синтаксисе: threade=threading.Thread(target=again())

Не должно быть () после again.

0 голосов
/ 07 мая 2020

проблема, с которой вы сталкиваетесь, заключается в том, что ваша вычислительная задача может занять больше, чем максимум 4 секунды, которые DialogFlow ожидает между вопросом и ответом.
Действительно, основное решение c - это когда-нибудь покупать, задавая другие вопросы.

Во время следующего взаимодействия вам необходимо проверить, завершен ли фоновый поток, а затем узнать время. В противном случае вам необходимо продлить этот процесс.

Несколько лучший подход - запускать события (а не задавать вопросы):

  • введите адрес
  • вызывается веб-перехватчик
  • запуск фонового потока, сон 3 se c, событие запуска IN_PROGRESS
  • намерение DialogFlow I1 запускается событием IN_PROGRESS, пользователю отображается сообщение (ie работает над ним)
  • веб-перехватчик вызывается после намерения I1, засыпает 3 se c, затем проверяет состояние фонового потока
...