💬
GAS用の OpenAI API ライブラリを作った話
はじめに
少し前に、GAS(Google Apps Script) から OpenAI の API を簡単に使うためのライブラリを作りましたので、その紹介をしたいと思います。
何ができるのか
これを使えば、以下のように実質2行くらいのコーディングで OpenAI の API が GAS から使えます 🙌
APIの流量制限時(レートリミット時)のリトライはライブラリにおまかせで良いので楽ちんです☝️
Azure の OpenAI にも対応👍️
const OPENAI_API_KEY = PropertiesService.getScriptProperties().getProperty('api_key');
const client = OpenAI.createOpenAIClient({
apiKey: OPENAI_API_KEY,
model: 'gpt-4.5-preview'
});
// シンプルな例
function testSimple() {
const result = client.simpleChat("こんにちは!居ますか?");
Logger.log(result);
// 出力例:こんにちは!なにかお手伝いできることはありますか?
}
実用的な使用例
例えば、Google スプレッドシートに溜まったアンケート回答に対して、AIでラベリングをするのも簡単です 🙌
ステップ1: 以下のようなアンケート結果が有ったとして(※これは架空のデータです)・・・
ステップ2: 以下のように生成AI(例ではClaude3.7)にスプレッドシートのスクリーンショット、ライブラリの使い方、分析をしたい旨、を伝えてGASを書いてもらいます(自分でGASを書くのが面倒な場合)
ステップ3: 以下のようにスプレッドシートのスクリプトエディタでGASを実行します
ステップ4: 以下のようにアンケート回答のラベリングができました!🙌
詳しい使い方
※ GitHub の README.md からのコピペです
- src/Code.js の内容を、 GASとして保存。(Google Drive → 新規 → その他 → Google Apps Script)
- 上記のGASを、ライブラリを使いたいGASへライブラリとして追加する
- スクリプトエディタの左メニューの「ライブラリ +」の + をクリックして、↑のスクリプトIDを指定
- 詳しい使い方は、src/Code.js や↓のサンプルを斜め読みしてください
シンプルなコードの例
//OpenAIの場合
const client = OpenAI.createOpenAIClient({
apiKey: '<YOUR_API_KEY>'
});
// Azure の場合
const client = OpenAI.createAzureOpenAIClient({
apiKey: '<YOUR_API_KEY>',
azureEndpoint: '<AZURE_ENDPOINT>',
});
const response = client.simpleChat("こんにちは!");
AIの回答をJSONで受け取る例
// ==== AIの回答をJSONで受け取る例 ====
const responseSchemaHuman = {
"title": "Human",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "名前"
},
"age": {
"type": "number",
"description": "年齢"
}
},
"required": ["name", "age"]
};
params = {
responseSchema: responseSchemaHuman
}
result = client.simpleChat("架空の人物になって自己紹介をして", params);
Logger.log(result);
// 出力例:
// {
// "name": "ヴィクトリア",
// "age": 27
// }
//
JSONスキーマは、受け取りたいJSONっぽい雰囲気のものを書いて、以下のようにChatGPTにJSONスキーマにしてもらえばOK。
AIの前提知識を関数呼び出しで補完する例
// ==== AIに利用可能な関数を伝えて、必要に応じて実行させる例(Function Calling機能) ====
function getWeather(location) {
return {weather: "晴れ"};
}
const functions = [{
func: getWeather,
description: "指定された地域の天気を調べます。",
parameters: {
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"loation": {
"type": "string",
"description": "天気を調べたい地域"
}
},
"required": ["location"],
"additionalProperties": false
}
}];
params = {
functions: functions,
}
result = client.simpleChat("アラスカの天気は?", params);
Logger.log(result);
// 出力例:
// アラスカの天気は晴れです。
//
画像をAIで処理する例
// ==== Drive上の画像を処理する例 ====
const myPng = DriveApp.getFileById("1KRr_7CdjYklHwSvL7EfRfp0EiStgxTIq");
params = {
model: "gpt-4o", // 画像が使えるモデルを指定
images:[myPng.getBlob()]
};
result = client.simpleChat("この画像を解説してください。", params);
Logger.log(result);
// 出力例:
// この画像は、スマートフォンやタブレットなどのデバイスで使用されるメニューの一部を示しています。画面の左側には、各メニュー項目のアイコンが表示されており、右側にはその項目の名前が書かれています。
//
AIで画像を生成する例
params = {
model: "dall-e-3", // 画像生成を使うときはこのモデルを指定
};
result = client.simpleImageGeneration("犬を描いてください。", params);
Logger.log(result);
// 出力例:
// https://the.url.of/generated/image
// (生成された画像のURLが出力される)
//
音声の文字起こしをする例
// ==== 音声の文字起こしの例 ====
const myVoice = DriveApp.getFileById("1nPivg4JwHhrE4Qax1du2CM2P5uIIY9Py");
params = {
// model: "whisper" // Azure の whisper
model: "whisper-1" // 本家 OpenAI の whisper
};
result = client.simpleVoiceToText(myVoice.getBlob(), params);
Logger.log(result);
// 出力例:
// みなさんお集まりいただきありがとうございます 本日は当プロジェクトの大型アップデートについて話し合いましょう
エンベディング(文字列のベクトル表現化)をする例
// ==== エンベディング(ベクトル化)の例 ====
params = {
model: "text-embedding-3-small", // embeddingsを使うときはこのモデルを指定。text-embedding-3-large でも良いよ。
};
result = client.simpleEmbedding(["わーい"], params);
Logger.log(result);
// 出力例;
// {
// "object": "list",
// "data": [
// {
// "object": "embedding",
// "index": 0,
// "embedding": [
// 0.002589861,
// 0.013294913,
// -0.079392985,
// ⋮
開発の動機
以下のような背景が有ってちょっと作ってみました。
- GASから生成AIを簡単に使えたら便利そう(自分がアンケート回答分析等に使いたかった)
- エンジニアではない方でも、生成AIにGASの書き方を聞くなどして、生成AI機能を搭載したGASを簡単に書けたならちょっとしたツールをサッと書いて業務の効率化ができそう
- 当時、GASから簡単に使えるOpenAI APIのクライアントライブラリは見当たらなかった
技術的なポイント
コード を見ての通り、 OpenAI の REST API へアクセスしているだけなので、とくに技術的なポイントは有りません😅
まとめ
AIに任せられるところは任せていきましょう! 🙌
Discussion