<目次>
(1) OpenAIのAPIを使ったSlackボットの作り方
(1-1) やりたいこと
(1-2) 前提条件
(1-3) サンプルコード
(1) OpenAIのAPIを使ったSlackボットの作り方
(1-1) やりたいこと
Slackボット
に問いかけると、OpenAIのAPIからの回答が返ってくるようにしたい
(1-2) 前提条件
(1-3) サンプルコード
import os
import time
from dotenv import load_dotenv
from slack_bolt import App
from slack_sdk import WebClient
# Flaskクラスのインポート
from flask import Flask, request,jsonify
from slack_bolt.adapter.flask import SlackRequestHandler
#ソケットモード用
from slack_bolt.adapter.socket_mode import SocketModeHandler
# 環境変数読み込み
import env
# ロギング
import traceback
# OpenAI
import openai
import pkg_resources
# モードに応じて書き換え
BOT_USER_ID = "ご自身のBOT_USER_ID"
# Botトークン(Flask)
WEBAPPS_SLACK_TOKEN = "ご自身のxoxbから始まるトークン"
WEBAPPS_SIGNING_SECRET = "ご自身のSigning Secret"
# Botトークン(ソケットモード)
SOCK_SLACK_BOT_TOKEN = "ご自身のxoxbから始まるトークン"
SOCK_SLACK_APP_TOKEN = "ご自身のSigning Secret"
# OpenAIのAPI設定
openai.api_key = "ご自身のOpenAI API Key"
# openai.api_version = "2022-02-16" # 使用するバージョンを指定
openai_version = pkg_resources.get_distribution("openai").version
# モード入れ替え(WebAPサーバ実行=Flask/ローカル実行=ソケットモード)
def app_mode_change(i_name):
if i_name == "__main__":
return App(token=SOCK_SLACK_BOT_TOKEN)
else:
return App(token=WEBAPPS_SLACK_TOKEN, signing_secret=WEBAPPS_SIGNING_SECRET)
# グローバルオブジェクト
s_app = app_mode_change(__name__)
# Flaskクラスのインスタンス生成
app = Flask(__name__)
#app.config['JSON_AS_ASCII'] = False
handler_flask, handler_socket = None,None
#ソケットーモードの場合のハンドラ設定
if __name__ == "__main__":
handler_socket = SocketModeHandler(app=s_app, app_token=SOCK_SLACK_APP_TOKEN, trace_enabled=True)
#Flaskでのハンドラー設定
else:
handler_flask = SlackRequestHandler(s_app)
# Flask httpエンドポイント
# 疎通確認用1
@app.route('/', methods=['GET', 'POST'])
def home():
return "Hello World Rainbow 2!!"
# 疎通確認用2
@app.route("/test", methods=['GET', 'POST'])
def hello_test():
return "Hello, This is test.2!!"
#イベント登録されたリクエストを受け付けるエンドポイント
@app.route("/slack/events", methods=["POST"])
def slack_events():
# ------------------------------------
# Challenge用
# ------------------------------------
# # Slackから送られてくるPOSTリクエストのBodyの内容を取得
# json = request.json
# print(json)
# # レスポンス用のJSONデータを作成
# # 受け取ったchallengeのKey/Valueをそのまま返却する
# d = {'challenge' : json["challenge"]}
# # レスポンスとしてJSON化して返却
# return jsonify(d)
# ------------------------------------
# 本番用
# ------------------------------------
return handler_flask.handle(request)
@s_app.event("message")
@s_app.event("app_mention")
def respondToRequestMsg(body, client:WebClient, ack):
ack()
type = body["event"].get("type", None)
# 二重で応答するのを防ぐため、メンションの時のイベントのみ応答対象とする
if type == 'app_mention':
try:
#-----------------------------------
# Slackのイベント情報から各種パラメータを取得
input_text = body["event"].get("text", None)
bot_user_id = os.environ.get('BOT_USER_ID')
channel = body["event"]["channel"]
ts = body["event"]["ts"]
thread_ts = body["event"].get("thread_ts", None)
user = body["event"]["user"]
attachment_files = body["event"].get("files", None)
# OpenAIからの返答を生成
output_text = generate_response(input_text)
time.sleep(3) # n秒待機 (実施しないと「The server responded with: {'ok': False, 'error': 'no_text'}」になる)
# Slackに返答
client.chat_postMessage(channel=channel, text=output_text ,thread_ts=ts)
except Exception as e:
print("-------------------------------------------------")
print("======== react_to_msg 例外発生:"+str(e))
traceback.print_exc()
# 前回の会話のリスト
previous_conversation = []
def generate_response(prompt):
global previous_conversation # 前回の会話のリストをグローバル変数として使用する
print(previous_conversation)
# previous_conversationは前回の発言のリストです
# ここでは、previous_conversationをテキストに変換して、promptに追加しています
prompt = "".join(previous_conversation) + "\n" + prompt
print("-------------------------------------------------"+prompt)
# APIを使用して、応答を生成します
response = openai.Completion.create(
model="text-davinci-003",
prompt=prompt,
max_tokens=200,
n=1,
stop=None,
temperature=0.5,
)
# 応答のテキストを取得します
message = response.choices[0].text.strip()
# previous_conversationの最大長を10に制限する
previous_conversation = previous_conversation[-9:] + [prompt, message]
return message
# __name__はPythonにおいて特別な意味を持つ変数です。
# 具体的にはスクリプトの名前を値として保持します。
# この記述により、Flaskがmainモジュールとして実行された時のみ起動する事を保証します。
# (それ以外の、例えば他モジュールから呼ばれた時などは起動しない)
if __name__ == '__main__':
EXEC_MODE = "SLACK_SOCKET_MODE"
# Slack ソケットモード実行
if EXEC_MODE == "SLACK_SOCKET_MODE":
handler_socket.start()
# Flask Web/APサーバ 実行
elif EXEC_MODE == "FLASK_WEB_API":
# Flaskアプリの起動
# →Webサーバが起動して、所定のURLからアクセス可能になります。
# →hostはFlaskが起動するサーバを指定しています(今回はローカル端末)
# →portは起動するポートを指定しています(デフォルト5000)
app.run(port=8000, debug=True)