チューニング済みのGeminiはGASから呼び出せるか?

 結論から言うと、できます。ただし、壁がいくつかあります。ネット上で見つかるAPIの利用例はチューニング無しのGeminiをREST APIから呼び出して使おうというものになります。基本的な考え方はそれと同じですが、チューニング済みのモデルに関しては他人に勝手に使われないように厳しいセキュリティーがかかっています。なので、チューニング無しのモデルと同様にアクセスしようとすると403 Forbiddenが返ってきます。

 困ったことに、Google AI Studioで提示されるサンプルコードはこの点を考慮していないようで、チューニング済みのモデルはそのまま試しても全然動きません。それでどうするのかというとOAuth 2.0でGoogleにログインして、セッションを維持しながらヘッダーにAuthorizationをくっつけてアクセスするべきだということになります。

 とは言っても、ちょっと試す程度の話でOAuthの実装までさせられたのではたまりませんよね。そこでGASの機能を活用して、認証を通していきます。ここで出てくるのが認証スコープの概念ですが、細かい部分はネット上に情報があるので割愛します。

いずれにしても、Google Cloud Platform(GCP)でプロジェクトを作成し、プロジェクト番号をGASの設定に貼り付けるくらいのことは必要です。また、APIを有効にする必要もあります。スクリプト側では認証スコープを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",
    "https://www.googleapis.com/auth/generative-language.tuning"
  ]

こんな感じです。特に一番最後のgenerative-languageがGeminiのチューニング済みモデルを呼び出すのに必要です。ちなみにこのスコープは、開発者向けのAPIリファレンスに記載がありましたが、検索しても簡単には出てこなかったです。ついでにAI Studioで取得したAPI鍵をスクリプトのプロパティに入れておくのがおすすめです。鍵をコードにハードコードするのはちょっと気が引けますからね。

const GOOGLE_AI_STUDIO_API_KEY = PropertiesService.getScriptProperties().getProperty("googleAiStudioApiKey");

するとこのようにして鍵を実行時に読み込めます。そしてこの鍵をモデル名とともに指定して、APIのアクセス先とします。

const GEMINI_ENDPOINT = "https://generativelanguage.googleapis.com/v1beta/tunedModels/モデル名:generateContent?key="+GOOGLE_AI_STUDIO_API_KEY;

上記の手順がちゃんとできていた場合、次のコードでHTTPSヘッダーに埋め込む認証トークンは次のようなコードで取得できます。

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

あとはこれらを活用してプロンプトを投げてあげるだけです。プロンプトを投げる関数を一つにまとめておくと便利ですね。

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

  const payload = setPrompt(text);
  let returnText = "";

  const options = {
    "method": "POST",
    "headers": headers,
    "muteHttpExceptions" : true,
    "payload": JSON.stringify(payload)
  };
  try{
    const response = UrlFetchApp.fetch(GEMINI_ENDPOINT, options);
    const responseData = JSON.parse(response.getContentText());
    returnText = responseData.candidates[0].content.parts[0].text;
  }catch(e){
    console.log("Error: " + e.message + "\r\n");
  }
  return returnText;
}

プロンプトデータの作り方は基本的に通常のGeminiと同様かと思います。このコードではsetPrompt(text)の中で処理しています。わかってしまえば何ということはないのですけど、チューニング済みモデル向けの手順が見当たらなかったので一つの成功例として載せておきます。

この記事が気に入ったらサポートをしてみませんか?