自动启动代理对话

可以将代理配置为开始与用户对话。 您还可以将自定义问候语与自定义代理外观结合起来。

Important

让智能体启动对话将在分析中显示该对话,并增加会话计数。

如果代理的用户没有与代理互动(例如,他们加载了页面但没有向代理提出任何问题),会话就会标记为未互动会话。 此行为可能会影响分析。

默认情况下,使用 Copilot Studio 创建并发布到网站的智能体加载时无问候,会被动等待用户开始对话。

不过,您可以使用自定义 CSS 和 JavaScript 代码,让智能体在加载时自动开始对话。 例如,您可以让代理在加载后立即说“您好,我是虚拟代理 Botty”。

首先,您需要部署一个自定义区域,其中包含用于触发问候的变量。 默认情况下,自定义画布会调用预定义的问候主题。 但是,您可以创建一个新主题用作问候语。 您将默认的问候主题重定向到此新主题。

Important

可以安装和使用本文中包含的示例代码,仅用于 Copilot Studio。 此示例代码“按原样”许可,所有服务级别协议或支持服务中均已排除。 使用本文档时的风险自负。

Microsoft 不提供任何明示担保、保证或条件,并且不提供任何默示担保,包括适销性、特定用途适用性以及不侵犯他人权利的默示担保。

自定义默认画布

使用一些简单的 CSS 和 JavaScript 样式选项配置聊天区域的外观。

