見出し画像

ChatGPT を LINE から使えるようにする方法


はじめに

ある日、妻から「私もChatGPTを使いたい。LINEからChatGPTへ質問したい」とリクエストがありました。そこで、無料で利用できるGoogle Apps Script (GAS) を使って、「ChatGPTをLINEから利用できるLINEチャネル」を作成しました。
この記事では、その作成方法を投稿します。

この記事の対象の方

  • LINE を使って ChatGPT を従量課金制で利用してみたい方

完成後の LINE イメージ

最初に完成後の LINE イメージを載せておきます。こちらの質問に対して回答が表示されています。

チャットボットの構成、料金について

LINE から ChatGPT (正確には OpenAI 社の API) へ質問するチャットボットの構成を以下に記載します。
チャットボットは、Google アカウントがあれば無料で使える Google Apps Script (GAS) で作成しています。LINE と GAS は無料で利用でき、OpenAI の利用は有料となります。OpenAI API は、サブスクリプション料金の ChatGPT とは異なり、利用料に応じた従量課金制です。

  • LINE チャネル

    • ユーザーからのメッセージを受け取り、チャットボットと送受信を行います。

  • Google Apps Script (GAS)

    • チャットボット本体。無料で利用できる GAS で作成します。受信した LINE メッセージをOpenAI API へ送信し、回答を LINE へ返信します

  • OpenAI API

    • ChatGPT の運営会社である OpenAI が提供しているインターネットから ChatGPT と同じ AI モデルを利用できるサービスです。チャットボットから呼び出して利用します

事前準備

以下の設定が完了している状態から開始します。

  • Google アカウントを持っていること

    • Google Apps Script (GAS) を作成し、チャットボット (GAS ではウェブアプリと呼ぶ) をインターネットへ公開します

  • LINE Developers コンソール へアクセスできること

    • LINE チャネルの作成と設定をします

  • OpenAI アカウントを持っていること

    • OpenAI アカウントへの課金

      • OpenAI API の利用に課金が必要です。料金は利用する AI のモデルや質問、回答のトークン(文字)数に応じて課金されます。料金の詳細は、こちら

      • OpenAI アカウント単位で Billing を設定します

    • OpenAI API キーの発行

      • チャットボットから OpenAI API へアクセスするのに利用します

      • OpenAI のプロジェクトごとに API キーを管理します

      • Quickstart - Account setup

OpenAI の設定

OpenAI API を利用するために必要な設定を OpenAI のダッシュボードから行います。

OpenAI へ課金する

ダッシュボードの右上 歯車マークの Settings -> 左のメニューの Billing を選択し、必要な金額を課金します。$ 5 から課金でき、オートチャージ機能もあるみたいです。
OpenAI ダッシュボード - Billing

OpenAI API キーを発行する

OpenAI API へアクセスするための API キーを作成します。ダッシュボードの左のメニューから API Keys を選択し、右上の Create new secret key から作成します。
OpenAI ダッシュボード - API Keys
API キーを作成したら、SECRET KEY をメモします。GAS から OpenAI API を呼び出す際に利用します。

LINE の設定

LINE Developers コンソール を開きます。公式の チャネルを作成する - LINE Developers を参考に LINE プロバイダーと LINE チャネルを作成します。

LINE プロバイダ作成

プロバイダー名は、 チャットボットプロバイダー にします。

LINE チャネルの作成

プロバイダーの画面からチャネルを作成します。 Messaging API を選択します。

必要な情報を入力します。

  • チャネルの種類: Messaging API

  • プロバイダー: チャットボットプロバイダー

  • 会社・事業者の所在国・地: 日本

  • チャネルアイコン(任意): 好きな画像

  • チャネル名: 好きなチャンネル名

  • チャネル説明: OpenAI API の GPT へ質問します

  • 大業種: 個人

  • 小業種: 個人(IT・コンピュータ)

  • メールアドレス: {自分のメールアドレス}

  • LINE公式アカウント利用規約ビの内容に同意します: 同意(チェック)

  • LINE公式アカウントAPI利用規約での内容に同意します: 同意(チェック)

確認画面が表示されるので OK します。

2 つの規約について確認があります。それぞれ 同意 します。

情報利用に関する同意について
LINEヤフーグループへの情報提供に関する個別規約への同意について

LINE チャネルの Messaging API 設定

