今回は、ChatGPT APIをLINEのボットで使う方法について解説します。今回もコピペで動くサンプルコードを載せていますので、ぜひ試してみてください。

全体像
今回作るBotの全体像は以下になります。

LINEからメッセージを送信したものを、LINE APIと連携したgasが受け取り、さらにそれをChatGPTのAPIに投げ、応答をLINEに返すという流れです。なので、必要となるのは
- LINEのMessaging API
- Google Apps Script
- ChatGPT API
の3つです。いずれも無料で利用できます(ChatGPTは無料分を超えたら有料。詳しくはこちら)。
LINE developersの登録
LINE上でChatGPTを使えるようにするには、LINE developersという開発者用のページにログインする必要があります。LINEのアカウントをお持ちの方は無料で利用できます。
設定方法については以下の記事の「Line Developerへの登録」という章にて解説していますので、そちらをご参照ください。
ChatGPTの登録
GASからChatGPTにアクセスするために、ChatGPT APIのAPIキーを取得します。取得方法については以下の記事の「ChatGPT APIの使い方」という章にて解説していますので、そちらをご参照ください。
Google Apps Scriptの設定
次に、Google Apps Script(GAS)の設定をします。
GASで実装すべきことの確認
GASはLINEとChatGPTのAPIの橋渡し的な存在となります。

したがって、必要な処理は以下の4点です。
- LINE ⇔ GAS間
- LINEからのメッセージの受け取り
- LINEへメッセージの返却
- GAS ⇔ ChatGPT API間
- メッセージを質問文としてChatGPTに投げる
- ChatGPTからの応答文を受け取る
Google Apps Script(GAS)の設定
GASの使い方や実行方法、LINEにスクリプトを設定する方法については以下の記事の「Google Apps Script(GAS)の設定」という章で解説しています。詳細は以下をご確認ください。
GASのサンプルコードはこちら
GASのスクリプトは以下になります。
2023/03/12追記:ソースコードをコピペするとGASでエラーになるというご指摘をいただきましたので、修正しました。ご指摘ありがとうございました。
const GPT_TOKEN = 'XXXXXXXXXXXXXXXXXX'; //ChatGPTのAPIキーを入れてください
const LINE_TOKEN = 'XXXXXXXXXXXXXXXXXX'; // LINEのAPIキーを入れてください
const LINE_ENDPOINT = "https://api.line.me/v2/bot/message/reply";
const GPT_ENDPOINT = 'https://api.openai.com/v1/chat/completions';
const MODEL_NAME = 'gpt-3.5-turbo';
const MODEL_TEMP = 0.5;
const MAX_TOKENS = 256;
// LINEからPOSTリクエストが渡されてきたときに実行される処理
function doPost(e) {
// LINEからPOSTされるJSON形式のデータをGASで扱える形式(JSオブジェクト)に変換
const json = JSON.parse(e.postData.contents);
// LINE側へ応答するためのトークンを作成(LINEからのリクエストに入っているので、それを取得する)
const reply_token = json.events[0].replyToken;
if (typeof reply_token === 'undefined') {
return;
}
// LINEから送られてきたメッセージを取得
const user_message = json.events[0].message.text;
// 改行で区切って配列にする
const user_msgarray = user_message.split(/\r\n|\n/);
// LINEのメッセージをChatGPTに投げるメッセージにセットする
const messages = [{ "role": "user", "content": user_msgarray[0] }]
const headers = {
'Authorization': 'Bearer ' + GPT_TOKEN,
'Content-type': 'application/json',
};
// リクエストオプション
const options = {
'method': 'POST',
'headers': headers,
'payload': JSON.stringify({
'model': MODEL_NAME, // 使用するGPTモデル
'max_tokens': MAX_TOKENS, // レスポンストークンの最大値(最大4,096)
'temperature': MODEL_TEMP, // 応答の多様性(0-1)※数値が大きいほどランダムな応答になる
'messages': messages
})
};
// HTTPリクエストでChatGPTのAPIを呼び出す
const res = JSON.parse(UrlFetchApp.fetch(GPT_ENDPOINT, options).getContentText());
// ChatGPTから返却されたメッセージを応答メッセージとしてLINEに返す
lineReply(json, res.choices[0].message.content.trimStart());
}
// LINEへの応答
function lineReply(json, replyText) {
// 応答用のメッセージを作成
const message = {
"replyToken": json.events[0].replyToken,
"messages": [{
"type": "text", // メッセージのタイプ(画像、テキストなど)
"text": replyText
}] // メッセージの内容
};
// LINE側へデータを返す際に必要となる情報
options = {
"method": "post",
"headers": {
"Content-Type": "application/json; charset=UTF-8", // JSON形式を指定、LINEの文字コードはUTF-8
"Authorization": "Bearer " + LINE_TOKEN // 認証タイプはBearer(トークン利用)、アクセストークン
},
"payload": JSON.stringify(message) // 応答文のメッセージをJSON形式に変換する
};
// LINEへ応答メッセージを返す
UrlFetchApp.fetch(LINE_ENDPOINT, options);
}
サンプルコード概要
function doPost(e)というのは、HTTPリクエストを受け取る際の書き方になります。「e」のなかにLINEから渡された情報が入っており、その情報をGASで扱える形式に変換して変数「json」に格納します。

