ניתוח ותיוג של הודעות Gmail באמצעות Gemini ו-Vertex AI

יש לך 5 דקות?
נשמח שתעזרו לנו לשפר את מאמרי העזרה בנושא Google Workspace. אתם רק צריכים למלא סקר קצר באינטרנט.

הפתרון הזה משתמש ב-Vertex AI וב-Gemini כדי לנתח הודעות ב-Gmail ולתייג אותן על סמך הסנטימנט שלהן.

רמת הקידוד: בינונית
משך הזמן: 30 דקות
סוג הפרויקט: תוסף ל-Google Workspace

  • תוסף ל-Google Workspace שמרחיב את Gmail בסרגל צד.
    תרשים 1: התוסף Sentiment Analysis מציג סרגל צד ב-Gmail שבו המשתמשים יכולים לתת ל-Gemini הנחיה לנתח הודעות ולהחיל עליהן תוויות על סמך הסנטימנט.
  • הודעה ב-Gmail עם סנטימנט ניטרלי.
    איור 2: התוסף מתייג הודעת Gmail בתווית נימה ניטרלית 😐.
  • הודעה ב-Gmail עם סנטימנט חיובי.
    איור 3: התוסף מסמן הודעה ב-Gmail בתווית HAPPY TONE 😊.
  • הודעה ב-Gmail עם סנטימנט שלילי.
    איור 4: התוסף מתייג הודעה ב-Gmail בתווית UPSET TONE 😡.

מטרות

  • להבין מה הפתרון עושה.
  • הסבר על הפעולות ששירותי Google מבצעים במסגרת הפתרון.
  • מגדירים את הסביבה.
  • מגדירים את פרויקט Google Apps Script.
  • מריצים את הסקריפט.

מידע על הפתרון הזה

צילום מסך של התוסף Sentiment Analysis ל-Google Workspace

הפתרון הזה הוא תוסף ל-Google Workspace שמחיל תוויות על סמך הסנטימנט של הודעות Gmail. כדי לנתח את תוכן ההודעה, התוסף משתמש ב-Vertex AI כדי להנחות את מודל Gemini 2.5 Flash ולהחזיר את אחת מהתגובות הבאות:

  • חיובית
  • שלילית
  • ניטרלית

התוסף משתמש בתשובה מ-Gemini כדי להוסיף תווית מתאימה ב-Gmail להודעה.

כדי להגביל את הבקשה ל-Vertex AI API, התוסף הזה מנתח רק את 10 ההודעות האחרונות בתיבת הדואר הנכנס של המשתמש ב-Gmail ומחיל עליהן תוויות. מידע נוסף על מכסות ומגבלות מופיע במסמכי Vertex AI.

איך זה עובד

הפתרון הזה מבוסס על Google Apps Script ומשתמש בשירותים ובמוצרים הבאים של Google:

דרישות מוקדמות

הגדרת הסביבה

בקטע הזה מוסבר איך להגדיר את הסביבה במסוף Google Cloud וב-Apps Script.

הגדרת פרויקט Cloud ב-Google Cloud Console

בקטע הזה מוסבר איך להפעיל את Vertex AI API ולהגדיר את מסך ההסכמה ל-OAuth בפרויקט שלכם ב-Cloud.

הפעלה של Vertex AI API

  1. במסוף Google Cloud, פותחים את הפרויקט ב-Google Cloud ומפעילים את Vertex AI API:

    הפעלה של ה-API

  2. מוודאים שמפעילים את ה-API בפרויקט הנכון בענן ולוחצים על הבא.

  3. מוודאים שמפעילים את ה-API הנכון ולוחצים על הפעלה.

מגדירים את מסך ההסכמה של OAuth

כדי להשתמש בתוספים ל-Google Workspace, צריך להגדיר מסך הסכמה. הגדרת מסך ההסכמה של OAuth בתוסף קובעת מה Google מציגה למשתמשים.

  1. במסוף Google Cloud, עוברים אל תפריט > > Branding.

    מעבר לדף Branding

  2. אם כבר הגדרתם את , אתם יכולים לקבוע את ההגדרות הבאות של מסך ההסכמה ל-OAuth בקטעים Branding,‏ Audience וData Access. אם מופיעה ההודעה not configured yet, לוחצים על Get Started:
    1. בקטע App Information בשדה App name, מזינים שם לאפליקציה.
    2. בקטע User support email, בוחרים כתובת אימייל לתמיכה שאליה משתמשים יפנו אם יש להם שאלות לגבי ההסכמה שלהם.
    3. לוחצים על Next.
    4. בקטע Audience, לוחצים על Internal.
    5. לוחצים על Next.
    6. בקטע Contact Information, מזינים כתובת אימייל שאליה אפשר לשלוח התראות על שינויים בפרויקט.
    7. לוחצים על Next.
    8. בקטע Finish, קוראים את המדיניות של Google בנושא נתוני משתמשים בשירותי API. אם אתם מסכימים, מסמנים את התיבה I agree to the Google API Services: User Data Policy.
    9. לוחצים על Continue.
    10. לוחצים על Create.
  3. כרגע אתם יכולים לדלג על הוספת היקפי הרשאות. בעתיד, כשתיצרו אפליקציה לשימוש מחוץ לארגון שלכם ב-Google Workspace, תצטרכו לשנות את סוג המשתמש ל-External. לאחר מכן מוסיפים את היקפי ההרשאות שהאפליקציה דורשת. למידע נוסף, אפשר לעיין במדריך המלא בנושא הגדרת הסכמה ל-OAuth.

