使用 Gemini API 自动执行 Google Workspace 任务

1. 准备工作

在此 Codelab 中,您将学习如何利用 Gemini API 的函数调用和多模态功能自动执行 Google Workspace 任务。

前提条件

  • 基本熟悉 Apps 脚本、JavaScript 或类似的编程语言

学习内容

  • 如何利用 Gemini API 的函数调用和多模态功能。
  • 如何将多个 Gemini API 调用链接在一起。
  • 如何使用 Gemini API 自动执行 Google Workspace 任务。

所需条件

  • 网络浏览器。
  • Gmail 账号。或者,已实现 Gemini API 的特定设置的 Google Workspace 账号。
  • 来自 Gemini API 支持的区域的连接。
  • 可选:一个包含 curl 程序的命令行界面,用于测试直接 API 请求。

此 Codelab 的完整代码可在 GitHub 上的 Gemini API Cookbook 中找到。如果您需要完整的代码,请查看此链接。

2. 设置 Gemini API

关于 Gemini

Gemini 模型是 Google 旗下最大、最强大的 AI 模型系列。如需在应用中利用这些模型,您可以使用 Gemini API。您还可以在 Google AI Studio 中试用 Gemini API。这是一个适用于该 API 的 Web 界面,您可以在其中试用提示、调整模型设置和微调自定义模型,而无需编写任何代码。

获取密钥

可选:测试密钥

如果您可以使用 curl 访问命令行,请将您的密钥添加到以下代码块的第一行,然后在终端中运行该代码块以测试 API 密钥。

export GOOGLE_API_KEY=Paste_your_API_key_here

curl "https://generativelanguage.googleapis.com/v1beta/models?key=${GOOGLE_API_KEY}"

您应该会看到 JSON 格式的模型列表,例如 models/gemini-1.0-pro。这意味着该功能已正常运行。

3. 可选:向 Gemini API 发出请求

在此可选步骤中,您将向 Gemini API 发出请求,以便在将内容生成功能添加到 Apps 脚本应用之前,更好地了解其运作方式。

模型简介

Gemini API 提供了多种模型,这些模型具有不同的功能和限制。您可以在 Gemini 模型页面上查看每种模型及其功能。

发出第一个请求

如需让 Gemini API 完成文本提示,您需要构建 JSON 请求并将其发送到 REST API 端点。

具体步骤如下:

  1. 在新文件中,输入以下 JSON 请求:
{
  contents: [
   {
     parts: [
       { text: 'The most important aspects of a persuasive presentation are:' }
     ]
   }
 ]
}

JSON 请求包含以下提示:The most important aspects of a persuasive presentation are:。模型会完成此指令,并直接向您提供结果。

JSON 请求有三个顶级字段需要填充:contentsgenerationConfigsafetySettings。只有 contents 是必需的。其他参数则用于控制输出。

  1. 将此 JSON 保存到 presentation.txt 文件中,然后直接将其传递给 curl,如下所示:
curl -H 'Content-Type: application/json' -X POST -d @presentation.txt \
  'https://generativelanguage.googleapis.com/v1beta/models/gemini-1.0-pro-latest:generateContent?key='${GOOGLE_API_KEY}

在此示例中,您在网址中设置了以下值:

  • v1beta 指定 API 版本。
  • gemini-1.0-pro-latest 指定 Gemini 1.0 Pro 为模型,并使用最新快照。
  • generateContent 指定您调用的 API 方法。

您应该会看到如下所示的结果:

{
  "candidates": [
    {
      "content": {
        "parts": [
          {
            "text": "* **Credibility:** The audience must trust that you are an expert on the subject matter and that you have their best interests at heart.\n* **Clearness:** Your message must be easy to understand and follow. Avoid using jargon or technical terms that your audience may not be familiar with.\n* **Concreteness:** Use specific examples and data to support your arguments. Avoid making vague or general claims.\n* **Emotional appeal:** In addition to appealing to the audience's logical side, you should also try to connect with them on an emotional level. Use storytelling, humor, and personal anecdotes to make your points more memorable and engaging.\n* **Strong closing:** End your presentation with a strong call to action. Tell the audience what you want them to do and why it is important for them to do it."
          }
        ],
        "role": "model"
      },
      "finishReason": "STOP",
      "index": 0,
      "safetyRatings": [...]
    }
  ],
  "promptFeedback": {
    "safetyRatings": [...]
  }
}