チャネル作成後に、 Messaging API 設定 を行います。応答メッセージ、あいさつメッセージ、 Webhook の変更は、別の管理画面 (LINE Official Account Manager) で行います。

  • Messaging API設定

    • 応答メッセージ: 無効

    • あいさつメッセージ: 無効

    • Webhook: 有効

    • チャネルアクセストークン(長期): 発行

LINE チャネルの画面 で Messaging API設定 を選択します。

下へスクロールしていき、応答メッセージの 編集 を選択すると、別のタブでLINE Official Account Manager が表示されます。

LINE Official Account Manager で 応答設定の 3 つの項目を変更します。変更内容は自動で保存されます。

  • あいさつメッセージ: 有効 -> 無効

  • Webhook: 無効 -> 有効

  • 応答メッセージ: 有効 -> 無効

LINE Official Account Manager 画面を閉じて、LINE Developers コンソールのチャネル画面へ戻ります。リロードすると、応答メッセージ、あいさつメッセージが 無効 に変わっていることが確認できます。

続いて、チャネルアクセストークンを発行し、メモします。GAS から LINE へ返信する際に利用します。

ここで LINE の設定は一旦終了し、 GAS の設定を行います。
GAS のチャットボット公開後に再度 LINE チャネルへ設定を追加します。

Google Apps Script (GAS) の設定

GAS プロジェクト作成

Apps Script へアクセスします。左上にある 新しいプロジェクト を選択します。

新規プロジェクトが作成されました。無題のプロジェクト を選択し、任意のプロジェクト名を入力します。例: line-openai-chat-bot

GAS スクリプトプロパティ設定

GAS のスクリプトプロパティ(環境変数のようなもの)に、LINE と OpenAI の呼び出しに必要な情報を登録します。スクリプトプロパティの設定値から値を取得するコードにすることで、AI モデルなどを変更したい場合には設定値のみを変更することで対応できるようにします。

  • スクリプトプロパティ設定値

    • OPENAI_MODEL:{利用するモデルの種類}

      • gpt-4o, gpt-3.5-turbo など利用したいモデルを入力します

      • 参考URL: OpenAI Docs - Models

    • OPENAI_API_KEY:{OpenAI API キー}

      • OpenAI ダッシュボードでメモした値を設定します

    • LINE_ACCESS_TOKEN:{自身の LINE チャネルアクセストークン}

      • LINE チャネルでメモした値を設定します

左のメニューバーで プロジェクト設定 を選択し、 スクリプトプロパティを追加から登録、保存します。

GAS スクリプト作成

コードを作成するために、エディタへ戻ります。

コードの既存の内容を削除し、新しいコードを貼り付けます。

コード

// LINEからWebhookを受け取り、OpenAIへメッセージを送信し、OpenAIのレスポンスをLINEへ送信するスクリプト

// POSTリクエストを受診すると実行される関数
function doPost(e) {

  // リクエストの入力値をチェック
  if (!e?.postData?.contents) {
    console.error('Value is required');
    // エラーレスポンスを返す
    return createGASResponse('error', 'Value is required');
  }

  const linePostData = JSON.parse(e.postData.contents).events[0];
  const lineReplyToken = linePostData.replyToken; // 返信用トークン
  const lineMessageText = linePostData.message.text; // メッセージテキスト

  // LINEから受け取ったメッセージをOpenAIへ転送
  responseOpenAI = callOpenAI(lineMessageText);

  // LINEに返信する
  replyLine(lineReplyToken, responseOpenAI);

  // 正常終了時のレスポンスを返す
  return createGASResponse('success', 'Value received');
}

// GASのレスポンスを生成する関数
function createGASResponse(status, message) {
  return {
    "status": status,
    "message": message
  };
}

// OpenAIに問い合わせ、回答を取得する関数
function callOpenAI(message) {
  const payload = {
    'model': PropertiesService.getScriptProperties().getProperty('OPENAI_MODEL'),
    // 'model': 'gpt-3.5-turbo',
    'messages': [
      // { 'role': 'system', 'content': 'Translate all user messages from Japanese to English.' },
      { 'role': 'user', 'content': message }
    ]
  };

  const options = {
    'method': 'post',
    'headers': {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer ' + PropertiesService.getScriptProperties().getProperty('OPENAI_API_KEY')
    },
    'payload': JSON.stringify(payload),
    'muteHttpExceptions': true
  };

  const url = 'https://api.openai.com/v1/chat/completions';
  const response = UrlFetchApp.fetch(url, options);

  if (response.getResponseCode() === 200) {
    const jsonResponse = JSON.parse(response.getContentText());
    const answer = jsonResponse.choices[0].message.content.trim();
    return answer;
  } else {
    console.error('Error response from OpenAI API: ' + response.getContentText());
    return 'OpenAI の呼び出しに失敗しました。再度実行してください。';
  }
}

