ささみ学習帳 - sasami's study book

ささみ学習帳

Microsoft365 や Power Platform について学んだこと・アイデアのメモ

Copilot Studio のチャットボットで Claude 3を使って会話履歴と文脈に基づいた回答をさせる💎

 

 

はじめに

GPT-4よりも優秀?と噂のClaude3をCopilot Studio チャットボットから利用できるようにしてみました。Copilot Studioのチャットボットで回答できなかった場合に、Claudeを使って回答を生成します。

今回の記事はXで益森さんに教えていただいたQiitaの記事を基にClaude  API用にアレンジしてみたものです。

qiita.com

 

1.Claude をカスタムコネクタを作成する

今回は、以前こちらの記事で解説したカスタムコネクタを利用します。

sasami-axis.hatenablog.com

 

2.ソリューションをインポートする

益盛さんのQiitaの記事で詳細されているこちらのページからリンクされているソリューションを利用します。

powerusers.microsoft.com

こちらはCopilot Studio (旧Power Virtual Agents)のチャットボットから Azure Open AI Service (以降AOAIと表記)を呼び出す内容となっていますので、これを基に変更を加えていきます。

ダウンロードしたソリューションをインポートします。

 

3.チャットボットの確認

インポートしたソリューションの中のチャットボット「ChatGPT Fallback Bot (PVA 2)」の仕組みを確認します。

このチャットボットのシステムトピックのFallbackトピック内でAOAIを呼び出しています。Fallbackトピックは、Copilotがユーザーの入力から既存のトピックをトリガーする十分な確信がない場合に実行されます。

会話の履歴を保持する動作は、チャットの入力テキストとAOAIの応答をグローバル変数FullDIalogに履歴として保存し、Power Automate クラウドフローを実行する際にパラメータとして渡しています。

今回はチャットボット側は特に修正する必要なく、呼び出すクラウドフローを修正するだけで対応できます。

 

4.クラウドフローを編集する

インポートしたソリューションの中のクラウドフロー「Chat Completion with ChatGPT」を編集していきます。

 

4-1.オリジナルのフローの解説

オリジナルはAOAIを呼び出すフローとなっています。

トリガーでチャットの入力テキスト(UnrecognizedTriggerPhrase)と過去の履歴(FullDialog)がパラメーターとして渡されています。

次に変数でシステムプロンプトを定義しています。

ここは好みで変更を加えます。

次にメッセージを格納するアレイ変数を定義しています。

次にトリガーの2つのパラメータを組み合わせてAPIパラメータのメッセージ部分のJSONを作成し解析しています。

解析したJSONをMessages変数にApply to Eachで格納していき

HTTPアクションでAOAIを呼び出して回答を生成しています。

AOAIからの応答からメッセージ部分(GeneratedAnswer)とトリガーパラメータのチャットの入力テキスト(UnrecognizedTriggerPhrase)をチャットボットに返しています。

4-2.修正後フロー

緑色の点線枠のアクションが修正したアクション、赤色の枠のアクションが追加したアクションです。

Initialize variable: Messages

AOAIとClaude では渡すJSONの構造が異なり、システムプロンプトはメッセージのアレイに含まれません。この為Valueの設定値を削除します。


変数を初期化する-FullDialogMessages

メッセージ履歴を格納する変数を追加しています。

条件-会話が3回以上続いている

オリジナルのフローでは会話の履歴をセッションが切れるまで蓄積する動作です。会話の履歴が長くなるとトークンの消費が増加してしまいますし、またClaude3は比較的長文で返す傾向がある(私の主観)のでトークンの無駄に消費してしまいます。

そこで益森さんのこちらの記事のアプローチを組み込んでAPIに渡すメッセージを直近の3つの会話履歴のみに制限しています。

qiita.com

  • Condition Expression

    • AND
      • length(body('Parse_JSON:_FullDialog'))
      • is greater than
      • 7

益森さんの記事では3つの会話で6以上で判定していますが、今回のフローではParse JSON: FullDialogに会話履歴+直近のチャット入力が結合されているため、必ず奇数になります。その為履歴6+1で7以上という判定になります。

Trueの場合、直近3つの履歴+チャット入力をFullDialogMessages変数に格納します。

  • Name
    • FullDialogMessages
  • Value
    • skip(body('Parse_JSON:_FullDialog'), sub(length(body('Parse_JSON:_FullDialog')), 7))

Falseの場合、すべてをFullDialogMessages変数に格納します。

  • Name
    • FullDialogMessages
  • Value
    • body('Parse_JSON:_FullDialog')

 

Apply to each: FullDialog Message

オリジナルフローではトリガーのFullDialogをループで処理していましたが、FullDialogMessages変数に置き換えて、APIに引き渡すメッセージ履歴の数をコントロールしています。

[カスタムコネクタ]メッセージを作成する

オリジナルフローのHTTPアクションを削除し、Claude APIのカスタムコネクタを利用します。

  • APIバージョン
    • 2023-06-01 ※2024-4-7現在
  • Body/Message
    • variables('Messages')
  • システムメッセージ 
    • variables('System Prompt')
  • その他パラメータはお好みで

 

API呼び出しアクションが変わっていますので、チャットボットに返す部分も修正が必要です。GeneratedAnswerの部分を変更しています。

  • GeneratedAnswer
    • outputs('メッセージを作成する')?['body/content'][0]?['text']

 

5.その他ソリューションの細かい修正

動作には影響ありませんが、気分的に変更しました。

  • 使用しなくなった環境変数の削除
  • 名前の変更
    • ソリューションやチャットボット、クラウドフローの名称の"ChatGPT”を"Claude"等に置き換え
  • チャットボットの言語設定
    • オリジナルのチャットボットは英語で作成されているため、日本語に対応するよう言語を追加
    • Copilot Studio → チャットボット→設定→言語

6.実行してみる

Copilot Studio でテスト実行してみると、文脈を理解した回答ができています。

 

さいごに

当初は思いつきでClaude を呼んで遊んでみただけでしたが、益森さんのアドバイスで文脈に基づいた回答ができる実用的なものに発展させることができました。ほぼそのまま利用させていただいております。大感謝です。