LINEから渡された情報のなかからテキストメッセージを取り出します。取り出したメッセージをChatGPTへの質問文としてセットします。

ChatGPT APIへのリクエストの設定で、「max_tokens」「temperature」とありますが、こちらはご自身の好みや目的に合わせて設定してください。この2つは任意設定なのでなくても動作しますが、LINEの最大文字数は10,000文字までですので何も設定しないと大量のトークンを消費する可能性があります。

ChatGPTにAPIリクエストをし、GAS(JavaScript)で使えるJSONの形式に変換して変数resに格納します。最後にlineReply関数を呼び出してLINEに応答メッセージを返せば完了です。

LINEへの応答は以下のように行います。

参考:LINE Developers/ Messaging APIリファレンス
応用:Botのキャラ設定をする
前回記事でも書いた通り、ChatGPT APIではBOTの振る舞いを設定することができます。今回は、マダム風アシスタントとしてマウントをとってもらいます。

最初のやりとりは何も設定していない状態、二番目のやりとりはマダム風アシスタントとしてふるまわせた結果です。

他にも、「関西弁で」「執事風に」「へっぽこアシスタント」「有名レストランのシェフとして」など、設定を追加することで振る舞いに大きな差が生まれます。
気になった点
ChatGPT APIをLINEから使ってみて、気になった点を以下に記載します。
ChatGPT APIは過去の会話履歴を保持していない
ChatGPT APIは前回記事でも触れたとおり、過去の会話履歴を保持していません。履歴を持たせるにはAPIリクエストに過去の会話を持たせる必要がありますが、GASで会話履歴を保持させるには「スクリプトプロパティ」を使用するようです。詳しくは以下の記事が参考になりましたので載せておきます。
翻訳の精度がイマイチ
もうひとつ気になったのが、翻訳の精度です。ChatGPTは英語学習に使えると聞いたので、試しに英文を翻訳させてみたのですが、基本的に直訳なのでかなり機械的な感じがしました。特に、格言などの意訳が必要な内容にはそれが顕著に出ています。

例えば、「It always seems impossible until it’s done.」の翻訳結果が「それは常に不可能に思える。それが達成されるまで。」となっています。間違ってはいないけど、めちゃくちゃストレートな翻訳となっています。同じ文章をDeepLに翻訳させた結果は以下です。

