運用 Google Chat、Vertex AI 與 Apps Script 針對事件做出回應

這個教學課程會說明如何製作符合下列條件的 Google Chat 應用程式: 即時回應事件。回應事件時,應用程式 建立並填入 Chat 聊天室,促進事件 透過訊息、斜線指令和對話方塊解決問題,並使用 AI 生成摘要 擷取及回報事件

事件是指需要立即團隊採取行動的事件 解決問題這類事件包括:

  • 在客戶關係管理 (CRM) 中建立一個定時案例 需要服務團隊共同解決問題。
  • 系統離線,提醒一群網站可靠性工程師 (SRE) ,這樣他們就能共同合作,讓網站再次上線
  • 發生規模極大的地震,因此緊急工作人員必須 協調各方回應

為進行本教學課程,系統會在使用者 用來回報事件。網頁會模擬 要求使用者輸入基本事件資訊:標題、 作答者的電子郵件地址與電子郵件地址

瞭解事件管理 Chat 應用程式的實際運作情形:

  • 觸發事件的網站。
    圖 1.可讓使用者檢舉事件的網站。
  • 通知:事件 Chat 聊天室已建立。
    圖 2.通知,說明事件 Chat 聊天室已建立。
  • 事件回應 Chat 聊天室。
    圖 3.事件回應 Chat 聊天室。
  • 使用斜線指令解決事件。
    圖 4.使用斜線指令解決事件。
  • 事件解決對話方塊。
    圖 5.事件解決對話方塊。
  • 在聊天室中共用的事件解決 Google 文件。
    圖 6.在聊天室中共用的事件解決 Google 文件。
  • Google 文件的 AI 摘要事件解決方式
    圖 7.Google 文件的 AI 摘要事件解決方式。

必要條件

如果貴機構需要啟用上述任何必備條件,可以參閱 請按照下列步驟開啟這項功能:

  • 企業或企業 具有存取權的 Google Workspace 帳戶 Google Chat
  • 希望 目錄 已開啟 Google Workspace 的聯絡人 (聯絡人共用)。事件應用程式會使用 查詢事件回應者的聯絡資訊,例如姓名 以及電子郵件地址事件回應者必須是 Google Chat 使用者 帳戶。

目標

  • 建構可回應事件的 Chat 應用程式。
  • 請採取下列行動,協助使用者回應事件:
    • 建立事件回應空間。
    • 張貼關於事件和回應的摘要訊息。
    • 透過互動式促進協同合作 Chat 應用程式功能。
  • 運用 Vertex AI 總結對話內容與解決方法。

架構

下圖顯示 Google Workspace 和 事件回應使用的 Google Cloud 資源 Google Chat 應用程式。

Google Chat 應用程式事件回應的架構

架構說明事件回應方式 Google Chat 應用程式會處理事件並解決問題。

  1. 使用者從託管於 Apps Script。

  2. 網站將非同步 HTTP 要求傳送至 Google Chat 應用程式,同樣由 Apps Script 代管。

  3. 事件回應 Google Chat 應用程式會處理這項要求:

    1. Apps Script Admin SDK 服務可獲得團隊成員 例如使用者 ID 和電子郵件地址

    2. 使用 Apps Script Advanced Chat 服務, 事件回應 Google Chat 應用程式會建立事件即時通訊 加入團隊成員,並從聊天室傳送訊息至聊天室。

  4. 團隊成員在 Chat 聊天室中討論事件。

  5. 團隊成員叫用斜線指令,向 事件。

    1. 使用 Apps Script 向 Chat API 發出 HTTP 呼叫 進階 Chat 服務會列出所有 Chat 聊天室的訊息。

    2. Vertex AI 收到列出的訊息後,就會產生摘要。

    3. Apps Script「DocumentApp」服務會建立 說明文件,並將 Vertex AI 的摘要新增至 文件。

    4. 事件回應 Google Chat 應用程式呼叫 Chat API,用於傳送訊息分享摘要連結 文件。

準備環境

本節說明如何建立及設定 Chat 應用程式。

建立 Google Cloud 專案

