Bluemix
Watson
conversation
ibmcloud
chatbot

【2019/2月更新】チャットボットを簡単に作れる!Watson Assistant(旧名: Conversation)の色々なTips(メモ)

image


記事更新のお知らせ


はじめに

石田です!お蔭様で当記事は長期間にわたり多くの皆様にアクセス頂いているようです。ありがとうございます!:blush: 当記事は前回は2018/8月に更新しましたが、早いものでもう半年が経過して、一部の記述が古くなったので、久々に記事をアップデートしました。


  • 当記事はAssistantのドキュメントから読み取った「使う上で知っておいた方が良い点、気が付いた点」などをトピック別/ランダムにご紹介したものです。全機能を網羅的にご紹介するものではありません。英語のDocumentを全部じっくり読むと、それなりに時間もかかりますので、その入口くらいの感じを目指しています。

  • レベル的には「応用編/Tips」的なものにしました。入門編の知識は「いまさら聞けない!? 簡単にチャットボットをつくれる「Watson Assistant」の基礎知識」として別記事に分離しました。はじめての方はまずは基礎知識のほうの記事をご参照ください

  • 今後も機能強化や変更があると思うので、末尾に改定履歴を付けました

  • 【凡例】:blue_book: ドキュメントへのリンク :newspaper:各種記事へのリンク

  • Watson Assistantは2018/11月現在もサーチ・スキルなど新機能のベータ中ですが、それらの内容はきちんと公開されたら別途記事に追記しますね!


まずはConversation -> Assistantで変わったこと

下記が新しいアイコンです。

image



  • 「名前が変わった+少し機能強化された」程度であり、上位互換性は保たれています. 移行などは不要ですので、ご安心ください。

  • 機能強化の詳細はRelease Noteにありますが、日本語だとIBM ソリューション・ブログ「 Watson Assistantのご紹介」の記事がまとまっています。

  • 1分でご説明するなら、目ぼしい変更/強化点は下記です



    1. :flag_us: 自動車とホテル向けのAssistantの提供 ( 日本語未対応なので関係なし )

    2. コンテンツ・カタログ(:flag_jp: 日本語もありますが、「ないよりまし」って感じ? )

    3. 脱線( Degression ) ~会話の話題が急にそれた時に、元に戻ったりする

    4. ダイアログ・フォルダー ~ フローをもっと綺麗に

    5. コンテキスト変数をUIパネルで設定可能に(JSONを直接編集しなくてもよくなった)

    6. 新しいAPIとSDKも公開(以前のものも使えますが)




さらに Watson@TokyoとAssistant on ICPも利用可能に!

もう有名ですが、2018/8月=前回の更新以降の大きい話題をいくつか。


Watson@Tokyo

image

Watson Assistantはじめ、主要なWatsonサービスが東京リージョンで利用できるようになってます。「クラウドはいいとしてもデータが国外に出るのは、、」というお客様にも敷居が低くなりました。


Watson Assistantがオンプレでも動く!( Watson on ICP )

image

従来、Watsonはクラウド上のサービスとして提供されてきましたが、Assistantを皮切りに様々なWatsonサービスがICP上で動くように提供され始めています。つまり、ファイアーウオールの内側=お客様のデータセンターでプライベートにWatsonが使えるようになりつつあります。金融や政府系のお客様など、国外やクラウドの利用が制限されている業種・業務でもWatsonをお使いただけます。(以下は私見です。残念ながら現時点ではかなり大きいICP基盤構成が必要ですので「自社内でWatsonを簡単/手軽に活用!」とはいかなそうですが、それでも大きいお客様向けには朗報かと思います。)


:loudspeaker: (2019/2) Watson Anywhere

publickey記事: :newspaper: IBM、WatsonをKubernetes対応にした「Watson Anywhere」発表。オンプレミスでもクラウドでもWatsonを実行可能に。IBM Think 2019

IBM Cloud Blog記事: :newspaper: Watson Anywhere

ちょうど今日(2019/2/13)がThink2019の初日で、上記の発表がありました。まあ、前記のWatson on ICPを新しい名前で宣伝したもの、ですね。


:loudspeaker: (2019/2) スキルのバージョン機能が正式公開に

標準でスキルのバージョニングおよび保存/復元ができるようになり、本番への反映作業が安心になります。(StandardでもPlusでもご利用いただけます)要は作業中のスキル一式のスナップショットが取れ、簡単に復元できると思ってください。本番でスキルを入れ替え・更新したい場合、従来は①エイヤで本番に対して作業 または ②独立したテスト環境を作り、そちらで更新&テスト。OKなら定義をインポート などの面倒な作業が必要でした。今回、スキルのバージョン保存ができるようになったので、本番に影響しない形でのテストや万が一の「本番戻し」がとても楽になりました。


  • 昨年、アーキテクチャー面でアシスタントとスキルが分離したので、この辺がすごく簡単になりました。スキルとアシスタントを各々複数バージョン(例えば開発・テスト・本番)持ち、それらの紐つけをUIで変えればいいいいだけ、です

  • 先日追加されたPlusプランでは標準で開発・テスト・本番の3つの環境が使えますので、当機能と非常に親和性があります

下記Mediumの記事にバージョン機能の紹介や本番反映のベスト・プラクティスが紹介されていますので、ご一読をおススメします。

Medium記事: :newspaper:Make Changes With Confidence

image

ドキュメント: :blue_book: Creating skill versions


:loudspeaker: (2019/2) サービスデスク統合

Plus&Premium限定ですが、サービスデスク用SaaSを提供されているIntercom社のサービスとの統合機能が利用可能になりました。近々ZenDesk社のサービスとの統合も予定されています。例えば以下のようなことが簡単にできるようになります。


  • フロントのWatsonから人間のエージェントへのスムースなピッチ

  • ピッチ時に顧客との対話内容の伝達(顧客に同じことを何度も言わせない)

  • 人間のエージェントが、ある程度まで進んだ対話をWatsonにピッチ

  • (キーワードではなく、顧客の意図である)トピック・ベースのエスカレーション