为了方便阅读,以下是经过常规格式设置的终端输出:

  • 可信度:受众必须相信您是相关主题方面的专家,并且您会尽最大努力维护他们的利益。
  • 清晰度:您的消息必须易于理解和遵循。避免使用受众群体可能不熟悉的行话或技术术语。
  • 具体性:使用具体示例和数据来支持您的论点。避免做出含糊不清或笼统的声明。
  • 情感诉求:除了诉诸受众的逻辑思维之外,您还应尝试在情感层面上与他们建立联系。运用讲故事、幽默和个人轶事等方式,让您的观点更令人难忘且更具吸引力。
  • 有力的结尾:在演示结束时,提供有力的号召性用语。告诉观众您希望他们做什么,以及他们为何必须这样做。

如需详细了解其他设置(包括 generationConfigsafetySettings),请参阅提示安全指南。

4. 从 Apps 脚本调用 Gemini API

  1. 访问 script.new,系统会自动为您创建一个 code.gs Apps 脚本文件。
  2. 将光标悬停在 code.gs 文件上,然后依次点击 8bfe57773be886ab.png > 重命名
  3. 将文件名更改为 utils.gs
  4. 在该文件中,移除 myFunction 函数,使文件为空。

将您的 API 密钥添加到项目中

  1. 在导航菜单中,选择项目设置
  2. 脚本属性下,点击添加脚本属性
  3. 属性下,输入 GOOGLE_API_KEY
  4. Value 下,输入您从 Google AI Studio 获得的 API 密钥。

fcfe205a93879c49.png

  1. 点击保存脚本属性
  2. 返回到编辑器。

添加 Gemini API 代码

utils.gs 文件中,按以下步骤操作:

设置 API 密钥和端点:

const properties = PropertiesService.getScriptProperties().getProperties();
const geminiApiKey = properties['GOOGLE_API_KEY'];
const geminiEndpoint = `https://generativelanguage.googleapis.com/v1beta/models/gemini-1.0-pro-latest:generateContent?key=${geminiApiKey}`;
  1. 添加以下函数,该函数使用特定提示调用 Gemini API:
function callGemini(prompt, temperature=0) {
  const payload = {
    "contents": [
      {
        "parts": [
          {
            "text": prompt
          },
        ]
      }
    ], 
    "generationConfig":  {
      "temperature": temperature,
    },
  };

  const options = { 
    'method' : 'post',
    'contentType': 'application/json',
    'payload': JSON.stringify(payload)
  };

  const response = UrlFetchApp.fetch(geminiEndpoint, options);
  const data = JSON.parse(response);
  const content = data["candidates"][0]["content"]["parts"][0]["text"];
  return content;
}
  1. 添加以下用于设置提示的函数:
function testGemini() {
  const prompt = "The best thing since sliced bread is";
  const output = callGemini(prompt);
  console.log(prompt, output);
}

测试应用

  1. 点击 76113423d1f91775.png 保存
  2. 在函数下拉列表中选择 testGemini,然后点击 5b9034ff679c8761.png
  3. 接受必要的权限。您的代码应会运行,并且您应会在执行日志中看到一些包含结果的控制台输出。

执行日志

成功了!

5. 使用图片调用 Gemini API

Gemini 系列模型最强大的功能之一是支持多模态输入,这意味着您不仅可以提供文本,还可以提供其他类型的内容!在本部分中,您将添加一个使用图片调用 Gemini API 的函数。

  • utils.gs 文件顶部现有 const geminiEndpoint 声明之后,添加以下行:
const geminiProVisionEndpoint = `https://generativelanguage.googleapis.com/v1beta/models/gemini-1.0-pro-vision-latest:generateContent?key=${geminiApiKey}`;

添加 Gemini Vision 代码

  1. utils.gs 文件添加一个函数,以调用此新添加的端点:
