ปรับแต่งรูปลักษณ์ของเอเจนต์

Note

บทความนี้อธิบายคุณสมบัติที่ใช้ในเอเจนต์หรือการไหลของเอเจนต์ที่ขับเคลื่อนโดยฮาร์เนสมาตรฐาน

พื้นที่ทํางานของตัวแทนควบคุมวิธีการที่ตัวแทนปรากฏต่อผู้ใช้ คุณสามารถกําหนดพื้นที่ทํางานได้สองวิธี:

คุณยังสามารถรวมพื้นที่ทํางานแบบกําหนดเองด้วยการกําหนดค่าการเริ่มการสนทนาอัตโนมัติ

คุณสามารถ เปลี่ยนชื่อตัวแทนและไอคอนในพอร์ทัลได้

หลังจากที่คุณเผยแพร่ตัวแทน ผู้ใช้สามารถโต้ตอบกับตัวแทน>ผ่านพื้นที่ เนื้อหาการคุยผ่านเว็บ

Important

คุณสามารถติดตั้ง และใช้โค้ดตัวอย่างที่รวมอยู่ในบทความนี้สําหรับใช้กับ Copilot Studio เท่านั้น โค้ดตัวอย่างได้รับอนุญาต "ตามสภาพ" และไม่รวมอยู่ในข้อตกลงระดับการให้บริการหรือบริการสนับสนุนใด ๆ คุณจะต้องเป็นผู้ยอมรับความเสี่ยงที่อาจจะเกิดขึ้นในการใช้งานดังกล่าว

Microsoft ไม่มีการรับประกัน การการันตี หรือเงื่อนไขและไม่รวมการรับประกันโดยนัยทั้งหมด ซึ่งรวมถึงอรรถประโยชน์ในเชิงพาณิชย์ ความเหมาะสมสำหรับวัตถุประสงค์เฉพาะกิจ และการไม่ละเมิดลิขสิทธิ์

เปลี่ยนชื่อและไอคอนของเอเจนต์

Important

  • หลังจากที่คุณอัปเดตไอคอนสําหรับตัวแทนแล้ว อาจใช้เวลาถึง 24 ชั่วโมงเพื่อให้ไอคอนใหม่ปรากฏทุกที่
  • ถ้าตัวแทนของคุณเชื่อมต่อกับ Omnichannel สำหรับฝ่ายบริการลูกค้า คุณสมบัติ ชื่อที่แสดง ในการลงทะเบียนพอร์ทัล Azure จะกำหนดชื่อของมัน
  • หากตัวแทนของคุณมีไว้เพื่อเผยแพร่ไปยัง Teams ให้ตรวจสอบ ข้อกําหนดสําหรับไอคอน ในเอกสารสําหรับนักพัฒนา Microsoft Teams
  1. ไปที่หน้า ภาพรวม สำหรับเอเจนต์ของคุณ

  2. เลือก แก้ไข ถัดจาก รายละเอียด

  3. เปลี่ยนชื่อและไอคอนของตัวแทนตามที่คุณต้องการ

  4. เลือก บันทึก

ปรับแต่งพื้นที่ทำงานเริ่มต้น (แบบง่าย)

ใช้ JavaScript และ CSS เพื่อปรับพื้นที่ทํางานเริ่มต้น

ขั้นแรก ให้กําหนดค่าตําแหน่งที่คุณกําลังปรับใช้พื้นที่ทํางานของตัวแทนของคุณ

  1. สร้างและเผยแพร่เอเจนต์

  2. คัดลอกโค้ด HTML ตัวอย่างลงในไฟล์ที่ชื่อว่าindex.html คุณยังสามารถใช้ ตัวแก้ไขลองทํา 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. เปิด index.html ในเบราว์เซอร์สมัยใหม่ เช่น Microsoft Edge

  6. ทดสอบเจ้าหน้าที่

หากเจ้าหน้าที่ไม่ตอบสนอง:

  • ตรวจสอบให้แน่ใจว่าเอเจนต์ได้รับการเผยแพร่แล้ว
  • ตรวจสอบค่าจุดสิ้นสุดโทเค็น
  • ยืนยันว่าจุดสิ้นสุดโทเค็นปรากฏขึ้นหลังจาก = โดยล้อมรอบด้วยเครื่องหมายอัญประกาศคู่ "

เรียกใช้จุดสิ้นสุดโทเค็นสําหรับตัวแทนของคุณ

หากต้องการปรับแต่งพื้นที่ทํางานของคุณ ไม่ว่าจะเป็นพื้นที่ทํางานเริ่มต้นหรือพื้นที่ทํางานแบบกําหนดเองที่คุณเชื่อมต่อ คุณจําเป็นต้องมีจุดสิ้นสุดโทเค็นสําหรับตัวแทนของคุณ

  1. ในการตั้งค่า เลือกช่อง

  2. เลือก อีเมล

  3. ถัดจากจุดสิ้นสุดโทเค็น ให้เลือก คัดลอก