// LINEへメッセージを返信する関数
function replyLine(replyToken, message) {
  const payload = {
    'replyToken': replyToken,
    'messages': [{ 'type': 'text', 'text': message }]
  };

  const options = {
    'method': 'post',
    'headers': {
      'Content-Type': 'application/json; charset=UTF-8',
      'Authorization': 'Bearer ' + PropertiesService.getScriptProperties().getProperty('LINE_ACCESS_TOKEN'),
    },
    'payload': JSON.stringify(payload),
    'muteHttpExceptions': true
  };

  const url = 'https://api.line.me/v2/bot/message/reply';
  const response = UrlFetchApp.fetch(url, options);
  const statusCode = response.getResponseCode();
  if (statusCode !== 200) {
    console.error('Failed to send message to LINE. Status code: ' + statusCode + ', Response body: ' + response.getContentText());
  }
}

コードの概要説明

LINE から GAS へメッセージが送信されると、 doPost(e) が実行されます。
doPost(e) の イベントパラメータ (e) から LINE メッセージを取り出し、 callOpenAI(lineMessageText) で OpenAI API へ送信、回答の受信を行います。
受け取った OpenAI API の回答と LINE メッセージ返信用トークンを利用して replyLine(lineReplyToken, responseOpenAI) で LINE へ返信します。
スクリプトプロパティに設定した 値を取得するには、 PropertiesService.getScriptProperties().getProperty({'スクリプトプロパティのプロパティ名'}) を利用します。

GAS デプロイ、インターネット公開

作成したコードをインターネットからアクセスできるようにデプロイします。右上の デプロイ -> 新しいデプロイ を選択します。

左上の 歯車マーク から デプロイの種類に ウェブアプリ を選択します。

説明、ウェブアプリの実行ユーザー、アクセスできるユーザーを設定し、 デプロイ を選択します。

  • 説明: 初回デプロイ

  • ウェブアプリ

    • 次のユーザーとして実行: 自分(自分のメールアドレス)

    • アクセスできるユーザー: 全員

GAS アクセスを承認

初回デプロイ時に、ウェブアプリ(チャットボット)からGoogleアカウントへのアクセスの承認が必要です。私の場合は、以下の手順で承認を行いました。

デプロイが完了すると、インターネット公開された ウェブアプリの URL が表示されるので、メモします。

これで GAS の設定は完了です。

LINE の設定 2

LINE Developers コンソールへ戻り、インターネット公開されたウェブアプリ(チャットボット)の URL を設定します。

LINE チャネル Webhook URL 設定

LINE チャネルの画面 で Messaging API設定 を選択します。

Webhook URL の 編集 から GAS ウェブアプリの URL を設定します。

Webhook URL を登録したら、 Webhook の利用 が表示されるため、 有効 に変更します。

Webhook URL のテストをします。検証 を選択します。正しく URL が設定されていれば 成功、 OK が表示されます。

これで LINE チャネルの設定は完了です。

LINE チャネル友だち追加

チャネルの Messaging API 設定 QRコードから友だち追加します。スマホからだと警告メッセージが表示されます。

LINE チャネルの友だち追加画面(Mac 版アプリ)

動作確認

LINE で質問を投げて、回答が返信されることを確認します。

GAS プロジェクト画面の実行数から ウェブアプリ(チャットボット) の実行結果を確認します。

開始時間、期間が LINE と一致していて、ステータスが 完了 となっていることを確認しました。

以上で動作確認完了です👏👏👏

まとめ

無料で利用できる LINE と GAS を活用した LINE チャットボットを作成しました。コード量は少なく、比較的簡単な設定で各サービスを連携させることができました。
ChatGPT は月額 $20 のサブスクリプション契約ですが、OpenAI API は利用料に応じた従量課金制のため、複数人で利用する場合や、LINE、Slack、Discord などブラウザ以外からアクセスしたい場合に便利だと思いました。
この投稿が、GAS を活用した LINE と OpenAI の連携の参考になれば幸いです。
!! 注意 !! 実際に使用する場合は、下記に記載している「チャットボットの不正アクセス制御について」もご確認ください。

