botframework - Botframework V4 上的网络聊天价值交换问题
问题描述
我在 Botframework V4 上运行的 bot 上使用 Direct Line、MS Speech Service 和 Webchat.js。
我使用 webchat.js 从网页启动机器人,将值传递给后端应用程序,例如
https://github.com/microsoft/BotFramework-WebChat/tree/master/samples/04.api/d.post-activity -event
用于在网络频道上实例化机器人的代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>FTD Bit_Bot</title>
</head>
<body style="background-color: #fff; background-image: url('img/FTDBackground.jpg');">
<div id="chatbot" role="main"
data-cb-width="320px"
data-cb-height="400px"
data-cb-border="1px solid #ededed"
data-cb-border-radius="0px"
data-cb-background-color="white"
data-cb-position="fixed"
data-cb-right="40px"
data-cb-bottom="100px"
data-cb-zIndex="1"
data-cb-bubble-background="rgba(217, 217, 217, 0.15)"
data-cb-bubble-from-user-background="#e22e2c"
data-cb-bubble-from-user-text-color="white"
data-cb-bubble-max-width="600"
data-cb-bot-avatar-image="http://demo.radical-thinking.net/bella/microsoft/chat-assets/img/Chat-in-day-Workshop-Icon.png"
data-cb-hide-send-box="false"
data-cb-hide-upload-button="true"
data-cb-send-box-button-color="#e22e2c"
data-cb-send-box-button-color-on-disabled="#CCC"
data-cb-send-box-button-color-on-focus="#333"
data-cb-send-box-button-color-on-hover="#333"
data-cb-send-box-height="30"
data-cb-suggested-action-text-color="black"
data-cb-suggested-action-border="solid 2px #e22e2c"
data-cb-suggested-action-height="30">
</div>
<!-- Include ajax library for speech service token request call -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<!-- Include webchat client functionality (https://github.com/Microsoft/BotFramework-WebChat) -->
<!-- Change to the latest directory to stop the 'No renderer for this activity' error. However the avatar won't show -->
<script src="https://cdn.botframework.com/botframework-webchat/latest/webchat.js" charset="utf-8"></script>
<script>
var chatbot = document.getElementById('chatbot');
// Style modifications
const styleOptions = {
// Colors
bubbleBackground: chatbot.dataset.cbBubbleBackground,
bubbleFromUserBackground: chatbot.dataset.cbBubbleFromUserBackground,
bubbleFromUserTextColor: chatbot.dataset.cbBubbleFromUserTextColor,
bubbleMaxWidth: parseInt(chatbot.dataset.cbBubbleMaxWidth), // maximum width of text message
// Avatar
botAvatarImage: chatbot.dataset.cbBotAvatarImage,
userAvatarInitials: '',
// Send box
hideSendBox: JSON.parse(chatbot.dataset.cbHideSendBox),
hideUploadButton: JSON.parse(chatbot.dataset.cbHideUploadButton),
sendBoxButtonColor: chatbot.dataset.cbSendBoxButtonColor,
sendBoxButtonColorOnDisabled: chatbot.dataset.cbSendBoxButtonColorOnDisabled,
sendBoxButtonColorOnFocus: chatbot.dataset.cbSendBoxButtonColorOnFocus,
sendBoxButtonColorOnHover: chatbot.dataset.cbSendBoxButtonColorOnHover,
sendBoxHeight: parseInt(chatbot.dataset.cbSendBoxHeight),
// Suggested actions
suggestedActionTextColor: chatbot.dataset.cbSuggestedActionTextColor,
suggestedActionBorder: chatbot.dataset.cbSuggestedActionBorder,
suggestedActionHeight: parseInt(chatbot.dataset.cbSuggestedActionHeight),
}
</script>
<script>
var chatbot = document.getElementById("chatbot");
//style tag start
var script = {
id: 'chatbotStyle',
type: 'text/css',
style: document.createElement('style'),
content: '@import url("https://fonts.googleapis.com/css?family=Roboto:300,400,600"); ::-webkit-scrollbar{width:10px}::-webkit-scrollbar-track{background:#f1f1f1}::-webkit-scrollbar-thumb{background:#888}::-webkit-scrollbar-thumb:hover{background:#555} #chatbot{ font-family: Roboto, sans-serif; font-weight: 400; position: fixed; right: 10px; bottom: 20px; text-align: center; } #chatbot img{ margin: auto; } #chatbot small{ display: block; font-size: 9px; } .initLaunchPad{ cursor: pointer; text-align: center; transition: .4s all; } .botHeader{min-height:40px;background:#ededed;border-radius:6px 6px 0 0;display:flex;justify-content:space-between;align-items:center;padding:4px} .botHeader img{float:left;width:32px;height:32px; border-radius:50%;background-color:#f9f9f9}.botHeader h5{float:left;padding:0!important;margin:4px 0 3px 6px} .botHeader h5 small{font-size: 12px;} .botHeader > div{width:40%;display:flex;align-items:center;text-align:left;height:32px} #botClose{cursor:pointer;font-size:12px;font-weight:600;padding:6px 8px;border-radius:4px;background-color:#e22e2c;color:#fff; } #botContainer{ display: none; border-radius: 8px; border:1px solid #cbcbcb; transition:.4s all; width: 310px; height: 420px; max-width:420px; max-height: 420px; margin-bottom: 4px; } #botBody{ height: 366px; } ',
append: function () {
this.style.type = this.type;
this.style.appendChild(document.createTextNode(this.content));
document.head.appendChild(this.style);
}
}; script.append();
//style tag end
//initLaunchPad started
var initLaunchPad = document.createElement('div');
initLaunchPad.classList.add('initLaunchPad');
var initBotIcon = document.createElement('img');
initBotIcon.src = "https://farm5.staticflickr.com/4876/39891228293_13c532f352_o.gif";
initBotIcon.width = 86;
initLaunchPad.appendChild(initBotIcon);
chatbot.appendChild(initLaunchPad);
$(function getSpeechAuthToken() {
var params = {
// Request parameters
};
$.ajax({
url: "https://brazilsouth.api.cognitive.microsoft.com/sts/v1.0/issuetoken" + $.param(params),
beforeSend: function (xhrObj) {
// Request headers
xhrObj.setRequestHeader("Ocp-Apim-Subscription-Key", "XXXXXX");
},
type: "POST",
// Request body
data: "{body}",
})
.done(function (data) {
speechAuthToken = data;
})
.fail(function () {
alert("error");
});
});
initBotIcon.addEventListener('click', function (e) {
e.preventDefault();
initLaunchPad.style.display = "none";
botContainer.style.display = "block";
/*Call bot API*/
(async function () {
const searchParams = new URLSearchParams(window.location.search);
//Speech Service Token Generation
const subscriptionKey = 'XXXXXX';
const region = 'brazilsouth';
let webSpeechPonyfillFactory;
//Speech Service Setting
webSpeechPonyfillFactory = await window.WebChat.createCognitiveServicesSpeechServicesPonyfillFactory({
credentials: {
authorizationToken: speechAuthToken,
region: region
}
});
//Direct-Line BotToken Generation
const res = await fetch('https://directline.botframework.com/v3/directline/tokens/generate', { method: 'POST', headers: { Authorization: 'Bearer ' + 'XXXXXX' } });
const { token } = await res.json();
window.WebChat.renderWebChat({
directLine: window.WebChat.createDirectLine({ token }),
store,
userID: "User",
styleOptions,
locale: 'pt-BR',
selectVoice: (voices, activity) =>
activity.locale === 'pt-BR'
? voices.find(({ name }) => /Daniel/iu.test(name))
: voices.find(({ name }) => /Daniel/iu.test(name)) ||
voices.find(({ name }) => /Daniel/iu.test(name)),
webSpeechPonyfillFactory
}, document.getElementById('botBody'));
document.querySelector('#botBody > *').focus();
var mainTag = chatbot.getElementsByClassName('main')[0];
mainTag.style.borderTop = chatbot.dataset.cbBorder;
})().catch(err => console.error(err));
//Bot Message Exchange Setting
const store = window.WebChat.createStore({}, ({ dispatch }) => next => action => {
if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') {
dispatch({
type: 'WEB_CHAT/SEND_EVENT',
payload: {
name: 'userName',
value: Paul
}
});
dispatch({
type: 'WEB_CHAT/SEND_EVENT',
payload: {
name: 'userGenre',
value: male
}
});
dispatch({
type: 'WEB_CHAT/SEND_EVENT',
payload: {
name: 'activityName',
value: chatBotMission
}
});
}
return next(action);
});
//initLaunchPad ended
var botContainer = document.createElement('div');
botContainer.id = "botContainer";
var botHeader = document.createElement('div');
botHeader.classList.add('botHeader');
var botClose = document.createElement('a');
botClose.id = "botClose";
botClose.innerText = "X";
botClose.title = "Close";
botHeader.innerHTML = "<div><img src='" + chatbot.dataset.cbBotAvatarImage + "'/> <h5>Bit_Bot <small>FTD Educação</small> </div></h5>";
botHeader.appendChild(botClose);
botClose.addEventListener('click', function (e) {
e.preventDefault();
initLaunchPad.style.display = "";
botContainer.style.display = "none";
return false;
});
botContainer.appendChild(botHeader);
var botBody = document.createElement('div');
botBody.id = "botBody";
botContainer.appendChild(botBody);
var poweredBy = document.createElement('div');
poweredBy.innerHTML = "<small>Powered by <img src='http://ainetw.com/img/icon.png' width=12 /> AI Networks</small>";
chatbot.appendChild(botContainer);
chatbot.appendChild(poweredBy);
</script>
</body>
</html>
机器人的代码片段在我的机器人中发送了数据收集:
public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
{
var studentProfile = await _studentProfileAccessor.GetAsync(turnContext, () => new StudentProfile(), cancellationToken);
DialogContext dc = await _dialogs.CreateContextAsync(turnContext, cancellationToken);
//Bot Channel Message Exchange Collection
if (turnContext.Activity.Name == "userName")
{
studentProfile.Name = turnContext.Activity.Value.ToString();
studentName = turnContext.Activity.Value.ToString();
}
if (turnContext.Activity.Name == "userGenre")
{
studentProfile.Gender = turnContext.Activity.Value.ToString();
conversationSessionID = turnContext.Activity.From.Id;
if (conversationSessionID.ToLower() == "user")
{
var myConversationSessionID = turnContext.Activity.Id;
if (myConversationSessionID.IndexOf("|") != -1)
{
conversationSessionID = myConversationSessionID.Substring(0, myConversationSessionID.IndexOf("|"));
}
}
studentGender = turnContext.Activity.Value.ToString();
//Variables persistance on DB
SessionVariable SessionVariable = new SessionVariable();
SessionVariable.AddSessionVariable(BellaMain.GlobalVariable.SystemID, BellaMain.GlobalVariable.CustomerID, conversationSessionID, "StudentName", studentName, "StudentGender", studentGender, "", "", "", "", "", "", "", "", "", "", "", 0);
}
if (turnContext.Activity.Name == "activityName")
{
if (turnContext.Activity.Value.ToString().ToLower() =="atividade2")
{
var message = $"**Olá {studentName}, bem vindo ao Quant Bot!**";
await turnContext.SendActivityAsync(message);
await dc.BeginDialogAsync(Activity2MainDialog, "activity2MainDialog", cancellationToken);
}
else
{
var message = $"**Olá {studentName}, bem vindo ao Quant Bot!**";
await turnContext.SendActivityAsync(message);
}
}
该应用程序工作正常,但是当有多个用户连接到它时,交换的数据会多次不匹配,例如
Webclient 1 发送用户名:Paul 和 Gender:男性 ==> 应用程序接收 Paul 和男性
Webclient 2 发送用户名:Mary 和 Gender : 女性 ==> 应用有时会收到保罗和男性!?它应该接收 Mary 和 female,而不是
我感觉发送的数据在 Azure 或其他地方缓冲,每次新的 Web 应用程序 bot 实例启动时都需要清除/刷新。
是否有意义?如何修复?谢谢
解决方案
首先,如果您确实这样做,请不要在您的客户中通过您的 Direct Line 授权。这是一个重大的安全问题,您很容易被破坏。
至于您的问题,请考虑生成唯一性userID
并将其传递给createDirectLine()
令牌调用。这样,用户 ID 将被烘焙到令牌中,并且不会专门成为页面的功能。由于令牌对每个用户都应该是唯一的,因此如果不能解决您的用户交叉问题,这应该会有所帮助。
如果没有,我建议从您的网络聊天代码中删除 Direct Line 直接 API 调用。就我而言,我有自己的令牌生成服务器,我从网络聊天中调用它。当 Web Chat 调用我的服务器的 API 时,令牌服务器会调用 Direct Line。我还在令牌服务器中生成用户 ID,以便将其烘焙到令牌中,然后将其返回给网络聊天以供使用。
如果这些选项都不能解决您的问题,那么我会仔细研究您在其他地方提到的外部数据收集。
希望有帮助!
推荐阅读
- python - 将 Series 添加到 DataFrame 会导致奇怪的行为
- java - Springboot - 验证@RequestBody
- python - 如何在python中保存网站中的所有图像
- flutter - 将字符串实时传递给另一个类
- reactjs - Redux thunk 调用者得到响应
- html - 嵌套 CSS flexbox 问题 - 仅适用于 Safari 14 / MacOS 浏览器
- npm - 顺风构建任务抛出顺风:找不到命令
- php - PHP 数组输出仅在水平方向显示
- javascript - 循环遍历特定的对象数组并分配给新对象
- python - 用箭头突出显示 matplotlib 条形图上的数据