Aditya Agarwal
Aditya Agarwal

Reputation: 231

Execute python script in background, while dialogflow response is sent back (Python Flask)

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()

So this is the python script, for my backend for Dialogflow Agent. The agent has the following conversation structure:

Hi->Please enter address->Please enter name (to waste time)->[and then it gives the travel time]

So this agent basically gives the travel time between the address entered and a fixed address (using the script in again()) Also, note that I am wasting time since if I directly try to output the travel time after the address, Dialogflow agent says, Deadline Exceeded. So to get over that, I tried threading so that the travel time is calculated in background, and meanwhile, the response is returned to dialogflow, it asks for the user's name, and then it outputs the travel time.

But the problem is that, DialogFlow still says Deadline Exceeded (at "Please enter you address"). And I suspect the reason is that, even though the python script returns the webhook, but dialogflow doesn't show the output, until the python script stops executing. So how do I get over that?

Just to summarize, I want that the request is returned (get_address action), and meanwhile the travel time is calculated (using again()) and returned in the next request.

So as suggested, I removed return {'fulfillmentText': textv} from if() part of results() function and replaced it with return {'followupEventInput': 'IN_PROGRESS'}, but still it says DEADLINE_EXCEEDED. As I said earlier, the problem seems to lie in the fact that results() function is not returning at all.

Upvotes: 0

Views: 360

Answers (2)

Aditya Agarwal
Aditya Agarwal

Reputation: 231

I figured it myself. The problem was with syntax of: threade=threading.Thread(target=again())

There should not be () after again.

Upvotes: 3

Beppe C
Beppe C

Reputation: 13993

the problem you face is that your have computational task that might take more than the max 4 seconds DialogFlow waits between a question and an answer.
Indeed a basic solution is to buy sometime, asking other questions.

During the following interaction(s) you need to check if the background thread is completed, then get the time. Otherwise you need to extend this process.

One slightly better approach is to trigger events (rather than asking questions):

  • enter address
  • webhook is invoked
  • start background thread, sleep 3 sec, trigger event IN_PROGRESS
  • DialogFlow intent I1 is triggered by event IN_PROGRESS, a message is displayed to the user (ie working on it)
  • webhook is invoked after the intent I1, sleep 3 sec, then check background thread status

Upvotes: 0

Related Questions