在页面重新加载/导航到另一个页面后,有没有办法在 MS Bot Framework Web Chat 中保留聊天记录? [英] Is there a way to persist chat history in MS Bot Framework Web Chat after a page reload/navigation to another page?

查看:10
本文介绍了在页面重新加载/导航到另一个页面后,有没有办法在 MS Bot Framework Web Chat 中保留聊天记录?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在页面重新加载和导航到机器人链接到的网站上的其他页面期间保持用户与机器人的对话.

I'm trying to persist the conversation a user has had with the bot during page reloads and navigation to other pages on the site the bot is linked to.

目前,这些操作会关闭机器人窗口并完全重新开始对话,直至再次触发机器人的欢迎消息.

Currently these actions close the bot window and restart the conversation entirely, to the point that the bot's welcome message is triggered again.

有问题的机器人按照文档中的说明嵌入到网页中:https://docs.microsoft.com/bs-latn-ba/azure/bot-service/bot-service-channel-connect-webchat?view=azure-bot-service-4.0

The bot in question is embedded in the webpage following the instructions from the docs: https://docs.microsoft.com/bs-latn-ba/azure/bot-service/bot-service-channel-connect-webchat?view=azure-bot-service-4.0

我读过其他文章,这些文章使用了 sessionId 来维护页面加载之间的聊天历史记录,尽管这是针对 DirectLine 频道的.以及其他一些建议将对话保存在数据库中并将消息传递回聊天窗口的文章.虽然这似乎不是最好的方法.

I have read other articles that have used the conversationId to maintain the chat history between page loads, though this was for the DirectLine channel. As well as some other articles that suggested persisting the conversation in a database and passing the messages back into the chat window. Though this seems doesn't seem the best way to go about it.

我尝试将 sessionId 传递到 iframe 中,但没有成功.有没有办法通过将 sessionId 传递到 iframe 来保持对话?

I attempted to pass conversationId into the iframe but it did not work. Is there a way persist the conversation by passing the conversationId into the iframe?

这是在 iframe 中显示聊天机器人的代码:

This is the code for showing the chatbot in an iframe:

<iframe src='https://webchat.botframework.com/embed/THECHATBOT?s=YOUR_SECRET_HERE' style='min-width: 400px;宽度:100%;最小高度:500px;'></iframe>

这是我将 sessionId 作为参数传递的尝试:

This is my attempt at passing conversationId as a parameter:

<iframe src='https://webchat.botframework.com/embed/THECHATBOT?s=YOUR_SECRET_HERE&conversationId?=THE_CONVERSATIONID_VALUE' style='min-width: 400px;宽度:100%;最小高度:500px;'></iframe>

我希望聊天窗口会填充用户之前的对话,我得到的是对话重置并且没有保留任何历史记录.

I expect the chat window to be populated with the conversation the user previously had, what I am getting is the conversation resets and no history is maintained.

推荐答案

如果您希望进行任何类型的网络聊天自定义,那么我强烈建议您不要使用网络聊天频道 <iframe> 选项.如果您需要一个简单的插件组件,它很有用,但它没有提供接近 BotFramework-WebChat 优惠.

If you are looking to do any sort of web chat customization, then I would highly recommend you steer away from using the Web Chat channel <iframe> option. It is useful if you need a simple plugin component, but it doesn't offer anywhere near the number of customization options that BotFramework-WebChat offers.

如果您考虑使用基于 v4 的网络聊天产品(在上面的链接中引用),那么以下示例将为您提供您正在寻求的功能.

If you will consider using the v4 react-based Web Chat offering (referenced in the link above), then the following example will provide you with the functionality you are seeking.

请注意,为简单起见,我将 sessionId 保存在会话存储中.

Please note, for simplicity, I'm saving the conversationId in session storage.

此外,我通过对本地运行的直线端点进行 API 调用来生成令牌.我在最后包含了代码来做同样的事情.您可以在 html 文件中针对 directline/tokens/generate 端点传递您的直线机密,但是出于安全原因,强烈建议不要这样做.

Also, I'm generating a token by making an API call against a locally run direct line endpoint. I've included code at the end for doing the same. You could pass in your direct line secret against the directline/tokens/generate endpoint in the html file, however that is highly discouraged for security reasons.

最后,createDirectLine() 方法中使用的 watermark 属性指定要显示的过去活动的数量(消息、卡片等).

Lastly, the watermark property used in the createDirectLine() method specifies the number of past activities to display (messages, cards, etc.).

