はじめに
以前に社内向けにチャットボットを作成して運用してその紹介記事を作成しました。
今回は実際にどのような技術やロジックでこのようなチャットボットを作成したのかを紹介します。
システム構成図
まず、開発環境、本番環境を紹介します。
開発環境
開発ではGitHubアクションを利用することで、CI/CDを実現しています。こうすることで、Githubにコードの変更をプッシュすると自動で本番環境に変更を適応することができます。これによってでデプロイの工数削減を図れます。
本番環境
チャットボットはAWSのEC2で動かしています。Slack APIのソケットモードを利用しているため、内向きの通信を確保しなくても、SlackBotを動かすことができます。ネットワークについて考慮する必要がなかったため、工数の削減になっています。また、移植性やデプロイ工数の削減のためにシステムはコンテナ化しています。
作り方
どのような仕組みでチャットボットを作成したのかを説明します。
Slack
チャットボットはSlackで利用するため、BoltというフレームワークでPythonで作成しました。Slack Botはソケットモードというもうのがあり、ネットワークに公開していなくても使えるため、動作確認に便利です。
Slack Botに対するメンションに対して、スレッドで返信するようにしました。body["event"]["ts"]
を使います。
@app.event("app_mention") def mention_handler(body, say): ... thread_ts = body["event"]["ts"] try: answer = agent.get_answer(text) except Exception as e: answer = "エラーが発生しました。" say(answer, thread_ts=thread_ts)
DB
次にDBについてです。ChatGPTに社内情報を答えさせるために、社内情報をDBに保存する必要があります。利用したDBはChromaDBです。これはベクトルの保存を目的とした組み込み型のキーバリュー型のDBです。組み込み型であるためSQLiteのようにDBサーバを持つ必要がありません。
社内情報をMarkdown形式で整形し、OpenAIのモデルのtext-embedding-ada-002
を使用してベクトルに変換します。データベースに格納する項目は以下となります。
・文章
・文章をベクトル化したデータ
OpenAI
このチャットボットはユーザからの質問に対して一問一答で答えることを目的としています。そのため、OpenAIのモデルはtext-davinci-003
です。これは文章補完に特化したGPT3.5になります。
会話
DBとOpenAIを組み合わせることで、社内情報を答えるチャットボットを作ることができます。質問内容を受け取ってから、回答を送信するまでの流れを紹介します。
1. 質問内容のベクトル化
OpenAIのモデルのtext-embedding-ada-002
を用いてベクトル化を行います。
2. 質問に答えるのに参考になるデータをDBから取得
ユーザからの質問に答えるために、DBから参考になるデータを取得します。これは、質問とDB内に格納されたベクトルとの距離を比較することで行います。ベクトル同士の距離が近いほど、内容も近いことを意味します。そのため、距離が最も近いベクトルのデータが、質問に最も参考になるデータとなります。
3. プロンプトの作成
OpenAIに投げるプロンプトのフォーマットは以下のようになります。input_text
には参考にする社内情報を格納し、question
には質問内容を格納します。
PROMPT_TEMPLATE = """回答は「。」で終わるようにして下さい。 回答がドキュメントに明示的に記載されていない場合、「答えられません。」と回答してください。 markdown input: {input_text} question: {question} answer: """
実際に作成したプロンプトの例は下記のようになります。
回答は「。」で終わるようにして下さい。 回答がドキュメントに明示的に記載されていない場合、「答えられません。」と回答してください。 markdown input: - 賞与の支給時期は、原則として、毎年2月及び8月の会社が定める日とする。 - 賞与支給額の算定対象期間は、次の各号のとおりとする。 - 2月支給分・・・上期決算期 (前年7月1日から前年12月31日まで) - 8月支給分・・・下期決算期 (当年1月1日から当年6月30日まで) question: 賞与はいつ支給されますか? answer:
回答内容が長すぎる場合は、途中で返答が切れてしまうため、回答内容の最後が「。」で終わらなかった場合は、下記のフォーマットを利用して、回答の続きを書きます。
PROMPT_CONTINUE_TEMPLATE = """解答は「。」で終わるようにして下さい。次の入力された文章の続き補完して下さい。 markdown input: {input_text} question: {question} answer: {answer}"""
おわりに
以上がChatGPTを用いたチャットボットの作り方でした。読者の方がChatGPTを用いたチャットボットを作成するときの参考になれば幸いです。