Asynchronous 如何管理Dialogflow/Api.ai中的5秒响应超时限制?

Asynchronous 如何管理Dialogflow/Api.ai中的5秒响应超时限制?,asynchronous,dialogflow-es,sendasynchronousrequest,request-timed-out,Asynchronous,Dialogflow Es,Sendasynchronousrequest,Request Timed Out,我正在使用Dialogflow创建一个代理/机器人,该代理/机器人使用诸如“我需要从人力资源部获得一封地址证明信”之类的操作项来响应不同类型的用户查询。这需要bot从公司数据库获取一些信息,并通过将检索到的信息填充到人力资源提供的模板信函文件中来生成文档/信函。执行此操作的逻辑已写入python文件中。数据库集成是使用webhook完成的 问题在于,解释用户请求、打开数据库和检索所需信息的完整过程需要5秒钟以上,这恰好是Dialogflow代理的响应超时限制。我对此做了一些研究,发现我们不能增加

我正在使用Dialogflow创建一个代理/机器人,该代理/机器人使用诸如“我需要从人力资源部获得一封地址证明信”之类的操作项来响应不同类型的用户查询。这需要bot从公司数据库获取一些信息,并通过将检索到的信息填充到人力资源提供的模板信函文件中来生成文档/信函。执行此操作的逻辑已写入python文件中。数据库集成是使用webhook完成的

问题在于,解释用户请求、打开数据库和检索所需信息的完整过程需要5秒钟以上,这恰好是Dialogflow代理的响应超时限制。我对此做了一些研究,发现我们不能增加这个限制,但我们可以通过异步调用保持会话的活动性。我无法找到正确的资源来提供答案

所以,我的问题是-

我们可以在dialogflow中进行异步调用吗

如果是,那么我们如何通过json将异步数据发送到Dailogflow代理

有没有其他方法来解决这个5秒响应超时限制

提前谢谢

我刚刚检查了和页面,确实有5秒的超时限制

这可能不是最好的解决方案,也可能不适合您的情况,但考虑到给定的5秒时间窗(我们希望确保动态对话,而不会让用户等待太久)


您以异步方式启动计算,然后返回给用户,告诉他们在几秒钟内请求结果,同时计算完成。它将保存在用户的私人空间中,此时用户将触发第二个意图,请求同时已预计算的结果,因此您可以获取并返回这些结果。

您可以通过设置多个后续事件将5秒意图限制延长至15秒。 目前,您只能一个接一个地设置3个后续事件(可以将超时时间延长到15秒)

下面是一个示例,说明如何在履行中心执行此操作:

功能1(代理){
//此函数处理您的意图实现
//您可以在此处初始化db查询。
//找到数据后,将其存储在单独的表中,以便快速搜索
//获取当前日期
var currentTime=new Date().getTime();
而(currentTime+4500>=新日期().getTime()){
/*等待4.5秒
您可以每秒检查数据库中是否有可用数据
如果没有,请调用下一个后续事件并执行以下操作:
在下一个后续事件中使用相同的while循环
(最多3次后续活动)
*/
/* 
如果(找到日期){
add('your data here');//将响应返回给用户
}
*/
} 
//添加后续事件
agent.setFollowupEvent('customEvent1');
//添加默认响应(以防后续事件出现问题)
代理。添加(“这是功能1”);
}
让intentMap=newmap();
intentMap.set('yourtintent name here',function1);;

代理handleRequest(intentMap)降低代码的复杂性,使其更快;如果您正在使用微服务或纳米服务体系结构,如firebase function、AWS lambda或Kubernetes,请尝试通过初始化函数内部的库而不是全局范围来减少死机启动和冷启动

如果有多个API调用,请尝试并行调用,而不是一个接一个地调用,以减少调用次数。e、 g.承诺所有方法

您还可以通过数据库或上下文解决问题

e、 用户问:我的余额是多少

我在检查你的余额。几秒钟后再问

并在后台获取耗时的API,将数据保存在高速数据库中,如MongoDB(相对高于慢速web服务API),并在上下文菜单或数据库中标记一个标志

当用户在几秒钟后再次请求时,检查标志是否为正,从高速数据库获取数据并将其提供给用户

提示:如果您使用的是GoogleAssistant,那么当从API获取数据完成时,您可以发送推送通知

更新:
回复评论:“你能解释一下“初始化函数内部的库而不是全局范围”是什么意思吗?”