Google Cloud 控制台

  1. 在 Google Cloud 控制台中,前往「選單」圖示 > IAM 與管理員 > 建立專案

    前往「建立專案」

  2. 在「Project Name」(專案名稱) 欄位,輸入專案的描述性名稱。

    選用:如要編輯「專案 ID」,請按一下「編輯」。無法變更專案 ID 因此請在專案建立後根據 專案。

  3. 按一下「地區」欄位中的「瀏覽」,即可查看可能的地理位置 專案。然後按一下「選取」
  4. 點選「建立」。Google Cloud 控制台前往「資訊主頁」頁面,已建立專案 幾分鐘內

gcloud CLI

在下列任一開發環境中,存取 Google Cloud CLI (`gcloud`):

  • Cloud Shell:透過 gcloud CLI 使用線上終端機 設定完畢,請啟用 Cloud Shell
    啟用 Cloud Shell
  • Local Shell:如要使用本機開發環境, 安裝初始化 使用 gcloud CLI
    如要建立 Cloud 專案,請使用「gcloud projects create」指令:
    gcloud projects create PROJECT_ID
    敬上 設定您要建立的專案 ID,以取代 PROJECT_ID

啟用 Cloud 專案的計費功能

Google Cloud 控制台

  1. 在 Google Cloud 控制台中,前往「帳單」。按一下 選單 > 帳單 >「我的專案」

    前往「我的專案帳單」頁面

  2. 在「選取機構」中,選擇相關聯的機構 管理 Google Cloud 專案
  3. 在專案列中,開啟「動作」選單 (), 按一下 [變更帳單],然後選擇 Cloud Billing 帳戶。
  4. 按一下 [設定帳戶]

gcloud CLI

  1. 如要列出可用的帳單帳戶,請執行:
    gcloud billing accounts list
  2. 將帳單帳戶連結至 Google Cloud 專案:
    gcloud billing projects link PROJECT_ID --billing-account=BILLING_ACCOUNT_ID

    更改下列內容:

    • PROJECT_ID 是以下項目的專案 ID: 您想啟用計費功能的 Cloud 專案。
    • BILLING_ACCOUNT_ID 是要連結的帳單帳戶 ID 套用配額

啟用 API

Google Cloud 控制台

  1. 在 Google Cloud 控制台中,啟用 Google Chat API、Google Docs API。 Admin SDK API 和 Vertex AI API

    啟用 API

  2. 確認您已在正確的位置啟用 API Cloud 專案,然後點選「下一步」

  3. 確認您要啟用的 API 正確無誤,然後按一下「啟用」

gcloud CLI

  1. 必要時,將目前的 Cloud 專案設為您建立的專案 使用 gcloud config set project 指令:

    gcloud config set project PROJECT_ID
    

    PROJECT_ID 替換為以下專案的專案 ID: 您建立的 Cloud 專案

  2. 啟用 Google Chat API、Google Docs API、Admin SDK API 和 Vertex AI API 使用 gcloud services enable 指令:

    gcloud services enable chat.googleapis.com docs.googleapis.com admin.googleapis.com aiplatform.googleapis.com
    

設定驗證與授權

驗證及授權 Google Workspace 和 Google Workspace 中的 Chat 擴充應用程式存取資源 處理事件回應的 Google Cloud

在本教學課程中,您可以在內部發布應用程式,因此可以使用預留位置 可能不準確或不適當在外部發布應用程式前,請替換預留位置 提供正確的資訊

  1. 前往 Google Cloud 控制台,前往 選單 > API 與服務 > OAuth 同意畫面

    前往 OAuth 同意畫面

  2. 在「使用者類型」下方選取「內部」,然後點選「建立」

  3. 在「應用程式名稱」中輸入 Incident Management

  4. 在「使用者支援電子郵件」部分,選取您的電子郵件地址或適當的電子郵件地址 Google 群組。

  5. 在「開發人員聯絡資訊」下方輸入您的電子郵件地址。

  6. 按一下 [儲存並繼續]。

  7. 按一下「新增或移除範圍」。畫面上會顯示包含範圍清單的面板 。

  8. 在「手動新增範圍」下方,貼上下列範圍:

    • https://www.googleapis.com/auth/chat.spaces.create
    • https://www.googleapis.com/auth/chat.memberships
    • https://www.googleapis.com/auth/chat.memberships.app
    • https://www.googleapis.com/auth/chat.messages
    • https://www.googleapis.com/auth/documents
    • https://www.googleapis.com/auth/admin.directory.user.readonly
    • https://www.googleapis.com/auth/script.external_request
    • https://www.googleapis.com/auth/userinfo.email
    • https://www.googleapis.com/auth/cloud-platform
  9. 按一下「Add to Table」

  10. 按一下「更新」

  11. 按一下 [儲存並繼續]。

  12. 查看應用程式註冊摘要,然後按一下「返回資訊主頁」

