Microsoft Bot Framework の基礎

この記事の対象: SDK v4

ボットとは、テキスト、グラフィックス (カード、画像など)、または音声を使用してユーザーが会話形式で対話するアプリです。 Azure AI Bot Service はクラウド プラットフォームです。 ボットをホストし、Microsoft Teams、Facebook、Slack などのチャンネルで利用できるようにします。

ボットに接続されたユーザーのアプリとボットとの間でやり取りされる情報は、Azure Bot Service のコンポーネントである Bot Framework Service によって送信されます。 それらによって送信されるアクティビティには、それぞれのチャンネルによって付加的な情報が追加される場合があります。 ボットを作成する前に、ユーザーと通信するためにアクティビティ オブジェクトがボットでどのように使用されているかを理解しておくことが大切です。

この図では、 会話の更新メッセージの 2 つのアクティビティの種類を示しています。これは、ユーザーがエコー ボットと通信するときに交換される可能性があります。

activity diagram

会話の更新は、当事者が会話に参加したときに Bot Framework サービスによって送信されます。 たとえば、Bot Framework Emulator による会話の開始時には、(会話に参加するユーザーとボットに 1 つずつ) 会話の更新アクティビティが 2 つ生じる場合があります。 これらの会話の更新アクティビティを見分けるには、アクティビティの追加されたメンバープロパティに誰が含まれているかを確認します。

メッセージアクティビティは、当事者間の会話情報を伝達します。 エコー ボットの例では、メッセージ アクティビティによって単純なテキストが伝達され、そのテキストがチャネルによってレンダリングされます。 また、メッセージ アクティビティでは、読み上げられるテキスト、推奨されるアクション、または表示されるカードが伝達される場合があります。

ヒント

Bot Framework プロトコルの実装は各チャンネルに依存しており、各チャンネルの実装方法は少し異なる場合があります。 たとえば、あるチャンネルでは最初に会話更新アクティビティを送信し、別のチャンネルでは第 1 メッセージ アクティビティを送信した後に会話更新アクティビティを送信します。 あるチャンネルには、1 度の会話更新アクティビティにボットとユーザーの両方が含まれる場合があり、別のチャンネルでは 2 つの会話更新アクティビティを送信する場合があります。

この例では、インバウンド メッセージ アクティビティに応じるメッセージ アクティビティがボットによって作成され、送信されました。 しかし、受信されたメッセージ アクティビティに対するボットの応答には、他にもさまざまな形態が考えられます。たとえば、会話の更新アクティビティに対し、何らかのウェルカム テキストを含むメッセージ アクティビティを送信することによってボットが応答することもよくあることです。 詳細については、ようこそ! ユーザー様を参照してください。

Bot Framework SDK

Bot Framework SDK を使用すると、Azure AI Bot Service でホストできるボットを構築できます。 このサービスでは、ボットとチャンネルまたはユーザーが対話する方法について、REST API とアクティビティ プロトコルを定義します。 SDK は、この REST API に基づいて構築され、会話ロジックに集中できるようにサービスを抽象化します。 SDK を使用するために REST サービスについて理解する必要はありませんが、機能の幾つかについて知っておくと役立つことでしょう。

ボットは、会話型インターフェイスを搭載したアプリです。 もう人が直接介入する必要がないような、ディナーの予約やプロファイル情報の収集などの繰り返し発生する単純なタスクを自動化されたシステムに移行するために使用できます。 ユーザーは、テキスト、インタラクティブ カード、および音声を使ってボットと会話します。 ボットとの対話では、簡単な質問と回答や、サービスへのアクセスをインテリジェントに提供する洗練された会話などが可能です。

Note

SDK と REST API から提供される機能のサポートは、チャンネルごとに異なります。 Bot Framework Emulator を使用してボットをテストできますが、ボットを使用するチャンネルごとに、ボットのすべての機能をテストする必要もあります。

