GSP1301

總覽
增益集可擴充 Google Workspace 功能,協助使用者提高工作效率並改善工作流程。在本實驗室中,您將建構 Google Workspace 外掛程式,運用 Gemini 和 Vertex AI 的功能分析 Gmail 內容的情緒。您會設定必要的雲端資源 (包括 Vertex AI API)、設定 Apps Script 專案,並部署外掛程式。
這項外掛程式可自動辨識並標示語氣負面的電子郵件,您可藉此優先處理客服回覆,或快速找出可能含有敏感內容的電子郵件。
完成實驗室活動後,您會有一個可實際運用 AI 的工具,提升業務效率和溝通品質。
課程內容
在本實驗室,您將執行下列作業:
- 開發可擴充 Gmail 功能的 Google Workspace 外掛程式。
- 整合 Vertex AI 與 Google Workspace,在 Gmail 外掛程式中使用 Gemini 和 Vertex AI 的自然語言處理功能。
- 實作 OAuth2 驗證機制,安全授權外掛程式存取使用者資料。
- 運用情緒分析功能,以程式輔助分析電子郵件內容,判斷情緒基調。
- 運用 Apps Script 編寫程式碼,與 Gmail 互動、管理使用者介面,以及連結外部 API。
設定和需求
瞭解以下事項後,再點選「Start Lab」按鈕
請詳閱以下操作說明。實驗室活動會計時,且中途無法暫停。點選「Start Lab」後就會開始計時,顯示可使用 Google Cloud 資源的時間。
您將在真正的雲端環境完成實作實驗室活動,而不是模擬或示範環境。為此,我們會提供新的暫時憑證,供您在實驗室活動期間登入及存取 Google Cloud。
為了順利完成這個實驗室,請先確認:
- 可以使用標準的網際網路瀏覽器 (Chrome 瀏覽器為佳)。
注意事項:請使用無痕模式 (建議選項) 或私密瀏覽視窗執行此實驗室,這可以防止個人帳戶和學員帳戶之間的衝突,避免個人帳戶產生額外費用。
- 是時候完成實驗室活動了!別忘了,活動一旦開始將無法暫停。
注意事項:務必使用實驗室專用的學員帳戶。如果使用其他 Google Cloud 帳戶,可能會產生額外費用。
如何開始研究室及登入 Google Cloud 控制台
-
點選「Start Lab」按鈕。如果實驗室會產生費用,畫面上會出現選擇付款方式的對話方塊。左側的「Lab Details」窗格會顯示下列項目:
- 「Open Google Cloud console」按鈕
- 剩餘時間
- 必須在這個研究室中使用的臨時憑證
- 完成這個實驗室所需的其他資訊 (如有)
-
點選「Open Google Cloud console」;如果使用 Chrome 瀏覽器,也能按一下滑鼠右鍵,選取「在無痕視窗中開啟連結」。
接著,實驗室會啟動相關資源,並開啟另一個分頁,顯示「登入」頁面。
提示:您可以在不同的視窗中並排開啟分頁。
注意:如果頁面中顯示「選擇帳戶」對話方塊,請點選「使用其他帳戶」。
-
如有必要,請將下方的 Username 貼到「登入」對話方塊。
{{{user_0.username | "Username"}}}
您也可以在「Lab Details」窗格找到 Username。
-
點選「下一步」。
-
複製下方的 Password,並貼到「歡迎使用」對話方塊。
{{{user_0.password | "Password"}}}
您也可以在「Lab Details」窗格找到 Password。
-
點選「下一步」。
重要事項:請務必使用實驗室提供的憑證,而非自己的 Google Cloud 帳戶憑證。
注意:如果使用自己的 Google Cloud 帳戶來進行這個實驗室,可能會產生額外費用。
-
按過後續的所有頁面:
- 接受條款及細則。
- 由於這是臨時帳戶,請勿新增救援選項或雙重驗證機制。
- 請勿申請免費試用。
Google Cloud 控制台稍後會在這個分頁開啟。
注意:如要使用 Google Cloud 產品和服務,請點選「導覽選單」,或在「搜尋」欄位輸入服務或產品名稱。
工作 1:存取實驗室環境
您已登入 Google Cloud 控制台,接著登入 Gmail。
- 點選「Open Gmail」,開啟 Gmail 登入頁面。
提示:將分頁安排在不同視窗,方便查看。
- 使用使用者名稱和密碼登入 Gmail。
注意:這些憑證也位於「Lab details」窗格,這些憑證已用來登入 Google Cloud 控制台。
- 進入 Gmail 後,點按「開始使用」,並關閉所有資訊視窗,這時應該會看到收件匣。
現在可以開始做實驗室活動了!
工作 2:設定 Google Cloud 環境
在這個步驟中,您會啟用 Vertex AI API,然後設定 OAuth 同意畫面,選定 Google Workspace 向使用者顯示的內容。
啟用 Vertex AI API
-
前往 Google Cloud 控制台,依序點選「導覽選單」>「API 和服務」>「程式庫」。
-
在「搜尋 API 和服務」方塊中輸入「Vertex AI API」,然後在搜尋結果中點選「Vertex AI API」。
-
點選「啟用」來啟用 API。
「API/服務詳細資料」頁面隨即開啟。
設定 OAuth 同意畫面
-
在左側窗格中,按一下「OAuth 同意畫面」。
-
點選「開始使用」。
-
在「應用程式資訊」部分,設定下列項目,然後點選「下一步」:
-
應用程式名稱:Gmail Sentiment Analysis with Gemini and Vertex AI
-
使用者支援電子郵件:
- 「目標對象」請選取「內部」,然後點選「下一步」。
- 在「聯絡資訊」部分,將「電子郵件地址」設為「」,然後點選「下一步」。
- 在「完成」部分,請同意《Google API 服務:使用者資料政策》,然後點選「繼續」。
- 點選「建立」。
點選「Check my progress」,確認目標已達成。
設定 OAuth 同意畫面。
工作 3:設定 Apps Script 專案
在這項工作中,您會建立外掛程式並設定為 Apps Script 專案。
取得 Google Cloud 專案編號
如要取得 Google Cloud 專案編號,以便在建立 Apps Script 專案時使用,請按照下列步驟操作:
-
前往導覽選單 (
),依序點選「Cloud 總覽」>「資訊主頁」。
-
在「專案資訊」部分,記下專案編號,之後會在本實驗室用到。
建立 Apps Script 專案
-
在「Student Resources」窗格中,點選連結「script.google.com/」,開啟 Apps Script 頁面。
-
點選「新專案」,建立 Apps Script 專案。
-
為專案命名:
- 點按左上方的「未命名專案」。
- 將專案命名為「Gmail Sentiment Analysis with Gemini and Vertex AI」,然後點選「重新命名」。
-
顯示資訊清單檔案:
- 在左窗格中,點按「專案設定」 (
)。
- 選取「在編輯器中顯示『appsscript.json』資訊清單檔案」。
-
變更 Google Cloud Platform 專案:
- 向下捲動至「Google Cloud Platform (GCP) 專案」部分,然後點選「變更專案」。
- 將「GCP 專案編號」設為先前記錄的專案編號。
- 點選「設定專案」。
點選「Check my progress」,確認目標已達成。
建立 Apps Script 專案。
工作 4:填入程式碼檔案
- 點選左側窗格的「編輯器」 (
),開啟編輯器視窗。
請按照下列操作說明,使用程式碼範例更新專案。
appsscript.json
- 開啟
appsscript.json
,將檔案內容替換為下列內容:
{
"timeZone": "America/Toronto",
"oauthScopes": [
"https://www.googleapis.com/auth/cloud-platform",
"https://www.googleapis.com/auth/gmail.addons.execute",
"https://www.googleapis.com/auth/gmail.labels",
"https://www.googleapis.com/auth/gmail.modify",
"https://www.googleapis.com/auth/script.external_request",
"https://www.googleapis.com/auth/userinfo.email"
],
"addOns": {
"common": {
"name": "Sentiment Analysis",
"logoUrl": "https://fonts.gstatic.com/s/i/googlematerialicons/sentiment_extremely_dissatisfied/v6/black-24dp/1x/gm_sentiment_extremely_dissatisfied_black_24dp.png"
},
"gmail": {
"homepageTrigger": {
"runFunction": "onHomepageTrigger",
"enabled": true
}
}
},
"exceptionLogging": "STACKDRIVER",
"runtimeVersion": "V8"
}
- 點按「儲存」(
) 即可儲存專案。
Code.gs
- 開啟 Code.gs,並將內容替換為下列程式碼:
/*
Copyright 2024-2025 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Replace with your project ID
const PROJECT_ID = '{{{project_0.project_id | Project ID}}}';
// Location for your Vertex AI model
const VERTEX_AI_LOCATION = 'us-east4';
// Model ID to use for sentiment analysis
const MODEL_ID = 'gemini-2.0-flash';
/**
* Triggered when the add-on is opened from the Gmail homepage.
*
* @param {Object} e - The event object.
* @returns {Card} - The homepage card.
*/
function onHomepageTrigger(e) {
return buildHomepageCard();
}
/**
* Builds the main card displayed on the Gmail homepage.
*
* @returns {Card} - The homepage card.
*/
function buildHomepageCard() {
// Create a new card builder
const cardBuilder = CardService.newCardBuilder();
// Create a card header
const cardHeader = CardService.newCardHeader();
cardHeader.setImageUrl('https://fonts.gstatic.com/s/i/googlematerialicons/mail/v6/black-24dp/1x/gm_mail_black_24dp.png');
cardHeader.setImageStyle(CardService.ImageStyle.CIRCLE);
cardHeader.setTitle("Analyze your Gmail");
// Add the header to the card
cardBuilder.setHeader(cardHeader);
// Create a card section
const cardSection = CardService.newCardSection();
// Create buttons for generating sample emails and analyzing sentiment
const buttonSet = CardService.newButtonSet();
// Create "Generate sample emails" button
const generateButton = createFilledButton('Generate sample emails', 'generateSampleEmails', '#34A853');
buttonSet.addButton(generateButton);
// Create "Analyze emails" button
const analyzeButton = createFilledButton('Analyze emails', 'analyzeSentiment', '#FF0000');
buttonSet.addButton(analyzeButton);
// Add the button set to the section
cardSection.addWidget(buttonSet);
// Add the section to the card
cardBuilder.addSection(cardSection);
// Build and return the card
return cardBuilder.build();
}
/**
* Creates a filled text button with the specified text, function, and color.
*
* @param {string} text - The text to display on the button.
* @param {string} functionName - The name of the function to call when the button is clicked.
* @param {string} color - The background color of the button.
* @returns {TextButton} - The created text button.
*/
function createFilledButton(text, functionName, color) {
// Create a new text button
const textButton = CardService.newTextButton();
// Set the button text
textButton.setText(text);
// Set the action to perform when the button is clicked
const action = CardService.newAction();
action.setFunctionName(functionName);
textButton.setOnClickAction(action);
// Set the button style to filled
textButton.setTextButtonStyle(CardService.TextButtonStyle.FILLED);
// Set the background color
textButton.setBackgroundColor(color);
return textButton;
}
/**
* Creates a notification response with the specified text.
*
* @param {string} notificationText - The text to display in the notification.
* @returns {ActionResponse} - The created action response.
*/
function buildNotificationResponse(notificationText) {
// Create a new notification
const notification = CardService.newNotification();
notification.setText(notificationText);
// Create a new action response builder
const actionResponseBuilder = CardService.newActionResponseBuilder();
// Set the notification for the action response
actionResponseBuilder.setNotification(notification);
// Build and return the action response
return actionResponseBuilder.build();
}
/**
* Generates sample emails for testing the sentiment analysis.
*
* @returns {ActionResponse} - A notification confirming email generation.
*/
function generateSampleEmails() {
// Get the current user's email address
const userEmail = Session.getActiveUser().getEmail();
// Define sample emails
const sampleEmails = [
{
subject: 'Thank you for amazing service!',
body: 'Hi, I really enjoyed working with you. Thank you again!',
name: 'Customer A'
},
{
subject: 'Request for information',
body: 'Hello, I need more information on your recent product launch. Thank you.',
name: 'Customer B'
},
{
subject: 'Complaint!',
body: '',
htmlBody: `Hello, You are late in delivery, again.
Please contact me ASAP before I cancel our subscription.
`,
name: 'Customer C'
}
];
// Send each sample email
for (const email of sampleEmails) {
GmailApp.sendEmail(userEmail, email.subject, email.body, {
name: email.name,
htmlBody: email.htmlBody
});
}
// Return a notification
return buildNotificationResponse("Successfully generated sample emails");
}
/**
* Analyzes the sentiment of the first 10 threads in the inbox
* and labels them accordingly.
*
* @returns {ActionResponse} - A notification confirming completion.
*/
function analyzeSentiment() {
// Analyze and label emails
analyzeAndLabelEmailSentiment();
// Return a notification
return buildNotificationResponse("Successfully completed sentiment analysis");
}
/**
* Analyzes the sentiment of emails and applies appropriate labels.
*/
function analyzeAndLabelEmailSentiment() {
// Define label names
const labelNames = ["HAPPY TONE 😊", "NEUTRAL TONE 😐", "UPSET TONE 😡"];
// Get or create labels for each sentiment
const positiveLabel = GmailApp.getUserLabelByName(labelNames[0]) || GmailApp.createLabel(labelNames[0]);
const neutralLabel = GmailApp.getUserLabelByName(labelNames[1]) || GmailApp.createLabel(labelNames[1]);
const negativeLabel = GmailApp.getUserLabelByName(labelNames[2]) || GmailApp.createLabel(labelNames[2]);
// Get the first 10 threads in the inbox
const threads = GmailApp.getInboxThreads(0, 10);
// Iterate through each thread
for (const thread of threads) {
// Iterate through each message in the thread
const messages = thread.getMessages();
for (const message of messages) {
// Get the plain text body of the message
const emailBody = message.getPlainBody();
// Analyze the sentiment of the email body
const sentiment = processSentiment(emailBody);
// Apply the appropriate label based on the sentiment
if (sentiment === 'positive') {
thread.addLabel(positiveLabel);
} else if (sentiment === 'neutral') {
thread.addLabel(neutralLabel);
} else if (sentiment === 'negative') {
thread.addLabel(negativeLabel);
}
}
}
}
/**
* Sends the email text to Vertex AI for sentiment analysis.
*
* @param {string} emailText - The text of the email to analyze.
* @returns {string} - The sentiment of the email ('positive', 'negative', or 'neutral').
*/
function processSentiment(emailText) {
// Construct the API endpoint URL
const apiUrl = `https://${VERTEX_AI_LOCATION}-aiplatform.googleapis.com/v1/projects/${PROJECT_ID}/locations/${VERTEX_AI_LOCATION}/publishers/google/models/${MODEL_ID}:generateContent`;
// Prepare the request payload
const payload = {
contents: [
{
role: "user",
parts: [
{
text: `Analyze the sentiment of the following message: ${emailText}`
}
]
}
],
generationConfig: {
temperature: 0.9,
maxOutputTokens: 1024,
responseMimeType: "application/json",
// Expected response format for simpler parsing.
responseSchema: {
type: "object",
properties: {
response: {
type: "string",
enum: ["positive", "negative", "neutral"]
}
}
}
}
};
// Prepare the request options
const options = {
method: 'POST',
headers: {
'Authorization': `Bearer ${ScriptApp.getOAuthToken()}`
},
contentType: 'application/json',
muteHttpExceptions: true, // Set to true to inspect the error response
payload: JSON.stringify(payload)
};
// Make the API request
const response = UrlFetchApp.fetch(apiUrl, options);
// Parse the response. There are two levels of JSON responses to parse.
const parsedResponse = JSON.parse(response.getContentText());
const sentimentResponse = JSON.parse(parsedResponse.candidates[0].content.parts[0].text).response;
// Return the sentiment
return sentimentResponse;
}
點按「儲存」 (
) 即可儲存專案。
工作 5:部署外掛程式
在這項工作中,您將部署外掛程式,然後驗證安裝作業。
部署外掛程式
-
在標題列中,依序點選「部署」>「測試部署作業」。
-
確認「Gmail」列於「應用程式」下方,然後點選「安裝」。
-
按一下「完成」。
驗證安裝
- 重新整理「Gmail」分頁。右側窗格應該會出現圖示
。
疑難排解
如果清單中沒有顯示外掛程式,請重新整理瀏覽器視窗。
如果仍未顯示,請返回 Apps Script 專案,從「測試部署」視窗解除安裝外掛程式,然後重新安裝。
工作 6:執行外掛程式
現在準備測試外掛程式。您將開啟外掛程式並授權,然後生成電子郵件,驗證分析功能是否正常運作。
-
在 Gmail 的右側窗格中,點選「情緒分析」 (
)。
-
側邊面板開啟後,點按「授予存取權」,授予外掛程式執行權限。
同意畫面開啟。選取電子郵件地址 (),然後依序點按畫面上的選項,允許存取權。
同意後,畫面右側會開啟「情緒分析」窗格。
- 在「情緒分析」窗格中,點選「Generate sample emails」。
外掛程式現在會產生範例電子郵件,以便測試分析功能。作業完成後,系統會顯示訊息,整個過程只需幾秒鐘。
-
等待範例電子郵件出現在收件匣中。可能需要重新整理收件匣,才能看到新郵件。
-
將範例電子郵件傳送至收件匣後,在「情緒分析」窗格中點選「Analyze emails」。
外掛程式畫面底部會顯示分析完成訊息。
注意:分析電子郵件可能需要一段時間。您可以重新整理頁面,查看套用標籤的狀態。
這個外掛程式會分析電子郵件,並對收件匣中的郵件套用適當的標籤 (「HAPPY TONE 😊」
、「UPSET TONE 😡」
或「NEUTRAL TONE 😐」
)。
您可能需要重新整理 Gmail,才能看到套用的標籤。
- 繼續實驗
您可以從實驗室 Gmail 帳戶傳送不同情緒 (正面、負面、中性) 的電子郵件至另一個實驗室 Gmail 帳戶,測試外掛程式。外部電子郵件無法測試。觀察外掛程式如何分析及標記每封電子郵件。
注意:程式碼只會從收件匣提取最近 10 封電子郵件,但您可以變更這個值。
-
關閉外掛程式:
完成外掛程式操作後,點選側邊面板右上角的「X」即可關閉。
點選「Check my progress」,確認目標已達成。
套用情緒分析。
恭喜!
您已順利完成「使用 Gemini 和 Vertex AI 分析 Gmail 情緒」實驗室。
在本實驗室中,您已學會如何執行下列工作:
-
建構 Google Workspace 外掛程式:開發實用工具,擴充 Gmail 功能。
-
整合 Vertex AI 與 Google Workspace:在 Gmail 外掛程式中使用 Gemini 和 Vertex AI 的自然語言處理功能。
-
實作 OAuth2 驗證機制:安全授權外掛程式,以利存取使用者資料。
-
套用情緒分析:用程式輔助分析電子郵件內容,判斷情緒基調。
-
使用 Apps Script:編寫程式碼,與 Gmail 互動、管理使用者介面,以及連線至外部 API。
現在您已有可正常運作的 Gmail 外掛程式,能協助您排定電子郵件的優先順序,提升工作效率。歡迎進一步測試外掛程式的功能,例如自訂情緒分析或新增功能。
Google Cloud 教育訓練與認證
協助您瞭解如何充分運用 Google Cloud 的技術。我們的課程會介紹專業技能和最佳做法,讓您可以快速掌握要領並持續進修。我們提供從基本到進階等級的訓練課程,並有隨選、線上和虛擬課程等選項,方便您抽空參加。認證可協助您驗證及證明自己在 Google Cloud 技術方面的技能和專業知識。
使用手冊上次更新日期:2025 年 3 月 25 日
實驗室上次測試日期:2025 年 2 月 25 日
Copyright 2025 Google LLC 保留所有權利。Google 和 Google 標誌是 Google LLC 的商標,其他公司和產品名稱則有可能是其關聯公司的商標。