他にもいろいろな機能がありますが、下記Mediumの記事が詳しいです。

Medium記事: :newspaper:Customer Service Just Got Smarter

ドキュメント: :blue_book: Integrating with Intercom


:loudspeaker: (2019/2) Watson Assistantの会話品質改善のベスト・プラクティス資料

英語で恐縮ですが、2019になってAssistantの会話品質を改善するためのベスト・プラクティスのホワイトペーパーとツール(Jupyter)が公開されましたのでご紹介します。支援ツールもありますが、むしろEffectivenessとCoverageを分けて考える、PrecisonとRecallも分けて考える、段階別にアプローチする、など「ノウハウ」面で得るところが多いかと思います。英語ですがホワイトペーパーは短いものですので、ぜひお目をお通しください。

image


ではここから記事本編です。↓↓↓↓


ドキュメントに関するTips


機能強化・変更の詳細はRelease Noteにまとまっています

IBM Cloud全般にいえることですが、Watsonサービスは継続的な機能強化・変更がなされています。それらの変更はドキュメントの「Release Note」にまとまっています。


  • 新機能の追加の場合はドキュメントにAPIのバージョン(日付)が指定されており、APIで「その日付をセットしたら新機能が使える」形になっていることが多いです。(=古いAPIバージョン(日付)なら既存の振る舞いのままでアプリに影響を与えない)


できれば英語で読みましょう

ドキュメントは翻訳されており言語を選べます(デフォルトはブラウザーの言語)が、翻訳が遅れている場合も多いです。ざっくり大筋を理解する目的なら日本語で読んだほうが効率がよいでしょうが、情報は新しいほうが良いですから、ドキュメントはなるべく英語で読むことをお勧めします。特に上記の機能強化のRelease Noteは英語で読むことを強く(×10)お勧めします。

image


機能の日本語サポート状況を調べる

ドキュメント上に新機能の記述があっても(制限があれば書いてあることが多いですが)「英語のみサポートで、日本語では使えない」場合もありえます。 様々な新機能の日本語サポート状況はドキュメント「Supported languages」でご確認いただけます。


ワークスペースのTips


ワークスペースはインポート/エクスポートできます

AssistantではワークスペースのIntent/Entity/Dialogの一式がJSON形式でエクスポート/インポートできます。

- 作成したワークスペースはJSON形式でダウンロードできます

- JSON形式のファイルをアップロードして「新規にワークスペースを作る」こともできます

- 「既存のワークスペースをJSONファイルで置換する」メニューはありません。置換したい場合はワークスペースを一旦消してから上記のアップロード操作を行ってください ( 無理やりインポートした場合は同名のワークスペースが新たに作成されます)

image


デモの中身を見てみるのをお勧めします

ワークスペースにはデフォルトでCustomer Service - Sampleが作られています。営業時間や近くの店舗の問い合わせ、来店予約などのユースケースを扱う際にコンテキストの設定/複数レスポンス/システムエンティティ/フォルダーなど、様々なAssistantの機能を意識的に使っており、一通り読み解くと「ああ、こういう場合は、こうすればいいのか~」などの学びが多いかと思います。

image


  • Conversationの時代は車の運転中に口頭で様々な指示を出す「Car Dashboard」のデモだったのですが、AssistantになってCustomer Serviceのデモに変わりました。以前のCarDemoもWatson conversationのデモ・ページに残っていますしGithubでcloneできます。

image


Try it out パネル

画面の右上にあるTry it Outで、様々な対話を(クライアント・アプリケーションなしで)すぐに実行(テスト)できます。

try-it-out-400.gif


  • 応答の右側のピンのマークをクリックすると1、左側のダイアログの該当ノードが青くなり「今ここやってるよ!」と教えてくれます(=Dialog node tracing)。

try-it-out-position-400.gif


  • テストのために後述するコンテキスト変数をセットすることもできます。下記の例では応答を「いらっしゃいませ。$(customer-name) さん」としており、実際にはクライアントのアプリからコンテキスト変数にセットされた顧客名を受け取ることを想定していますが、今はアプリが無いのでパネルから一時的にセットしています。結果、きちんとそれらしい応答になっています。(未セットの場合はNULLになります)2
    image


トレーニングは自動的に起動されます