ปรับแต่งไอคอน สีพื้นหลัง และชื่อของเอเจนต์

styleOptionsใช้วัตถุ เพื่อกําหนดค่าลักษณะที่กําหนดไว้ล่วงหน้า

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับสิ่งที่คุณสามารถกำหนดเองและการลิงก์ไปยังไฟล์ defaultStyleOptions.js กรุณาดูที่ การปรับแต่ง เนื้อหาการคุยผ่านเว็บ

เปลี่ยนไอคอนของเอเจนต์

  1. index.htmlอัปเดตไฟล์ด้วยโค้ดตัวอย่างต่อไปนี้:

    const styleOptions = {
      "accent": "#00809d",
      "botAvatarBackgroundColor": "#FFFFFF",
      "botAvatarImage": "https://learn.microsoft.com/azure/bot-service/v4sdk/media/logo_bot.svg",
      "botAvatarInitials": "BT",
      "userAvatarImage": "https://avatars.githubusercontent.com/u/661465",
      "userAvatarInitials": "U"
    };
    
  2. แทนที่รูปภาพอวาตาร์ทั้งสองด้วยรูปภาพบริษัทของคุณ หากคุณไม่มี URL รูปภาพ ให้ใช้สตริงรูปภาพที่เข้ารหัสด้วย Base64 แทน

เปลี่ยนสีพื้นหลัง

  1. เพิ่ม index.html องค์ประกอบเข้าไปในคำนิยาม backgroundColor ของคุณใน styleOptions :

    const styleOptions = {
      "backgroundColor": "lightgray",
      // ...
    };
    
  2. เปลี่ยน backgroundColor เป็นสีใดก็ได้ที่คุณต้องการ ใช้ชื่อสีมาตรฐานของ CSS, ค่า RGB หรือ HEX

เปลี่ยนชื่อของเอเจนต์

  1. อัปเดต <h1> ข้อความส่วนหัวใน index.html ไฟล์ด้วยรหัสต่อไปนี้:

    <body>
      <div id="banner">
        <h1><img src="contoso-agent.png"> Contoso agent name</h1>
      </div>
      <!-- ... -->
    
  2. เปลี่ยนข้อความเป็นอะไรก็ได้ที่คุณต้องการเรียกเอเจนต์ คุณยังสามารถแทรกรูปภาพได้ แต่คุณอาจต้องจัดรูปแบบให้พอดีกับส่วนหัวเรื่อง

ปรับแต่งและโฮสต์พื้นที่ทำงานแชทของคุณ (ขั้นสูง)

คุณสามารถเชื่อมต่อตัวแทน Copilot Studio ของคุณกับพื้นที่ทํางานแบบกําหนดเองที่คุณโฮสต์เป็นเว็บแอปแบบสแตนด์อโลนได้ ตัวเลือกนี้ทํางานได้ดีที่สุดหากคุณต้องการฝัง iFrame ที่กําหนดเองในหน้าเว็บหลายหน้า

Note

การโฮสต์พื้นที่ทำงานแบบกำหนดเองจำเป็นต้องมีการพัฒนาซอฟต์แวร์ คําแนะนํานี้มีไว้สําหรับผู้เชี่ยวชาญด้าน IT ที่มีประสบการณ์ เช่น ผู้ดูแลระบบ IT หรือนักพัฒนาที่มีความเข้าใจที่ดีเกี่ยวกับเครื่องมือสําหรับนักพัฒนา โปรแกรมอรรถประโยชน์ และสภาพแวดล้อมการพัฒนาแบบรวม (IDEs)

เริ่มต้นด้วยหนึ่งในตัวอย่างเหล่านี้ที่สร้างขึ้นเพื่อทํางานกับ Copilot Studio:

  • Full bundle เป็นพื้นที่ทํางานแบบกําหนดเองที่สามารถแสดงเนื้อหาที่สมบูรณ์ทั้งหมดจาก Copilot Studio ตัวอย่างเช่น:

    พื้นที่ทำงานแบบกำหนดเองรวมเต็ม

  • การอัปโหลดไฟล์และการอัปโหลดไฟล์ เป็นพื้นที่ทํางานแบบกําหนดเองที่มีความสามารถในการรับตําแหน่งที่ตั้งของผู้ใช้และส่งไปยังตัวแทน Copilot Studio ตัวอย่างเช่น:

    ตำแหน่งและไฟล์ที่อัปโหลดพื้นที่ทำงานแบบกำหนดเอง

อีกวิธีหนึ่งคือ ลองใช้ตัวอย่าง เนื้อหาการคุยผ่านเว็บ พื้นที่ทํางาน จาก Bot Framework