建立及部署 Chat 應用程式

在下一節中,您將複製與更新整個 內含所有必要應用程式的 Apps Script 專案 因此不必另外複製 貼上每個檔案

有些函式的名稱結尾有底線,例如: 來自「ChatApp.gs」的processSlashCommand_()。底線會隱藏函式 瀏覽器開啟事件初始化網頁。如要 資訊,請參閱 私人函式

Apps Script 支援兩種檔案類型:.gs 指令碼和 .html 檔案。為遵守這項支援功能,應用程式會納入應用程式的用戶端 JavaScript 且 CSS 已加到 <script /> 標記中的 <style /> 標記內 HTML 檔案

或者,您也可以在 GitHub 上查看整個專案。

前往 GitHub 查看

以下是每個檔案的總覽:

Consts.gs

定義由其他程式碼檔案參照的常數, 包括 Cloud 專案 ID、Vertex AI 位置 ID 斜線指令 ID 來關閉事件

查看 Consts.gs 程式碼

apps-script/incident-response/Consts.gs
const PROJECT_ID = 'replace-with-your-project-id';
const VERTEX_AI_LOCATION_ID = 'us-central1';
const CLOSE_INCIDENT_COMMAND_ID = 1;
ChatApp.gs

處理 Chat 互動事件,包括 訊息、資訊卡點擊、斜線指令和對話方塊回應 開啟對話方塊來收集事件,藉此執行 /closeIncident 斜線指令 來解決問題透過呼叫 Chat API 的 spaces.messages.list 方法。 使用 Admin SDK Directory 服務取得使用者 ID: Apps Script。

查看 ChatApp.gs 程式碼

apps-script/incident-response/ChatApp.gs
/**
 * Responds to a MESSAGE event in Google Chat.
 *
 * This app only responds to a slash command with the ID 1 ("/closeIncident").
 * It will respond to any other message with a simple "Hello" text message.
 *
 * @param {Object} event the event object from Google Chat
 */
function onMessage(event) {
  if (event.message.slashCommand) {
    return processSlashCommand_(event);
  }
  return { "text": "Hello from Incident Response app!" };
}

/**
 * Responds to a CARD_CLICKED event in Google Chat.
 *
 * This app only responds to one kind of dialog (Close Incident).
 *
 * @param {Object} event the event object from Google Chat
 */
function onCardClick(event) {
  if (event.isDialogEvent) {
    if (event.dialogEventType == 'SUBMIT_DIALOG') {
      return processSubmitDialog_(event);
    }
    return {
      actionResponse: {
        type: "DIALOG",
        dialogAction: {
          actionStatus: "OK"
        }
      }
    };
  }
}

/**
 * Responds to a MESSAGE event with a Slash command in Google Chat.
 *
 * This app only responds to a slash command with the ID 1 ("/closeIncident")
 * by returning a Dialog.
 *
 * @param {Object} event the event object from Google Chat
 */
function processSlashCommand_(event) {
  if (event.message.slashCommand.commandId != CLOSE_INCIDENT_COMMAND_ID) {
    return {
      "text": "Command not recognized. Use the command `/closeIncident` to close the incident managed by this space."
    };
  }
  const sections = [
    {
      header: "Close Incident",
      widgets: [
        {
          textInput: {
            label: "Please describe the incident resolution",
            type: "MULTIPLE_LINE",
            name: "description"
          }
        },
        {
          buttonList: {
            buttons: [
              {
                text: "Close Incident",
                onClick: {
                  action: {
                    function: "closeIncident"
                  }
                }
              }
            ]
          }
        }
      ]
    }
  ];
  return {
    actionResponse: {
      type: "DIALOG",
      dialogAction: {
        dialog: {
          body: {
            sections,
          }
        }
      }
    }
  };
}