יצירה והגדרה של פרויקט Apps Script

כדי ליצור ולהגדיר את פרויקט Apps Script עבור התוסף, מבצעים את השלבים הבאים:

  1. לוחצים על הלחצן הבא כדי לפתוח את הפרויקט של Apps Script‏ Gmail Sentiment Analysis with Gemini and Vertex AI.
    פתיחת פרויקט Apps Script

  2. לוחצים על סקירה כללית .

  3. בדף הסקירה הכללית, לוחצים על סמל יצירת העותק הסמל ליצירת עותק.

  4. כדי לקבל את מספר הפרויקט ב-Cloud:

    1. במסוף Google Cloud, לוחצים על סמל התפריט > IAM & Admin> Settings.

      כניסה לדף IAM & Admin Settings

    2. מעתיקים את הערך בשדה מספר הפרויקט.
  5. מקשרים את הפרויקט ב-Cloud לפרויקט ב-Apps Script:

    1. בפרויקט Apps Script שהעתקתם, לוחצים על Project Settings (הגדרות הפרויקט) הסמל של הגדרות הפרויקט.
    2. בקטע פרויקט Google Cloud Platform (GCP)‎, לוחצים על שינוי הפרויקט.
    3. בקטע מספר פרויקט GCP, מדביקים את מספר הפרויקט ב-Cloud.
    4. לוחצים על הגדרת פרויקט.

בדיקת התוסף

כדי לנסות את התוסף, מתקינים פריסת בדיקה ואז פותחים את התוסף ב-Gmail:

  1. יוצרים ומתקינים פריסת בדיקה של Apps Script:
    1. בפרויקט Apps Script שהעתקתם, לוחצים על עורך .
    2. פותחים את קובץ Code.gs ולוחצים על הפעלה. כשמוצגת בקשה, מאשרים את הסקריפט.
    3. לוחצים על פריסה > בדיקת פריסות.
    4. לוחצים על התקנה > סיום.
  2. פתח את Gmail.

    מעבר ל-Gmail

  3. בסרגל הצד משמאל, פותחים את התוסף Sentiment Analysis.

  4. אם מוצגת בקשה, מאשרים את התוסף.

  5. אופציונלי: כדי ליצור הודעות לבדיקה באמצעות התוסף, לוחצים על יצירת אימיילים לדוגמה. שלוש הודעות מופיעות בתיבת הדואר הנכנס. אם הם לא מופיעים, צריך לרענן את הדף.

  6. כדי להוסיף תוויות, לוחצים על ניתוח הודעות אימייל.

התוסף בודק את 10 ההודעות האחרונות בתיבת הדואר הנכנס שלכם, ואז מחיל אחת מהתוויות הבאות על סמך תוכן ההודעה:

  • נימה שמחה 😊
  • טון ניטרלי 😐
  • טון כועס 😡

בדיקת הקוד

בודקים את הקוד של Apps Script לפתרון הזה:

הצגת קוד המקור

Code.gs

gmail-sentiment-analysis/Code.gs
/*
Copyright 2024 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.
*/

/**
 * 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();
}

Cards.gs

gmail-sentiment-analysis/Cards.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.
*/

/**
 * 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();
}

Gmail.gs

gmail-sentiment-analysis/Gmail.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.
*/

/**
 * 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);
      }
    }
  }
}

/**
 * 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: `<p>Hello, You are late in delivery, again.</p>
<p>Please contact me ASAP before I cancel our subscription.</p>`,
      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");
}

Vertex.gs

gmail-sentiment-analysis/Vertex.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 = '[ADD YOUR GCP PROJECT ID HERE]';

// Location for your Vertex AI model
const VERTEX_AI_LOCATION = 'us-central1';

// Model ID to use for sentiment analysis
const MODEL_ID = 'gemini-2.5-flash';

/**
 * 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;
}

appsscript.json

gmail-sentiment-analysis/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"
}

הסרת המשאבים

כדי להימנע מחיובים בחשבון Google Cloud בגלל השימוש במשאבים שנעשה במסגרת המדריך הזה, מומלץ למחוק את פרויקט Cloud.

  1. במסוף Google Cloud, עוברים לדף Manage resources. לוחצים על תפריט > IAM & Admin > Manage Resources.

    כניסה ל-Resource Manager

  2. ברשימת הפרויקטים, בוחרים את הפרויקט שרוצים למחוק ולוחצים על Delete .
  3. כדי למחוק את הפרויקט, כותבים את מזהה הפרויקט בתיבת הדו-שיח ולוחצים על Shut down.

השלבים הבאים