function callGeminiProVision(prompt, image, temperature=0) {
  const imageData = Utilities.base64Encode(image.getAs('image/png').getBytes());

  const payload = {
    "contents": [
      {
        "parts": [
          {
            "text": prompt
          },
          {
            "inlineData": {
              "mimeType": "image/png",
              "data": imageData
            }
          }          
        ]
      }
    ], 
    "generationConfig":  {
      "temperature": temperature,
    },
  };

  const options = { 
    'method' : 'post',
    'contentType': 'application/json',
    'payload': JSON.stringify(payload)
  };

  const response = UrlFetchApp.fetch(geminiProVisionEndpoint, options);
  const data = JSON.parse(response);
  const content = data["candidates"][0]["content"]["parts"][0]["text"];
  return content;
}
  1. 添加以下测试函数:
function testGeminiVision() {
  const prompt = "Provide a fun fact about this object.";
  const image = UrlFetchApp.fetch('https://storage.googleapis.com/generativeai-downloads/images/instrument.jpg').getBlob();
  const output = callGeminiProVision(prompt, image);
  console.log(prompt, output);
}

此函数会从互联网加载测试图片,并将其传递给您定义的函数。稍后,您将连接它以使用电子表格中的图表,因此这只是一个测试。

测试应用

  • 保存并运行 testGeminiVision 函数,然后检查输出。

849c6728bfb5ec52.png

6. 使用工具调用 Gemini API

除了文字和图片之外,您还可以在提示中提供对工具的访问权限。

添加工具处理代码

  • utils.gs 文件添加一个接受工具规范的函数:
function callGeminiWithTools(prompt, tools, temperature=0) {
  const payload = {
    "contents": [
      {
        "parts": [
          {
            "text": prompt
          },
        ]
      }
    ], 
    "tools" : tools,
    "generationConfig":  {
      "temperature": temperature,
    },    
  };

  const options = { 
    'method' : 'post',
    'contentType': 'application/json',
    'payload': JSON.stringify(payload)
  };

  const response = UrlFetchApp.fetch(geminiEndpoint, options);
  const data = JSON.parse(response);
  const content = data["candidates"][0]["content"]["parts"][0]["functionCall"];
  return content;
}

如需详细了解此架构和可用字段,请参阅 FunctionDeclaration API 参考文档

测试应用

  1. 定义一种模型可用于查找当前日期和时间的工具:
function testGeminiTools() {
  const prompt = "Tell me how many days there are left in this month.";
  const tools = {
    "function_declarations": [
      {
        "name": "datetime",
        "description": "Returns the current date and time as a formatted string.",
        "parameters": {
          "type": "string"
        }
      }
    ]
  };
  const output = callGeminiWithTools(prompt, tools);
  console.log(prompt, output);
}

此处使用的格式为 FunctionDeclaration 架构。您实际上并未调用日期时间函数。您只会收到模型请求函数调用的指示。您将在后续步骤中处理函数调用。

  1. 保存并运行 testGeminiTools 函数以查看输出。

执行日志

7. Google Workspace 演示集成概览

现在,您已经了解了函数调用的工作原理,可以轻松将 Gemini 模型的功能扩展到其他服务。在接下来的几部分中,您将针对 Google Workspace 产品(例如 Google 云端硬盘、Google 幻灯片和 Google 表格)构建集成。下图是一个简化图:

3 个工具

从宏观层面来看,当用户查询到来时,您可以使用 Gemini API 的函数调用来确定要使用哪个工具。您将构建三个可执行以下操作的工具:

  • 设置会议。图中的 setupMeeting() 函数会调用 Gemini 1.0 Pro API 来总结 Google 云端硬盘中的博客,并将总结内容添加到 Google 日历中新建的会议中。
  • 根据图表中的数据分析撰写电子邮件草稿。图表中的 draftEmail() 函数会调用 Gemini 1.0 Pro Vision 来分析 Google 表格中的图表,并根据分析结果在 Gmail 中撰写电子邮件。
  • 创建演示文稿框架。图中的 createDeck() 函数会调用 Gemini 1.0 Pro,为 Google 幻灯片中的演示文稿集思广益,生成项目符号。

对于每种工具,您需要执行以下三项操作:

  1. 确定 Gemini API 的函数调用响应是否要求在 if...else 块中调用该特定工具。
  2. 添加用于实现工具功能的实际函数。
  3. 使用 Gemini API 声明工具,以便 Gemini 模型知道该工具的存在,并能返回正确的函数调用响应。

8. 使用 Apps 脚本设置会议

