Azure Cognitive Service – カスタム質問応答と連携したボットの応答を分析・モニタリングする方法

こんばんは。今日は、Azure Cognitive Service – Languageが提供するカスタム質疑応答機能の応答モニタリングについて書きたいと思います。

そもそもどんなことがモニタリングできるのか、どんな方法でモニタリングできるのか、調べて分かったことをまとめていきたいと思います。

それではまいります。

Contents

Azure Cognitive Service – Language側でモニタリングできること

こちらの公式ドキュメントにまとめられていましたので、こちらに沿って実際に確認していました。Language側では、基本的にAzure Monitorの診断設定ログを活用する方向性のようです。

https://docs.microsoft.com/ja-jp/azure/cognitive-services/language-service/question-answering/how-to/analytics

診断設定ログの分析

[事前準備] 診断設定を有効にする

まず、Languageリソースの診断設定で、(最低限)”Trace”ログを有効化しておきます。

ナレッジベースの応答一覧

最初にナレッジベースが返した応答の一覧です。Docsのクエリを少しカスタマイズして時刻なども出力するようにしています。

以下のように、実際にユーザが投げかけた質問文とそれに対するナレッジベースの応答、また回答の信頼度スコアなどが確認できます。

これで、どういった質問の投げかけが多いか、どういったナレッジの参照が多いか、などをモニタリングできそうです。

// All QnA Traffic
AzureDiagnostics
| where ResourceProvider == "MICROSOFT.COGNITIVESERVICES"
| where OperationName=="CustomQuestionAnswering QueryKnowledgebases" // This OperationName is valid for custom question answering enabled resources
| extend answer_ = tostring(parse_json(properties_s).answer)
| extend question_ = tostring(parse_json(properties_s).question)
| extend score_ = tostring(parse_json(properties_s).score)
| extend answerSpanScore_ = tostring(parse_json(properties_s).answerSpanScore)
| extend kbId_ = tostring(parse_json(properties_s).kbId)
| project TimeGenerated, question_, answer_, score_,answerSpanScore_, kbId_
| order by TimeGenerated desc

ただ1点、この場合以下で”SURFACE”と投げかけた時のようにアクティブラーニングの機能で信頼度スコアが近しく複数のオプションが提示された場合の選択結果が反映されていないようでした。

(ログ上は一番スコアが高かった?1つの回答しか記録されていなさそうで、実際には他の質問を選択して回答を得ていたとしてもその事実はこのクエリからは確認できない)

規定のクエリの条件を少し変えてみると、Feedbackを受け取っている事実は確認することができましたが、最終的にユーザが選択した質問が何だったかはパッとは分からないようでした。

qnaIdなどを辿っていくと分かるのかな・・?またわかったらUpdateします。

// All QnA Traffic
AzureDiagnostics
| where ResourceProvider == "MICROSOFT.COGNITIVESERVICES"
//| where Category == "Trace"
//| where OperationName=="CustomQuestionAnswering QueryKnowledgebases" // This OperationName is valid for custom question answering enabled resources
| extend answer_ = tostring(parse_json(properties_s).answer)
| extend question_ = tostring(parse_json(properties_s).question)
| extend score_ = tostring(parse_json(properties_s).score)
| extend answerSpanScore_ = tostring(parse_json(properties_s).answerSpanScore)
| extend kbId_ = tostring(parse_json(properties_s).kbId)
| extend qnaId_ = tostring(parse_json(properties_s).qnaId)
| extend userQuestion_ = tostring(parse_json(properties_s).userQuestion)
| project TimeGenerated, OperationName, Category, question_, answer_, score_,answerSpanScore_, kbId_, qnaId_, userQuestion_
| order by TimeGenerated desc

日・ナレッジベース・ユーザ毎のアクセス数

以下クエリで日・ナレッジベース・ユーザ毎のアクセス数推移が確認できます。

ここでいうユーザとは何を指しているのでしょうか・・?公式ドキュメント調べてみましたが見つけられず・・こちらもわかったら更新したいと思います。

// Traffic count per KB and user in a time period
let startDate = todatetime('2022-04-01');
let endDate = todatetime('2022-05-01');
AzureDiagnostics
| where ResourceProvider == "MICROSOFT.COGNITIVESERVICES"
| where OperationName=="CustomQuestionAnswering QueryKnowledgebases" // This OperationName is valid for custom question answering enabled resources
| where TimeGenerated <= endDate and TimeGenerated >=startDate
| extend kbId_ = tostring(parse_json(properties_s).kbId)
| extend userId_ = tostring(parse_json(properties_s).userId)
| summarize ChatCount=count() by bin(TimeGenerated, 1d), kbId_, userId_

