OpenAI API と Slack App で気軽に使える Slack Bot を構築しました!
ケップルのプロダクト開発組織 KEPPLE CREATORS LAB で組織開発や採用を行っている池浦(@neer_chan)です。
みなさん、 Generative AI を使っていますか? OpenAI の ChatGPT が 2023 年に流行り出してから Google Bard や Microsoft Bing など多くの Chat Bot がこの世に生を享けました。弊社では社内のワークフローで本格的に取り入れており、利用シーンがますます多くなっています。
そのような状況の中、社内で利用しているコミュニケーションツール Slack でも ChatGPT を利用したいという声があり、Slack App として ChatGPT を利用できる環境を整えました。今回は、その Slack App の構築に関する記事になります。
Generative AI / ChatGPT について
そもそも Generative AI とは、AI の力を利用し新しいコンテンツを生み出す技術です。生み出すコンテンツはさまざまで、画像や文章だけでなく音楽なども含まれます。Generative AI の代表的な手法は GAN ( Generartive Adversarial Networks ) や VAE ( Variational Auto Encoder ) があります。それぞれの詳細について書き始めると日が暮れてしまうので、ぜひ一度調べてみてください!
Generative AI によるサービスの中でも、テキストの入力によってコンテンツを生み出すのが ChatGPT に代表される Chat Bot になります。ChatGPT は OpenAI によって開発されている GPT(自然言語処理モデル)を利用しており、従来の Chat Bot と比べると、そのあまりにも自然な対話性能や高い回答精度が注目を浴びる理由になっています。
回答の精度が高いといっても平気な顔して嘘をつく側面もあり、利用者側のリテラシーが求められますが、それを差し引いても従来の Chat Bot と比べて高い性能を持っています。
OpenAPI の API Key を作成する
ChatGPT は OpenAI が提供しているチャットインターフェースで利用することもできますが、OpenAI platform で提供されている API を介して利用することもできます。
OpenAI の Organization を作成すれば OpenAI を利用するメンバーや請求の管理も一元化できるため、企業で利用するならば Organization を作成するとよいでしょう。OpenAI の API Key はユーザー単位で発行する必要があるので、管理画面左下の USER > API keys から作成しましょう。
また、API 経由で送信した情報を学習に利用されないようにしたほうがよいため、オプトアウトの申請も忘れずに行いましょう!
Slack App を作成する
OpenAI の API Key を作成したら、次は Slack App を作成しましょう。Slack App は Slack API > Your Apps > Create New App から作成できます。親の顔より見た Incoming Webhook は 2020 年に非推奨となり、それ以来は Slack App 経由で Webhook を設定するようになりましたから、Slack App の方が馴染んでいる方も多いかもしれません。
今回は Slack App 自体に任意の処理を実行してもらうのではなく、Slack App が提供する Subscription 機能で任意の処理をキックし OpenAI API を呼び出します。
任意の処理を実行するアプリケーションの構築は、Slack が提供するフレームワーク Slack Bolt を利用するのがお手軽です。さまざまな言語をサポートしていますが、弊社のほとんどのプロダクトで TypeScript を採用していることから、今回は TypeScript で実装しました。
Slack App から OpenAI API を呼ぶ
OpenAI API は Authorization ヘッダーを利用した Bearer 認証で呼び出します。
Request Body には model と messages を最低限渡せば Response は返却されます。 執筆時点( 2023年 8 月)では gpt-4 を利用できますが、今回は gpt-3.5-turbo を使います。
interface ChatGptMessage {
role: 'system' | 'user' | 'assistant';
content: string
}
const messages: ChatGptMessage[] = [{
role: 'user',
content: '猫と犬の違いを教えてください'
}]
const createCompletion = async (
messages: ChatGptMessage[],
) => {
// .....
const response = await axios.post(
'https://api.openai.com/v1/chat/completions',
{
model: 'gpt-3.5-turbo',
messages,
},
{
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${process.env.OPEN_AI_API_KEY}`,
},
},
);
// .....
};
Slack Bolt でアプリケーションを作成する場合、Slack Bolt アプリケーションと Slack App を接続する方法は「 Socket モード 」と「 HTTP モード 」があります。 Socket モードを利用するメリットは、パブリックなWeb エンドポイントを提供しなくてよいことが挙げられます。
一方で HTTP モードではパブリックな Web エンドポイントを用意する必要がありますが、 ngrok を利用すればローカルでの検証も行えますし、Web エンドポイントを用意することも容易であるため、今回は HTTP モードで実装しました。(容易と用意をかけています)
また、Web エンドポイントは AWS SAM を利用して Lambda と API Gateway で構築しました。
Lambda のハンドラーでは専用の Receiver をスタートさせた上で event や context をそのまま渡せばよいのでとても簡単です。
export const lambdaHandler = async (event: APIGatewayProxyEvent, context: APIGatewayEventRequestContext, callback: APIGatewayProxyCallback): Promise<APIGatewayProxyResult> => {
const handler = await awsLambdaReceiver.start();
return handler(event, context, callback);
};
Receiver をコンストラクタ引数に渡して App を作成し、リスナー内に Slack Events API が呼び出されたときの処理を書きます。今回のケースでは、Slack App に対してメッセージを受け取ったときに処理を実行するため、app.message のリスナーを利用しました。
const app = new App({
token: process.env.SLACK_BOT_USER_OAUTH_TOKEN,
receiver: awsLambdaReceiver,
});
app.message(async ({ message, event, client, say }) => {
// OpenAI API を呼び出す処理を書く
}
Slack App の Tips
Slack App を触ったことがある人はご存知かもしれませんが、それなりに難しい・分かりにくい部分が多いので、初めて Slack App を作成する人に役立つような Tips を紹介します。
さまざまなトークンやシークレット
Bot User OAuth Token, Verification Token, Signing Secret, Client Secret のように似たようなパラメータが多くあります。
はじめに Token について見ていくと、Verification Token は 2019 年頃から非推奨になっているため、基本的に利用することはありません。ですので、特定の Workspace にアクセスする権限を持った Bot User OAuth Token を利用します。こちらは特定の Workspace に Slack App をインストールすると発行されるトークンです。
Client Secret は、oauth.v2.access で OAuth 認証を行う際に Client ID と一緒に利用するシークレットです。 Slack Bolt の App をインスタンス化するだけであれば、 Sining Secret のみでよいため、今回のケースでは使用していません。
リトライ処理の制御
Slack Events API が呼び出されたとき、特定の条件でリトライが発生します。処理中で何らかのエラーが発生した場合やコネクションが確立できなかった場合にリトライが発生することは想像に難くないと思いますが、 3秒以内にレスポンスを返却しなかった場合にもリトライが発生します。また、リトライ条件に合致した場合には、計 3 回のリトライが行われます。
このリトライ仕様がなかなかに厄介で、OpenAI API を叩くような処理の場合は往々にしてレスポンスまで 3 秒以上を要します。考え得る正しい対応としては Slack Events API のリクエストをキューイングし、先にレスポンスを返却することがあります。一方で、ちょっとした業務を楽にするための Slack App を作るためにキューイングの仕組みを作るのは大袈裟だなと感じる人は、以下のように X-Slack-Retry-Num というヘッダーの存在を判定し回避することもできます。
if (event.headers['X-Slack-Retry-Num']) {
return { statusCode: 200, body: JSON.stringify({ message: "No need to resend" }) };
}
上記の対応を行うと、本当にリトライしてほしいタイミングでリトライされなくなるため注意が必要です。
まとめ
完成した Chat Bot は本家のチャットインターフェースのように会話が行えました。
ビジネスにおいて Generative AI の浸透はより一層進んでいくと思うので、今後は Generative AI をいかに身近なものにできるかが重要になると考えています。実際に ChatGPT を利用することでワークフローに充てる人的な工数も削減できている実績があるので、みなさんも積極的に使っていきましょう!
エンジニアリングという観点では GitHub Copliot X がとても楽しみで、何から何まで AI に頼っていく世界が着々と近づいていますね。
WE ARE HIRING!
KEPPLE CREATORS LAB では一緒に働くメンバーを募集しています。
募集しているポジションの詳細はこちらをご覧ください。
▼KEPPLE CREATORS LAB ブランディングサイト
▼KEPPLE CREATORS LAB 求人一覧
この記事が気に入ったらサポートをしてみませんか?