Assistantではインテントやエンティティの定義を追加変更した場合には、再トレーニングが必要です。(Dialogは変更したら即反映します/トレーニング不要です)


  • トレーニングは対話式にも実行できます。たとえば、Try it Out!でのテスト実行の結果、分類されるべきインテントが意図したものと違っていた場合には、その場で正しい意図に変更できます。

  • この変更の反映タイミングですが、Assistantとは別のスタンドアロンのWatsonサービスであるNLC(Natural Language Classifier)では自分で「再度トレーニング」する操作を行っていましたが、Assistantに搭載されているNLCでは割り当てるべきインテントを変更したらバックグラウンドで自動的にトレーニングが開始されます。(トレーニング中はその旨がパネルに表示されます)

  • 以下の例では、「パソコンが起動しません」との入力に対するインテントが意図せず「修理(#REPAIR)」に分類されてしまったので、「相談(#QUESTION)」に訂正しています。すると自動的にトレーニングが始まり、次回は期待したとおり「相談(#QUESTION)」インテントに分類されます。

change_intent_min.gif


APIでログを記録しない(オプトアウト)設定が可能

パブリック環境のデフォルトでは会話の内容はログされます3。IBMはログをサービス改善のためにのみ使いますが、ご心配があったり機密保持などの観点で問題になる場合はオプトアウトを設定できます。(これ、他社様ではできなかったりします。) 具体的にはAPIコール時にでヘダーやフラグを設定すればいいだけです。(X-Watson-Learning-Opt-Out learning_opt_out) 詳しくはAPIリファレンスをご参照ください。

:blue_book: :APIリファレンス Data collection


GDPR対応で「特定のユーザーのログを照会/削除する」機能が利用可能

:blue_book: 詳細はドキュメント「European Union General Data Protection Regulation (GDPR)」にありますが、要はアプリケーションで/message APIで会話する際のHTTPヘッダーで X-Watson-Metadata: customer_id プロパティをセットしていただける場合は、後からそのcustomer_idに紐つくログを紹介したり、まとめて削除したりできます。


インテント(Intent)のTips


Absolute ScoringとIrrelevant(「不適」)

2017/2月のアップデートで、ユーザー入力に対するインテントの確信度(スコア)の計算方法が相対的なものから絶対的なものに変更されています。今までは他のインテントとの兼ね合い・相対値として確信度のスコアを計算していましたが、今後はユーザーの入力を独立して評価・スコア算出するようになりました。当変更により


  • ①1つのユーザー入力に対して複数のインテントを返すことも可能になりました

  • ②確信度が低い入力( スコア=0.2以下 )に関しては応答として「Irrelevant(不適)」を返すようになりました。(要は「ほげ~」的な入力を撥ねることもできるようになった、ってことですね)

別の言い方をすると、今までのNLC=自然言語分類器では、どんな入力であろうと分類の結果として必ず何らかのインテントが割り当てられていたのですが、現在の振る舞いでは「不適当(Irrelevant)」=「該当インテントなし」が返る場面もありうる、ということです。なお「Irrelevant」が返った場合のユーザーへの応答はダイアログでanything_elseノードかtrueノードで救います4

:blue_book: :Absolute scoring and Mark as irrelevant

:newspaper: :Irrelevant - FEB Update - changed scorine intents - HOW TO HANLDE THIS?


コンテンツ・カタログ

Assistantでは「Content Catalog」という「サンプル集」が付きました。日本語も4パターンあります。(とはいえ、いくつかの例がインテントに追加されるだけなので、「発話とインテントの関係のニュアンスを理解するにはよいかもね」くらいの感じ5です)

image


:crown: (Plus&Premium限定) Intent Conflict Resolution

会話が複雑になりインテントの数が多くなってくると「発話」と「インテント」の関連付けで辻褄が合わなくなってくる場合がありえます。たとえば「同じような発話が異なるインテントに割り振られている場合」など。チームで作業している場合はなおさらです。Intent Conflict Resolutionはこのような「定義上の衝突」を検知してくれる機能です。以下は例ですがインテントの定義パネル上で当機能をONにすると「what do you sell(どんなものを売っているの)」という発話が競合しているよ、と教えてくれます。

image

実際に詳細を見ると、what do you sellや似たような発話が「会社に関する質問」と「商品に対する質問」の2つのインテントに割り当てられていることがわかります。対応としては「競合をしないようにいずれか(または両方)の発話を直す」ことになります。

image

:point_right: 要は「この定義、似ててぶつかっとるで~」と教えてくれます。

Youtube動画での細かい説明とマニュアルへのリンクです。

:tv: Watson Assistant - Intent Conflict Resolution

:blue_book: Resolving intent conflicts


:crown: (Plus&Premium限定) Disambiguation

Intent Conflict Resolutionは「インテントの定義時」に競合を発見するものでしたが、Disambiguation(=明確化?)は「対話の実行時」に適用できる機能です。現在のAssistantは1つの発話に対しインテントを(確信度付で)複数返す場合がありえます。仮に、ある発話に対して2つのインテントが考えられ、確信度が両方ともそれなりに高かったらどうすればよいでしょうか。今まででしたら「確信度の高いほうを選ぶ」など、なんらかの基準で1つを選択したうえで回答することになります。結果、利用者の意図と違っている可能性もあるでしょう。当機能を使うと「どちらの意図か判断に迷うときは積極的に聞き返す」ことができるようになります。(「判断に迷うとき」の条件はドキュメントに細かい記述があります)

以下の例ではピザの注文アプリにてお客様が「ペパロニはありますか ?( Do you have pepparoni ?) 」と聞いていますが、お客様の意図は ①単にメニューの種類を聞いているだけ ②ペパロニのピザを注文したい のどちらか、わかりません。そこで「有無をわかればいいだけですか、注文したいのですか?」と対話式に選択肢を聞いています。(ここの選択肢の表現も設定可能です)

image

:point_right: 要は「どっちの意味やねん」と聞き返せます。

Youtube動画での細かい説明とマニュアルへのリンクです。

:tv: Watson Assistant - Disambiguation

:blue_book: Disambiguation


:crown: (Plus&Premium限定) Intent Recommendations

image

(2018/11/28) Plusプランで「Intent Recommendations」という機能がでました。(「Entity Recommendations」と紛らわしいですが、別ものです) 現在は:flag_us:英語のみ&ベータです。

Youtubeの紹介動画がありますが、要はコールセンターのログなどの「ユーザーの発話」が記録されているCSVファイルをアップロードすると、当該インテントに割り当てる「実際の文例」をお勧めしてくれるものです。(=「こんなインテントがいいんじゃない」ではなくて、「このインテントにはこの例文を使うといいんじゃない」ってこと)実際の発話を簡単に例文に取り込めるのがミソかと。


エンティティ(Entity)のTips


正規表現でのパターン抽出ができます

値のみならず、正規表現でのマッチングによるエンティティの抽出ができます。以下の例では電話番号とメアドが抽出されていますね。

image

:blue_book: :Defining entities


間違い(ミススペル)があっても一致(あいまい一致:Fuzzy Matching)

エンティティの抽出時にあいまい一致(Fuzzy Matching)が使えます。英語:flag_us:ではミススペル、ステミング、部分一致などが対象ですが、日本語:flag_jp:ではミススペルのみベータとしてサポートしてます。日本語でのミススペルってどうなのかな?と思いやってみたのですが

image

以下のような結果でした。(仕様として書いてあるわけではないです)

- 当然ながらFuzzy Matching OFFの時は正確に一致しないとヒットしません

一文字でも違ってたら、駄目です。

- ONの時一文字の違い(不足、多い、間違い)は許容され、ヒットします。しかし二文字の違いは、だめのようです。(まあ妥当な仕様と思います)

ケース
指定
結果

一文字少ない
ダックフンド

@animal:犬

一文字違う
ダックスンド

@animal:犬

一文字多い
ダックスフンド

@animal:犬

二文字少ない
ダクフンド
ヒットせず

二文字違う
ダックスラシ
ヒットせず

二文字多い
ダックス**スフ**フンド

@animal:犬


  • 正解「イヌ」に対する「イ」など、あまりに短い場合はヒットしません

image

:blue_book: :Creating entities


:new::flag_us: Entity Recommendations

(2018/07/12機能追加) 現時点は英語のみ:flag_us:ですが、エンティティの同義語を提案してくれるEntity Recommendationsが使えるようになりました。エンティティ定義画面で「Show Recommendations」ボタンを押すと候補を提示してくれるので、選択します。以下の例では肉の種類に「チキン」を設定した場合のシノニム候補を表示し、「hends」と「birds」を選択しています。

entity_recommends_03.gif

:blue_book: Synonyms


:new::flag_us: (Beta) Contexual Entity

(2018/07/12機能追加) 現時点は英語のみ:flag_us:かつベータですが、エンティティの定義を発話(文脈)の中の使われかた(単語の位置? )から導き出すContexual Entityが使えるようになりました。具体的にはIntentの定義分で「ここはエンティティだよ!」とアノテートしていくと、エンティティの定義ができあがるというものです。単語ではなく文脈(位置?)でエンティティを指定できる点が新しいです。以下の例ではインテントの入力となる文章群で「フライトでの行き先(@destination)はここだよ!」とマークを付けて教えています。すると自動的に@destinationのエンティティの定義が作られます。その後「Ticket to London, please」と発話すると、「London」という単語がエンティティのシノニムには未登録にもかかわらず、きちんと@destinationとして認識されています。

contextual_entity_05.gif


ダイアログ(dialog)のTips


会話の始まりは welcome で

新規にダイアログを作成するとデフォルトで会話の始まりである「ようこそ(welcome)」と、どこにも割り当てられなかった入力を救うための「その他(anything_else)」というノードが自動的に作成されます。「ようこそ」ノードでは会話の開始(例. ようこそ!など)やコンテキスト変数の初期化を設定できます。(会話の始まりは「挨拶」をするタイミングなので勿論あったほうがよいでしょうが「必須」ではありません。無ければ無いで構いません。)

image

※「welcome」や「anything_else」はAssistantが用意している「Special condition」という事前に定義された条件の一種です。「welcome」とは別に「conversation_start」というSpecial conditionもあります。両者は「会話の始まりで使う」という意味でほぼ同じと思っていただいてよいですが、少しだけ違いがあります。詳しくはドキュメントを。


「何もヒットしない」入力=最後は anything_elseノードかtrueで救う

image

トップ・レベル(一番左)の末尾のノードとして、anything_else条件が設定されたノードが自動的に作られます。ノードの条件の評価は上から&左から順番に評価されますが、条件にまったくマッチしなかった場合の対話はこの anything_elseのノードか、または条件としてtrueを指定したノード(何でも真になる=何でもアリ)で救います。anything_elseとtrueはいずれも意味は同じなのでしょうが、デモのサンプルなど見るとトップレベルはanything_else、それより下のレベルではtrueのほうを使っているようでした) ご参考までに(そんなことはしないと思いますが)これらの「何もヒットしない場合を救うノード」は必須ではありません。意図的に書かなかったり手で削除してしまうことも可能ですが、その場合はクライアントにレスポンスが何も返りません。その状態で改めてユーザー入力が入ってくると、トップレベルの場合はそのまま再度評価が実行されます。第二レベルより下の層ではいったん上のレベルに戻ってから再度評価が実行されます。(※)いずれにしても全体の制御が失われてハングしまうわけではありませんのでご安心ください。