例如,在firebase函数的情况下,它实际上是在容器化环境中执行的,当您暂时不调用函数时,它只是从内存中释放函数的容器,当您再次调用它时,它会在实际执行之前再次初始化容器,该初始化称为冷启动,因此,第一次调用所需的时间稍长,后续调用所需的时间较少,即使第一次调用的执行时间相同,但函数在容器初始化完成之前无法开始执行,容器的初始化包括所有库和数据库连接初始化以及所有。这一切都没关系,在微/纳米服务架构中,你无法摆脱冷启动,但有时它会花费越来越多的时间,给用户带来挫折和糟糕的体验,dialogflow first call之类的服务每次都会失败,这是不好的,还有更多:像firebase这样的服务实际上为每个函数创建了单独的容器例如,如果您有多个函数firebase实际上将每个函数部署在单独的容器中,那么调用每个函数只初始化该函数的容器而不是所有其他函数的容器,真正的问题就来了,您调用一个函数并初始化全局范围内的所有内容,而不考虑您的fu
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
import * as _cors from 'cors';
import firestore from './../db'
import * as mongoose from "mongoose";

const defaultApp = admin.initializeApp(functions.config().firebase)


const dbURI = `mongodb://xxxxxx:xxxxxx@ds00000.mlab.com:123456/mydb`;
// const dbURI = `mongodb://localhost:27017/mydb`;


mongoose.connect(dbURI, {
        useNewUrlParser: true, useUnifiedTopology: true
    }).catch(e => {
        console.log("mongo connection failed for reason: ", e);
    })



var cors = _cors({ origin: true });// set these options appropriately According to your case,
// see document: https://www.npmjs.com/package/cors#configuration-options
// true means allow everything


// http example
export const addMessage = functions.https.onRequest((req, res) => {
    const original = req.query.text;
    admin.database().ref('/messages').push({ original: original }).then(snapshot => {
        res.redirect(303, snapshot.ref);
    });
});


export const signup = functions.https.onRequest(async (req, res) => {

    ... signup stuff using mongodb

    res.send("user signed up");
})

//databse trigger example
export const makeUppercase = functions.database.ref('/messages/{pushId}/original')
    .onWrite(event => {
        const original = event.data.val();
        console.log('Uppercasing', event.params.pushId, original);
        const uppercase = original.toUpperCase();
        return event.data.ref.parent.child('uppercase').set(uppercase);
    });

//cors example
export const ping = functions.https.onRequest(async (req, res) => {
    cors(req, res, () => {
        res.send("this is a function");
    })
})

import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
import * as _cors from 'cors';
import firestore from './../db'
import * as mongoose from "mongoose";

const dbURI = `mongodb://xxxxxx:xxxxxx@ds00000.mlab.com:123456/mydb`;
// const dbURI = `mongodb://localhost:27017/mydb`;


export functions initFirebase(){
    if (admin.apps.length === 0) {
        console.log("initializing firebase database");
        admin.initializeApp(functions.config().firebase)
    }else{
        console.log("firebase is already initialized");
    }
}

export function initMongoDb() {

    if (mongoose.connection.readyState !== mongoose.STATES.connected
        && mongoose.connection.readyState !== mongoose.STATES.connecting) {

        console.log("initializing mongoose");

        mongoose.connect(dbURI, {
            useNewUrlParser: true, useUnifiedTopology: true
        }).catch(e => {
            console.log("mongo connection failed for reason: ", e);
        })
    } else {
        console.log("mongoose already connected: ", mongoose.STATES[mongoose.connection.readyState]);
    }
}



var cors = _cors({ origin: true });// set these options appropriately According to your case,
// see document: https://www.npmjs.com/package/cors#configuration-options
// true means allow everything


// http example
export const addMessage = functions.https.onRequest((req, res) => {
    initFirebase()

    const original = req.query.text;
    admin.database().ref('/messages').push({ original: original }).then(snapshot => {
        res.redirect(303, snapshot.ref);
    });
});



export const signup = functions.https.onRequest(async (req, res) => {
    

    if(req.body.name && req.body.email && req.body.password){
        initMongoDb();

        ... signup stuff using mongodb

        res.send("user signed up");
    }else{
        res.status(400).send("parameter missing");
    }
})

//database trigger example
export const makeUppercase = functions.database.ref('/messages/{pushId}/original')
    .onWrite(event => {        
        const original = event.data.val();
        console.log('Uppercasing', event.params.pushId, original);
        const uppercase = original.toUpperCase();
        return event.data.ref.parent.child('uppercase').set(uppercase);
    });

//cors example
export const function3 = functions.https.onRequest(async (req, res) => {
    cors(req, res, () => {
        res.send("this is a function");
    })
})


Update: a ping call to function on start of mobile app or on page load in web also works well



Inzamam Malik, 
Web & Chatbot developer. 
malikasinger@gmail.com