🤠

GPTを使ったLINE BOTをAWS Lambda×TypeScript(Node.js)で作る

2023/06/20に公開

はじめに

今更ですが、GPTを使ってLINE BOTを作ってみたいと思ったのでChatGPTに聞きつつ、最新の情報は提供してくれないのでOpenAIのAPIリファレンスを見ながら、作っていきたいと思います。AutoGPTを触った際にOpenAIのAPIに既に登録していたのでChatGPTからの説明では登録の手順を省いてしまっていますが、一応軽く紹介しておきたいと思います。

環境、使用したサービス

・ Mac OS
・ Node.js -v.18.15.00
・ TypeScript -v.5.1.3
・ AWS( Lambda , API Gateway )
・ 下記の様々な随時必要なライブラリなど(dotenvは必要なさそう…)

import * as line from "@line/bot-sdk";
import dotenv from "dotenv";
import { Configuration, OpenAIApi } from "openai";
import { Handler } from 'aws-lambda';

実装に必要なもの一覧(アカウントなど)

・ OpenAI API(お金かかります)
・ LINE Developers(無料、課金プランもある)
・ AWS(従量課金制、個人利用程度なら無料)

大まかな手順(本来は詳細は随時)

Chat GPTが示してくれた詳細な手順

1.LINE Developersでアカウントを作成またはログインします。

2.新しいチャネルを作成します。チャネルのタイプは「Messaging API」を選択します。

3.チャネルの設定を構成します。必要な情報(チャネル名、チャネルアイコンなど)を入力します。

4.チャネルのメッセージング設定を構成します。メッセージングAPIの利用を有効にし、Webhookを利用する設定にします。Webhook URLは後で使用しますので、この時点では設定しなくても構いません。

5.チャネルのアクセストークンを取得します。これは後でLINE BOTとの通信に使用します。

6.開発環境でNode.jsを使用して新しいプロジェクトを作成します。

7必要なパッケージをインストールします。例えば、Expressフレームワークやaxiosなどのパッケージが必要になるかもしれません。

8.メインのアプリケーションファイルを作成し、LINE BOTの処理を記述します。Webhookのエンドポイントを作成し、受信したメッセージを解析して適切な応答を返します。

9.AWSのアカウントを作成またはログインします。

10.AWS Lambdaを作成します。ランタイムとしてNode.jsを選択し、必要な権限を設定します。

11.Lambda関数のコードを作成します。先ほど作成したNode.jsのアプリケーションコードをAWS Lambdaにデプロイします。必要なパッケージを含めてデプロイすることを忘れないでください。

12.Lambda関数のトリガーとしてAPI Gatewayを設定します。API GatewayのエンドポイントURLは後で使用します。

13.LINE Developersのチャネル設定で、Webhook URLをAPI GatewayのエンドポイントURLに設定します。

14.LINE BOTが正しく動作するかテストします。適切な応答が返ってくることを確認します。

OpenAI APIの登録手順

アカウントの作成、ログイン

下記のカードからアクセスしてGet startedを押すと登録画面に遷移するので、アカウントを持っていない人はアカウントの作成。ChatGPTなどで作成している人も多いと思うのでそのような人は、登録画面にあるLog inからログインをします。
https://openai.com/product

発行までの手順

1. 下記のような画面にアクセスできたら、下記の画像では見えないようになっていますが右上のHelpの横にPersonalというところがあるのでクリックします。

この画面になりましたら、色々していきます。

2. 左側のBillingをクリックしてPayment methods(クレジットカードの登録)とUsage limits(APIの利用料金の上限設定)を行います。

soft limit → メールで通知してくれるライン
hard limit → これ以上はリクエストを受け付けなくなるライン(これ以上は課金したく無いよライン)

3. 左側のUserのAPI keysを選択し「+ Create new secret key」のボタンを押し新しい秘密鍵を発行できます。後ほど使用しますのでここでどこかに控えておくか、後ほど必要になった際に発行してください。

LINE Developersですること

LINE Developersでアカウントを作成またはログインします。