/**
 * Responds to a CARD_CLICKED event with a Dialog submission in Google Chat.
 *
 * This app only responds to one kind of dialog (Close Incident).
 * It creates a Doc with a summary of the incident information and posts a message
 * to the space with a link to the Doc.
 *
 * @param {Object} event the event object from Google Chat
 */
function processSubmitDialog_(event) {
  const resolution = event.common.formInputs.description[""].stringInputs.value[0];
  const chatHistory = concatenateAllSpaceMessages_(event.space.name);
  const chatSummary = summarizeChatHistory_(chatHistory);
  const docUrl = createDoc_(event.space.displayName, resolution, chatHistory, chatSummary);
  return {
    actionResponse: {
      type: "NEW_MESSAGE",
    },
    text: `Incident closed with the following resolution: ${resolution}\n\nHere is the automatically generated post-mortem:\n${docUrl}`
  };
}

/**
 * Lists all the messages in the Chat space, then concatenate all of them into
 * a single text containing the full Chat history.
 *
 * For simplicity for this demo, it only fetches the first 100 messages.
 *
 * Messages with slash commands are filtered out, so the returned history will
 * contain only the conversations between users and not app command invocations.
 *
 * @return {string} a text containing all the messages in the space in the format:
 *          Sender's name: Message
 */
function concatenateAllSpaceMessages_(spaceName) {
  // Call Chat API method spaces.messages.list
  const response = Chat.Spaces.Messages.list(spaceName, { 'pageSize': 100 });
  const messages = response.messages;
  // Fetch the display names of the message senders and returns a text
  // concatenating all the messages.
  let userMap = new Map();
  return messages
    .filter(message => message.slashCommand === undefined)
    .map(message => `${getUserDisplayName_(userMap, message.sender.name)}: ${message.text}`)
    .join('\n');
}

/**
 * Obtains the display name of a user by using the Admin Directory API.
 *
 * The fetched display name is cached in the provided map, so we only call the API
 * once per user.
 *
 * If the user does not have a display name, then the full name is used.
 *
 * @param {Map} userMap a map containing the display names previously fetched
 * @param {string} userName the resource name of the user
 * @return {string} the user's display name
 */
function getUserDisplayName_(userMap, userName) {
  if (userMap.has(userName)) {
    return userMap.get(userName);
  }
  let displayName = 'Unknown User';
  try {
    const user = AdminDirectory.Users.get(
      userName.replace("users/", ""),
      { projection: 'BASIC', viewType: 'domain_public' });
    displayName = user.name.displayName ? user.name.displayName : user.name.fullName;
  } catch (e) {
    // Ignore error if the API call fails (for example, because it's an
    // out-of-domain user or Chat app)) and just use 'Unknown User'.
  }
  userMap.set(userName, displayName);
  return displayName;
}
ChatSpaceCreator.gs

接收使用者在事件中輸入的表單資料 並用來設定 Chat 建立並填入資料,然後張貼關於 事件。

查看 ChatSpaceCreator.gs 程式碼

apps-script/incident-response/ChatSpaceCreator.gs
/**
 * Creates a space in Google Chat with the provided title and members, and posts an
 * initial message to it.
 *
 * @param {Object} formData the data submitted by the user. It should contain the fields
 *                          title, description, and users.
 * @return {string} the resource name of the new space.
 */
function createChatSpace(formData) {
  const users = formData.users.trim().length > 0 ? formData.users.split(',') : [];
  const spaceName = setUpSpace_(formData.title, users);
  addAppToSpace_(spaceName);
  createMessage_(spaceName, formData.description);
  return spaceName;
}

/**
 * Creates a space in Google Chat with the provided display name and members.
 *
 * @return {string} the resource name of the new space.
 */
