はじめに
こんにちは。アプリケーションチームの栗田です。
ChatGPT をはじめとした、生成系 AI の勢いがすごいですね!
今回は AWS Lambda を使って、Chatwork から ChatGPT に質問できるようにしてみました。
備忘録として残しておきます。
概要説明
Chatwork から Lambda 経由で ChatGPT API を呼び出します。
ストレージを持たせてませんので、過去の質問を維持したやりとりはできません。
(維持したい場合は、S3 や DynamoDB を使って TTL つきで管理するとライトにできそうです)
やってみた
以下を使います。
お持ちでない場合は準備しておきましょう。
Lambda を作成する
OpenAI ライブラリを Lambda レイヤーにアップロードする
OpenAI の Python ライブラリを使用するので、Zip ファイルにかためておきます。
$ mkdir python $ python3 -m pip install -t ./python openai $ zip -r openai.zip ./python
作成した Zip ファイルを Lambda レイヤーにアップロードします。
ランタイムは Python3.9
とします。
Lambda レイヤーに追加する
作成した Lambda レイヤーを関数に追加します。
Lambda を実装する
Chatwork からのメッセージを、ChatGPT へ問い合わせする処理の実装をします。
特定のワード("教えてChatGPT")が含まれた場合のみ ChatGPT へ問い合わせるようにしています。
また、ChatGPT の使用感の確認を優先したため、細かなチェック処理やロギングは省いています。ご了承ください。
from decimal import Decimal import json import os import openai import requests openai.api_key = os.environ['OPENAI_API_KEY'] OPENAI_API_ENDPOINT = 'https://api.openai.com/v1/engine/davinci-codex/completions' CHATWORK_API_KEY = os.environ['CHATWORK_API_KEY'] CHATWORK_ROOMID = os.environ['CHATWORK_ROOMID'] CHATWORK_ENDPOINT = os.environ['CHATWORK_ENDPOINT'] WAKE_WORDS = ("教えてChatGPT", "教えて ChatGPT") def lambda_handler(event, context): # TODO 署名チェック request_signature = event["headers"]["x-chatworkwebhooksignature"] print(request_signature) # Chatwork メッセージ取得 json_item = json.dumps(event) j = json.loads(json_item) webhook_body = eval(j["body"]) account_id = webhook_body["webhook_event"]["account_id"] room_id = webhook_body["webhook_event"]["room_id"] message_id = webhook_body["webhook_event"]["message_id"] request_message = webhook_body["webhook_event"]["body"] # WAKE_WORDS が含まれなかったら何もしない if not request_message.startswith(WAKE_WORDS): print("Does not contain wake_words.") return { 'statusCode': 200, } print('account_id: {0}'.format(account_id)) print('request_message: {0}'.format(request_message)) # ChatGPT リクエスト question = request_message for word in WAKE_WORDS: request_message.replace(word, '') response = openai.ChatCompletion.create( model="gpt-3.5-turbo", temperature=0.6, max_tokens=1000, messages=[ {"role": "user", "content": question.strip()}, ] ) print("Received response:" + json.dumps(response, default=decimal_to_int, ensure_ascii=False)) answer = response["choices"][0]["message"]["content"] # Chatwork 結果送信 # [rp aid={account_id} to={room_id}-{message_id}] headers = {'X-ChatWorkToken': CHATWORK_API_KEY} chatwork_message = '[rp aid={0} to={1}-{2}]{3}'.format(account_id, room_id, message_id, answer) payload = {'body': chatwork_message} url = '{0}/rooms/{1}/messages'.format(CHATWORK_ENDPOINT, CHATWORK_ROOMID) response = requests.post(url, headers=headers, data=payload) return { 'statusCode': 200 } def decimal_to_int(obj): if isinstance(obj, Decimal): return int(obj)
環境変数
os.environ['XXX']
は Lambda の環境変数です。
ご利用の動作環境に合わせて変更してください。
キー | 概要 |
---|---|
CHATWORK_API_KEY | Chatwork の API トークンを指定します。 |
CHATWORK_ENDPOINT | Chatwork のエンドポイントを指定します。 |
CHATWORK_ROOMID | ChatGPT とやりとりをする Chatwork のルーム ID を指定します。 |
OPENAI_API_KEY | OpenAI の API トークンを指定します。 |
タイムアウト
Lambda のタイムアウトはデフォルト 3 秒です。
ChatGPT のレスポンスは少し時間がかかるので、延ばしておくことをおすすめします。
以下の例では 1 分に指定しています。
Chatwork の Webhook を設定する
Chatwork から Lambda へメッセージを送信するため、Webhook を設定します。
今回は Lambda の関数 URL を利用して連携します。便利ですね。
Lambda 関数 URL
Lambda から 関数 URL をコピー します。
Chatwork Webhook
Chatwork の右上アカウントメニューから [サービス連携] を選択します。
[Webhook] タブから設定を作成します。 Webhook URL 欄にコピーした 関数 URL をペーストしましょう。
その他の項目は画像を参考に設定してください。以下の例では、指定のチャットルームに新規のメッセージ投稿があった場合、Lambda が起動するようになっています。
ChatGPT に質問してみる
実際にやってみました。
「よい開発チームを作るために大切なことを教えてください」
非常にわかりみがある答えが返ってきました笑
また、実際にチームメンバーにも公開して使ってもらいました。
- AWS の操作質問
- メール本文のサンプル作成
- エラーコードの解析支援
- サンプルコードの実装
- テストデータのパターン作成
などなど、困ったときのよき相談役として使えそうだなと思いました。
他にも「おいしいラーメン屋の屋号を考えて」「子供が喜びそうな、ゆるキャラの名前を 5 個考えて」などの質問が見られ、メンバーのコミュニケーションに役立ちました。笑
おわりに
ChatGPT は日本語のブレも少なく、高精度な回答をしてくれると感じました。ただし、間違った回答が含まれることがあるので、自身で理解せずそのまま使うのは危険です。
また、個人情報や機密情報を入力するのは控えましょう。ChatGPT はよき相談役になりえますが、友人ではなく他人です。取り扱いには十分注意しましょう。
開発業務と AI の親和性の高さを感じたので、Amazon CodeWhisperer や GitHub Copilot も試してみたいですね。
今回は Chatwork から ChatGPT に質問する、簡単なサンプルを作成しました。
どなたかの参考になれば幸いです。