やったこと
最近はやってるOpenAIにLINE経由で質問して回答を受け取れるようにしました!
接続イメージは以下の通り。
LINE Messaging APIとOpenAIの準備
LINE Messaging API
公式のガイドに沿って、LINE Developer Consle上でMessaging APIを作成します。
「Messasing API設定」タブからチャネルアクセストークンを確認しておきます。
Webhookの設定も必要なのですが、それはLambda構築後に実施します。
OpenAI
OpenAIのアカウントを作成します。
OpenAI APIのトップでサインアップを実施。
ログイン後、右上の「Personal」から「View API Keys」でAPI Keysを確認します。
以下の画面でAPI Keyを発行して確認します。
一度作ったものを画面上で再確認するのは不可能なので、別途しっかり管理する必要があります。
Lambda
関数の作成
AWS Lambda関数を作成します。
詳細設定から、最近(去年くらい?)用意された関数URLを有効化します。
以前はAPI Gatewayの設定とかが必要だったので、今回みたいにサクッと外部のAPIを連携させたいときは便利だなと思いました。
認証タイプは今回はとりあえずお試しなのでNONE、CORS設定にもチェックを入れます。
関数の作成を実施。
右下に関数URLが表示されているので、これをコピー。
LINE Developer ConsoleでWebhook URLを設定
LINE Developer Consoleで、作成したMessaging APIのWebhook URLに設定します。
ここまで書いて思い出しましたがMessaging APIは自動で応答メッセージがあるのでこれは無効化しておきます。
Layerの追加
今回、openaiと@line/bot-sdkをnode_modulesとして使うので、Lambdaレイヤーに追加します。
ローカルコンピューター上で「nodejs」ディレクトリを作成し、以下の通りnode_modulesをインストール。
PS C:\Users\flets\OneDrive\node\nodejs> npm i @line/bot-sdk openai
PS C:\Users\flets\OneDrive\node\nodejs> npm ls
node@ C:\Users\flets\OneDrive\node
+-- @line/bot-sdk@7.5.2
`-- openai@3.1.0
PS C:\Users\flets\OneDrive\node\nodejs>
Lambdaコンソールの左のナビゲーションペインで「レイヤー」を選択し、右上の「レイヤーの作成」をクリック。
以下の通りレイヤー名を適当に入力して、nodejs.zipをアップロード元に設定して「作成」をクリック。
コードの記述
以下の通り記述します。
モジュール呼び出し、トークン・Key設定
まず、handler
関数の手前でLINEとOpenAIのモジュールをImportして、LINEのチャネルアクセストークンとOpenAIのAPI Keyも設定します。(直書きでごめんなさい)
import line from "@line/bot-sdk";
import { Configuration, OpenAIApi } from "openai";
//事前に確認したものを記述
const LINE_TOKEN = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const GPT_KEY = "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
LINE Messaging APIとのやりとり
handler
関数の中身を書きます。
まずは、LINE Messaging APIとやりとりする枠を書きます。
export const handler = async(event) => {
//LINEのMessaging APIに接続
const client = new line.Client({
channelAccessToken: LINE_TOKEN,
});
//LINEからWebhookでアクセスしてきたときのBodyをJSONに格納
const reqBody = JSON.parse(event.body);
console.log(reqBody)
let message = {};
//このあと、ここでOpenAIのAPIを呼び出してmessageの中身を埋めます
//LINE Messaging APIでメッセージをPushする宛先
const toToken = reqBody.events[0].source.userId;
//メッセージをPush
await client.pushMessage(toToken, message).catch((err) => {
// error handling
console.error(err);
});
//Webhookに対するResponse(200応答が必要らしい)
const response = {
statusCode: 200,
body: JSON.stringify(message),
};
return response;
};
OpenAIのAPI呼び出し、messageへの格納
OpenAIのAPIにアクセスして、レスポンスデータをMessageに格納します。
LINEからのWebhookがテキストメッセージじゃないとダメなので、if分で分岐も一応入れておきます。
//WebhookがテキストだったらOpenAIになげる
if (reqBody.events[0].message.type == "text") {
//OpenAIアクセス設定
const configuration = new Configuration({
apiKey: GPT_KEY,
});
//オブジェクト作成
const openai = new OpenAIApi(configuration);
//APIアクセス、レスポンス格納
//max_tokensを変えればレスポンスの最大文字数が変化
//ただし、max_tokensの値が純粋な最大文字数ではないので注意
//ただしLINE、OpenAIそれぞれで上限値ありなので要確認
const response = await openai.createCompletion({
model: "text-davinci-003",
prompt: reqBody.events[0].message.text,
max_tokens: 1000,
temperature: 0,
});
message = {
type: "text",
text: response.data.choices[0].text.trim()
};
} else {
//LINEからのWebhookがテキストメッセージじゃなかった場合
message = {
type: "text",
text: "テキストを入力してください。"
};
}
全文
全文は以下の通り。
import line from "@line/bot-sdk";
import { Configuration, OpenAIApi } from "openai";
const LINE_TOKEN = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const GPT_KEY = "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
export const handler = async(event) => {
const client = new line.Client({
channelAccessToken: LINE_TOKEN,
});
const reqBody = JSON.parse(event.body);
console.log(reqBody)
let message = {};
if (reqBody.events[0].message.type == "text") {
const configuration = new Configuration({
apiKey: GPT_KEY,
});
const openai = new OpenAIApi(configuration);
const response = await openai.createCompletion({
model: "text-davinci-003",
prompt: reqBody.events[0].message.text,
max_tokens: 1000,
temperature: 0,
});
message = {
type: "text",
text: response.data.choices[0].text.trim()
};
} else {
message = {
type: "text",
text: "テキストを入力してください。"
};
}
const toToken = reqBody.events[0].source.userId;
await client.pushMessage(toToken, message).catch((err) => {
// error handling
console.error(err);
});
const response = {
statusCode: 200,
body: JSON.stringify(message),
};
return response;
};
これでコンソール画面上でDeploy
を実施。
上部に「関数myGptFunctionが正常に更新されました」と表示されればOK!
動作確認
とりあえず作ってみましたが結構面白いので、しばらくこれでChatGPTで遊んでみようと思います。
参考
ほぼ以下2つのコピペです。
OpenAIのAPI Reference
LINE Messaging APIのAPI Reference