<!DOCTYPE html>
<html>

  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>WebChat</title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style>
    html,
    body {
      height: 100%;
      width: 100%;
      margin: 0;
    }

    #webchat {
      height: 100%;
      width: 40%;
    }

    #webchat>* {
      height: 100%;
      width: 100%;
    }
  </style>
  </head>

  <body>
    <div id="webchat" role="main"></div>
    <script type="text/javascript"
      src="https://unpkg.com/markdown-it/dist/markdown-it.min.js"></script>
    <script
      src="https://cdn.botframework.com/botframework-webchat/master/webchat.js"></script>
    <script>
    ( async function () {
      let { token, conversationId } = sessionStorage;

      if (!token) {
        const res = await fetch( 'http://localhost:3500/directline/token', { method: 'POST' } );
        const { token: directLineToken } = await res.json();

        sessionStorage['token'] = directLineToken;
        token = directLineToken;
      }

      if (conversationId) {
        const res = await fetch(`https://directline.botframework.com/v3/directline/conversations/${ conversationId }`, {
          method: 'GET',
          headers: {
            'Authorization': `Bearer ${ token }`,
          },
        });

        let { conversationId } = await res.json();
        sessionStorage['conversationId'] = conversationId;
      } 

      const directLine = createDirectLine({
        token,
        webSockets: true,
        watermark: 10
      });

      window.WebChat.renderWebChat( {
        directLine: directLine,
      }, document.getElementById( 'webchat' ) );
      document.querySelector( '#webchat > *' ).focus();
    } )().catch( err => console.error( err ) );
    </script>
  </body>
</html>

这是生成令牌的代码.我已将此附加到我的 bot 中 index.js 文件的末尾.您也可以将其作为单独的项目运行.

Here is the code for generating the token. I have this appended to the end of my index.js file in my bot. You can also run this as a separate project.

当我在本地运行我的机器人时,端点变得可用.如果您正在运行 C# 机器人,您应该能够执行类似的操作.此处使用的端口应与上述directline/token调用中引用的端口相同.

As I run my bot locally, the endpoint becomes available. You should be able to do something similar if you are running a C# bot. The port used here should be the same port referenced in the above directline/token call.

directLineSecret 是通过 .env 文件存储和访问的.

The directLineSecret is stored and accessed from a .env file.

/**
 * Creates token server
 */
const bodyParser = require('body-parser');
const request = require('request');
const corsMiddleware = require('restify-cors-middleware');

const cors = corsMiddleware({
  origins: ['*']
});

// Create server.
let tokenServer = restify.createServer();
tokenServer.pre(cors.preflight);
tokenServer.use(cors.actual);
tokenServer.use(bodyParser.json({
  extended: false
}));
tokenServer.dl_name = 'DirectLine';
tokenServer.listen(process.env.port || process.env.PORT || 3500, function() {
  console.log(`
${ tokenServer.dl_name } listening to ${ tokenServer.url }.`);
});

// Listen for incoming requests.
tokenServer.post('/directline/token', (req, res) => {
  // userId must start with `dl_`
  const userId = (req.body && req.body.id) ? req.body.id : `dl_${ Date.now() + Math.random().toString(36) }`;
  const options = {
    method: 'POST',
    uri: 'https://directline.botframework.com/v3/directline/tokens/generate',
    headers: {
      'Authorization': `Bearer ${ process.env.directLineSecret }`
    },
    json: {
      User: {
        Id: userId
      }
    }
  };
  request.post(options, (error, response, body) => {
    if (!error && response.statusCode < 300) {
      res.send({
        token: body.token
      });
    } else {
      res.status(500);
      res.send('Call to retrieve token from DirectLine failed');
    }
  });
});

希望得到帮助!

重新更新 - 2021 年 8 月 6 日

从技术上讲,上面 HTML 中的脚本可以工作,但它的实现并不十分清楚.我提供了这个片段来简化代码.

The script in the HTML above, technically, works though its implementation is not really clear. I've provided this snippet which simplifies the code.

另外,请注意下面的第一行:CDN 从那时起略有变化.当前的稳定版本来自 latest,而不是 master.

Also, note the first line below: The CDN has since changed slightly. The current stable version pulls from latest, not master.

<script src="https://cdn.botframework.com/botframework-webchat/latest/webchat.js"></script>

<script>
  ( async function () {
    let { token, conversation_Id } = sessionStorage;

    if ( !token ) {
      const res = await fetch( 'http://localhost:3500/directline/conversations', { method: 'POST' } );
      const { token: directLineToken, conversationId } = await res.json();

      sessionStorage[ 'token' ] = directLineToken;
      sessionStorage[ 'conversation_Id' ] = conversationId
      token = directLineToken;
    }

    const directLine = createDirectLine( {
      token
    } );

    window.WebChat.renderWebChat( {
      directLine: directLine,
    }, document.getElementById( 'webchat' ) );
    document.querySelector( '#webchat > *' ).focus();
  } )().catch( err => console.error( err ) );
</script>

这篇关于在页面重新加载/导航到另一个页面后,有没有办法在 MS Bot Framework Web Chat 中保留聊天记录?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