制御のジャンプ( Jump To )

対話の流れ上、別のノードに制御を移したい場合には「 Jump To..」でジャンプ先のノードを指定できます。ジャンプ先のノードには条件(Condition)のパートとレスポンスのパートがありますが、そのどちらから継続するのかも指定できます。要はgo toだと思えばよいでしょう。

定義としては以下の2か所のいずれかでJumpしたい旨を指定します。

image

「ジャンプ先のノードを選択してね」と表示されるので、飛びたい先のノードをクリックします。するとノード中のジャンプ先の候補が表示されるので、選択すればオーケーです。簡単です。

image

以下はジャンプ先で条件の評価をせずにレスポンスだけ返す場合の例です。パソコンの修理相談が終わって、相談のお礼~改めて別の相談を開始するシナリオです。結びの挨拶から再開の流れは各ノードに逐一書くのではなくて、共通的に処理したほうが何かと便利かと思いclosingというノードを作りました。右側は実際の対話とレスポンスです。Jump Toの流れに沿ってレスポンスが順次出力されていますね?

image


Skip User Inputって何するもの?

新しくSkip User InputというJump方式が追加されています。

image

これ、ドキュメントには


when the node is configured to skip user input, it is equivalent to forcing the dialog to process the first child node after the current node in succession.


とあり、「強制的に最初の子のノードに制御がわたる6」ことはわかるのですが、使い道がいまいちわかりません。でCustomer-Serviceのサンプルを見たら、わかりました。