function setUpSpace_(displayName, users) {
  const memberships = users.map(email => ({
    member: {
      name: `users/${email}`,
      type: "HUMAN"
    }
  }));
  const request = {
    space: {
      displayName: displayName,
      spaceType: "SPACE",
      externalUserAllowed: true
    },
    memberships: memberships
  };
  // Call Chat API method spaces.setup
  const space = Chat.Spaces.setup(request);
  return space.name;
}

/**
 * Adds this Chat app to the space.
 *
 * @return {string} the resource name of the new membership.
 */
function addAppToSpace_(spaceName) {
  const request = {
    member: {
      name: "users/app",
      type: "BOT"
    }
  };
  // Call Chat API method spaces.members.create
  const membership = Chat.Spaces.Members.create(request, spaceName);
  return membership.name;
}

/**
 * Posts a text message to the space on behalf of the user.
 *
 * @return {string} the resource name of the new message.
 */
function createMessage_(spaceName, text) {
  const request = {
    text: text
  };
  // Call Chat API method spaces.messages.create
  const message = Chat.Spaces.Messages.create(request, spaceName);
  return message.name;
}
DocsApi.gs

呼叫 Google Docs API,在 並在檔案中加入事件資訊摘要 於 VertexAiApi.gs 建立,至文件中。

查看 DocsApi.gs 程式碼

apps-script/incident-response/DocsApi.gs
/**
 * Creates a Doc in the user's Google Drive and writes a summary of the incident information to it.
 *
 * @param {string} title The title of the incident
 * @param {string} resolution Incident resolution described by the user
 * @param {string} chatHistory The whole Chat history be included in the document
 * @param {string} chatSummary A summary of the Chat conversation to be included in the document
 * @return {string} the URL of the created Doc
 */
function createDoc_(title, resolution, chatHistory, chatSummary) {
  let doc = DocumentApp.create(title);
  let body = doc.getBody();
  body.appendParagraph(`Post-Mortem: ${title}`).setHeading(DocumentApp.ParagraphHeading.TITLE);
  body.appendParagraph("Resolution").setHeading(DocumentApp.ParagraphHeading.HEADING1);
  body.appendParagraph(resolution);
  body.appendParagraph("Summary of the conversation").setHeading(DocumentApp.ParagraphHeading.HEADING1);
  body.appendParagraph(chatSummary);
  body.appendParagraph("Full Chat history").setHeading(DocumentApp.ParagraphHeading.HEADING1);
  body.appendParagraph(chatHistory);
  return doc.getUrl();
}
VertexAiApi.gs

產生 Chat 對話的摘要 如何快速上手此摘要張貼在特別建立的 「DocsAPI.gs」中的文件。

查看 VertexAiApi.gs 程式碼

apps-script/incident-response/VertexAiApi.gs
/**
 * Summarizes a Chat conversation using the Vertex AI text prediction API.
 *
 * @param {string} chatHistory The Chat history that will be summarized.
 * @return {string} The content from the text prediction response.
 */
function summarizeChatHistory_(chatHistory) {
  const prompt =
    "Summarize the following conversation between Engineers resolving an incident"
      + " in a few sentences. Use only the information from the conversation.\n\n"
      + chatHistory;
  const request = {
    instances: [
      { prompt: prompt }
    ],
    parameters: {
      temperature: 0.2,
      maxOutputTokens: 256,
      topK: 40,
      topP: 0.95
    }
  }
  const fetchOptions = {
    method: 'POST',
    headers: { Authorization: 'Bearer ' + ScriptApp.getOAuthToken() },
    contentType: 'application/json',
    payload: JSON.stringify(request)
  }
  const response = UrlFetchApp.fetch(
    `https://${VERTEX_AI_LOCATION_ID}-aiplatform.googleapis.com/v1`
      + `/projects/${PROJECT_ID}/locations/${VERTEX_AI_LOCATION_ID}`
      + "/publishers/google/models/text-bison:predict",
    fetchOptions);
  const payload = JSON.parse(response.getContentText());
  return payload.predictions[0].content;
}
WebController.gs

提供事件初始化網站。

查看 WebController.gs 程式碼