「LINE Developers」で検索するか下記のカードからアカウントの作成、またはアカウントをすでに持ってる人はログインをします。

https://developers.line.biz/ja/

LINE Developersでプロバイダーを作成します。

プロバイダー名は個人的に動作確認するだけや、個人的に使うだけであれば「テスト」などの名前でいいと思いますので適当に作成します。他のプロバイダも存在している場合には「GPT BOT」や分かりやすい名前をつけましょう。

Messaging APIを選択して必要な項目を入力していきます

チャンネル作成の際に入力する内容がわからない方向けの各項目の説明

・チャンネルの種類
→今回は「Messaging API」を選択。

・プロバイダー
→最初に作成したものを選択

・会社・事業者の所在国・地域
→大体の方は日本かと思います

・チャネルアイコン
→名前の通りLINEのトークの際に表示されるアイコンなので任意で好きな画像

・チャネル名
→一応名前として表示されるもので7日間変更できませんが、わかりやすい好きなものでいいと思います。(例:AI Bot,GPT Botなど

・チャネル説明
→名前の通り説明する文を書きます(例:ユーザーからのメッセージに対してAIが回答するチャンネルです。など

・大業種、小業種
→個人的に利用するため個人を選択しましたが利用目的に合わせて選択してください。

・メールアドレス
→「チャネルに関する重要なお知らせが、このメールアドレスに送信されます。」とのことです。

・URL入力欄
→一般に公開する上でのプライバシーポリシーやサービス利用規約がある場合にはそのURLを入力しますが、今回は個人的に利用するだけなので空欄で行きます。

とりあえず必要な項目を埋めて作成します。様々な規約の確認が出ますので確認して問題なければ同意して進みます。

チャネルシークレットとチャネルアクセストークンの二つを控えておく

1.チャンネルシークレット
チャネル基本設定の下の方にあるチャンネルシークレットと書かれたところからチャンネルシークレットを確認できます。

2.チャネルアクセストークン
Messaging API設定の下の方にあるチャネルアクセストークン(長期)の発行から発行できます。

LINE Official Account Managerの設定を確認

チャネル基本設定のところにある「チャネルアイコンとチャネル名は、LINE Official Account Managerで変更できます。」のLINE Official Account Managerに遷移して設定を確認します。

応答設定の応答機能のチャットをオフにしてWebhookURLを有効にしてください。

一旦LINE Developersですることは完了です。

ーーーーーーーーーーーーーーーーーーーーーー

AWS Lamda実行するコード

今回はコードに関しては詳しくは説明しません。下記のページアクセスするとNode.jsとPythonのコードのサンプルを確認できますのでそこを見ていただけると、なんとなく理解できると思います。一応アコーディオンの中でNode.jsのコードの軽い説明を入れますが、とりあえず概要をという方は読み飛ばしてください。
https://platform.openai.com/docs/api-reference/chat?lang=node.js

コードの軽い解説

最初に npm initしたり、必要なパッケージなどをインストールする必要があります。

ベースとなるコード

const { Configuration, OpenAIApi } = require("openai");

const configuration = new Configuration({
  apiKey: process.env.OPENAI_API_KEY,
});
const openai = new OpenAIApi(configuration);

// ↑ ここまでは雛形のようなもの
// ↓ ここから軽く説明します。
const completion = await openai.createChatCompletion({
  model: "gpt-3.5-turbo",
  messages: [{"role": "system", "content": "You are a helpful assistant."}, {role: "user", content: "Hello world"}],
});
console.log(completion.data.choices[0].message);

modelが使用する言語モデルを指定する部分になります。少し前に出た関数などを組み込んで使用したい場合はまた末尾に日時を足したりというようなことがありますので、モデルに関しては先程のOpenAPIのページでも確認できます。OpenAPIのrate-limitsのページはこちら

messagesの部分が送信する部分になります。
"role": "system", "content": "You are a helpful assistant."
→システム(GPT)に対してあなたは親切なアシスタントです。と伝えている部分になります。AIに対して人格設定を行いたい場合はcontentの値に対してあなたはラーメン屋の店主です。のように伝えるとそのように振る舞うようになりますが、トークン数が増えてしまいますので扱いには注意してください。
role: "user", content: "Hello world"
→ユーザー、つまりあなたが「Hello world」。とシステムに送っている部分になります。

返信されるデータの形

{
   "id":"chatcmpl-abc123",
   "object":"chat.completion",
   "created":1677858242,
   "model":"gpt-3.5-turbo-0301",
   "usage":{
      "prompt_tokens":13,
      "completion_tokens":7,
      "total_tokens":20
   },
   "choices":[
      {
         "message":{
            "role":"assistant",
            "content":"\n\nThis is a test!"
         },
         "finish_reason":"stop",
         "index":0
      }
   ]
}

上記はAPIリファレンスのもので実際に返されたデータではありませんが、上記の形で返されますので自分の欲しいデータにアクセスして使っていくということになります。

実際のコードではこれをベースにLINEとのやりとりを出来るように書くだけです。

実際に使用したコード

index.ts
import * as line from "@line/bot-sdk";
import dotenv from "dotenv";
import { Configuration, OpenAIApi } from "openai";
import { Handler } from 'aws-lambda';

dotenv.config();

// LINE Messaging API設定
const lineConfig = {
    channelAccessToken: process.env.CHANNEL_ACCESS_TOKEN as string,
    channelSecret: process.env.CHANNEL_SECRET as string,
};
// OpenAI GPT設定
const configuration = new Configuration({
    apiKey: process.env.OPENAI_API_KEY,
});

const openai = new OpenAIApi(configuration);

// LINE Messaging APIのハンドラ関数
export const handler: Handler = async (event) => {
    // イベントの処理
    try {
        const body = JSON.parse(event.body);
        const events = body.events;

        // LINE Messaging APIのクライアントを作成
        const client = new line.Client(lineConfig);

        // イベントの処理ロジック
        const promises = events.map(async (event) => {
            if (event.type === "message" && event.message.type === "text") {
                const message = event.message.text;
                const gptResponse = await openai.createChatCompletion({
                    model: "gpt-3.5-turbo",
                    max_tokens: 1024,

                    //  人格設定の欄
                    // messages: [
                    //     {
                    //         role: "system",
                    //         content: `人格設定を入力します`,
                    //     },
                    // ],

                    messages: [{ role: "system", content: "You are a helpful assistant." }, { role: "user", content: message }],
                });

                const replyMessage: string | undefined = gptResponse.data.choices[0]?.message?.content;
                const sendMessage = replyMessage ?? "";
                // 取得した回答をユーザーに返信
                return client.replyMessage(event.replyToken, {
                    type: "text",
                    text: sendMessage,
                });
            }
        });

        await Promise.all(promises);

        return {
            statusCode: 200,
            body: JSON.stringify({ message: "success" }),
        };
    } catch (error) {
        console.error(error);
        return {
            statusCode: 500,
            body: JSON.stringify({ message: "error" }),
        };
    }
};

AWSですること

AWSのアカウントを作成またはログインします。

AWSのページに飛んで右上のコンソールにログインからアカウントの作成またはログインします。

AWS Lambdaに関数を設定します。

1. 下記のようなページにアクセスできたら左上の検索欄で「Lambda」と検索すると候補に'Lambda'と表示されますのでLambdaへアクセスします。

2. Lambdaのページにアクセスできたら右上の[関数の作成]をクリックします。

3. 必要な情報を入力して関数を作成します

入力する各情報について

・関数名
→「LINE GPT BOT」などわかりやすい名前をつける。なんでも良い。

・ランタイム
→使用した言語を選ぶ。AWS上でコードをいじれるのは Node.js、Python、Ruby だけ

・アーキテクチャ
→とりあえずデフォルトの「x86_64」で良し。

・デフォルトの実行ロールの変更
→とりあえずそのままで良し。

・詳細設定
→必要であれば設定すると良いが、とりあえずそのままで良し。

4. 先程のコードをアップします(CLIを使用しない方法でアップします)

先程のコードをコンパイルして以下の4ファイルをzipファイルにします。

-index.js(index.tsのコンパイルしたもの)
-node_modules
-package-lock.json
-package.json

そのzipファイルをエディターが出ているコードソースの右上のアップロード元からzipファイルを選択してください。

5. ランタイム設定を確認します

ランタイムが自分の書いた言語と一致していることと、ハンドラがindex.handlerであることを確認してください。

AWS API Gatewayの設定を行なっていきます

1. Lambdaの時と同じ要領で左上の検索欄から「API Gateway」を検索しアクセスします。

2. APIを作成します。

APIの作成手順

API タイプ
→今回は「HTTP API」を選択。

統合を作成して設定
→統合は無視して、API名はわかりやすいものを設定
(統合を行えばもっと簡単に終わりそうですが…)

ルートを設定
→特にやることはないので「次へ」を選択

ステージを設定
→初期設定の「$default」を選択。(自動デプロイはオン)

3. 左側のサイドバーから色々設定をしていく
・「Develop」の「Routes」に飛んで'API名'のルートのボックスの右上の[Create]を選択し「ANY ▼」を「POST ▼」にし、作成。

AWS Lambdaに戻ります。

1. 関数の概要というボックスの中の関係図のようなところを見ます
[トリガーを追加]から飛びます

ソースにはAPI Gatewayを選択

既存のAPIを使用を選択し先程作成したAPIを選択します。

デプロイされるステージは「$default」

セキュリティーは今回はとりあえず「開く」で進めていきます。

ひとまずAPI Gatewayで受け取ったらLambdaの関数に渡すための準備が終わりました。

AWS API GatewayのURLをLINE DevelopersのWebhook URLに設定

先程作成したAPI Gatewayの「URLを呼び出す」の下にあるURLをコピーします。

LINE Developersに戻りWebhook URLに設定

[検証]を押してみて成功と出れば、大丈夫です。
初回は時間がかかってしまうのか、タイムアウトとなる場合はもう一度検証を試してみてください

実際にLINEで送信してみてできているかを確認

本当はローカルやngrokなどで正しく動作しているか確認しながら進めていくのがいいと思うのですが、サンプルのコードが最低限の実装ならほとんど完成していた為そのまま進めてしまいました。

それでは、LINE DevelopersのQRコードから友達追加をしてみて、実際に何かメッセージを送ってみましょう!!

返信まで少し時間がかかりますが、数分待っても返信がこないという場合には正しく動作していないので、Lambdaのモニタリングというところを押して「CloudWacthログを表示」に飛ぶとエラーログなどがまとめられていたりするので、そこからエラーを解消してみましょう。

作ったのが1ヶ月上前だという話

私が実際にLINE BOTを作ったのが1ヶ月上前ですので細かな修正した部分などが抜けて正しく動作しないかもしれません。その際は大変申し訳ございません。

LINE DevelopersやAWSを触るのが初めてで、API Gatewayの設定をしている時なども統合というやつを使えばもっと簡単に出来るのだろうか?LINEにメッセージを送っているのにWebhookが発火していない?と手探りで色々やっていましたので拙い部分が多くあるかと思いますがご容赦ください。

最後にまとめ

私のようなバックエンドの知識なしなし人間でも、こうして色々できてしまうAPI,AWSの便利さを実感しました。実際にいつも使っているLINEのアカウントを応答にアレンジを加えたりして作れるというのはとても目に見えてわかりやすく楽しかったです。

今はNode.jsで頑張って色々とやってますがDocumentがPythonのコードしかないという事も多々あるなぁと感じ始めているので、それを抜きにしてもですがPythonを学び始めないとなと思いました。

AIの扱い方に関して規制を作っていこうというEUの流れが世界中に広がって専門的な資格を持った人じゃないとAIとか言語モデルとか使っちゃいけないよという事になったら困るのでたくさん触っておきたいところです。最後までお読みいただきましてありがとうございました。失礼しますm(_ _)m

Discussion