【GAS】Open AI APIを使って画像生成する方法を完全解説(LINE BOT化も)
こんにちは、えぬ(@nmukineer)です!
Open AI APIとGASを使って、日本語から画像を自動生成するスクリプトを書いてみました。生成された画像は、指定したGoogle Driveのフォルダに自動保存されるようにしています。
Open AI APIの設定
Open AIとは、イーロン・マスクらが設立した、アメリカの人工知能(AI:Artificial Intelligence)の非営利研究団体です。
APIを公開しており、アカウント登録をすれば使用することができます(Open AI API)。
ただし、料金は無料ではなく従量制となっていますが、いきなり料金が発生するわけではないので安心して下さい。
2023年1月時点では、登録時に18ドルのクレジットをもらうことができます(3カ月間有効)。
最近ではChatGPT(チャット形式で質問に答えてくれるAI)が非常によくできておりTwitterでざわついたりしていますね。
そんなOpen AIには言葉から画像を生成してくれるDALL-Eというサービスがあります。
このDALL-EのAPIが2022年11月3日に使用可能となり、気軽に外部サービスからもAI画像生成を試すことができるようになりました。
ここからは、Open AIのアカウント登録を済ませサインインまでできている、という前提で話を進めていきます。
API Keyの発行
APIを利用するには、API Keyを発行する必要があります。
Open AIのマイページログイン後、右上の「Personal」から、「View API keys」を選択します。(筆者はすでに1つAPI Keyを作成しているのでそのようになっていますが、初回の作成時は異なる表示になっているかもしれません。)
「Create new secret key」を選択してAPI Keyを発行します。
こちらのような画面に発行されたAPI keyが表示されます。赤枠の「コピーボタン」を押してコピーし、メモ帳などに貼り付け保存しておきます(インターネット上には公開しないでください)
画像生成APIの使い方
画像生成を行うAPIのドキュメントを見ていきます。
curlコマンドの場合、以下のようにすることで画像URLを含むレスポンスを受け取ることができます。YOUR_API_KEY
の部分には上で生成したAPI keyを入れるようにしましょう。
curlコマンド
curl https://api.openai.com/v1/images/generations \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-d '{
"prompt": "A cute baby sea otter",
"response_format": "b64_json"
}'
レスポンス
{
"created": 1589478378,
"data": [
{
"url": "https://..."
},
{
"url": "https://..."
}
]
}
リクエストパラメータ
画像生成APIにリクエストする際に必要となるパラメータは主に下記の4つがあります。この4つ以外にもう一つuser
というオプションパラメータもあるようですが、ヘビーユースしない限りは必要なさそうですのでここでは割愛します。
パラメータ | 説明 | 例 |
prompt(必須) | 画像生成したい言葉を指定します。基本的には英語で指定したほうがよさそうです。 | “cute cat” |
n(任意。デフォルトは1) | 生成する画像の枚数。 | 2 |
size(任意。デフォルトは”1024×1024″) | 出力する画像のサイズ。 “256×256”, “512×512”, “1024×1024” の3つのうちどれかを指定します。 | “512×512” |
response_format(任意。デフォルトは”url”) | レスポンスフォーマット。 “url”か”b64_json”のどちらかを指定します。画像へのリンクが欲しい場合は”url”, 直接画像データを取得したい場合は”b64_json”を指定するとよさそうです。 | “b64_json” |
GASスクリプト
画像生成を行うOpen AI APIの使い方がわかったところで、GASのコードを書いていきます。
GASのプロジェクト作成方法については以下の記事を参考にしてください。
フローチャート
コードを書く前に、簡単にフローチャートを書いてみます。
まず、画像生成APIを使う際に指定する言葉は英語である必要がありますので、日本語を英語に翻訳する必要があります。
その後、翻訳した英語をパラメータとして画像生成APIリクエストを行います。
画像生成結果はurlとしてレスポンスされるので、そのURLから画像をダウンロードします。ダウンロードしたら、Google Driveに保存します。
日本語を英語に翻訳するコード
英語を日本語に翻訳するGASコードは以下の記事で紹介していますので、ご参照いただければ幸いです。今回もそのまま利用します。
Open AI 画像生成APIを叩いて画像URLを取得するコード
Open AI画像生成APIを叩いて画像URLを取得するコードはこちらです。
const IMAGE_GENERATION_URL = 'https://api.openai.com/v1/images/generations';
const OPEN_AI_API_KEY = PropertiesService.getScriptProperties().getProperty('OPEN_AI_API_KEY');
function generateImage(text) {
const options = {
"method" : "get",
'contentType': 'application/json',
"headers": { "Authorization":"Bearer " + OPEN_AI_API_KEY },
"payload": JSON.stringify({
prompt: text,
n: 1, //デフォルトと同じであれば省略可
size: "1024x1024", //デフォルトと同じであれば省略可
response_format: "url" //デフォルトと同じであれば省略可
})
}
const response = UrlFetchApp.fetch(IMAGE_GENERATION_URL, options);
const imageUrl = JSON.parse(response.getContentText()).data[0].url;
return imageUrl;
}
GASのスクリプトプロパティにOPEN_AI_API_KEY
を登録しておきましょう。スクリプトプロパティの登録方法は以下の記事内で説明しておりますので参考にしていただければ幸いです。
引数及び戻り値の仕様は以下のようにしました。(レスポンスエラーのハンドリングは省略しています)
- 引数:生成したい画像を説明するテキスト(型:String)
- 例:”cute cat”など
- 戻り値:生成された画像のURL(型:String)
生成された画像URLから画像をダウンロードしてGoogle Driveに保存するコード
以下のスクリプトで画像URLから画像をダウンロードし、Google Driveに保存します。
Google Driveに保存した際に画像の名前を変更しますが、ここではDate.now()
を使ってタイムスタンプとしています。
// Open AIサーバーから画像ダウンロードしてGoogle Driveに保存
const FOLDER_ID = PropertiesService.getScriptProperties().getProperty('FOLDER_ID');
const imageFolder = DriveApp.getFolderById(FOLDER_ID);
function downloadImageFromOpenAiServer(imageUrl) {
const response = UrlFetchApp.fetch(imageUrl);
const blob = response.getBlob();
let newFile = imageFolder.createFile(blob);
newFile.setName(Date.now());
return newFile.getDownloadUrl();
}
ここではスクリプトプロパティにFOLDER_ID
を設定しておきましょう。(FOLDER_IDは、Google Driveの任意のフォルダのIDのことです)
ここで作成したメソッドの引数及び戻り値は以下の仕様としました。
- 引数:画像URL(型:String)
- 戻り値:Google Driveの画像ダウンロードURL(型:String)
GASコード全体
以上をまとめたGASコードがこちらです。
今回は生成したい画像の説明文をmain関数の中ベタ打ちしていますが、外部からテキストを受け取ってそれに従って画像生成する、というようなこともできそうです。
const IMAGE_GENERATION_URL = 'https://api.openai.com/v1/images/generations';
const FOLDER_ID = PropertiesService.getScriptProperties().getProperty('FOLDER_ID');
const OPEN_AI_API_KEY = PropertiesService.getScriptProperties().getProperty('OPEN_AI_API_KEY');
const imageFolder = DriveApp.getFolderById(FOLDER_ID);
// メイン処理
function main() {
const originalText = 'かわいくない猫'; // ここに生成したい画像を説明する文を書く
const translatedText = translateJaToEn(originalText);
console.log(translatedText);
const url = generateImage(translatedText);
const driveUrl = downloadImageFromOpenAiServer(url);
console.log(driveUrl);
}
// 画像生成
function generateImage(text) {
const options = {
"method" : "get",
'contentType': 'application/json',
"headers": { "Authorization":"Bearer " + OPEN_AI_API_KEY },
"payload": JSON.stringify({
prompt: text,
n: 1, //デフォルトと同じであれば省略可
size: "1024x1024", //デフォルトと同じであれば省略可
response_format: "url" //デフォルトと同じであれば省略可
})
}
const response = UrlFetchApp.fetch(IMAGE_GENERATION_URL, options);
const imageUrl = JSON.parse(response.getContentText()).data[0].url;
console.log(imageUrl);
return imageUrl;
}
// Open AIサーバーから画像ダウンロードしてGoogle Driveに保存
function downloadImageFromOpenAiServer(imageUrl) {
const response = UrlFetchApp.fetch(imageUrl);
const blob = response.getBlob();
let newFile = imageFolder.createFile(blob);
newFile.setName(Date.now());
return newFile.getDownloadUrl();
}
// 英語から日本語に変換
function translateEnToJa(text) {
return LanguageApp.translate(text, 'en', 'ja');
}
// 日本語から英語に変換
function translateJaToEn(text) {
return LanguageApp.translate(text, 'ja', 'en');
}
動作確認
上記のGASを実行してみましょう。
画像生成ワード「かわいい猫」:”cute cat”
うーん、まあ、かわいいですね…普通な気もするけど。
では、かわいいの逆の言葉でやってみましょう。
画像生成ワード「ブサイクな猫」:”ugly cat”
確かに…!AIすごい!
猫ばっかりだとアレなので、人物もやってみましょう。
画像生成ワード「筋力トレーニングに励む太り気味のエンジニア」:”An overweight engineer who works hard at strength training”
確かに!!!でもなぜアニメ風?笑 あとエンジニア感があまりないような…?(眼鏡か!)
LINE Bot化する
LINE Messaging APIの準備
LINE Messaging APIを使ってLINEのチャンネル作成を行います。方法については以下の記事内に記載してあります。参考にしていただければ幸いです。
LINE Bot化したGASスクリプト
LINE Botとして動作するように修正を加えたGASスクリプト全体がこちらです。(不要な関数は削除してあります)
const IMAGE_GENERATION_URL = 'https://api.openai.com/v1/images/generations';
const FOLDER_ID = PropertiesService.getScriptProperties().getProperty('FOLDER_ID');
const OPEN_AI_API_KEY = PropertiesService.getScriptProperties().getProperty('OPEN_AI_API_KEY');
const imageFolder = DriveApp.getFolderById(FOLDER_ID);
const LINE_API_ACCESS_TOKEN = PropertiesService.getScriptProperties().getProperty('LINE_API_ACCESS_TOKEN');
const LINE_REPLY_URL = 'https://api.line.me/v2/bot/message/reply';
// LINEからのWebhookで起動
function doPost(e) {
const eventData = JSON.parse(e.postData.contents).events[0];
const replyToken = eventData.replyToken;
const userMessage = eventData.message.text;
const messageType = eventData.message.type;
let replyMessage = "";
console.log(messageType);
console.log(userMessage);
if (messageType == 'text') {
const translatedText = translateJaToEn(userMessage);
console.log(translatedText);
replyMessage = generateImage(translatedText);
} else {
replyMessage = "ごめんなさい~そのタイプのメッセージには対応できないんです!「かわいい猫」と打って送信してみてください!";
}
replyAsImage(replyToken, replyMessage);
}
// 画像生成
function generateImage(text) {
const options = {
"method" : "get",
'contentType': 'application/json',
"headers": { "Authorization":"Bearer " + OPEN_AI_API_KEY },
"payload": JSON.stringify({
prompt: text,
n: 1, //デフォルトと同じであれば省略可
size: "512x512", //デフォルトと同じであれば省略可
response_format: "url" //デフォルトと同じであれば省略可
})
}
const response = UrlFetchApp.fetch(IMAGE_GENERATION_URL, options);
const imageUrl = JSON.parse(response.getContentText()).data[0].url;
console.log(imageUrl);
return imageUrl;
}
// 日本語から英語に変換
function translateJaToEn(text) {
return LanguageApp.translate(text, 'ja', 'en');
}
// LINEに画像メッセージとして返事
function replyAsImage(token, imageUrl) {
const payload = {
'replyToken': token,
'messages': [{
'type': 'image',
'originalContentUrl': imageUrl,
'previewImageUrl': imageUrl
}]
};
const options = {
'payload' : JSON.stringify(payload),
'myamethod' : 'POST',
'headers' : {"Authorization" : "Bearer " + LINE_API_ACCESS_TOKEN},
'contentType' : 'application/json'
};
UrlFetchApp.fetch(LINE_REPLY_URL, options);
}
動作確認
試しに4つほど生成してみました。結構いい感じの画像が作れているのではないでしょうか?
余談ですが…「何でも承認してくれる上司」はLINE Bot化してありますのでこちらでもぜひ遊んでみてください(承認欲求が満たされます笑)
まとめ
今回Open AI APIとGASを使って、日本語から画像を自動生成して保存するスクリプトを書いてみました。
さらに、LINE Bot化してスマホから簡単に試すことができるようにしてみました。
お読みいただきありがとうございました!