apps-script/incident-response/WebController.gs
/**
 * Serves the web page from Index.html.
 */
function doGet() {
  return HtmlService
    .createTemplateFromFile('Index')
    .evaluate();
}

/**
 * Serves the web content from the specified filename.
 */
function include(filename) {
  return HtmlService
    .createHtmlOutputFromFile(filename)
    .getContent();
}

/**
 * Returns the email address of the user running the script.
 */
function getUserEmail() {
  return Session.getActiveUser().getEmail();
}
Index.html

內含事件初始化網站的 HTML。

查看 Index.html 程式碼

apps-script/incident-response/Index.html
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <link href='https://fonts.googleapis.com/css?family=Roboto' rel='stylesheet'>
    <?!= include('Stylesheet'); ?>
  </head>
  <body>
    <div class="container">
      <div class="content">
        <h1>Incident Manager</h1>
        <form id="incident-form" onsubmit="handleFormSubmit(this)">
          <div id="form">
            <p>
              <label for="title">Incident title</label><br/>
              <input type="text" name="title" id="title" />
            </p>
            <p>
              <label for="users">Incident responders</label><br/>
              <small>
                Please enter a comma-separated list of email addresses of the users
                that should be added to the space.
                Do not include <?= getUserEmail() ?> as it will be added automatically.
              </small><br/>
              <input type="text" name="users" id="users" />
            </p>
            <p>
              <label for="description">Initial message</label></br>
              <small>This message will be posted after the space is created.</small><br/>
              <textarea name="description" id="description"></textarea>
            </p>
            <p class="text-center">
              <input type="submit" value="CREATE CHAT SPACE" />
            </p>
          </div>
          <div id="output" class="hidden"></div>
          <div id="clear" class="hidden">
            <input type="reset" value="CREATE ANOTHER INCIDENT" onclick="onReset()" />
          </div>
        </form>
      </div>
    </div>
    <?!= include('JavaScript'); ?>
  </body>
</html>
JavaScript.html

處理表單行為,包括提交、 錯誤等等。隨附於 透過 WebController.gs 中的自訂 include 函式傳入 Index.html

查看 JavaScript.html 程式碼

apps-script/incident-response/JavaScript.html
<script>
  var formDiv = document.getElementById('form');
  var outputDiv = document.getElementById('output');
  var clearDiv = document.getElementById('clear');

  function handleFormSubmit(formObject) {
    event.preventDefault();
    outputDiv.innerHTML = 'Please wait while we create the space...';
    hide(formDiv);
    show(outputDiv);
    google.script.run
      .withSuccessHandler(updateOutput)
      .withFailureHandler(onFailure)
      .createChatSpace(formObject);
  }

  function updateOutput(response) {
    var spaceId = response.replace('spaces/', '');
    outputDiv.innerHTML =
      '<p>Space created!</p><p><a href="https://mail.google.com/chat/#chat/space/'
        + spaceId
        + '" target="_blank">Open space</a></p>';
    show(outputDiv);
    show(clearDiv);
  }

  function onFailure(error) {
    outputDiv.innerHTML = 'ERROR: ' + error.message;
    outputDiv.classList.add('error');
    show(outputDiv);
    show(clearDiv);
  }

  function onReset() {
    outputDiv.innerHTML = '';
    outputDiv.classList.remove('error');
    show(formDiv);
    hide(outputDiv);
    hide(clearDiv);
  }

  function hide(element) {
    element.classList.add('hidden');
  }

  function show(element) {
    element.classList.remove('hidden');
  }
</script>
Stylesheet.html

事件初始化網站的 CSS。是 由自訂 include 函式包含在 Index.htmlWebController.gs

查看 Stylesheet.html 程式碼

