پیام های Gmail را با Gemini و Vertex AI تجزیه و تحلیل و برچسب گذاری کنید

این راهکار از هوش مصنوعی Vertex و Gemini برای تجزیه و تحلیل پیام‌های Gmail و برچسب‌گذاری آنها بر اساس احساساتشان استفاده می‌کند.

سطح کدنویسی : متوسط
مدت زمان : ۳۰ دقیقه
نوع پروژه : افزونه‌ی Google Workspace

  • یک افزونه‌ی Google Workspace که Gmail را در نوار کناری گسترش می‌دهد.
    شکل ۱: افزونه‌ی تحلیل احساسات ، یک نوار کناری در جیمیل نمایش می‌دهد که در آن کاربران می‌توانند از Gemini بخواهند که پیام‌ها را بر اساس احساساتشان تحلیل و برچسب‌گذاری کند.
  • یک پیام جیمیل با لحنی خنثی.
    شکل ۲: این افزونه یک پیام جیمیل را با برچسب NEUTRAL TONE 😐 برچسب‌گذاری می‌کند.
  • یک پیام جیمیل با مضمون شادی
    شکل ۳: این افزونه یک پیام جیمیل را با برچسب HAPPY TONE 😊 برچسب‌گذاری می‌کند.
  • یک پیام جیمیل با لحنی غمگین
    شکل ۴: این افزونه یک پیام جیمیل را با برچسب UPSET TONE 😡 برچسب‌گذاری می‌کند.

اهداف

  • بفهمید که راه حل چه کاری انجام می‌دهد.
  • بفهمید که سرویس‌های گوگل در این راهکار چه کاری انجام می‌دهند.
  • محیط را تنظیم کنید.
  • پروژه اسکریپت برنامه‌های گوگل (Google Apps Script) را راه‌اندازی کنید.
  • اسکریپت را اجرا کنید.

درباره این راهکار

تصویر از افزونه تحلیل احساسات گوگل ورک اسپیس

این راهکار، یک افزونه‌ی Google Workspace است که برچسب‌ها را بر اساس احساسات پیام‌های Gmail اعمال می‌کند. برای تجزیه و تحلیل محتوای پیام، این افزونه از Vertex AI برای فراخوانی مدل Gemini 2.5 Flash استفاده می‌کند و یکی از احساسات زیر را برمی‌گرداند:

  • مثبت
  • منفی
  • خنثی

با دریافت پاسخ از Gemini، افزونه یک برچسب جیمیل مربوطه را به پیام اعمال می‌کند.

برای محدود کردن درخواست به API هوش مصنوعی Vertex، این افزونه فقط ۱۰ پیام اخیر در صندوق ورودی کاربر Gmail را تجزیه و تحلیل و برچسب‌گذاری می‌کند. برای کسب اطلاعات بیشتر در مورد سهمیه‌ها و محدودیت‌ها، به مستندات Vertex AI مراجعه کنید.

چگونه کار می‌کند؟

این راهکار با استفاده از اسکریپت Google Apps ساخته شده و از سرویس‌ها و محصولات گوگل زیر استفاده می‌کند:

پیش‌نیازها

محیط خود را تنظیم کنید

این بخش نحوه پیکربندی و تنظیم محیط شما در کنسول Google Cloud و Apps Script را توضیح می‌دهد.

پروژه ابری خود را در کنسول گوگل کلود پیکربندی کنید

این بخش به شما نشان می‌دهد که چگونه Vertex AI API را فعال کنید و صفحه رضایت OAuth را در پروژه Cloud خود پیکربندی کنید.

فعال کردن API هوش مصنوعی ورتکس

  1. در کنسول Google Cloud، پروژه Google Cloud خود را باز کنید و Vertex AI API را فعال کنید:

    فعال کردن API

  2. تأیید کنید که API را در پروژه Cloud صحیح فعال می‌کنید، سپس روی Next کلیک کنید.

  3. تأیید کنید که API صحیح را فعال می‌کنید، سپس روی فعال کردن کلیک کنید.

صفحه رضایت OAuth را پیکربندی کنید

