🤖

【Azure Logic Apps】ChatGPTと話せるLINE Botを開発するハンズオン!~③複数往復の対話

2023/04/16に公開

0. 前回まで

第 1 弾の記事では ChatGPT API と話せる LINE Bot を Azure Logic Apps で爆速構築し、第 2 弾となる前回ではさらにトークン消費量の節約も試みました。

https://zenn.dev/himanago/articles/azure-logic-app-chatgpt-linebot

https://zenn.dev/himanago/articles/azure-logic-app-chatgpt-linebot2

この記事では最後に残る課題「複数往復の対話」を解決していきます。

1. ChatGPT API における複数往復の会話の前提

質問に、過去のやりとりの履歴を含めて送るだけで、会話の流れを意識して応答してくれます。

しかし、過去のやりとりについてもトークンが消費されるため、量が大きくなってしまいます。

そこで、過去のやりとりをすべて送るのではなく、過去のやりとりのうち一部、たとえば最大で3往復分のメッセージのみを送ることで、トークンの消費量を減らすことができます。

2. 複数往復の会話の実装

それでは、複数往復の会話を実装していきましょう。

(1) Cosmos DB のデプロイ

まずは、過去のやりとりを保存するための Azure Cosmos DB をデプロイします。

Cosmos DB は Azure で使える NoSQL データベースで、JSON ドキュメントを格納することができ、JSON をやりとりに使用する ChatGPT API の会話記録を保存するのにうってつけです。

ブラウザの新しいタブで Azure ポータルを開き、左上のメニューを開き、

「リソースの作成」をクリック。

「データベース」から「Azure Cosmos DB」を探し、「作成」をクリックします。

「API オプションの選択」で「コア (SQL)」の「作成」をクリックします。

「Azure Cosmos DB アカウントの作成」の画面で、以下のように設定します。

  • サブスクリプション:今回作成・使用している Logic Apps と同じもの
  • リソースグループ:今回作成・使用している Logic Apps と同じもの
    ※前回は rg-chatgpt-linebot-20230318 としていました
  • アカウント名: cosmos-chatgpt-linebot-xxxxxx
    ※同一の名前を設定できません。xxxxxx は他と被らないよう適当にランダムな文字列を設定してください
  • 場所:(Asia Pacific) 東日本
  • 容量モード:プロビジョニングされたスループット
  • Free レベル割引の適用:適用
    ※今回使用するサブスクリプション内でほかに Free レベルの Cosmos DB アカウントが既に存在する場合、選択できません。
    ※その場合は容量モードを Serverless に設定するのもおすすめです
  • 合計アカウント スループットを制限する:チェックを入れた状態

設定できたら、「レビュー + 作成」をクリックします。

内容を確認し、「作成」をクリックします。

デプロイ完了まで待ち(少し時間がかかります)、「リソースへ移動」をクリックします。

Cosmos DB の画面が開いたら、左側のメニューから「概要」をクリックし「コンテナーの追加」をクリックします。

作成するコンテナー(リレーショナルデータベースのテーブルのようなもの)の情報を以下のように入力します。

  • Database id: Create new を選択し、名称を chatgpt-linebot とします。また、Share throughput across containers にチェックが入っていることを確認します。
  • Database throughput (autoscale): Autoscale が選択され、Database Max RU/s が 1000 となっていることを確認します。
  • Container id:chatHistory と入力
  • Indexing:Automatic が選択されていることを確認します。
  • partition key:/id と入力されていることを確認します。※重要!

すべて設定・確認ができたら OK をクリックします。

ここまでできたら、Cosmos DB の設定をしていたタブはそのままに、Logic Apps を編集していたタブに戻ります。

(2) Logic Apps フローの改修

Cosmos DB への会話履歴保存処理の追加

これまで編集していた部分(「条件」→「スイッチ」→「ケース 1 : テキスト」の中)の最後のほうの処理の、「JSON の解析」と「メッセージの設定(テキスト)」の間の「+」をクリックし、「並列分岐の追加クリックします。

検索欄に Cosmos を入力し、表示された Azure Cosmos DB の「ドキュメントを作成または更新 (V3)」をクリックします。

すると、Cosmos DB との接続を設定する入力欄が表示されるので、以下のように設定します。

  • 接続名:cosmos-connestion
  • Authentication Type:Access Key ※デフォルトのまま
  • Account ID:cosmos-chatgpt-linebot-xxxxxx ※先ほど作成した Cosmos DB アカウント名
  • Access Key to your Azure Cosmos DB account:Cosmos DB の「キー」の「プライマリ キー」の値をコピーして貼り付けます。

「プライマリ キー」は、Cosmos DB のタブに戻り、左側のメニューから「キー」をクリックするとそこから取得できます(アカウント名も、URL の一部から取得できます)。

「ドキュメントを作成または更新 (V3)」の設定ができるようになるので、以下のように設定します。

  • Azure Cosmos DB アカウント名:Use connection settings (cosmos-chatgpt-linebot-xxxxxx)
  • データベース ID:chatgpt-linebot
  • コレクション ID:chatHistory
  • ドキュメント:以下をそのままコピペします。
{
  "id": @{items('For_each')?['source']?['userId']},
  "messages": [
    @{first(skip(variables('ChatGPT入力メッセージ'), sub(length(variables('ChatGPT入力メッセージ')), 2)))},
    @{last(skip(variables('ChatGPT入力メッセージ'), sub(length(variables('ChatGPT入力メッセージ')), 2)))},
    {
      "content": "@{trim(body('JSON_の解析')?['choices'][0]['message']['content'])}",
      "role": "assistant"
    }
  ]
}