apps-script/incident-response/Stylesheet.html
<style>
  * {
    box-sizing: border-box;
  }
  body {
    font-family: Roboto, Arial, Helvetica, sans-serif;
  }
  div.container {
    display: flex;
    justify-content: center;
    align-items: center;
    position: absolute;
    top: 0; bottom: 0; left: 0; right: 0;
  }
  div.content {
    width: 80%;
    max-width: 1000px;
    padding: 1rem;
    border: 1px solid #999;
    border-radius: 0.25rem;
    box-shadow: 0 2px 2px 0 rgba(66, 66, 66, 0.08), 0 2px 4px 2px rgba(66, 66, 66, 0.16);
  }
  h1 {
    text-align: center;
    padding-bottom: 1rem;
    margin: 0 -1rem 1rem -1rem;
    border-bottom: 1px solid #999;
  }
 #output {
    text-align: center;
    min-height: 250px;
  }
  div#clear {
    text-align: center;
    padding-top: 1rem;
    margin: 1rem -1rem 0 -1rem;
    border-top: 1px solid #999;
  }
  input[type=text], textarea {
    width: 100%;
    padding: 1rem 0.5rem;
    margin: 0.5rem 0;
    border: 0;
    border-bottom: 1px solid #999;
    background-color: #f0f0f0;
  }
  textarea {
    height: 5rem;
  }
  small {
    color: #999;
  }
  input[type=submit], input[type=reset] {
    padding: 1rem;
    border: none;
    background-color: #6200ee;
    color: #fff;
    border-radius: 0.25rem;
    width: 25%;
  }
  .hidden {
    display: none;
  }
  .text-center {
    text-align: center;
  }
  .error {
    color: red;
  }
</style>

尋找 Cloud 專案編號和 ID

  1. 在 Google Cloud 控制台中,前往 Cloud 專案。

    前往 Google Cloud 控制台

  2. 按一下 [設定和公用程式] &gt;「專案設定」

  3. 記下「專案編號」和「專案 ID」欄位中的值。個人中心 並用於後續章節

建立 Apps Script 專案

如要建立 Apps Script 專案並連結至 Cloud 專案:

  1. 點選下方按鈕,開啟「使用 Google Chat 回覆事件」 Apps Script 專案。
    開啟專案
  2. 按一下「總覽」圖示
  3. 在總覽頁面上,按一下「用來建立副本的圖示 建立副本」
  4. 為 Apps Script 專案副本命名:

    1. 按一下「透過 Google Chat 回覆事件副本」

    2. 在「Project title」中輸入 Incident Management Chat app

    3. 按一下 [重新命名]

  5. 在 Apps Script 專案副本中,前往 Consts.gs 檔案,然後將 YOUR_PROJECT_ID 換成 Cloud 專案

設定 Apps Script 專案的 Cloud 專案

  1. 在您的 Apps Script 專案中, 按一下 專案設定圖示「Project Settings」
  2. 在「Google Cloud Platform (GCP) Project」(Google Cloud Platform (GCP) 專案) 下方,按一下 [變更專案]
  3. 在「GCP 專案編號」中,貼上 Cloud 專案的專案編號。
  4. 按一下「設定專案」。Cloud 專案和 Apps Script 專案現已連結。

建立 Apps Script 部署作業

備妥所有程式碼後,請部署 Apps Script 專案。設定 Deployment ID 時 Google Cloud 中的即時通訊應用程式。

  1. 在 Apps Script 中,開啟事件回應應用程式的專案。

    前往 Apps Script

  2. 按一下「部署」>新增部署作業

  3. 如果尚未選取「外掛程式」和「網頁應用程式」,請 選取類型,按一下部署類型 專案設定圖示,然後選取「外掛程式」和「網頁應用程式」

  4. 在「說明」中輸入這個版本的說明,例如: Complete version of incident management app

  5. 在「執行身分」中,選取「使用者存取網頁應用程式」

  6. 在「擁有存取權的使用者」中,選取「< Workspace 機構中的所有人」, 「你的 Workspace 機構」就是你的 Google Workspace 機構

  7. 按一下「部署」。Apps Script 報告成功 並提供部署作業 ID 和事件網址 初始化網頁。

  8. 請記下網頁應用程式網址,以便在稍後啟動事件時查看。 複製部署作業 ID。您在設定 Google Cloud 控制台中的即時通訊應用程式。

  9. 按一下 [完成]。

在 Google Cloud 控制台中設定 Chat 應用程式