首先,您在 Google 日历中自动设置会议,但您还添加了说明,即 Google 云端硬盘中文件的摘要。

具体步骤如下:

  1. 下载此文本文件,其中包含 Gemini 1.5 Pro 发布博文的文本内容。
  2. 将文件上传到 Google 云端硬盘中的根文件夹。
  3. 在编辑器中,创建一个 main.gs 文件,然后添加以下代码:
function main() {
  const userQuery = "Set up a meeting at 10AM tomorrow with Helen to discuss the news in the Gemini-blog.txt file.";

  var tool_use = callGeminiWithTools(userQuery, WORKSPACE_TOOLS);
  Logger.log(tool_use);
  
  if(tool_use['name'] == "setupMeeting") {
    setupMeeting(tool_use['args']['time'], tool_use['args']['recipient'], tool_use['args']['filename']);
    Logger.log("Your meeting has been set up.");
 }
  else
    Logger.log("no proper tool found");
}

在此处,您调用了 Gemini API 的函数调用功能。接下来,您需要定义工具函数。

  1. 在编辑器左侧,点击服务旁边的 + 添加服务 > Google 日历 API > 添加。这会启用高级 Google 日历服务,您需要在稍后使用一些高级 API 时用到该服务。

添加服务

  1. utils.gs 文件中,添加以下代码:
function attachFileToMeeting(event, file, fileName) {
  // Get the iCal ID for the event.
  const iCalEventId = event.getId();

  // Log the ID and title for debugging.
  console.log(`iCal event ID: ${iCalEventId}`);
  console.log(`event Title: ${event.getTitle()}`);

  // Set up the options for listing the event with the advanced Google Calendar service.
  const options = {
      iCalUID: iCalEventId,
    };

  // Use the primary calendar as the calendar ID to list events.
  const calendarId = 'primary';

  // Use the advanced Google Calendar service to list the event.
  const calEvents = Calendar.Events.list(calendarId, options);

  // Get the Calendar ID used by the advanced Google Calendar service.
  const eventId = calEvents.items[0].id;

  // Get the file URL for the attachment.
  const fileUrl = file.getUrl();

    // Set up the patch options to add the file.
    var patch = {
      attachments: [{
        'fileUrl': fileUrl,
        'title': fileName
      }]
    };

    // Patch the event to add the file as an attachment.
    Calendar.Events.patch(patch, 'primary', eventId, {"supportsAttachments": true});  
}