対話には、順番に処理されるアクティビティの交換が含まれます。

アクティビティ

ユーザー (またはチャンネル) とボットとの間の対話はすべて、アクティビティとして表されます。 Bot Framework アクティビティ スキーマは、ユーザーまたはチャンネルとボットとの間で交換できるアクティビティを定義します。 アクティビティは、人間が作成したテキストや音声、アプリ間の通知、他のメッセージに対する反応などです。

ターン

人が会話するときは、通常、代わる代わる順番に話します。 ボットの場合、一般的には、ボットがユーザー入力に反応します。 Bot Framework SDK では、"ターン" は、ボットがユーザーから受信するアクティビティと、ボットが即時応答としてユーザーに送り返すアクティビティで構成されています。 ターンは、特定のアクティビティの受信に関連付けられた処理として考えることができます。

たとえば、ユーザーがボットに何らかのタスクを実行するように求める場合があります。 ボットは、タスクの詳細情報を取得するための質問で応答する場合があります。この時点で、このターンは終了します。 次のターンで、ボットは、ボットの質問に対する回答を含んでいる可能性のある新しいメッセージをユーザーから受信します。あるいは、テーマの変更や、タスクを実行するための最初の要求を無視する要求を表す場合もあります。

ボット アプリケーションの構造

SDK は、ボット アプリの会話の理由を処理するボット クラスを定義します。 ボット クラス:

  • ユーザーの入力を認識して解釈します。
  • 入力に関する理由を推論し、関連するタスクを実行します。
  • ボットが実行していることや、完了したことに関する応答を生成します。

SDK では、チャンネルとの接続を処理するアダプタークラスも定義されています。 アダプターの特長は以下のとおりです。

  • ユーザーのチャンネルとの間で要求を処理するメソッドと、要求を生成するメソッドを提供します。
  • ボットのターン ハンドラーの外部でのターン処理を伴う、ミドルウェア パイプラインが含まれています。
  • ボットのターン ハンドラーを呼び出し、ターン ハンドラーで処理されないエラーをキャッチします。

さらに、ボットは、ターンごとに状態を取得して格納する必要がある場合が多いです。 状態は、ストレージボットの状態プロパティ アクセサー クラスによって処理されます。 SDK は組み込みのストレージを提供しませんが、ストレージの抽象化とストレージ レイヤーの実装のいくつかを提供します。 状態の管理に関するトピックでは、これらの状態とストレージの機能について説明します。

A bot has connectivity and reasoning elements, and an abstraction for state