首先,需要配置要部署机器人区域的位置。

  1. 创建并发布智能体

  2. 复制以下 HTML 代码并将其保存到名为 index.html 的文件。 或者,将代码复制并粘贴到w3schools.com HTML 试用编辑器中。

    
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8" />
      <meta name="viewport" content="width=device-width, initial-scale=1.0" />
      <meta name="description" content="Contoso Web Chat Assistant" />
      <title>Contoso Sample Web Chat Test</title>
      <script src="https://cdn.botframework.com/botframework-webchat/latest/webchat.js"></script>
      <script>
        let webChatInstance = null;
        let directLineUrl = null;
    
        // Replace with your token endpoint
        const tokenEndpoint = "<YOUR TOKEN ENDPOINT>";
        const styleOptions = {"accent":"#0078D4","autoScrollSnapOnPage":true,"autoScrollSnapOnPageOffset":0,"avatarBorderRadius":"7%","avatarSize":31,"backgroundColor":"#e8e9eb","botAvatarBackgroundColor":"#ffffff00","botAvatarImage":"https://powercatexternal.blob.core.windows.net/creatorkit/Assets/ChatbotLogoBlue.png","botAvatarInitials":"B","bubbleAttachmentMaxWidth":480,"bubbleAttachmentMinWidth":250,"bubbleBackground":"#f0eded","bubbleBorderColor":"#f5f5f5","bubbleBorderRadius":41,"bubbleBorderStyle":"solid","bubbleBorderWidth":1,"bubbleFromUserBackground":"#ebefff","bubbleFromUserBorderColor":"#f5f5f5","bubbleFromUserBorderRadius":41,"bubbleFromUserBorderStyle":"solid","bubbleFromUserBorderWidth":1,"bubbleFromUserNubOffset":0,"bubbleFromUserNubSize":0,"bubbleFromUserTextColor":"#242424","bubbleImageHeight":10,"bubbleImageMaxHeight":240,"bubbleImageMinHeight":240,"bubbleMessageMaxWidth":480,"bubbleMessageMinWidth":120,"bubbleMinHeight":50,"bubbleNubOffset":0,"bubbleTextColor":"#242424","emojiSet":true,"fontSizeSmall":"70%","hideUploadButton":false,"messageActivityWordBreak":"break-word","monospaceFont":"Consolas","paddingRegular":10,"paddingWide":10,"primaryFont":null,"sendBoxBackground":"#e8e9eb","sendBoxBorderTop":"solid 1px #808080","sendBoxButtonColor":"#0078d4","sendBoxButtonColorOnHover":"#006cbe","sendBoxButtonShadeBorderRadius":40,"sendBoxButtonShadeColorOnHover":"","sendBoxHeight":60,"sendBoxPlaceholderColor":"#171616","sendBoxTextColor":"#2e2d2d","showAvatarInGroup":"status","spinnerAnimationHeight":16,"spinnerAnimationPadding":12,"spinnerAnimationWidth":16,"subtleColor":"#000000FF","suggestedActionBackgroundColor":"#006FC4FF","suggestedActionBackgroundColorOnHover":"#0078D4","suggestedActionBorderColor":"","suggestedActionBorderRadius":10,"suggestedActionBorderWidth":1,"suggestedActionLayout":"flow","suggestedActionTextColor":"#FFFFFFFF","typingAnimationBackgroundImage":"url('https://wpamelia.com/wp-content/uploads/2018/11/ezgif-2-6d0b072c3d3f.gif')","typingAnimationDuration":5000,"typingAnimationHeight":20,"typingAnimationWidth":64,"userAvatarBackgroundColor":"#222222","userAvatarImage":"https://avatars.githubusercontent.com/u/8174072?v=4&size=64","userAvatarInitials":"U"};
        const backgroundImage = "";
        document.addEventListener('DOMContentLoaded', () => {
          const root = document.documentElement;
          root.style.setProperty('--primary-color', createGradient(styleOptions.accent));
          root.style.setProperty('--header-textColor', styleOptions.suggestedActionTextColor);
          if (backgroundImage) {
            const webchatElement = document.getElementById('webchat');
            webchatElement.style.backgroundImage = `url(${backgroundImage})`;
            webchatElement.style.backgroundSize = 'cover';
            webchatElement.style.backgroundPosition = 'center';
            webchatElement.style.backgroundRepeat = 'no-repeat';
            const overlay = document.createElement('div');
            overlay.className = 'webchat-overlay';
            webchatElement.appendChild(overlay);
          }
        });
        function createGradient(baseColor) {
          const r = parseInt(baseColor.slice(1,3), 16);
          const g = parseInt(baseColor.slice(3,5), 16);
          const b = parseInt(baseColor.slice(5,7), 16);
          const lighterColor = `#${Math.min(255, r+30).toString(16).padStart(2,'0')}${Math.min(255, g+30).toString(16).padStart(2,'0')}${Math.min(255, b+30).toString(16).padStart(2,'0')}`;
          const darkerColor = `#${Math.max(0, r-30).toString(16).padStart(2,'0')}${Math.max(0, g-30).toString(16).padStart(2,'0')}${Math.max(0, b-30).toString(16).padStart(2,'0')}`;
          return `linear-gradient(135deg, ${lighterColor}, ${baseColor}, ${darkerColor})`;
        }
        const environmentEndPoint = tokenEndpoint.slice(
          0,
          tokenEndpoint.indexOf("/powervirtualagents")
        );
        const apiVersion = tokenEndpoint
          .slice(tokenEndpoint.indexOf("api-version"))
          .split("=")[1];
        const regionalChannelSettingsURL = `${environmentEndPoint}/powervirtualagents/regionalchannelsettings?api-version=${apiVersion}`;
        function showChat() {
          const popup = document.getElementById("chatbot-popup");
          const openButton = document.getElementById("open-chat");
          popup.classList.add("visible");
          openButton.classList.add("hidden");
        }
        function hideChat() {
          const popup = document.getElementById("chatbot-popup");
          const openButton = document.getElementById("open-chat");
          popup.classList.remove("visible");
          openButton.classList.remove("hidden");
        }
        function createCustomStore() {
          return window.WebChat.createStore(
            {},
            ({ dispatch }) =>
              (next) =>
              (action) => {
                if (action.type === "DIRECT_LINE/CONNECT_FULFILLED") {
                  dispatch({
                    type: "DIRECT_LINE/POST_ACTIVITY",
                    meta: { method: "keyboard" },
                    payload: {
                      activity: {
                        channelData: { postBack: true },
                        name: "startConversation",
                        type: "event",
                      },
                    },
                  });
                }
                return next(action);
              }
          );
        }
        async function restartConversation() {
          try {
            if (!directLineUrl) {
              console.error("DirectLine URL not initialized");
              return;
            }
            const response = await fetch(tokenEndpoint);
            const conversationInfo = await response.json();
            if (!conversationInfo.token) {
              throw new Error("Failed to get conversation token");
            }
            const newDirectLine = window.WebChat.createDirectLine({
              domain: `${directLineUrl}v3/directline`,
              token: conversationInfo.token,
            });
            const webchatElement = document.getElementById("webchat");
            webChatInstance = window.WebChat.renderWebChat(
              {
                directLine: newDirectLine,
                styleOptions,
                store: createCustomStore(),
              },
              webchatElement
            );
          } catch (err) {
            console.error("Failed to restart conversation:", err);
          }
        }
        async function initializeChat() {
          try {
            const response = await fetch(regionalChannelSettingsURL);
            const data = await response.json();
            directLineUrl = data.channelUrlsById.directline;
            if (!directLineUrl) {
              throw new Error("Failed to get DirectLine URL");
            }
            const conversationResponse = await fetch(tokenEndpoint);
            const conversationInfo = await conversationResponse.json();
            if (!conversationInfo.token) {
              throw new Error("Failed to get conversation token");
            }
            const directLine = window.WebChat.createDirectLine({
              domain: `${directLineUrl}v3/directline`,
              token: conversationInfo.token,
            });
            webChatInstance = window.WebChat.renderWebChat(
              {
                directLine,
                styleOptions,
                store: createCustomStore(),
              },
              document.getElementById("webchat")
            );
          } catch (err) {
            console.error("Failed to initialize chat:", err);
          }
        }
        initializeChat();
      </script>
      <style>
        :root {
          --primary-gradient: var(--primary-color);
          --chat-width: 450px;
          --chat-height: 520px;
          --header-height: 56px;
          --border-radius: 16px;
          --transition-speed: 0.3s;
        }
        * {
          margin: 0;
          padding: 0;
          box-sizing: border-box;
          font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
            Roboto, sans-serif;
        }
        body {
          min-height: 100vh;
          background-color: #f3f4f6;
        }
        #chatbot-popup {
          display: none;
          position: fixed;
          bottom: 32px;
          right: 32px;
          width: var(--chat-width);
          height: var(--chat-height);
          background: white;
          border-radius: var(--border-radius);
          box-shadow: 0 18px 40px -5px rgba(0, 0, 0, 0.2),
            0 15px 20px -5px rgba(0, 0, 0, 0.1);
          overflow: hidden;
          opacity: 0;
          transform-origin: bottom right;
          transform: scale(0.95);
          transition: all var(--transition-speed) ease-in-out;
          z-index: 999;
        }
        #chatbot-popup.visible {
          display: block;
          opacity: 1;
          transform: scale(1);
        }
        #chatbot-header {
          background: var(--primary-color);
          padding: 16px 20px;
          height: var(--header-height);
          display: flex;
          justify-content: space-between;
          align-items: center;
          color: var(--header-textColor);
        }
        .header-title {
          display: flex;
          align-items: center;
          gap: 12px;
          font-size: 16px;
          font-weight: 500;
        }
        .header-buttons {
          display: flex;
          gap: 12px;
          align-items: center;
        }
        .icon-button {
          background: none;
          border: none;
          color: var(--header-textColor);
          cursor: pointer;
          padding: 8px;
          border-radius: 8px;
          display: flex;
          align-items: center;
          justify-content: center;
          transition: all 0.2s ease;
        }
        .icon-button:hover {
          color: var(--header-textColor);
          background: rgba(255, 255, 255, 0.1);
        }
        .icon-button:focus {
          outline: 2px solid rgba(255, 255, 255, 0.5);
          outline-offset: 2px;
        }
        #webchat {
          height: calc(100% - var(--header-height));
          background-color: #f9fafb;
          position: relative;
        }
        .webchat-overlay {
          position: absolute;
          top: 0;
          left: 0;
          right: 0;
          bottom: 0;
          background: rgba(255, 255, 255, 0.85);
          pointer-events: none;
          z-index: 1;
        }
        #webchat > div {
          position: relative;
          z-index: 2;
        }
        #webchat .webchat__basic-transcript__content {
          white-space: pre-wrap !important;
          word-break: break-word !important;
        }
        #webchat .webchat__bubble__content {
          padding: 8px 12px !important;
        }
        #webchat .webchat__bubble {
          max-width: 85% !important;
          margin: 8px !important;
        }
        #webchat .webchat__basic-transcript__content ul,
        #webchat .webchat__basic-transcript__content ol,
        #webchat .webchat__bubble__content ul,
        #webchat .webchat__bubble__content ol {
          padding-left: 24px !important;
          margin: 8px 0 !important;
          list-style-position: outside !important;
        }
        #webchat .webchat__basic-transcript__content li,
        #webchat .webchat__bubble__content li {
          margin: 4px 0 !important;
          padding-left: 4px !important;
        }
        #open-chat {
          position: fixed;
          bottom: 32px;
          right: 32px;
          width: 64px;
          height: 64px;
          border-radius: 50%;
          background: var(--primary-gradient);
          border: none;
          cursor: pointer;
          display: flex;
          align-items: center;
          justify-content: center;
          box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
          transition: all var(--transition-speed) ease-in-out;
          z-index: 998;
        }
        #open-chat.hidden {
          opacity: 0;
          transform: scale(0.95) translateY(10px);
          pointer-events: none;
        }
        #open-chat:hover {
          transform: translateY(-4px);
          box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
        }
        #open-chat:focus {
          outline: 3px solid rgba(79, 70, 229, 0.5);
          outline-offset: 2px;
        }
        #open-chat svg {
          width: 28px;
          height: 28px;
          color: white;
          transition: transform 0.2s ease;
        }
        .main-content {
          max-width: 1200px;
          margin: 0 auto;
          padding: 48px 24px;
        }
        .main-content h1 {
          font-size: 36px;
          color: #111827;
          text-align: center;
        }
        .main-content p {
          font-size: 18px;
          color: #4b5563;
          line-height: 1.6;
          margin-bottom: 48px;
          text-align: center;
          max-width: 800px;
          margin-left: auto;
          margin-right: auto;
        }
        .content-grid {
          display: grid;
          grid-template-columns: repeat(2, 1fr);
          gap: 32px;
          margin-bottom: 32px;
        }
        .content-box {
          background: linear-gradient(135deg, #e6e6e6, #c4c4c4, #9f9f9f);
          padding: 32px;
          border-radius: 12px;
          box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1),
                      0 2px 4px -1px rgba(0, 0, 0, 0.06);
          min-height: 300px;
          display: flex;
          flex-direction: column;
          justify-content: center;
          align-items: center;
          text-align: center;
          position: relative;
          overflow: hidden;
        }
        .content-box::before {
          content: '';
          position: absolute;
          top: 0;
          left: 0;
          right: 0;
          height: 4px;
        }
        .content-box.featured {
          grid-column: span 2;
          min-height: 350px;
          background: linear-gradient(135deg, #e6e6e6, #c4c4c4, #9f9f9f);
          color: #000000;
        }
        .content-box h2 {
          font-size: 24px;
          margin-bottom: 16px;
          position: relative;
        }
        .content-box p {
          font-size: 16px;
          color: #6b7280;
          margin-bottom: 0;
        }
        .content-box.featured p {
          color: #000000;
        }
        @media (max-width: 768px) {
          .content-grid {
            grid-template-columns: 1fr;
          }
          .content-box.featured {
            grid-column: span 1;
          }
          .main-content {
            padding: 24px 16px;
          }
          .main-content h1 {
            font-size: 28px;
          }
          #chatbot-popup {
            width: 100%;
            height: 100%;
            bottom: 0;
            right: 0;
            border-radius: 0;
          }
        }
      </style>
    </head>
    <body>
      <div class="main-content">
        <h1>Header</h1>
        <p>Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat.</p>
        <div class="content-grid">
          <div class="content-box featured">
            <h2>Featured Content</h2>
            <p>Primary content area with custom styling and gradient background</p>
          </div>
          <div class="content-box">
            <h2>Section One</h2>
            <p>Content box with minimal design</p>
          </div>
          <div class="content-box">
            <h2>Section Two</h2>
            <p>Another content section with consistent styling</p>
          </div>
        </div>
      </div>
      <div id="chatbot-popup" role="complementary" aria-label="Chat Assistant">
        <div id="chatbot-header">
          <div class="header-title">
            <svg
              class="chat-icon"
              width="24"
              height="24"
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              stroke-width="2"
              stroke-linecap="round"
              stroke-linejoin="round"
              aria-hidden="true"
            >
              <path
                d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"
              ></path>
            </svg>
            <span>Contoso Assistant</span>
          </div>
          <div class="header-buttons">
            <button
              class="icon-button"
              id="restart-button"
              onclick="restartConversation()"
              aria-label="Restart Conversation"
            >
              <svg
                width="20"
                height="20"
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
                stroke-linecap="round"
                stroke-linejoin="round"
                aria-hidden="true"
              >
                <path
                  d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"
                ></path>
                <path d="M3 3v5h5"></path>
              </svg>
            </button>
            <button
              class="icon-button"
              id="close-button"
              onclick="hideChat()"
              aria-label="Close Chat"
            >
              <svg
                width="20"
                height="20"
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
                stroke-linecap="round"
                stroke-linejoin="round"
                aria-hidden="true"
              >
                <line x1="18" y1="6" x2="6" y2="18"></line>
                <line x1="6" y1="6" x2="18" y2="18"></line>
              </svg>
            </button>
          </div>
        </div>
        <div id="webchat" role="main"></div>
      </div>
      <button
        id="open-chat"
        onclick="showChat()"
        aria-label="Open Chat Assistant"
      >
        <svg
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          stroke-width="2"
          stroke-linecap="round"
          stroke-linejoin="round"
          aria-hidden="true"
        >
          <path
            d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"
          ></path>
        </svg>
      </button>
    </body>
    </html>
    
    
  3. 获取您的智能体的令牌终结点

  4. index.html 中,在第 const tokenEndpoint = "<YOUR TOKEN ENDPOINT>"; 行,用您的智能体的令牌端点替换占位符。

  5. 使用新式浏览器(例如,Microsoft Edge)打开 index.html ,以在自定义画布中打开代理。

  6. 测试代理,以确保收到来自它的响应,并且它正常工作。

    如果遇到问题,请确保已发布智能体,并且令牌终结点位于正确的位置。 标记终结点应该位于行 const tokenEndpoint = "<YOUR TOKEN ENDPOINT>"; 中的等号 (=) 后,并且两侧有双引号 (")。

检索智能体的令牌终结点

无论您使用的是默认画布还是连接的自定义画布,都需要智能体的令牌端点。

  1. 在导航菜单中的设置下面,选择渠道

  2. 选择电子邮件。 此时会显示此通道的配置面板。

  3. 令牌终结点旁边,选择复制

更改代理的默认问候语

文件 index.html 中的代码会导致在加载代理时自动调用某个主题。 默认情况下,该代码调用问候主题。 还可以创建新主题并将默认问候主题转移到该新主题。

在这两种情况下,都可以更改要正常调用的主题

如果您修改了问候主题或创建了新的主题,您应明确告知用户正在与智能体(或“虚拟智能体”)进行对话。 此类指示可帮助用户了解自己是在与机器而非人类交谈。

我们建议您修改预设的问候主题,这样您无需编辑 index.html 代码。

  1. 转到智能体的主题页面,并选择问候主题。

  2. 编辑消息节点内的文本。 还可以 添加或删除节点

  3. 选择“保存”

  4. 发布您的智能体

现在,您可以访问部署代理自定义画布的网页来测试代理。 您将看到机器人通过自动显示问候主题来启动对话。

创建新的自定义主题

Warning

使用自定义主题开始对话会增加您的计费会话。 记帐会话是客户与代理之间的交互,代表了一个单元的消耗。 计费会话在触发自定义主题时开始。 有关详细信息,请参阅管理消息容量

  1. 转到智能体的主题页面。

  2. 选择“从空白>”。

  3. 输入新主题的名称。

  4. 添加消息节点并配置所需消息。

  5. 编辑完成后选择保存

  6. 再次进入主题页面,选择问候主题。

  7. Greeting 主题中删除所有消息节点

  8. 要自动将智能体转至新主题,添加重定向节点,并将新主题设为目标。

  9. 选择保存,并发布您的智能体

现在,您可以访问部署代理自定义画布的网页来测试代理。 您可以看到代理通过自动显示新主题开始对话。