image

サンプルではオフィスヘの道案内をしていますが、顧客が発話で「今、タイムズスクエアにいるんだけど、ここからどういけばいいの?」と「今いる場所」を言った場合は、現ノードの応答として、その場所からの道筋を示した後で、子ノードに飛んで実際のオフィスの場所を案内しています。「今いる場所」を言わなかった場合は、何もせず即座に子ノードに飛び同様にオフィスの場所を案内します。このように「最終的には言うことは同じなのだけど、その前にオプション的に何か付け加えて言いたい」場合に使えるのですね。


制御のジャンプ( Jump To )とWait for User input

実はJump to..にはもうひとつ、Wait for User Inputというモードがあります。前の2つ(条件と応答)はGOTO文として制御が飛んでそのまま評価・実行されますが、Wait for User Inputの場合はいったんユーザーに応答し、その回答をもらってから改めて処理を継続する、という流れになります。例えば、何か処理を進めるに際して「これでよろしいですか?」と確認するような場面が考えられます。

実は私自身も操作含め、ちょっと混乱したのでこの辺を整理します。

まず、ノードの末尾の表示ですが、ここは機能としては「Jumpするか、しないか」の意味しかありません。


  • And then Wait for user input(左)はデフォルトの振る舞いで、レスポンスを返して次のユーザー入力を待ちます。次回はこのノードを起点に評価が始まります。

  • And Then Jump to .. の場合は勿論制御がJumpします。

image

前述の通り、Jump先のノードを選ぶと以下の3つの選択肢が表示されます。

image

以下は②条件(If bot recognizes(condition))と③Respondの場合の動きです。各々、指定された箇所に制御が移り、あとは中断なく処理が進む点は既にご紹介しました。

image