チャットボットを削除する場合

利用しなくなった際は、以下を削除しましょう

  • LINE チャネルを削除

  • LINE プロバイダーを削除

  • Googleアカウントの許可サービスから削除

  • GAS プロジェクトを削除

  • OpenAI API キーを削除

チャットボットの機能について

  • 質問は毎回新規の質問となります

    • 前回の会話を引き継ぐ機能はありません

    • 常にGoolge スプレットシートに会話を保存して、チャットで「クリア」を入れたら会話の履歴を消すなどで実現できるかもしれませんが、未検証です。

  • 指示プロンプトについて

    • 未設定の状態です

    • callOpenAI 関数のコメントアウトを解除し、 content へ入力することで設定可能ですが、こちらも未検証です。
      // { 'role': 'system', 'content': 'Translate all user messages from Japanese to English.' },

チャットボットの不正アクセス制御について

GAS をインターネットに公開しているため、不正なアクセスが行われる可能性があります。LINE メッセージが該当の LINE チャネルから送られたか検証する方法として、公式ページでは 署名を検証する 方法が紹介されていますが、GAS では HTTP ヘッダーの値を取得できないため実施できません。
GAS の公開 URL が外部に漏れ、LINE メッセージフォーマットで不正リクエストが送られてくる可能性は低いですが、最悪の場合、OpenAI に課金済みのクレジットがなくなるまでアクセスされ続ける可能性もあります。
しかし、OpenAIに対する課金を $ 5 ずつ行うなどして、大きなリスクとは考えずに、割り切って対策を行わないという選択もあるかと思います。


チャットボットへアクセス制御の追加

上記の不正アクセスの制御の代替案として、LINE ユーザー ID を利用したチェック処理を追加する方法を以下に記載します。ここで利用する LINE ユーザー ID は、LINE プロバイダーごとに割り振られるため、友だち追加後にしか確認できません。

GAS のスクリプトプロパティへ 利用を許可する LINE ユーザー IDのプロパティを登録します。設定値には、仮の LINE ユーザー IDを登録します。

  • スクリプトプロパティ設定値

    • LINE_USER_IDS: testuser001(仮)

GAS のエディタからコードを修正します。
以下のユーザーIDチェック処理を17行目へ追加します。

  const lineSrcUserId = linePostData.source.userId; // LINE送信ユーザーID

  // ユーザーIDがスクリプトプロパティから取得したIDと一致するかチェック
  if (!checkUserId(lineSrcUserId)) {
    console.error('Unauthorized user: ' + lineSrcUserId);
    // LINEに返信する
    replyLine(lineReplyToken, '許可ユーザーに含まれていません。 USERID: ' + lineSrcUserId);
    // エラーレスポンスを返す
    return createGASResponse('error', 'Unauthorized user');
  }

以下のユーザー ID チェック関数を一番下の行へ追加します。

// ユーザーIDがスクリプトプロパティから取得したユーザーIDsに含まれているかチェックする関数
function checkUserId(userId) {
  const userIDs = PropertiesService.getScriptProperties().getProperty('LINE_USER_IDS').split(',');
  return userIDs.includes(userId);
}

コードを修正したら、ウェブアプリ(チャットボット)を再デプロイします。再デプロイしたら、ウェブアプリの URL も新しい URL へ変わります。

新しい ウェブアプリの URL をメモします。

LINE Developers コンソールの LINE チャネル画面の Messaging API 設定から Webhook URL へ新しいウェブアプリの URL を設定します。

再度 LINE メッセージを送信します。追加したユーザーIDチェックが有効になり、ユーザーが許可されていないメッセージとUSERIDが返信されるので USERID をメモします。

GAS の スクリプトプロパティ LINE_USER_IDS へメモした USERID を登録します。複数ユーザー登録する場合は、カンマ(,)区切りで登録します。
例)U677a3d1fb8741d5a72e4245d0acfd04a,U677a3d1fb8741d5a72e4245d0acfd04b

ユーザーIDを登録、保存したら、再度 LINE メッセージを送信します。返信が表示されていることが確認できます。

これで スクリプトプロパティで許可登録した LINE ユーザーのみが OpenAI API に対して質問を投げれるようになりました。

以上で全て終了です。お疲れ様でした🍻🍻🍻

参考URL

この記事が気に入ったらサポートをしてみませんか?