BotBuilder将事件数据反向通道到会话中



TLDR:如何使用从反向通道发送的数据初始化我的对话,并在与用户的整个对话中使用该信息?

使用Microsoft机器人构建器,提供了一个"反向通道"机制,通过该机制我可以向机器人发送数据或从机器人发送数据。

与此答案类似,我正在使用反向通道方法向机器人发送 conversationStarted 事件,以便按您的期望开始对话。

收到事件后,我启动一个对话框,该对话框向用户发送主动消息。

bot.on('event', event => {
if (event.name === 'conversationStarted') {
bot.beginDialog(event.address, determineWhichDialogToStart(event))
}
})

然后,我可以使用中间件或事件侦听器来拦截此事件并查看其内容。果然我可以看到事件

{ type: 'event',
name: 'conversationStarted',
text: '',
myMetaProperty: 'foobar',
attachments: [],
entities: [],
address:
{ id: '8f5d3952-df3b-4340-89b4-97360f8d4965',
channelId: 'emulator',
user: { id: '33abc508-86d7-49c1-aa68-00a3491fda12' },
conversation: { id: '4e8a943d-6a45-41f2-aa11-6671cc1ca4f3' },
bot: { id: 'bot' },
serviceUrl: 'http://localhost:3010/' },
source: 'emulator',
agent: 'botbuilder',
user: { id: '33abc508-86d7-49c1-aa68-00a3491fda12' } }

但是我可以收听以查看此事件的事件无法访问会话,因为消息尚未发送到一个似乎

。如果我使用botbuilder中间件或routing事件,我会看到它已转换为消息而不是事件,并且丢失了传递给事件的元数据。(见myMetaProperty)

{ type: 'message',
agent: 'botbuilder',
source: 'emulator',
sourceEvent: {},
address:
{ id: '8f5d3952-df3b-4340-89b4-97360f8d4965',
channelId: 'emulator',
user: { id: '33abc508-86d7-49c1-aa68-00a3491fda12' },
conversation: { id: '4e8a943d-6a45-41f2-aa11-6671cc1ca4f3' },
bot: { id: 'bot' },
serviceUrl: 'http://localhost:3010/' },
text: '',
user: { id: '33abc508-86d7-49c1-aa68-00a3491fda12' } }

我尝试根据 Github 上的评论在我的receive事件/中间件中访问会话,但是当我可以访问会话时,这不是会话。

bot.on('receive', event => {
bot.loadSessionWithoutDispatching(event.address, (error, session) => {
session.conversationData.myMetaProperty = event.myMetaProperty
})
})

这实际上最终会开始一个新会话 - 查看了loadSession/loadSessionWithoutDispatching,它们都会导致startSession,因此当我尝试在对话框中使用它时,我向会话添加数据会丢失

bot.dialog('example', [
(session, args, next) => {
console.log(session.conversationData.myMetaProperty) // nope
console.log(session.cantUseThisEither) // nope
session.send('foo')
next()
}
])

现在只是为了重申这个问题,因为已经有一些背景知识,我如何使用从反向通道发送的数据初始化我的对话,并在与用户的整个对话中使用该信息?

我最终启动了一个通用对话框,该对话框设置了我的会话,然后转到根对话框。

bot.on('event', event => {
if (event.name === 'conversationStarted') {
bot.beginDialog(event.address, 'initialise-conversation', {
myMetaProperty: event.myMetaProperty
});
}
});
bot.dialog('initialise-conversation', (session, args, next) => {
session.conversationData.myMetaProperty = args.myMetaProperty
session.beginDialog('/');
});

然后,每当我需要在整个对话中myMetaProperty时,我都可以从session.conversationData

--

作为对以下评论的回应,这里有一些可能对某人有所帮助的其他信息。

您在机器人上收到的事件的形状必须明显包含address。例如,这是我发送给我的机器人的那个。

{ myMetaProperty: 'foo',
name: 'conversationStarted',
type: 'event',
address:
{ id: '4q5aaBw77aNGGvrpkeji8A',
channelId: 'custom-directline',
user: { id: 'c214imy6PCJZY4G1x2AXSD' },
conversation: { id: 'bGvMBjEmFTg3DMxsbvJGjH' },
bot: { id: 'bot' },
serviceUrl: 'https://localhost:3010/' },
source: 'custom-directline',
agent: 'botbuilder',
user: { id: 'c214imy6PCJZY4G1x2AXSD' } }

首先确保您发送的是地址。将消息路由回个人的关键信息位是用户和会话对象。

例如,如果您使用botframework网络聊天的反向通道发送信息,则可以执行以下操作。

var user = { id: uuidv4() };
var botConnection = new BotChat.DirectLine({...});
botConnection.postActivity({
type: 'event',
from: user,
name: 'conversationStarted',
myMetaProperty: 'foo',
}).subscribe();
BotChat.App({
user: user,
botConnection: botConnection,
}, document.getElementById("bot"));

这将由上述事件侦听器拾取。

需要注意的另一件事是模拟器(可能还有其他客户端/通道)发送一个conversationUpdate事件,我在使用它时刚刚传递给我的conversationStarted事件。这是侦听器,以便在有用的情况下进行参考。

bot.on('conversationUpdate', message => {
message.membersAdded &&
message.membersAdded
.filter(identity => identity.id === message.address.bot.id)
.forEach(identity => bot.emit('conversationStarted', message));
});

您可以通过beginDialog(address: IAddress, dialogId: string, dialogArgs?: any, done?: (err: Error) => void): void;传递数据,您可以将要发送的数据作为此函数中的第三个参数传递。

您可以参考 https://github.com/Microsoft/BotBuilder/blob/master/Node/core/src/bots/UniversalBot.ts#L243 中的源代码以获取更多详细信息。

最新更新