翻って以下が①Wait for user inputの場合の動きです。Jump元で設定したレスポンス(普通は質問)が一旦ユーザーに返されます。ユーザーが入力すると、その入力に応じて②条件(If bot recognizes(condition)の判断から処理が再開する流れになります。

image


ノードから外部のサービスを呼び出せます

ノードのJSONエディターで”actions"の構文を書いて、外部の(REST)サービスを呼び出し、結果を入手できます。呼び出し方法は(TYPE) は①Client ②Serverの二通り。①は通常のRESTFUL Webサービスの呼び出し、②はIBM Cloud Functionsを介した呼び出しです。

image

下図はドキュメントからの転載ですが、①Clientの場合のフローです。ちとややこしいですね。クライアント側のアプリとの取り決めが多くなりそうで、複雑です。

image

以下は②Cloud Functionsを使う場合ですが、こちらのほうが直感的で良いように思います。

:warning: 現時点(2018/7)でこれが使えるのは米国南部とドイツのみ。またAssistantとCloud Functionsは同一ロケーションである必要があります。

image

:blue_book: :Making programmatic calls from a dialog node

:newspaper: :@schiyodaさんのQiita記事「Watson Assistant から IBM Cloud Functions の Action を呼び出す方法


ユーザーに複数のことを聞きたいときに- スロット

スロット(slot filling)とは何でしょうか。以下のドキュメントの先頭にあるYouTube動画(6分)を見ていただくのが一番オススメですが、ここでは「何をするものか」だけご紹介します。

:tv: Gathering information with slots

シナリオとしてレストランの予約ボットを考えます。お客様からの予約を正しく受けるには最低でも ①人数 ②来店日 ③来店時間 を聞かなくてはなりませんよね。お客様がチャットで必ずこの3つを一度に伝えてくれればいいのですが、そうはうまくいきません。「x月x日に予約したい」と言われれば、来店日はわかりますが、追加で人数と来店時間を聞かなくてはなりません。要は「お客様が何と言われるか」によって「追加で何を聞くべきか」が変わってくるわけですが、お客様の表現の全ての組合せをダイアログのフローで拾うように実装するのはかなり煩雑です。これを簡単に1ノードで実装できるのがスロット機能です。「スロット」の本来の意味は「溝(みぞ), 細長い小さい穴」だそうですが、要は「スロット・マシーン」のように3つの値が揃ったら予約完了!という感じですかね。

image

なおスロット機能はノードに対して設定しますが、デフォルトでは無効になっていますので、使う場合は右上の「Customize」で明示的に有効にする必要があります。詳しくは下記の@schiyodaさんの記事がオススメです。前述のような場面の実装がとても楽になりますよ!

image

:newspaper: :@schiyodaさんのQiita記事「Watson Assistantのスロット機能の使い方

:blue_book: :Gathering information with slots


レスポンスのTips


レスポンス(response)のエスケープ

レスポンスはJSON形式ですが、レスポンスの出力中に予約文字 (#, @, $), クオート、改行文字( carriage returns, line feeds) タブなどの文字がある場合は、直前にエスケープ文字 バックスラッシュ())を置きます。また、レスポンスのテキスト中に以下のようにエスケープしたhtmlのリンクを埋め込むことで、ユーザーにURLを提示することもできます。なお、ダイアログのエディターから入力する場合はHTML中のダブル・クオートのエスケープは自動的に行われます。

image

JSONをご自身で直に書く場合はエスケープが必要です。もしエスケープに問題があればJSONエディター編集中に以下のようにエラーになるので、気が付きます

image

URLの埋め込みはTry it Outでも7、クライアントのWebアプリでも、HTMLとして処理すれば正しくリンクとして表示されます。

image


:new: リッチ・レスポンス

(2018/07/12機能追加) レスポンスで、テキストだけでなくイメージ(image)や選択肢(Option)なども返せるようになりました。以下のようにパネルで設定できますしTry it outでテストできます。

image


  • 上記の例のように複数のレスポンスを連結して書くこともできます

  • 選択肢(Option)の場合は、ひとつを選択すると対応するValueの値で発話が発生したものとみなされ、処理が継続されます

  • 外部のFunctionsを呼び出した際の処理待ちのために「pause」も設定できます

:blue_book: Rich Responses


回答のバリエーション

ボットの回答がいつも同じ物言いでは、つまりませんよね。Assistantでは問いかけに対するレスポンスの文言を複数登録しておけば、色々な言いかたで回答できます。以下の例では挨拶に対して3種類のレスポンスを登録しています。それらの提示の順番も①sequential ②randomのいずれかを下部のスイッチで切り替えられます。

image


1ノード内で条件により複数のレスポンスを出しわけ

ユーザーの入力を処理する際には、複数のノードを組み合わせてややこしく判定せずとも、1ノード内で複数の条件を記述し、各々で異なるレスポンスを返せます2ので、フローがシンプルになります。


  • 1ノード内にレスポンスを複数書けます

  • 各々のレスポンスに条件を書けます

  • ノードの末尾以外に、各々のレスポンスにもJump Toを書けます

:warning: 複数レスポンスを許可するにはノード毎に右上の「Customise」パネルを開いて明示的に許可する設定が必要です。デフォルトでは複数レスポンスは利用できない(OFF)ようになっています。

image

この方法はCar Dashboardのデモでも多用しています。Multiple conditioned responsesに2分弱の動画があるのでそれを見ていただくとご理解が進みますが、以下はサマリーです。

以下の例ではユーザーの「止めて」との指示での様々なエンティティの言いかたに関して、1ノード中でまとめて別々のレスポンスを返しています。Try it outでの結果と突き合わせてみてください。

image

なお「条件付レスポンス」からもJump toが使えるようになっています。


脱線( Digressions )

Assistantになってからの新機能です。会話の最中に現在の文脈と関係の無い発話が行われた場合に、いったん横道に逸れてから元に戻ってくることができます。わかりやすく言うなら「ああ、そういえば」と言われた時の話です。たとえばピザの注文中でサイズとトッピングを聞いているときに、急に「トッピングは何があるの?」とか「お店は何時まで開いてる?」とか聞かれた場合に、現在のノードからいったんFAQを扱うノードに制御を移し、回答してから戻ってきて注文のフローを継続する、といった使い方ができます。くわしくは下記の記事が参考になります。

:newspaper: :@schiyodaさんのQiita記事「Watson Assistant の Digressions(脱線)機能の使い方

:blue_book: :Digressions


会話のステート保持に関するTips


Assistantは本来はステートレスなサービス

image

Assistantはステートレスなサービスであり、会話の状態を保持しません。ステート(State=状態)とは、通常のWebアプリケーションと同じ概念です。チャットボットのような会話アプリは発話-応答のペアを何度もやりとりして会話が進みますが、Assistant本体は発話-応答の1ペアのやりとり(=ターン(Turn)と呼びます) で処理が完結し、以前のこと(ステート)は一切記憶(記録)しません。つまり「ログインの状態」とか「さっき聞いたお客様の名前」とかは次回のターンでは何も覚えていないのです。ITインフラの観点ではステートレスなデザインにすることでスケーラビリティや高可用性を確保しやすくなるのでいいのですが、業務的には対話が成り立たないので困りますよね。。そこで「じゃ、Assistant側は何も覚えなくていいけど、対話で聞いたことをメモして、毎回やりとりすればいじゃん」という考えが出てきます。このメモに該当するのが「コンテキスト変数」です。


コンテキスト変数( Context Variables )で状態を保持

image

上図のようにお互いがコンテキスト変数に記憶しておきたい内容をセットして毎回やりとりすることで、Assistantをステートレスに保ちながら会話内容に継続性を持たすことができます。具体的にはAssistantのAPIにはコンテキスト用の領域がありますので、クライアントとなるアプリケーションとAssistantは、そこにJSON形式でデータをセットし、その領域を介してステートを保持します。(APIでcontextをセットして送り返すのはクライアントとなるアプリケーション側の責任です)

・コンテキスト変数はmessageのAPIにも含まれています。

・ノード中で利用する場合は接頭子 「\$」を付けます。(例. $(customer_name) )

:blue_book: :Context variables

以下の例では会話の開始時のPOSTリクエストのcontextフィールド経由で顧客名と前回コンタクト日を渡し、応答では受け取った値を使って応答します。たとえばCRMなど外部のシステムからデータを取ってきて、対話に利用するようなシナリオで使えますね。

★welcomeのテキスト

image

★message APIで渡すJSON構造(node.jsの場合)

image

image

★実行結果 コンテキスト変数に値がセットされています。

image

また、Car Dashboardデモではこんな風にコンテキスト変数をbooleanにして、条件でそのまま使うような使いかたもありました。なるほど~。

image


  • コンテキスト変数はクライアント・アプリケーションとの間だけでなく、Dialogのノード間でjump等で制御の流れがかわる場合のデータのやりとりにも利用できます。(例. あるノードで名前を聞いてコンテキスト変数にセットし、Jump先では呼びかけに使うなど)

:triangular_flag_on_post: (2019/2月) Assistantのアーキテクチャー変更(AssistantとSkillの分離)に伴い、コンテキストの扱いもAPI V1/V2で変わっています。要はV2ではコンテキストをアプリが毎回送り返さなくてもいいようになりました。この辺の話は記事 :newspaper:Watson Assistant API V1/V2の違い」をご参照ください。


コンテキスト変数を設定するエディターが出ました

Dialogのノードでコンテキスト変数を操作する場合、従来のJSONエディター以外にAssistantになってコンテキスト・エディター8が出ました。JSONエディターは後述する”action"などコンテキスト変数以外にも出番がありますが、コンテキスト変数を編集する目的ならContext Editorのほうがパネルで設定できるので使いやすいです。

image


エンティティの値をコンテキスト変数にセットする

前項の例のようにクライアント・アプリケーションからコンテキスト変数が渡されるなら、応答中では$(変数名)で参照すればいいだけですが、発話からエンティティの値を抜いてコンテキスト変数に保管して、応答で使いたいときもあるでしょう。その場合のValueの書き方の例をお示しします。

下記のように@animalエンティティがSynonymsで定義されています。ここでコンテキスト・エディターにどう書くと何が抽出できるか、ですが

image

@animal」のようにエンティティ名だけを書いた場合(左側)は、発話がシノニムでヒットしても、「鳥」という「値(Entity Values)」が返ります。「@animal.literal」のようにエンティティ名.literalと書いた場合(右側)は、発話がシノニムでヒットした場合、シノニムの値が返ります。

image

なお、エンティティをパターンで定義した場合は .literalを書かないと値が取れませんのでご注意ください。

image

:blue_book: :Common context variable tasks


Spring Expression Language (SpEL) のTips

上記のコンテキスト変数の表現はjsonですが、ノード中ではSpring Expression (SpEL) languageが利用できます。たとえばカウンターを保持してカウントアップする、条件により変数の値を変える、などの処理も行えます。(Assistantのコンテキストで使う時は <? ~ ?>で囲むと「その中に書かれている式を改めて評価しろ」という意味になります。)

以下の例ではノード内でリトライのカウント(retry_count)を+1したり、リトライの回数が3回以上になったらオペレーター呼び出しのフラグ(call_operator_flag)をONにする、などの操作をしています。SpELでは他にも色々な表現ができるようなので、「こんなことをしたい」というのがあればSpELのドキュメントを見てみるとよいかもしれません。

image


ノードでの変数の参照

ダイアログのノード中ではコンテキスト変数以外にエンティティの値を参照し、条件で指定できます。たとえば「入力テキストにエンティティの指定があるか(有無)」「入力テキストにエンティティがあり、その値は何か」など。以下にノードの条件での表記方法をまとめます。

対象
冒頭の記号
形式
表記例(いずれか)

Entityあり
@
@entity_name
@appliance

Entityのあり
@

@entity_name:value

@appliance:radio

@

@entity_name(value)

@appliance(radio)

@

@entity_name == 'value'

@appliance == 'air conditioner'

Context
$
context.variable_name
context.customer_name

$
$variable_name
$customer_name

$
$variable_name == 'value'
$variable_name == 'value'

Car Dashboardデモの例ではユーザーの希望する音楽のジャンルが@genreエンティティの値が"rock"にセットされ、その値をレスポンス内の埋め込みに利用しています。

image


レスポンスの確信度(confidence)の判定

記事の前半で「最新のNLCはインテントとしてIrrelevant(不適)を返すことがある」とご紹介しました。Irrelevant(不適)かどうかの判断のスコアのしきい値は0.2で固定であり、結構低めです。つまり、あまりに外した質問は撥ねられるとしても「絶対間違いない」スコアとの間に「ビミョー」な領域が残ります。ユーザーからの問いかけに対して、あまりにハズした回答は好ましくないので、NLCが応答内容に自信が無いようなら(=NLCの分類結果の確信度が x%以下だったら)、「ユーザーに別の言い方をするようにお願いする」とか「改めて内部的にDiscoveryを呼び出して、そちらの応答を使う」などのシナリオが考えられます。この場合の実装方法ですが、AssistantのAPIのResponseにはintentsのフィールドがあります。ここのconfidenceをクライアントのアプリケーションでチェックすることで、振る舞いを変えることができます。

image

注:この例ではIntentは1つですが、Intent*s*と複数形になっているように、複数のIntentのArrayであり、候補が複数返る可能性がある点にご注意ください

ノードの条件にconfidenceを追加することも可能です。この場合はIntentが決まっても、指定した確信度の閾値以下の場合には条件にヒットしません。

例) ~ and intents[0].confidence >= 0.XX

以下の例では「スマホについて聞いてもいい?」との問いかけで「hello」という意味のないインテントになってしまっています。(確信度は0.76)

image

ここで「#hello」に対して「確信度が0.8以上であること」との条件を追加指定すると、#helloのノードにはヒットしなくなり、anything_elseに落ちることで再度の入力を促しています。

image

ついでですが、条件にエンティティを書いていて&fuzzy matchingを使うときは確信度0.3以上でないとヒットしないそうです。


The confidence of an entity is either 0 or 1, unless you have activated fuzzy matching of entities. When fuzzy matching is enabled, the default confidence level threshold is 0.3.



基盤/インフラ的なTips


:loudspeaker: (2019/2) APIの認証はIAMベースに変更されました

認証に関し、今まではuserid/passwordでしたが、現在は全リージョンでIAMのAPIKEYを使う方法がデフォルトになっています。まだUserid/Passwordの認証をお使いのお客様は2019/10/30までに移行してください。記事 :newspaper: 【重要】従来型(古い)Watsonインスタンスをお使いの方は来年(2019)の10/30までに新しい環境に移行しないと、たぶん死にますのでご注意を!


Assistant向けの新しいSDKとAPI

従来のConversationのAPIも引き続き動きますが、新しいAPI/SDKも出ています。

image

:blue_book: 旧: Watson Assistant API V1

:orange_book: 新: Watson Assistant API V2

:blue_book: 旧: Watson Conversation API 削除済み


SlackやFB Messengerとの統合は簡単です

SlackやFacebook Messengerなどの既存サービスをAssistantのチャットUIとして簡単に統合できます。具体的な方法をネットで検索すると「いったい、どの方法がいいの!」という位あれこれ記事が出てきますが、要はSlackなど既存サービスのWebhookを活用して連携する方法であり、具体的には ①IBM提供のBotkitを使う方法(別途、統合のためにNode.jsが必要) ② IBM Cloud Functions(=Apache OpenWhisk)を使う方法 のどちらかの方法になると思います。Assistantでは「Deploy」のパネルで方法をご覧いただけます。

image

:newspaper: :@schiyodaさんのQiita記事「Watson Assistant の ユーザー・インターフェースに Slack を使用する

:newspaper: :@schiyodaさんのQiita記事「Watson Assistant の ユーザー・インターフェースに Facebook Messenger を使用する

:blue_book: : Deploying to a channel with the Conversation connector


Discoveryとの統合

image

チャットボットの拡張として、ロングテールな質問に対応するためにDiscoveryとの統合も考えられます。要は「8:2の法則」を意識して、

① よくある8割のFAQはAssistantで対応する

② あまり頻繁ではない2割のロングテールの質問はDiscoveryで対応する

ようなデザインです。アイデアの肝は 発話に対するインテントの確信度などを基準にして、「Assistantで答えられない場合は、Discoveryに回す」ことです。実装はフロントのアプリでやってもよいですし、前述のCloud Functionsで統合することもできます。考慮点としては「ロングテールな質問の答えを、利用者にどのように提示するか」があります。というのもAssistantは基本的に「チャット会話」ですが、Discoveryは「文書の検索」だからです。口語体でチャット会話している最中に、急に硬く長い文章が表示されたら、驚きますよね。ので「生憎ぴったりの回答が無いのですが、ご参考までに文献をお示ししますね」と言ってDiscoveryの検索結果候補を提示する、などなんらかの工夫をしたほうがよろしいでしょう。


:loudspeaker: (2019/2) サーチ・スキル(Discivery統合)

image

まだ限定ベータですが、Watson Discoveryと簡単に統合できる「サーチ・スキル」が近々出てくるようです。上のようにDiscivery側のメタデータで認識しているフィールドをAssistant側でマッピングしておくと、質問をDiscoveryで検索の上、該当フィールドの値をリスト形式で表示してくれます。

image

従来のダイアログのスキルとは別に「サーチ」のスキルができ、アシスタントはサーチスキルを使うよう構成できます。

最終的にどのような形でGAするかはわかりませんが、以下のシナリオで、自分でCloud Functionとかで統合しなくても済むのはありがたいですね。


User Conversationパネル

ユーザーとの対話の内容を記録・集計・検索するパネルが付きました。現状の分析や会話精度の改善に使えます。

【Overview】

image

【個別の会話内容】

image


  • ログの保存期間はレベルに応じて7/30/90日だそうです

  • 当ツールからは生ログをダウンロードできませんが、LOG APIをcurlで叩けばJSON形式で簡単に手に入ります。


GDPR対応のための新機能

GDPRの「希望があれば顧客の情報を削除する」に対応するために ①顧客のタグ付け(Customer tagging=APIに顧客のIDを追加) ②タグを指定して顧客のログを消す(The ability to delete a customer’s logs based on their label) ことができるようになりました。当機能はオプションであって自動的に適用されるものではない点にはご注意ください。

:newspaper: New Watson Assistant updates to provide GDPR support

:blue_book: https://console.bluemix.net/docs/services/conversation/information-security.html


おまけ

Niklas HeidloffさんがBlogでAssistant関連のツールを公開してくれています。いずれもGitHub上のオープンソースです。①"Deploy to Bluemix"ボタン押して②Conversationのインスタンスをbindして③ツール起動後のUIで対象のワークスペースを選択するだけで普通に動きました。便利かも。。。

:newspaper: : Introducing the Conversation Inspector for IBM Watson

Conversationのクライアント。指定したワークスペースとやりとりして通信内容(JSON)を表示してくれます。

image

:newspaper: :Introducing the Conversation Optimizer for IBM Watson

ConversationのログAPIを叩いてログを入手し、エラーや確信度の低いインテントなどをリストしてくれる。前述の「User Conversation」パネルみたいなもの。

image


各種リソースのご紹介


:blue_book: ドキュメント


:newspaper: ブログ記事


:tv: 動画やデモ


:clipboard: 改定履歴


日付
変更内容

1.0
2018-06-26
初版公開

1.1
2018-07-12

July 12, 2018 機能追加の反映

1.2
2018-08-14
2018/08/06付のIntent Conflict ResolutionとDisambiguationの紹介を追記

1.3
2018-11-28
Plusプラン+Watson@Tokyo Watson on ICPを追記





  1. 以前は対応するノードが自動的に青く表示されていましたが、クリックしたら表示するように変わったようです 



  2. なお日本語環境で$timezoneが"Asia/Seoul"になっていますが、東京とソウルは時差がありませんので問題ありません。ここを別の都市に変えると「現在時刻」が変わります。 



  3. 当然ですがパブリックな共用環境であっても、他人様のログは見えませんのでご安心ください。 



  4. 例えば、「申し訳ありませんが解釈できませんでした。お手数ですが違う言い方で試してみていただけますか。」などど返事することが考えられます 



  5. EntityもDialogもありませんので、これならサンプルをじっくり読み解いたほうがいいような気もしました。 



  6. 従来の"Jump_to_next"と同類です 



  7. 以前はTry-it-outではURLがそのままテキストとして表示されていましたが、改善されました 



  8. 以前はJSONエディターしかありませんでしたので直に編集してました 



  • ドキュメントに関するTips
  • ワークスペースのTips
  • インテント(Intent)のTips
  • エンティティ(Entity)のTips
  • ダイアログ(dialog)のTips
  • レスポンスのTips
  • 会話のステート保持に関するTips
  • Spring Expression Language (SpEL) のTips
  • 基盤/インフラ的なTips
  • おまけ
  • 各種リソースのご紹介
  • :clipboard: 改定履歴