LINE BotでChatGPTと会話する(ソースコード編)
概要
LINE BotでChatGPTと会話する(セットアップ編)のソースコードの解説記事です。
一通り確認はしていますが、ChatGPTの力を借りて解説を書いています。時々ミスがあるかもしれません。
シーケンス図で下記のようなものです。
関数ごとの解説
この章では関数毎の役割を解説しています。全体の理解にお役立てください
doPost(e)
役割
この関数は、エントリーポイント(LINEのWebhookが初めにアクセスする場所)になっています。
LINEのWebhookからのPOSTリクエストを処理し、ユーザーのメッセージに対する応答を生成して返信する役割を担っています。
詳細
e.postData.contentsをJSON形式に解析し、POSTリクエストの内容を取得します。
解析したデータから、LINEのリプライトークン(replyToken)とユーザーのメッセージ(userMessage)を抽出します。
replyTokenが未定義の場合、エラーをスローします。
ユーザーのメッセージに対するChatGPTの応答(replyMessage)を取得します。
replyMessageを使ってLINEに応答を送信します。
処理が正常に完了した場合は、"post ok"というJSONレスポンスを返します。エラーが発生した場合は、エラーメッセージをログに記録し、"error"というJSONレスポンスを返します。
getChatGptResponse(message)
役割
この関数は、ユーザーから受け取ったメッセージをOpenAIのChatGPT APIに送信し、生成された応答を取得する役割を担っています。
詳細
ユーザーのメッセージを含むメッセージオブジェクト(messages)を作成します。
OpenAI APIにリクエストを送信するためのヘッダー(headers)とオプション(options)を設定します。
設定したオプションを用いて、ChatGPT APIにPOSTリクエストを送信します。
APIからの応答をJSON形式で解析し、応答メッセージを返します。
エラーが発生した場合、エラーメッセージをログに記録し、デフォルトのエラーメッセージを返します。
sendLineReply(replyToken, message)
役割
この関数は、指定されたリプライトークンとメッセージを使ってLINEに応答を送信する役割を担っています。
詳細
返信メッセージのペイロード(payload)を作成します。
LINE APIにリクエストを送信するためのヘッダー(headers)とオプション(options)を設定します。
設定したオプションを用いて、LINE APIにPOSTリクエストを送信します。
エラーが発生した場合、エラーメッセージをログに記録します。
それぞれの関数が連携して、LINEのメッセージを処理し、ChatGPTからの応答を生成してユーザーに返信する一連の流れを実現しています。
1行ごとの解説
ソースコード1行毎の細かなコメントです。それぞれのソースコードが何を意味しているのかを理解するためにお役立てください。
// スクリプトのプロパティサービスからLINEチャンネルのアクセストークンを取得
const LINE_CHANNEL_ACCESS_TOKEN = PropertiesService.getScriptProperties().getProperty('LINE_CHANNEL_ACCESS_TOKEN');
// スクリプトのプロパティサービスからOpenAIのアクセストークンを取得
const OPENAI_ACCESS_TOKEN = PropertiesService.getScriptProperties().getProperty('OPENAI_ACCESS_TOKEN');
// LINEのメッセージ返信エンドポイントURLを設定
const LINE_ENDPOINT = 'https://api.line.me/v2/bot/message/reply';
// OpenAIのChatGPT APIエンドポイントURLを設定
const OPENAI_API_URL = 'https://api.openai.com/v1/chat/completions';
// LINEからのPOSTリクエストを処理する関数
function doPost(e) {
try {
// POSTリクエストの内容をJSONとして解析
const json = JSON.parse(e.postData.contents);
// LINEのリプライトークンを取得
const replyToken = json.events[0].replyToken;
// ユーザーからのメッセージを取得
const userMessage = json.events[0].message.text;
// リプライトークンが未定義の場合はエラーをスロー
if (typeof replyToken === 'undefined') {
throw new Error('Reply token is undefined');
}
// ChatGPTの応答を取得
const replyMessage = getChatGptResponse(userMessage);
// LINEに応答を送信
sendLineReply(replyToken, replyMessage);
// 正常に処理されたことを示すJSONレスポンスを作成して返す
return ContentService.createTextOutput(JSON.stringify({'content': 'post ok'})).setMimeType(ContentService.MimeType.JSON);
} catch (error) {
// エラーが発生した場合、エラーメッセージをログに記録し、エラーを示すJSONレスポンスを返す
Logger.log('Error in doPost: ' + error.message);
return ContentService.createTextOutput(JSON.stringify({'content': 'error'})).setMimeType(ContentService.MimeType.JSON);
}
}
// OpenAIのChatGPTにメッセージを送信し、応答を取得する関数
function getChatGptResponse(message) {
// ユーザーのメッセージを含むメッセージオブジェクトを作成
const messages = [{'role': 'user', 'content': message}];
// リクエストヘッダーを設定
const headers = {
'Authorization': 'Bearer ' + OPENAI_ACCESS_TOKEN,
'Content-type': 'application/json'
};
// リクエストオプションを設定
const options = {
'muteHttpExceptions': true,
'headers': headers,
'method': 'POST',
'payload': JSON.stringify({
'model': 'gpt-3.5-turbo', // 使用するモデルを指定
'max_tokens': 2048, // 応答の最大トークン数を設定
'temperature': 0.9, // 応答の多様性を設定
'messages': messages // 送信するメッセージを設定
})
};
try {
// OpenAI APIにリクエストを送信
const response = UrlFetchApp.fetch(OPENAI_API_URL, options);
// APIからの応答をJSONとして解析
const jsonResponse = JSON.parse(response.getContentText());
// 応答メッセージを返す
return jsonResponse.choices[0].message.content;
} catch (error) {
// エラーが発生した場合、エラーメッセージをログに記録し、エラーメッセージを返す
Logger.log('Error in getChatGptResponse: ' + error.message);
return 'Sorry, I couldn\'t process your request.';
}
}
// LINEにメッセージを返信する関数
function sendLineReply(replyToken, message) {
// 返信メッセージのペイロードを設定
const payload = {
'replyToken': replyToken,
'messages': [{
'type': 'text',
'text': message
}]
};
// リクエストヘッダーを設定
const headers = {
'Content-Type': 'application/json; charset=UTF-8',
'Authorization': 'Bearer ' + LINE_CHANNEL_ACCESS_TOKEN
};
// リクエストオプションを設定
const options = {
'method': 'POST',
'headers': headers,
'payload': JSON.stringify(payload)
};
try {
// LINE APIにリクエストを送信
UrlFetchApp.fetch(LINE_ENDPOINT, options);
} catch (error) {
// エラーが発生した場合、エラーメッセージをログに記録
Logger.log('Error in sendLineReply: ' + error.message);
}
}
Discussion