เช่นเดียวกับพื้นที่ทํางานเริ่มต้น คุณสามารถใช้ styleSetOptions เพื่อปรับแต่งพื้นที่ทํางานแบบกําหนดเองได้ คุณสมบัติแบบปรับแต่งได้ทั้งหมดอยู่ใน defaultStyleOptions.js สําหรับข้อมูลเพิ่มเติมเกี่ยวกับสิ่งที่คุณสามารถกําหนดเอง ดูเนื้อหาการคุยผ่านเว็บ กําหนดเอง

รองรับการตั้งค่าการเชื่อมต่อในแคนวาสแบบกำหนดเอง

เมื่อเอเจนต์ที่ทำงานโดยใช้ชุดเครื่องมือมาตรฐานต้องการการเชื่อมต่อจากผู้ใช้ พื้นที่ทำงานการแชทจะได้รับการ์ดที่ปรับเปลี่ยนได้ที่จําเป็นสําหรับการเชื่อมต่อ แคนวาสแบบกำหนดเองของคุณต้องจัดการกับการกระทำของการ์ด Action.OpenUrlDialog หากไม่มีการจัดการนี้ การเลือก Connect จะไม่เปิดหน้าต่างการเชื่อมต่อที่โฟกัส

เปิดหน้าต่างการเชื่อมต่อ

  1. ลงทะเบียน Action.OpenUrlDialog ในตัวแสดงผลการ์ดที่ปรับเปลี่ยนได้ของคุณและอ่านคุณสมบัติ url รับเฉพาะ absolute http:// หรือ https:// URL เท่านั้น
  2. ตัดสินใจว่าต้นทางของปลายทางนั้นน่าเชื่อถือหรือไม่ก่อนเปิด ไว้วางใจเฉพาะต้นทางที่คุณควบคุมหรือที่ทีมความปลอดภัยของคุณตรวจสอบและอนุญาตให้ลงรายการเท่านั้น
  3. เปิด URL โดยตรงจากที่ผู้ใช้เลือกด้วย window.open(url, "_blank", "popup"). การเปิดหน้าต่างจากการกระทําของผู้ใช้จะช่วยลดโอกาสที่เบราว์เซอร์จะบล็อกหน้าต่างนั้น
  4. สําหรับปลายทางที่เชื่อถือได้ ในwindowFeaturesอาร์กิวเมนต์ของ window.open, ละเว้น noopener และnoreferrerดังนั้นหน้าต่างการเชื่อมต่อสามารถส่งผลลัพธ์กลับไปยังwindow.opener สําหรับปลายทางอื่น ๆ ให้ใช้ noopener,noreferrer และไม่รับข้อความตอบกลับ
  5. เก็บข้อมูลอ้างอิงที่ส่งกลับมา Window และรหัสกิจกรรมของการ์ดที่ต้องการการเชื่อมต่อไว้ หากป๊อปอัพถูกบล็อก หรือผู้ใช้ปิดโดยไม่ได้ผลลัพธ์ที่ถูกต้อง ให้คง Continue หรือการดําเนินการกู้คืนอื่นไว้ อย่าตีความการปิดหน้าต่างว่าเป็นการสร้างการเชื่อมต่อสำเร็จ

JavaScript SDK การ์ดที่ปรับเปลี่ยนได้ไม่ใช้งาน Action.OpenUrlDialog โดยค่าเริ่มต้น ลงทะเบียนแอ็กชันผ่าน SerializationContext.actionRegistry หรือจัดการแอ็กชันโดยตรงในเรนเดอเรอร์ที่คุณดูแล Action.OpenUrl Fallback สามารถเปิดปลายทางในไคลเอนต์ที่ไม่รองรับการดําเนินการกล่องโต้ตอบ แต่ fallback ไม่สามารถส่งผลลัพธ์ป๊อปอัพกลับมาได้

Important

หน้าต่างการเชื่อมต่อที่มีการเข้าถึง window.opener สามารถนำทางหรือส่งผลกระทบต่อหน้าแชทได้ ตรวจสอบปลายทางและการรีไดเร็กต์ร่วมกับทีมรักษาความปลอดภัยเว็บของคุณ อย่าอนุญาตให้ปลายทางที่เชื่อถือได้เปลี่ยนเส้นทางไปยังไซต์ที่ไม่น่าเชื่อถือในขณะที่ยังคงการเข้าถึงของผู้ที่เปิด

หากคุณฝังเว็บแชทของ Bot Framework การจัดการ Action.OpenUrlDialog จะเปิดหน้าต่างการเชื่อมต่อ หน้าต่างที่มีต้นทางเดียวกันจะได้รับความน่าเชื่อถือโดยค่าเริ่มต้น สําหรับปลายทางข้ามต้นทางที่ตรวจสอบแล้ว ให้ตั้งค่า styleOptions.callURLActionTrustedOrigin เป็นต้นทางที่อนุญาตอย่างชัดแจน แยกแหล่งที่มาหลายรายการด้วยเครื่องหมายจุลภาค คุณยังสามารถตั้งค่า callURLActionPopupWindowHeight และ callURLActionPopupWindowWidth ได้ อย่าเพิ่ม origin ที่คุณยังไม่ได้รีวิว