افزونه‌های Google Workspace نیاز به پیکربندی صفحه رضایت دارند. پیکربندی صفحه رضایت OAuth افزونه شما، آنچه گوگل به کاربران نمایش می‌دهد را تعریف می‌کند.

  1. در کنسول گوگل کلود، به Menu > برویدGoogle Auth platform > برندسازی .

    به بخش برندسازی بروید

  2. اگر قبلاً تنظیمات را انجام داده‌اید Google Auth platformمی‌توانید تنظیمات صفحه رضایت OAuth زیر را در Branding ، Audience و Data Access پیکربندی کنید. اگر پیامی با این مضمون مشاهده کردید Google Auth platform هنوز پیکربندی نشده است ، روی شروع کار کلیک کنید:
    1. در قسمت اطلاعات برنامه ، در قسمت نام برنامه ، نامی برای برنامه وارد کنید.
    2. در ایمیل پشتیبانی کاربر ، یک آدرس ایمیل پشتیبانی انتخاب کنید که کاربران در صورت داشتن هرگونه سوال در مورد رضایت خود بتوانند با شما تماس بگیرند.
    3. روی بعدی کلیک کنید.
    4. در قسمت مخاطبان ، داخلی (Internal) را انتخاب کنید.
    5. روی بعدی کلیک کنید.
    6. در قسمت اطلاعات تماس ، یک آدرس ایمیل وارد کنید که از طریق آن بتوانید از هرگونه تغییر در پروژه خود مطلع شوید.
    7. روی بعدی کلیک کنید.
    8. در قسمت Finish ، سیاست داده‌های کاربر سرویس‌های API گوگل را مرور کنید و در صورت موافقت، گزینه «من با سیاست‌های داده‌های کاربر سرویس‌های API گوگل موافقم» را انتخاب کنید.
    9. روی ادامه کلیک کنید.
    10. روی ایجاد کلیک کنید.
  3. فعلاً می‌توانید از اضافه کردن محدوده‌ها صرف نظر کنید. در آینده، وقتی برنامه‌ای برای استفاده در خارج از سازمان Google Workspace خود ایجاد می‌کنید، باید نوع کاربر (User type) را به خارجی (External) تغییر دهید. سپس محدوده‌های مجوز مورد نیاز برنامه خود را اضافه کنید. برای کسب اطلاعات بیشتر، به راهنمای کامل پیکربندی رضایت OAuth مراجعه کنید.

پروژه Apps Script خود را ایجاد و تنظیم کنید

برای ایجاد و تنظیم پروژه Apps Script خود برای افزونه، مراحل زیر را انجام دهید:

  1. برای باز کردن پروژه «تحلیل احساسات جیمیل با Gemini و Vertex AI Apps Script» روی دکمه زیر کلیک کنید.
    پروژه Apps Script را باز کنید

  2. روی نمای کلی کلیک کنید.

  3. در صفحه مرور کلی، روی «ایجاد کپی» کلیک کنید آیکون مربوط به کپی کردن .

  4. شماره پروژه ابری خود را دریافت کنید:

    1. در کنسول گوگل کلود، به Menu > IAM & Admin > Settings بروید.

      به تنظیمات IAM و مدیریت بروید

    2. در فیلد شماره پروژه ، مقدار را کپی کنید.
  5. پروژه Cloud خود را با پروژه Apps Script خود متصل کنید:

    1. در پروژه کپی‌شده‌ی Apps Script خود، روی تنظیمات پروژه کلیک کنید. آیکون مربوط به تنظیمات پروژه .
    2. در زیر پروژه پلتفرم ابری گوگل (GCP) ، روی تغییر پروژه کلیک کنید.
    3. در قسمت شماره پروژه GCP ، شماره پروژه Cloud را وارد کنید.
    4. روی تنظیم پروژه کلیک کنید.

افزونه را تست کنید

برای امتحان کردن افزونه، یک نسخه آزمایشی نصب کنید و سپس افزونه را در Gmail باز کنید:

  1. یک استقرار آزمایشی Apps Script ایجاد و نصب کنید:
    1. در پروژه‌ی Apps Script کپی‌شده، روی Editor کلیک کنید.
    2. فایل Code.gs را باز کنید و روی Run کلیک کنید. وقتی از شما خواسته شد، اسکریپت را تأیید کنید.
    3. روی استقرار > آزمایش استقرارها کلیک کنید.
    4. روی نصب > انجام شد کلیک کنید.
  2. جیمیل را باز کنید.

    به جیمیل بروید

  3. در نوار کناری سمت راست، افزونه Sentiment Analysis را باز کنید.

  4. در صورت درخواست، افزونه را تأیید کنید.

  5. اختیاری: برای ایجاد پیام‌هایی برای آزمایش با افزونه‌تان، روی «ایجاد ایمیل‌های نمونه» کلیک کنید. سه پیام در صندوق ورودی شما ظاهر می‌شود. اگر آنها را نمی‌بینید، صفحه را رفرش کنید.

  6. برای افزودن برچسب‌ها، روی «تحلیل ایمیل‌ها» کلیک کنید.

این افزونه ۱۰ پیام آخر موجود در صندوق ورودی شما را بررسی می‌کند و سپس بر اساس محتوای پیام، یکی از برچسب‌های زیر را اعمال می‌کند:

  • لحن شاد 😊
  • تُن خنثی 😐
  • لحن ناراحت 😡

کد را مرور کنید

کد Apps Script را برای این راه حل بررسی کنید:

مشاهده کد منبع

کد.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();
}

کارت‌ها.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();
}

جیمیل.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. در کنسول گوگل کلود، به صفحه مدیریت منابع بروید. روی منو > مدیریت و دسترسی به منابع (IAM & Admin) > مدیریت منابع (Manage Resources) کلیک کنید.

    به مدیریت منابع بروید

  2. در لیست پروژه‌ها، پروژه‌ای را که می‌خواهید حذف کنید انتخاب کنید و سپس روی «حذف کلیک کنید.
  3. در کادر محاوره‌ای، شناسه پروژه را تایپ کنید و سپس برای حذف پروژه، روی خاموش کردن (Shut down) کلیک کنید.

مراحل بعدی