function setupMeeting(time, recipient, filename) {
  const files = DriveApp.getFilesByName(filename);
  const file = files.next();
  const blogContent = file.getAs("text/*").getDataAsString();
  
  var geminiOutput = callGemini("Give me a really short title of this blog and a summary with less than three sentences. Please return the result as a JSON with two fields: title and summary. \n" +  blogContent);
  // The Gemini model likes to enclose the JSON with ```json and ```
  geminiOutput = JSON.parse(geminiOutput.replace(/```(?:json|)/g, ""));  
  const title = geminiOutput['title'];
  const fileSummary = geminiOutput['summary'];

  const event = CalendarApp.getDefaultCalendar().createEventFromDescription(`meet ${recipient} at ${time} to discuss "${title}"`); 
  event.setDescription(fileSummary);
  attachFileToMeeting(event, file, filename);
}

此代码会执行以下操作:

  • setupMeeting() 函数会遍历您的 Google 云端硬盘,并找到 Gemini-blog.txt 文件。此文件名由 Gemini API 在第 3 步中自动返回。
  • setupMeeting() 函数会调用 Gemini API 来总结文件内容,使用自由格式的说明通过 CalendarApp 设置会议,并将总结添加到会议中。
  • setupMeeting() 函数调用 attachFileToMeeting() 函数,以使用高级 Google 日历服务将博客文件附加到会议中。
  1. utils.gs 文件顶部,添加以下代码:
const WORKSPACE_TOOLS = {
 "function_declarations": [
   {
     "name": "setupMeeting",
     "description": "Sets up a meeting in Google Calendar.",
     "parameters": {
       "type": "object",
       "properties": {
         "time": {
           "type": "string",
           "description": "The time of the meeting."
         },
         "recipient": {
           "type": "string",
           "description": "The name of the recipient."
         },   
         "filename": {
           "type": "string",
           "description": "The name of the file."
         },                     
       },
       "required": [
         "time",
         "recipient",
         "filename"
       ]
     }
   },
   // You add tools here.        
 ]
};
  1. 在编辑器中,返回到 main.gs 文件,然后点击 5b9034ff679c8761.png
  2. 如果 Google Workspace 要求您授予运行脚本的权限,请点击确定

几秒钟后,执行日志会显示一条消息,告知您会议已设置完毕。

  1. 在 Google 日历中,找到包含摘要和附件的会议。

会议邀请

9. 使用 Apps 脚本撰写电子邮件草稿

接下来,您将自动执行在 Gmail 中撰写电子邮件的操作。假设您在 Google 表格中进行数据分析。您将所有数字都放在相应位置,然后创建图表。您想使用 Gemini Pro Vision API 根据图表撰写电子邮件草稿。

具体步骤如下:

  1. 打开此工作表,然后依次点击文件 -> 复制
  2. 复制文档对话框的名称文本框中,将默认名称 Copy of CollegeExpenses 替换为 CollegeExpenses
  3. main.gs 文件中,将之前的用户查询替换为新的查询,然后将以下代码添加到 if...else 语句中:
function main() {
  // const userQuery = "Set up a meeting at 5PM with Helen to discuss the news in the Gemini-1.5-blog.txt file.";  
  const userQuery = "Draft an email for Mary with insights from the chart in the CollegeExpenses sheet.";

  if(...) {...}
  // Add this code
  else if(tool_use['name'] == "draftEmail") {
    draftEmail(tool_use['args']['sheet_name'], tool_use['args']['recipient']);
    Logger.log("Check your Gmail to review the draft");
  }
  else {...}

}
  1. utils.gs 文件中,添加以下代码:
function draftEmail(sheet_name, recipient) {
  
  const prompt = `Compose the email body for ${recipient} with your insights for this chart. Use information in this chart only and do not do historical comparisons. Be concise.`;

  var files = DriveApp.getFilesByName(sheet_name);
  var sheet = SpreadsheetApp.openById(files.next().getId()).getSheetByName("Sheet1");
  var expenseChart = sheet.getCharts()[0];

  var chartFile = DriveApp.createFile(expenseChart.getBlob().setName("ExpenseChart.png"));
  var emailBody = callGeminiProVision(prompt, expenseChart);
  GmailApp.createDraft(recipient+"@demo-email-provider.com", "College expenses", emailBody, {
      attachments: [chartFile.getAs(MimeType.PNG)],
      name: 'myname'
  });
}

此函数从工作表中检索大学费用图表,并将其发送给 Gemini Pro Vision 以草拟电子邮件。Gemini Pro Vision 会从图表中提取信息,并代表您撰写电子邮件正文。

  1. utils.gs 文件中,将以下代码添加到 You add tools here 注释后面的 WORKSPACE_TOOLS 对象:
  WORKSPACE_TOOLS = {
    "function_declarations": [
      // You add tools here.

      {
        "name": "draftEmail",
        "description": "Write an email by analyzing data or charts in a Google Sheets file.",
        "parameters": {
          "type": "object",
          "properties": {
            "sheet_name": {
              "type": "string",
              "description": "The name of the sheet to analyze."
            },
            "recipient": {
              "type": "string",
              "description": "The name of the recipient."
            },            
          },
          "required": [
            "sheet_name",
            "recipient"
          ]
        }
      },   


    ]
  };
  1. 在编辑器中,返回到 main.gs 文件,然后点击 5b9034ff679c8761.png
  2. 10 到 20 秒后,打开 Gmail。您应该会看到类似如下所示的电子邮件草稿:

您可以在发送电子邮件草稿之前对其进行修改。这封电子邮件完全由 Gemini Pro Vision 在您提供简短提示和图表后撰写。

10. 使用 Apps 脚本创建框架演示

接下来,您可以使用 Apps 脚本自动在 Google 幻灯片中创建框架演示文稿。

具体步骤如下:

  1. main.gs 文件中,将之前的用户查询替换为新的查询,并将以下代码添加到 if...else 语句中:
function main() {
  // const userQuery = "Draft an email for Mary with insights from the chart in the CollegeExpenses sheet.";
  const userQuery = "Help me put together a deck about water conservation.";

  if(...) {...}
  // Add this code
  else if(tool_use['name'] == 'createDeck') {
    deckURL = createDeck(tool_use['args']['topic']);
    Logger.log("Deck URL: " + deckURL);
  }
  else {...}

}
  1. utils.gs 文件中,添加以下代码:
function createDeck(topic) {
  const prompt = `I'm preparing a ${NUM_SLIDES}-slide deck to discuss ${topic}. Please help me brainstorm and generate main bullet points for each slide. Keep the title of each slide short. Please produce the result as a valid JSON so that I can pass it to other APIs.`;
  
  var geminiOutput = callGemini(prompt, 0.4);
  // The Gemini model likes to enclose the JSON with ```json and ```
  geminiOutput = geminiOutput.replace(/```(?:json|)/g, "");
  const bulletPoints = JSON.parse(geminiOutput);
    
  // Create a Google Slides presentation.
  const presentation = SlidesApp.create("My New Presentation");

  // Set up the opening slide.
  var slide = presentation.getSlides()[0]; 
  var shapes = slide.getShapes();
  shapes[0].getText().setText(topic);

  var body;
  for (var i = 0; i < NUM_SLIDES; i++) {
      slide = presentation.appendSlide(SlidesApp.PredefinedLayout.TITLE_AND_BODY);
      shapes = slide.getShapes();
      // Set title.
      shapes[0].getText().setText(bulletPoints['slides'][i]['title']);
  
      // Set body.
      body = "";
      for (var j = 0; j < bulletPoints['slides'][i]['bullets'].length; j++) {
        body += '* ' + bulletPoints['slides'][i]['bullets'][j] + '\n';
      }
      shapes[1].getText().setText(body);
  } 

  return presentation.getUrl();
}

此函数调用 Gemini API 来针对特定主题进行头脑风暴,并以以下格式返回项目符号

的 JSON,然后使用 Apps 脚本填充框架演示文稿。

  1. utils.gs 文件中,将以下代码添加到 You add tools here 注释后面的 WORKSPACE_TOOLS 对象:
  WORKSPACE_TOOLS = {
    "function_declarations": [
      // You add tools here.

      {
        "name": "createDeck",
        "description": "Build a simple presentation deck with Google Slides and return the URL.",
        "parameters": {
          "type": "object",
          "properties": {
            "topic": {
              "type": "string",
              "description": "The topic that the presentation is about."
            },
          },
          "required": [
            "topic"
          ]
        }
      },


    ]
  };
  1. utils.gs 文件顶部,定义以下常量:
const NUM_SLIDES = 3;

这是 Gemini 模型在开头幻灯片之外创建的幻灯片数量。

  1. 在编辑器中,返回到 main.gs 文件,然后点击 5b9034ff679c8761.png。几秒钟后,您会在执行日志中看到演示文稿网址。
  2. 使用浏览器打开该网址。您应该会看到一个填充了项目符号的框架演示。

草稿演示文稿

11. 探索建议

除了这三种集成之外,您还可以探索以下想法:

  • 在 Google Chat 中构建聊天机器人。大语言模型 (LLM) 最常见的应用场景之一是构建聊天机器人。借助 Gemini API,您可以轻松为 Google Chat 构建聊天机器人。如需了解详情,请参阅 Google Chat API 和 Codelab 构建内置 Gemini 的 Google Chat 应用
  • 使用 Google 云端硬盘或 Keep 中的自有数据进行检索增强生成 (RAG)。在此 Codelab 中,您仅使用一个文本文件进行总结。不过,您也可以将个人 Google 云端硬盘和 Keep 中的内容(例如笔记、PDF 和图片)与 Gemini API、矢量数据库以及可选的编排工具(例如 LangChain)搭配使用,以执行 RAG 并根据您的数据对模型的回答进行个性化设置。
  • 使用 Gemini API 的多轮函数调用功能。Gemini API 的函数调用不限于一轮,您可以进行多轮函数调用,以处理更复杂的任务。
  • 超越 Google Workspace。现在,您已了解如何将 Gemini API 与 Google Workspace 集成,接下来可以超越 Google Workspace 的范畴,利用其他 API。

12. 恭喜

您了解了 Gemini API 的多模态功能和函数调用。您使用它们通过 Apps 脚本自动执行了一些 Google Workspace 任务!

了解详情