ดําเนินการต่อหลังจากตั้งค่าการเชื่อมต่อสําเร็จ (ตัวอย่าง)

[ส่วนนี้เป็นเอกสารก่อนการนำออกใช้ และอาจเปลี่ยนแปลงได้]

Important

บทความนี้มีเอกสารรุ่นพรีวิว Microsoft Copilot Studio และอาจจะมีการเปลี่ยนแปลงในอนาคต

คุณลักษณะพรีวิวไม่ได้มีไว้สำหรับการนำไปใช้งานจริงและอาจมีฟังก์ชันการทำงานที่จำกัด คุณลักษณะเหล่านี้สามารถใช้ได้ก่อนการเปิดตัวอย่างเป็นทางการเพื่อให้คุณสามารถเข้าใช้งานได้ก่อนเวลาและให้ข้อคิดเห็น

หากคุณกำลังสร้างเอเจนต์ที่พร้อมสำหรับการใช้งานจริง โปรดดู ภาพรวมของ Microsoft Copilot Studio

หน้าต่างการเชื่อมต่อที่เชื่อถือได้สามารถส่งผลลัพธ์การเสร็จสิ้นไปยังหน้าแชทด้วย window.opener.postMessage. ใช้จุดกําเนิดที่แน่นอนของหน้าแชทเป็นจุดเริ่มต้นเป้าหมาย ไม่ใช่ *.

ในหน้าแชท:

  1. หาก window.open ส่งกลับ null อย่ารับข้อความสําหรับการพยายามนั้น มิฉะนั้น ให้ยอมรับข้อความเฉพาะเมื่อ event.source ตรงกับการอ้างอิงป๊อปอัพที่เก็บไว้และ event.origin ตรงกับต้นทางที่คาดหวัง

  2. ตรวจสอบว่าข้อมูลข้อความมี type: "postback" และค่าที่อยู่ในรูปแบบที่เอเจนต์หรือรันไทม์ของคุณคาดหวัง

    ตัวอย่างต่อไปนี้ส่งข้อความพร้อมข้อความ "hello-world" ไปยังเอเจนต์ มันไม่แสดงใน UI แชท

    { "type": "postback", "value": { hello: "World!" } }
    

    ตัวอย่างต่อไปนี้ส่งข้อความพร้อม JSON { hello: "World!" } ไปยังเอเจนต์

    { "type": "postback", "value": { hello: "World!" } }
    
  3. ส่งค่าที่ยอมรับผ่านกลไก Postback ของ Bot Framework ใช้รหัสกิจกรรมที่เก็บไว้เป็น replyToId; ไม่รับรหัสกิจกรรมตอบกลับจากป๊อปอัพ

  4. ยอมรับผลลัพธ์ได้สูงสุดหนึ่งผลลัพธ์สําหรับแต่ละป๊อปอัพ ลบตัวรอรับเหตุการณ์และล้างตัวจับเวลาหลังจากยอมรับผลลัพธ์, ปฏิเสธข้อความผิดรูปแบบจากป๊อปอัพที่เชื่อถือได้, ตรวจพบว่าป๊อปอัพปิดแล้ว, หรือถึงเวลาที่จำกัด เนื้อหาการคุยผ่านเว็บ มีการจำกัดเวลา 5 นาที

  5. ประสานงานกับเอเจนต์หรือรันไทม์เพื่อเชื่อมโยงการโพสต์กลับกับการโต้ตอบเดิมที่ต้องมีการเชื่อมต่อ และกลับมาดำเนินเทิร์นนั้นต่อเพียงครั้งเดียว

การส่งข้อความผ่านเบราว์เซอร์เป็นการดำเนินการที่ดีที่สุด ตัวบล็อกป๊อปอัพ, การนําทาง, นโยบายตัวเปิดข้ามแหล่งที่มา (COOP) หรือหน้าต่างที่ปิดอยู่ อาจทําให้การดําเนินการต่ออัตโนมัติไม่สําเร็จ คงให้มี Continue หรือเส้นทางการกู้คืนอื่น ๆ พร้อมใช้งาน และอย่าตีความข้อความที่ขาดหายไปว่าเป็นความสำเร็จ

ปรับใช้พื้นที่ทำงานแบบกำหนดเองของคุณ

หากต้องการโฮสต์พื้นที่ทํางานแบบกําหนดเองของคุณ ให้ปรับใช้ไฟล์ทั้งหมดไปยังเว็บแอป