ChatGPT APIは、文法について質問したり、例文を作ってもらう文には問題ありませんでしたが、翻訳ツールとして使うには向いてなさそうです。
LINE×DeepL APIで翻訳Botを作る方法については以下をご参照ください。
まとめ
今回は、ChatGPT APIを用いてLINE上でChatGPTを使う方法について解説しました。LINE上で使えるようになると、わざわざPCを開く手間もなく、新たにアプリを入れる必要もないのでお手軽ですね。
なお、スマホからはBingアプリ・EdgeアプリからChatGPTのチャット機能を利用することができます。音声入力にも対応しており、現時点では無料なので利用制限など気にせず使いたい方はそちらもご検討ください。
オシャレなオフィスで、自宅・カフェより快適にお仕事を。【BIZcomfort】
コメント
とても分かりやすい内容でした。
サンプルコードをコピペした際に’などの記号が全角?になっておりGASからエラーが吐かれます。対処法をおしえていただけますでしょうか?
コメントありがとうございます。
今試してみたところ、私の環境でもエラーになっていました。
ソースコードが長かったので折り畳み表示にした際に、意図せず文字形式が変換されてしまっているところがあったようです。
ご指摘いただけて大変助かりました。ブログのほうにも追記して更新させていただきました。
もし、設定していて分からない点や動かないなどありましたら、また気軽にコメントいただければと思います。
引き続き質問失礼します。
GAS側でのエラー表示は消えたのですが、LINEBOTが何を送信しても無反応で、既読だけつく状態です。
APIキーの部分にのみ変更を加え、LINEBOT側の設定も応答メッセージ等もオフにしている状態です。
何かわかることがあればぜひ教えていただきたいです。
GASで既読はつくのに無反応ということは、以下が考えられます。
・「Webhook設定」がオフになっている
LINE Developers>Messaging API設定の「Webhook設定」がオフになっている
LINE Official Account Manager>応答設定の「Webhook」がオフになっている
両方オンになっていないと、応答が得られません。
・ChatGPTのAPIキーが設定されていない
OpenAIの公式サイトから、ChatGPTのAPIキーを発行して、それをGASのスクリプトに設定する必要があります。
上記を試してみて、また分からないことがありましたらご質問いただければと思います。
わざわざ返答をくださりありがとうございます。
webhook設定は両方オンにしておりました。
また、APIキーの設定も済んでおります。
また、API keysのLAST USEDの表示がneverから日付に変わっているためchatGPT側に送信する段階までは到達しているかと思います。
まだわかることがあれば教えていただければ幸いです。
よろしくお願いいたします。
APIの利用履歴が表示されているということは、LINEのメッセージをもとに
ChatGPTのAPIを呼び出すところまでは上手くいってそうですね。
そうなると、
・ChatGPTからGASに値がうまくわたっていないか、
・ChatGPTから渡された値をLINEに返すときに失敗しているか
のいずれかが原因かな?と思います。
lineReply(json, res.choices[0].message.content.trimStart());
を、
lineReply(json, “test”);
に変えて実行してみてください。
これでLINEに応答がなかったらLINEへの応答部分に原因がありそうです。
LINE_TOKENの値に、「チャネルアクセストークン(長期)」の値を
正しく設定できているか確認してみてください。
LINEに応答があった場合は、
lineReply(json, res.choices[0].message.content.trimStart());
を、
lineReply(json, res.choices[0].message.content);
にして試してみてください。
またいつでもご質問いただければと思います。
LINEのアクセストークンの値の設定確認しました。
また、lineReply(json, res.choices[0].message.content.trimStart());
を、
lineReply(json, “test”);
に変更した際も応答がありませんでした。
別サイトに記載のおうむ返しをするGASのソースコードでデプロイした際には正常に動作したので、LINE DevelopersやLINE Official Account Managerの設定などには問題はないと思います。
度重なる質問でご迷惑おかけしますが、よろしくお願いします。
GASからLINEに応答する際に失敗しているようですが、
同じソースコード、同じ設定をしていて、何が失敗の原因になっているかこちらでは分かりかねますので、
参考にされた別サイトのソースコードをベースに、ChatGPT APIの通信用に書き換えて動かしてみていただければと思います。
オウム返しをする場合、LINEに値を返却するときに以下のようになっているかと思いますので、
‘messages’: [{
‘type’: ‘text’,
‘text’: LINEから受け取った値,
}]
‘text’の値に、ChatGPTのAPIから返却された値を入れてみてください。
ソースコードの編集が難しそうであれば、こちらで中身を確認させていただきますのでまた連絡いただければと思います!
ソースコードの編集を試してみましたが難しそうでしたのでご連絡させていただきました。
以下成功したおうむ返しのソースコードになります。
/** メッセージが送付された際に、実行される関数 */
function doPost(e) {
// アクセストークン
const ACCESS_TOKEN = ‘トークン入れる’
const replyToken = JSON.parse(e.postData.contents).events[0].replyToken;
const userMessage = JSON.parse(e.postData.contents).events[0].message.text;
const url = ‘https://api.line.me/v2/bot/message/reply’;
const headers = {
‘Content-Type’: ‘application/json; charset=UTF-8’,
‘Authorization’: ‘Bearer ‘ + ACCESS_TOKEN
};
//メッセージ送信内容
const payload = JSON.stringify({
‘replyToken’: replyToken,
‘messages’: [{
‘type’: ‘text’,
‘text’: userMessage
}]
})
const options = {
‘headers’: headers,
‘method’: ‘post’,
‘payload’: payload
};
// レスポンス
const response = UrlFetchApp.fetch(url, options);
const data = JSON.parse(response.getContentText());
console.log(data);
}
コメントありがとうございます。
上記のソースコードをベースに、ChatGPTとの通信処理を追加しました。
/* ▼追加 */
const GPT_TOKEN = ‘GPTのアクセストークン’;
const LINE_ENDPOINT = “https://api.line.me/v2/bot/message/reply”;
const GPT_ENDPOINT = ‘https://api.openai.com/v1/chat/completions’;
const MODEL_NAME = ‘gpt-3.5-turbo’;
const MODEL_TEMP = 0.5;
const MAX_TOKENS = 256;
/* ▲追加 */
/** メッセージが送付された際に、実行される関数 */
function doPost(e) {
// アクセストークン
const ACCESS_TOKEN = ‘トークン入れる’;
const replyToken = JSON.parse(e.postData.contents).events[0].replyToken;
const userMessage = JSON.parse(e.postData.contents).events[0].message.text;
/* ▼追加 */
// LINEのメッセージをChatGPTに投げるメッセージにセットする
const messages = [{ “role”: “user”, “content”: userMessage }]
const headers_gpt = {
‘Authorization’: ‘Bearer ‘ + GPT_TOKEN,
‘Content-type’: ‘application/json’,
};
// リクエストオプション
const options_gpt = {
‘method’: ‘POST’,
‘headers’: headers_gpt,
‘payload’: JSON.stringify({
‘model’: MODEL_NAME, // 使用するGPTモデル
‘max_tokens’: MAX_TOKENS, // レスポンストークンの最大値(最大4,096)
‘temperature’: MODEL_TEMP, // 応答の多様性(0-1)※数値が大きいほどランダムな応答になる
‘messages’: messages
})
};
// HTTPリクエストでChatGPTのAPIを呼び出す
const res = JSON.parse(UrlFetchApp.fetch(GPT_ENDPOINT, options_gpt).getContentText());
/* ▲追加 */
const url = “https://api.line.me/v2/bot/message/reply”;
const headers = {
‘Authorization’: ‘Bearer ‘ + ACCESS_TOKEN,
‘Content-type’: ‘application/json’
};
//メッセージ送信内容
const payload = JSON.stringify({
“replyToken”: replyToken,
“messages”: [{
“type”: “text”,
“text”: res.choices[0].message.content // “messages”から変更
}]
})
const options = {
“headers”: headers,
“method”: “post”,
“payload”: payload
};
// レスポンス
const response = UrlFetchApp.fetch(url, options);
const data = JSON.parse(response.getContentText());
console.log(data);
}
追加・変更した部分についてはコメントしています。
ご確認よろしくお願いします。