本節說明如何在 Google Cloud 控制台中設定 Google Chat API 提供 Chat 應用程式相關資訊,包括 您剛透過 Apps Script 建立的部署作業 ID 專案。

  1. 在 Google Cloud 控制台中,按一下「選單」 &gt; 更多產品 &gt; Google Workspace &gt; 產品庫 &gt; Google Chat API &gt; 管理 &gt; 設定

    前往 Chat API 設定

  2. 在「應用程式名稱」中輸入 Incident Management

  3. 在「顯示圖片」中輸入 https://developers.google.com/chat/images/quickstart-app-avatar.png

  4. 在「說明」中輸入 Responds to incidents.

  5. 按一下「啟用互動功能」切換鈕,將其設為「開啟」。

  6. 在「功能」下方,選取「接收 1:1 訊息」、「加入聊天室和群組對話」

  7. 在「連線設定」下方,選取「Apps Script 專案」

  8. 在「部署作業 ID」中,貼上 Apps Script 部署作業 ID 複製先前從 Apps Script 專案複製的程式碼 可能面臨擴充性、監控、持續整合 和部署等方面的挑戰

  9. 註冊一個斜線指令, 完整實作的 Chat 應用程式可以使用:

    1. 在「斜線指令」下方,按一下「新增斜線指令」

    2. 在「Name」(名稱) 中輸入 /closeIncident

    3. 在「指令 ID」中輸入 1

    4. 在「說明」中輸入 Closes the incident being discussed in the space.

    5. 選取「開啟對話方塊」

    6. 按一下 [完成]。斜線指令已完成註冊並列在清單中。

  10. 在「Visibility」(顯示設定) 下方選取 將這個即時通訊應用程式提供給「您」中的特定使用者和群組 Workspace 網域並輸入您的電子郵件地址。

  11. 在「記錄」底下,選取 [將錯誤記錄至 Logging]

  12. 按一下 [儲存]。畫面上會顯示設定儲存訊息,表示該應用程式

測試 Chat 應用程式

如要測試事件管理 Chat 應用程式,請啟動 檢查 Chat 應用程式是否有額外事件 符合預期:

  1. 前往 Apps Script 部署作業網頁應用程式網址。

  2. 當 Apps Script 要求存取您的資料時, 請按一下「查看權限」,然後使用適當的 Google 帳戶登入 在 Google Workspace 網域中,然後按一下「Allow」

  3. 系統隨即會開啟事件初始化網頁。輸入測試資訊:

    1. 在「事件標題」中輸入 The First Incident
    2. (選用) 在「事件回應者」中,輸入 事件回應者。這些使用者必須是 您 Google Workspace 機構的 Google Chat 帳戶,或是 無法建立聊天室。請勿輸入您自己的電子郵件地址,因為 自動加入。
    3. 在「初始訊息」中輸入 Testing the incident management Chat app.
  4. 按一下「建立 Chat 聊天室」。系統隨即會顯示 creating space 訊息。

  5. 聊天室建立後,系統會顯示 Space created! 訊息。按一下 開啟聊天室,在新分頁中開啟 Chat 中的聊天室。

  6. 您和其他事件回應者可以視需要在 空白鍵。應用程式使用 Vertex AI 總結這些訊息,並分享 回溯性文件

  7. 如要結束事件回應並開始解決程序,請在 Chat 聊天室,請輸入「/closeIncident」。事件管理 對話方塊就會開啟。

  8. 在「關閉事件」中輸入事件解決方式的說明。 就像 Test complete

  9. 按一下「關閉事件」

事件管理應用程式會列出聊天室中的訊息,並總結 可將摘要貼到 Google 文件中,進而分享 在聊天室中建立新文件

清除所用資源

如要避免系統向您的 Google Cloud 帳戶收取 但建議採用 Cloud 專案

  1. 在 Google Cloud 控制台中,前往「管理資源」頁面。按一下 選單 &gt; IAM 與管理員 &gt;「管理資源」

    前往 Resource Manager

  2. 在專案清單中選取要刪除的專案,然後按一下 刪除
  3. 在對話方塊中輸入專案 ID,然後按一下「Shut down」(關閉) 即可刪除 專案。