🤖

Google AppsScript から Gemini や PaLM を呼び出す

2023/12/23に公開

tl;dr

Vertex AI の大規模言語モデルを GAS から呼び出すことができます。appsscript.json の scopes の設定と ScriptApp ライブラリを使ってトークンを取得すれば簡単に cloud の API を呼び出すことができます。

事前準備

プロジェクトの設定から Show "appsscript.json" manifest file in editor にチェックしておくこと。

appsscript.json に oauthScopes を追加しておくこと。

appsscript.json
{
  ...,
  "oauthScopes": [
    "https://www.googleapis.com/auth/cloud-platform",
    "https://www.googleapis.com/auth/cloud-platform.read-only",
    "https://www.googleapis.com/auth/script.external_request"
  ],
  ...
}

token の取得

Vertex AI の API を呼び出すにはアカウント認証して、token を取得する必要があります。
Google が提供している、OAuth2.0ライブラリ "apps-script-oauth2" を使用する必要があると思っていましたが、もっと簡単な方法で取得できました。

ScriptApp.getOAuthToken();

なんとこれだけでトークンが取得できます。

実装

上記を踏まえて実装。

// 以下設定はそれぞれの環境によって変えてください。
// Vertex AI の Cloud Console からコードを表示で見ることができます。
const API_ENDPOINT = "{your API_ENDPOINT}"
const PROJECT_ID =  "{your project id}"
const GEMINI_MODEL_ID = "gemini-pro"
const PALM_MODEL_ID = "text-unicorn@001" // ここは bison でも良い。
const LOCATION_ID = "{your location}"

// GEMINI と PALM の ENDPOINT
// streamGenerateContent と predict で response が変わることに注意
const GEMINI_ENDPOINT = `https://${API_ENDPOINT}/v1/projects/${PROJECT_ID}/locations/${LOCATION_ID}/publishers/google/models/${GEMINI_MODEL_ID}:streamGenerateContent`;
const PALM_ENDPOINT = `https://${API_ENDPOINT}/v1/projects/${PROJECT_ID}/locations/${LOCATION_ID}/publishers/google/models/${PALM_MODEL_ID}:predict`;

function setPrompt(prompt) {
  return {
    "contents": [
        {
            "role": "user",
            "parts": [
                {
                    "text": prompt
                }
            ]
        }
    ],
    "generation_config": {
        "maxOutputTokens": 1024,
        "temperature": 0,
        "topP": 1
    }
  }
}

function setPalmPrompt(prompt) {
  return {
    "instances": [
        {
            "content": prompt
        }
    ],
    "parameters": {
        "candidateCount": 1,
        "maxOutputTokens": 256,
        "temperature": 0,
        "topK": 40
    }
  }
}


function getToken() {
  return ScriptApp.getOAuthToken();
}

function callPalm(text, token) {
  const headers = {
    "Authorization": "Bearer " + token,
    "Content-Type": "application/json"
  };

  const payload = setPalmPrompt(text);

  const options = {
    "method": "POST",
    "headers": headers,
    "payload": JSON.stringify(payload)
  };

  // link: https://cloud.google.com/vertex-ai/docs/reference/rest/v1beta1/projects.locations.publishers.models/predict
  const response = UrlFetchApp.fetch(PALM_ENDPOINT, options);
  const responseData = JSON.parse(response.getContentText());

  console.log(responseData);
  return responseData.predictions[0].content;
}

function callGemini(text, token) {
  const headers = {
    "Authorization": "Bearer " + token,
    "Content-Type": "application/json"
  };

  const payload = setPrompt(text);

  const options = {
    "method": "POST",
    "headers": headers,
    "payload": JSON.stringify(payload)
  };

  // link: https://cloud.google.com/vertex-ai/docs/reference/rest/v1beta1/projects.locations.publishers.models/streamGenerateContent
  const response = UrlFetchApp.fetch(GEMINI_ENDPOINT, options);
  const responseData = JSON.parse(response.getContentText());

  // candidates で返ってきているテキストを全て繋ぎ合わせる
  let returnText = "";
  for(let data of responseData) {
    returnText += data.candidates[0].content.parts[0].text;
  }
  console.log(returnText);
  return returnText;
}

function run() {
  const token = getToken();
  const text = "ぷろんぷと";
  
  console.log(callPalm(text, token));
  console.log(callGemini(text, token));
}

おわりに

GAS に組み込んでちょっとしたタスクを Gemini で自動化していくの楽しいです。
みなさんも良い GAS Gemini ライフを!!

Greek Alphabet Software Academy

Discussion