LINE Bot with GAS + Gemini AI
LINE Developer アカウントの作成
dev-bot
として作成した
Messaging API の利用
2024年9月4日をもって、LINE DevelopersコンソールからMessaging APIチャネルを直接作成することはできなくなりました。
今後は、あらかじめLINE公式アカウントを作成した上で、LINE Official Account Manager (opens new window)でMessaging APIの利用を有効にすることでMessaging APIチャネルを作成できます。
仕様変更後のMessaging APIチャネルの作成方法
仕様変更後は、次の手順でMessaging APIチャネルを作成してください。
- LINE公式アカウントを作成する。
- 作成したLINE公式アカウントでMessaging APIの利用を有効にする。
Messaging API を有効にする
- メニュー > チャット > Messaging API
- Messaging API を利用する
- プロバイダー名を入力して作成
📝dev-test
で作成した
LINE チャンネルのアクセストークンを取得
-
https://developers.line.biz/console/
にログイン
🚨 公式LINEアカウントのページとは異なるので注意 ⚠️ - プロバイダーメニュー内に先ほど作成したプロバイダー名 (
dev-test
) があるので選択 - チャンネル名タブ: 公式アカウント名
dev-bot
に MessagingAPI のマークが付いてるのでクリック -
Messaging API設定
タブをクリック - 下部に
チャネルアクセストークン
があるのでトークンを保存しておく -
応答メッセージ
は bot から返すので無効
にしておく
GAS の準備 と Webhook の設定
- SpredSheet を作成
- 拡張機能 > Apps Script を選択
Webhook URL の作成
Apps Script をデプロイすることで LINE BOT と接続するための Webhook URL を作成する
- デプロイ > 新しいデプロイ を選択
- アクセスできるユーザーを
全員
にしてデプロイする
-
ウェブアプリURL
が表示されるのでコピーする
LINE BOT に Webhook URL を設定
- LINE developers console から作成した BOT のチャンネルに移動
-
Messaging API設定
タブを開く -
Webhook設定
の設定に Apps Script をデプロイした際に発行されたウェブアプリURL
を入力して保存し、Webhookの利用をON
にする
GAS オウム返しをする Script の作成
message/reply
API を使い、LINE bot 宛に投稿があれば、送られたメッセージを取得してそのまま返すだけのスクリプトを作成した
// ref. https://developers.line.biz/ja/reference/messaging-api/#send-reply-message
const REPLY_API = 'https://api.line.me/v2/bot/message/reply';
const ACCESS_TOKEN = 'YOUR_LINE_CHANNEL_ACCESS_TOKEN';
// LINE BOT にメッセージが合った際に実行される
function doPost(e) {
const json = JSON.parse(e.postData.contents);
// ref: https://developers.line.biz/ja/reference/messaging-api/#message-event
const replyToken = json.events[0].replyToken;
const messageText = json.events[0].message.text;
if ( !replyToken || typeof replyToken === 'undefined' ) {
return;
}
const option = {
'headers': {
'Content-Type': 'application/json; charset=UTF-8',
'Authorization': 'Bearer ' + ACCESS_TOKEN,
},
'method': 'post',
'payload': JSON.stringify({
'replyToken': replyToken,
'messages': [{
'type': 'text',
'text': messageText,
}],
}),
};
// POST message
UrlFetchApp.fetch(REPLY_API, option);
return;
}
Script を変更したら デプロイ > デプロイの管理
から新しいバージョンを作成してデプロイし直す
LINE BOT とのトークに投稿してオウム返しに返信が来ていたら OK
絵文字は (emoji)
に変換されるっぽい
Gemini AI に回答させる
Gemini 無料でも使えるようだったので、LINE からの投稿を Gemini に回答させるようにした
1. Gemini API Key を発行する
Google AI Studio から 2024年9月22日現在 Gemini 1.5 Flash の無料で使える API キーが発行できる
Google AI Studio にログインして Get API key
をクリックすれば API キーが発行される
2. GAS から Gemini AI を呼び出す
curl \
-H 'Content-Type: application/json' \
-d '{"contents":[{"parts":[{"text":"Explain how AI works"}]}]}' \
-X POST 'https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash-latest:generateContent?key=YOUR_API_KEY'
Google AI Studio に curl で呼び出すサンプルが載っているので、これを GAS から fetch で呼び出せばよい
GAS に Gemini AI を呼び出す関数を追加する
const GEMINI_API_KEY = `YOUT_GEMINI_API_KEY`;
const GEMINI_API = `https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash-latest:generateContent?key=${GEMINI_API_KEY}`;
const askGemini = async ({ prompt }) => {
if (!prompt || prompt.length < 3) {
return "回答できませんでした";
}
const options = {
headers: {
"Content-Type": "application/json",
},
method: "post",
payload: JSON.stringify({
contents: [
{
parts: [
{
text: `次の質問に240文字以内で回答してください。
質問: ${prompt}`,
},
],
},
],
}),
};
const res = UrlFetchApp.fetch(GEMINI_API, options);
const json = JSON.parse(res.getContentText());
// console.log(json.candidates[0].content.parts);
const text = json.candidates[0].content.parts[0].text;
return text ?? "回答できませんでした";
};
LINE の投稿を質問として、askGemini
関数を呼び出す
// LINE BOT にメッセージが合った際に実行される
- function doPost(e) {
+ async function doPost(e) {
const json = JSON.parse(e.postData.contents);
// ref: https://developers.line.biz/ja/reference/messaging-api/#message-event
const replyToken = json.events[0].replyToken;
const messageText = json.events[0].message.text;
if ( !replyToken || typeof replyToken === 'undefined' ) {
return;
}
+ // Ask Gemini
+ const answerText = await askGemini({
+ prompt: messageText,
+ });
const option = {
'headers': {
'Content-Type': 'application/json; charset=UTF-8',
'Authorization': 'Bearer ' + ACCESS_TOKEN,
},
'method': 'post',
'payload': JSON.stringify({
'replyToken': replyToken,
'messages': [{
'type': 'text',
- 'text': messageText,
+ 'text': answerText,
}],
}),
};
// POST message
UrlFetchApp.fetch(REPLY_API, option);
return;
}
GAS を更新したら再度デプロイを行う
LINE BOT に質問をして AI から回答がされれば OK
[参考]
AI が回答するまで回答中の loading を表示させる
AI の回答に時間がかかる場合があるので、返答があるまで考え中を示す loader を表示させたい
reply token の有効期間は Webhook が受信してから 1分以内なので、最大 60秒 loader を表示させれば良さそう
LINE Messaging API の loading API を利用すればOK
loading API は chatId
に 会話しているユーザーのID, loadingSeconds
にローディングアニメーションを表示する秒数を指定して POST すればよい。
Loader を表示する関数を作成し Gemini API を呼び出す前でその関数を呼び出すようにする
Loader を表示する関数
// ref. https://developers.line.biz/ja/reference/messaging-api/#display-a-loading-indicator
const LINE_CHAT_LOADING_API = "https://api.line.me/v2/bot/chat/loading/start";
const showLoading = ({ userID }) => {
const option = {
headers: {
"Content-Type": "application/json; charset=UTF-8",
Authorization: "Bearer " + ACCESS_TOKEN,
},
method: "post",
payload: JSON.stringify({
chatId: userID,
loadingSeconds: 60,
}),
};
UrlFetchApp.fetch(LINE_CHAT_LOADING_API, option);
};
userID を取得して showLoading
関数を呼び出す
// LINE BOT にメッセージが合った際に実行される
async function doPost(e) {
const json = JSON.parse(e.postData.contents);
// ref: https://developers.line.biz/ja/reference/messaging-api/#message-event
const replyToken = json.events[0].replyToken;
const messageText = json.events[0].message.text;
+ const userID = json.events[0]?.source.userId;
if ( !replyToken || typeof replyToken === 'undefined' ) {
return;
}
+ // Show Loading
+ if (userID) {
+ showLoading({ userID });
+ }
// Ask Gemini
const answerText = await askGemini({
prompt: messageText,
});
const option = {
'headers': {
'Content-Type': 'application/json; charset=UTF-8',
'Authorization': 'Bearer ' + ACCESS_TOKEN,
},
'method': 'post',
'payload': JSON.stringify({
'replyToken': replyToken,
'messages': [{
'type': 'text',
'text': answerText,
}],
}),
};
// POST message
UrlFetchApp.fetch(REPLY_API, option);
return;
}
GAS を更新して再度デプロイを行う
LINE BOT に質問をして、回答が返ってくるまでの間に 「...」 が表示されるようになっていればOK
[参考]