このドキュメントの記述のポイントは、id には LINE Messaging API の userId を指定していることです。これにより、ユーザーごとに会話履歴が保存されるようになります。

動的なコンテンツや式を組み合わせて自分で作ることもできますし、非効率な記述もありますが、今回は簡略化のためにこのようにしています。

続いて、新規作成時と更新時両方で使えるように、パラメータを追加します。

「ドキュメントを作成または更新 (V3)」の下にある「Add new parameter」を開き、「IsUpsert」にチェックを入れます。

どこか外側をクリックすると表示が切り替わるので、「IsUpsert」を はい にします。

このように設定できていれば OK です。

Cosmos DB 保存されている会話履歴を利用する処理の追加

今度は、会話履歴を取得し、ChatGPT へのリクエストに利用する処理を追加していきます。

さきほどの少し上、「配列変数に追加 2」と「配列変数に追加」の間の「+」をクリックし、「アクションの追加」をクリックします。

Cosmos と入力し、表示された Azure Cosmos DB の「すべてのドキュメントを取得 (V3)」をクリックします。

追加されたアクションに、以下のように設定します。

  • Azure Cosmos DB アカウント名:Use connection settings (cosmos-chatgpt-linebot-xxxxxx)
  • データベース ID:chatgpt-linebot
  • コレクション ID:chatHistory

そして「Add new parameter」を開き、「パーティション キーの値」をチェックします。

どこか外側をクリックすると表示が切り替わるので、「パーティション キーの値」に "" (ダブルクォーテーション 2 つ)を入力します。

入力した 2 つのダブルクォーテーションの間に入力カーソルを置き、動的なコンテンツから「HTTP 要求の受信時」の「userId」を入れます。

このようになれば OK です。LINE ユーザー ID に紐つく会話履歴を取得する処理となります。

続いて、その下にアクションを追加します。

検索に「制御」と入力し、表示された「条件」をクリックします。

「条件 2」が追加されます。

「会話履歴が取得できたかどうか」という条件分岐になるように以下のように設定します。

まず左側のテキストボックスには、カーソルを入れると「動的なコンテンツ」などが選択できるようになりますが、ここで「式」を選択し、「fx」と書かれた欄に length(body('すべてのドキュメントを取得_(V3)')?['Documents']) を貼り付けて OK をクリックします。

続いて、真ん中の選択肢を 次の値より大きい にし、右側のテキストボックスに 0 を入力します。

「条件 2」の「True」の中にアクションを追加していきます。会話履歴が存在していた場合に、会話履歴をリクエストに含めるための処理です。

「True」内の「アクションの追加」をクリックします。

検索に JSON と入力し、「ビルトイン」内に表示された「JSON の解析」をクリックします。

「JSON の解析 2」としてアクションが追加されるので、以下のように設定します。

  • コンテンツ:@{first(body('すべてのドキュメントを取得_(V3)')?['Documents'])} をコピペ
    ※コピペすると、表示が変わります
  • スキーマ:以下の JSON をコピペします。
{
    "properties": {
        "_attachments": {
            "type": "string"
        },
        "_etag": {
            "type": "string"
        },
        "_rid": {
            "type": "string"
        },
        "_self": {
            "type": "string"
        },
        "_ts": {
            "type": "integer"
        },
        "id": {
            "type": "string"
        },
        "messages": {
            "items": {
                "properties": {
                    "content": {
                        "type": "string"
                    },
                    "role": {
                        "type": "string"
                    }
                },
                "required": [
                    "content",
                    "role"
                ],
                "type": "object"
            },
            "type": "array"
        }
    },
    "type": "object"
}

さらにその下にもアクションを追加していきます。

「アクションの追加」をクリックします。

変数 と検索し、「ビルトイン」の「配列変数に追加」をクリックします。

名前に ChatGPT入力メッセージ を選択、値で動的なコンテンツで「JSON の解析 2」の content を選択します。

すると以下のように自動的に「For each 2」が追加されます。

「For each 2」が追加されたら、「配列変数に追加 3」の値を消し、以下の JSON を貼り付けます。

{
  "content": "@{items('For_each_2')['content']}",
  "role": "@{items('For_each_2')['role']}"
}

これでフローの修正は完了です。

(3) 動作確認

動作確認をしてみましょう。

ちゃんと会話の流れに沿った回答をしてくれていますね!

途中で話題を変えてもきちんと答えてくれます。

ただし、たまに翻訳によるトークン節約処理がうまく働かず、英語で返答が返ってきたりすることがあります。

その場合は、文脈を理解してくれるので「日本語で答えて」と言えば日本語にしてくれます。

もしこれが気になる場合は、トークン節約処理のアクションを削ってみてください。

3. まとめ

以上で、ChatGPT API を使って会話できる LINE Bot を使ってみました。

最初はテンプレートから爆速で一問一答できるところまで作ることができましたが、最終的には Cosmos DB まで使って少し本格的な Bot まで進化させることになりました。

とはいえ、Logic Apps を用いれば Cosmos DB を使った処理も簡単に実装できるので、今回のような会話の履歴を保存しておくような Bot は簡単に作れると思います。

ChatGPT に限らずさまざまな Bot にも応用できるので、ぜひ試してみてください。

そして ChatGPT が LINE から気軽に使えるので、今回完成した Bot もぜひ活用していってください!

ここまで読んでくださりありがとうございました。また、ハンズオンを最後まで実施していただけた方、ありがとうございます。

お疲れさまでした!

★Special Thanks

本ハンズオン資料について、さきさか しげる さんと のりじ さんにレビュー・フィードバックのご協力をいただきました。ありがとうございました!

Discussion