Generate Answer APIの待機時間

続いてGenerate Answer APIの待機時間。これはサンプルクエリをたたいてみてもヒットしなかった。公式ドキュメントみてみたら、Language のカスタム質疑応答の前身、QnA MakerのAPIとして紹介されていた。Languageだと回答取得にQuestionAnsweringAPIが呼ばれているようなので、クエリが古いのかな・・?

https://docs.microsoft.com/ja-jp/rest/api/cognitiveservices-qnamaker/qnamaker5.0preview1/knowledgebase/generate-answer

// Latency of GenerateAnswer
AzureDiagnostics
| where ResourceProvider == "MICROSOFT.COGNITIVESERVICES"
| where OperationName=="Generate Answer"
| project TimeGenerated, DurationMs
| render timechart

すべての操作の平均待機時間

続いてすべての操作の平均待機時間。ナレッジベース照会の時間だけでなく、ListKeyのような内部処理の時間も含めて一覧化されるよう。

// Average Latency of all operations
AzureDiagnostics
| where ResourceProvider == "MICROSOFT.COGNITIVESERVICES"
| project DurationMs, OperationName
| summarize count(), avg(DurationMs) by OperationName
| render barchart

未回答の質問

最後、未回答の回答。これは、回答がヒットしなかった質問の一覧が出力されるクエリになっている。このクエリ結果をもとに、ヒットしなかった質問に対する回答をナレッジベースに足すか、想定しない入力が多ければ、そうした入力を防ぐ or 入力された場合のハンドリングを検討することに活用できそうです。

// All unanswered questions
AzureDiagnostics
| where ResourceProvider == "MICROSOFT.COGNITIVESERVICES"
| where OperationName=="CustomQuestionAnswering QueryKnowledgebases" // This OperationName is valid for custom question answering enabled resources
| extend answer_ = tostring(parse_json(properties_s).answer)
| extend question_ = tostring(parse_json(properties_s).question)
| extend score_ = tostring(parse_json(properties_s).score)
| extend kbId_ = tostring(parse_json(properties_s).kbId)
| where score_ == 0
| project question_, answer_, score_, kbId_

Azure Bot Service側でモニタリングできること

続いてBot Service側。こちらは「会話分析」機能を用いるか、アプリコードを改修してApplication Insightsにカスタムイベントログを出力する、といった方向性になりそうです。

会話分析

こちらに説明があります。が、このメニュー、2021年9月以降非推奨とワーニングがでています。ので、推奨の通り今後は別の方法でのモニタリングを検討する必要がありそうです。

https://docs.microsoft.com/ja-jp/azure/bot-service/bot-service-manage-analytics?view=azure-bot-service-4.0

いちおう確認できる情報を簡単に紹介します。

ユーザのリテンション状況

チャネル別ユーザ数

チャネル別アクティビティ数

ボットにApplication Insightsを統合して分析

こちらに記載の方法でBotにApplication Insightsを統合することで、蓄積されるログからボットの利用状況を詳細に分析できるようです。

https://docs.microsoft.com/ja-jp/composer/how-to-capture-telemetry?WT.mc_id=Portal-Microsoft_Azure_BotService&tabs=v2x#analyze-bots-behavior

具体的に分析できることはこちらにまとめられています。が、これみただけでもかなり詳細な分析ができそうなことがわかります。Language側の診断ログでは回答精度に関する分析ができそうですが、こちらはユーザの体験状況を分析することに役立ちそうです。

また自分のボットでも実験した結果を更新したいと思いますが、今日はちょっと疲れてきたのでまた残りは後日・・

https://docs.microsoft.com/ja-jp/azure/bot-service/bot-builder-telemetry?view=azure-bot-service-4.0&tabs=csharp

20220417 Update:

ちょっと実装してみましたが、途中でうまくいかなくなってしまいました。MicrosoftにFeedback中なので回答をもらって随時Updateしていきたいと思います。ムズカシイ・・・

最後までご覧いただきありがとうございました!

おしまい

この記事を気に入っていただけたらシェアをお願いします!

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

ABOUT US
Yuu113
初めまして。ゆうたろうと申します。 兵庫県出身、東京でシステムエンジニアをしております。現在は主にデータ分析、機械学習を活用してビジネスモデリングに取り組んでいます。 日々学んだことや経験したことを整理していきたいと思い、ブログを始めました。旅行、カメラ、IT技術、江戸文化が大好きですので、これらについても記事にしていきたいと思っています。