SDK では、Web 要求の送受信に特定のアプリケーション レイヤーを使用する必要はありません。 Bot Framework には、ASP.NET (C#)、restify (JavaScript)、 aiohttp (Python) 用のテンプレートとサンプルがあります。 ただし、アプリに別のアプリケーション レイヤーを使用することもできます。

SDK を使用してボットを作成する場合には、HTTP トラフィックを受信して、これをアダプターに転送するコードを指定します。 Bot Framework には、独自のボットの開発に使用できるテンプレートとサンプルがいくつか用意されています。

Note

Bot Framework JavaScript SDK、C#、Python SDK は引き続きサポートされますが、Java SDK については、最終的な長期サポートは 2023 年 11 月に終了する予定です。 このリポジトリ内の重要なセキュリティとバグの修正のみが行われます。

Java SDK を使用して構築された既存のボットは引き続き機能します。

新しいボットの構築については、Power Virtual Agents の使用を検討し、適切なチャットボット ソリューションの選択についてお読みください。

詳細については、「The future of bot building」をご覧ください。

ボット ロジック

ボット オブジェクトには、ターン用の会話の推論またはロジックが含まれ、ターン ハンドラーが公開されます。このターン ハンドラーは、ボット アダプターからの受信アクティビティを受け入れるメソッドです。

SDK には、ボット ロジックを管理するための異なるパラダイムがいくつか用意されています。

  • アクティビティ ハンドラーは、受信アクティビティの種類とサブタイプがイベントであるイベント ドリブン モデルを提供します。 ユーザーとの限られた短時間の操作を行うボットのアクティビティ ハンドラーについて考えてみましょう。
    • アクティビティ ハンドラーを使用して、ボットが認識、反応するアクティビティの種類やサブタイプごとにハンドラーを実装します。
    • Teams アクティビティ ハンドラーを使用して、Teams チャンネルに接続できるボットを作成します。 (Teams チャンネルでは、ボットが何らかのチャンネル固有の動作を処理する必要があります)
  • ダイアログ ライブラリは、ユーザーとの長時間の会話を管理するための状態ベースのモデルを提供します。
  • 独自のボット クラスを実装し、ターンごとに処理するための独自のロジックを提供します。 例については、ユーザー入力を収集する独自のプロンプトを作成する方法を参照してください。

ボット アダプター

アダプターには、ターンを開始するためのプロセス アクティビティメソッドがあります。

  • 要求本文 (アクティビティに変換される要求ペイロード) と要求ヘッダーを引数として受け取ります。
  • 認証ヘッダーが有効かどうかをチェックします。
  • ターンの コンテキスト オブジェクトが作成されます。 コンテキスト オブジェクトには、アクティビティに関する情報が含まれています。
  • ミドルウェア パイプラインを通してコンテキスト オブジェクトを送信します。
  • 次に、コンテキスト オブジェクトをボット オブジェクトのターン ハンドラーに送信します。

アダプターの更なる特長は以下のとおりです。

  • 応答アクティビティを書式設定して送信します。 通常、これらの応答はユーザー向けのメッセージですが、ユーザーのチャンネルが直接使用する情報を含めることもできます。
  • メッセージの更新メッセージの削除など、Bot Connector REST API によって提供される他のメソッドを表示します。
  • ターンでキャッチされないエラーや例外をキャッチします。

ターン コンテキスト

"ターン コンテキスト" オブジェクトは、アクティビティに関する情報 (送信者と受信者やチャンネル、アクティビティの処理に必要なその他のデータなど) を提供します。 また、ターン中に、ボットの各種レイヤーの境界を越えて情報を追加することもできます。

ターン コンテキストは、SDK の中で最も重要なアブストラクションの 1 つです。 インバウンド アクティビティをすべてのミドルウェア コンポーネントおよびアプリケーション ロジックに伝達するだけでなく、ミドルウェア コンポーネントとボット ロジックからアウトバウンド アクティビティを送信するためのメカニズムも備えています。

ミドルウェア

ミドルウェアは、他のメッセージング ミドルウェアとよく似ています。連続する一連のコンポーネントで構成され、各コンポーネントが順に実行されるため、それぞれがアクティビティで動作できます。 ミドルウェア パイプラインの最終ステージは、アプリケーションがアダプターの process activity メソッドに登録したボット クラスのターン ハンドラーへのコールバックです。 ミドルウェアは、アダプターが呼び出すオン ターンメソッドを実装します。

ターン ハンドラーはその引数としてターン コンテキストを受け取り、通常はターン ハンドラー関数の内部で実行されているアプリケーション ロジックによってインバウンド アクティビティの内容を処理して、1 つ以上のアクティビティを応答として生成し、ターン コンテキストの "アクティビティの送信" 関数を使用してそれらを送信します。 ターン コンテキストで "アクティビティの送信" を呼び出すと、ミドルウェア コンポーネントがアウトバウンド アクティビティで呼び出されます。 ミドルウェア コンポーネントは、ボットのターン ハンドラー関数の前後で実行されます。 実行は本質的に入れ子なっているため、玉ねぎのようであると言われることもあります。

ミドルウェアのトピックでは、ミドルウェアについて詳しい説明します。

ボットの状態とストレージ

他の Web アプリと同様、ボットは本質的にステートレスです。 ボット内の状態は、最新の Web アプリケーションと同じパラダイムに従います。また、Bot Framework SDK には、状態の管理を容易にするための状態管理抽象化が用意されています。

状態の管理に関するトピックでは、これらの状態とストレージの機能について説明します。

メッセージング エンドポイントとプロビジョニング

通常、アプリケーションには、メッセージを受信する REST エンドポイントが必要です。 また、使用するプラットフォームに従って、ボットのリソースをプロビジョニングする必要もあります。

ボットの作成に関するクイックスタートに従って、シンプルなエコー ボットを作成してテストします。

HTTP の詳細

アクティビティは、Bot Framework サービスから HTTP POST 要求を介してボットに送信されます。 ボットは、インバウンド POST 要求に対し、200 HTTP 状態コードで応答します。 ボットからチャンネルに送信されるアクティビティは、別の HTTP POST で Bot Framework サービスに送信されます。 それに対する肯定応答が 200 HTTP の状態コードで返されます。

これらの POST 要求とその受信確認応答の順序は、プロトコルでは規定されていません。 しかし、一般的な HTTP サービスのフレームワークに合わせるため、これらの要求は入れ子にするのが通常です。つまり、アウトバウンド HTTP 要求は、ボットからインバウンド HTTP 要求のスコープ内で行われます。 先の図には、このパターンが示されています。 2 つの異なる HTTP 接続が連続して存在するため、セキュリティ モデルには、その両方に対する手立てが必要となります。

Note

ボットは 15 秒以内に、ほとんどのチャンネルでステータス 200 で通話を確認します。 ボットが 15 秒以内に応答しない場合は、HTTP GatewayTimeout エラー (504) が発生します。

アクティビティ処理スタック

前のシーケンス図について、メッセージ アクティビティの到着に注目し、さらに詳しく見ていきましょう。

Sequence diagram illustrating how an activity is processed by a bot.

チャンネルはユーザーのメッセージを Azure AI Bot Service に送信し、サービスはメッセージをボットのメッセージング エンドポイントに転送します。 ボットの応答は、ターンのスコープ内でユーザーに送信されます。

上の例では、ボットがメッセージ アクティビティに対して、同じテキスト メッセージが含まれた別のメッセージ アクティビティで応答しました。 処理は、HTTP POST 要求で始まります。このとき、アクティビティ情報は JSON ペイロードとして伝達されて、Web サーバーに届きます。 大抵の場合、ASP.NET プロジェクトは C# ボットで使用され、Express や restify などの一般的なフレームワークは JavaScript Node.js ボットに使用されます。

"アダプター" は SDK の統合コンポーネントで、SDK ランタイムのコアです。 アクティビティは、HTTP POST 本文で JSON として渡されます。 この JSON は逆シリアル化されて Activity オブジェクトが作成され、これが "アクティビティの処理" メソッドを通じてアダプターに渡されます。 アクティビティを受け取ったアダプターにより、"ターン コンテキスト" が作成され、ミドルウェアが呼び出されます。

上述したように、ターン コンテキストは、アウトバウンド アクティビティを送信するメカニズムをボットに提供します。この送信処理は、多くの場合、インバウンド アクティビティに対する応答として実行されます。 ターン コンテキストは、"アクティビティの送信更新、および削除" 応答メソッドを備えています。 各応答メソッドは、非同期プロセスで実行されます。

重要

プライマリ ボット ターンが完了すると、それを処理していたスレッドによってコンテキスト オブジェクトの破棄処理が行われます。 いずれのアクティビティ呼び出しに対しても必ず await を実行します。これにより、プライマリ スレッドでは生成されたアクティビティで待機してから、その処理が終了され、ターン コンテキストの破棄が行われます。 そうしないと、応答 (そのハンドラーも含まれる) にかなりの時間がかかり、コンテキスト オブジェクトに基づいた処理が試みられた場合、"コンテキスト破棄済み" エラーが返されることがあります。

ボット テンプレート

アプリで使用するアプリケーション レイヤーを選択する必要があります。ただし、Bot Framework には、ASP.NET (C#)、restify (JavaScript)、aiohttp (Python) 用のテンプレートとサンプルがあります。 このドキュメントは、これらのプラットフォームのいずれかを使用することを想定して説明されていますが、SDK では必要ありません。 テンプレートにアクセスしてインストールする方法については、ボットの作成に関するクイック スタートを参照してください。

ボットは Web アプリケーションであり、SDK の各言語用のテンプレートが用意されています。 すべてのテンプレートには、既定のエンドポイント実装とアダプターが用意されています。 各テンプレートには次のものが含まれます。

  • リソースのプロビジョニング
  • 受信アクティビティをアダプターまでルーティングする言語固有の HTTP エンドポイント実装。
  • アダプター オブジェクト
  • ボット オブジェクト

異なるテンプレート種類の大きな違いは、ボット オブジェクトにあります。 テンプレートは次のとおりです。

  • 空のボット
    • 会話の最初のターンで "hello world" メッセージを送信して、ユーザーを会話に迎えるアクティビティ ハンドラーが含まれます。
  • エコー ボット
    • アクティビティ ハンドラーを使用して、ユーザーを迎え入れ、ユーザー入力をエコー バックします。
  • コア ボット
    • SDK の多くの機能をまとめて、ボットのベスト プラクティスを示します。
    • アクティビティ ハンドラーを使用してユーザーを迎え入れます。
    • コンポーネント ダイアログと子ダイアログを使用して会話を管理します。
    • ダイアログでは、言語理解 (LUIS) と QnA Maker の機能が使用されます。

Note

Azure AI QnA Maker は 2025 年 3 月 31 日に廃止されます。 2022 年 10 月 1 日以降、新しい QnA Maker リソースまたはナレッジ ベースを作成できなくなります。 Azure AI Language の一部として、質問応答機能の新しいバージョンが提供されました。

Azure AI Language の機能であるカスタム質問応答は、QnA Maker サービスの更新バージョンです。 Bot Framework SDK での質問と回答サポートの詳細については、「自然言語理解」を参照してください。

Note

Language Understanding (LUIS) は、2025 年 10 月 1 日に廃止されます。 2023 年 4 月 1 日以降は、新しい LUIS リソースを作成することはできません。 より新しいバージョンの言語理解が、現在、Azure AI Language の一部として提供されています。

Azure AI Language の機能である会話言語理解 (CLU) は、LUIS の更新バージョンです。 Bot Framework SDK での言語理解のサポートの詳細については、「自然言語の理解」を参照してください。

追加情報

ボット リソースの管理

ボットのリソース (アプリ ID やパスワードなど) や、接続されているサービスの情報を管理する必要があります。 ボットをデプロイする際には、この情報への安全なアクセスが必要になります。 煩雑さを避けるために、Bot Framework SDK の記事の大部分では、この情報を管理する方法について説明していません。

チャンネル アダプター

SDK では、チャンネル アダプターを使用することもできます。このアダプター自体は、Bot Connector Service がチャンネルに対して標準的に実行するタスクを追加で実行します。

SDK には、一部の言語でチャンネル アダプターがいくつか用意されています。 Botkit リポジトリと Community リポジトリを通じて、他のチャンネル アダプターを利用できます。 詳細については、Bot Framework SDK リポジトリのチャンネルとアダプターの表を参照してください。

The Bot Connector REST API

Bot Framework SDK は、Bot Connector REST API をラップして構築します。 SDK をサポートする基礎となる HTTP 要求について知りたい場合は、コネクタの認証と関連する記事を参照してください。 ボットが送受信するアクティビティは、Bot Framework アクティビティ スキーマに準拠します

次のステップ