目次
- はじめに
- 2つのサンプルケース
- SlackへBOTを登録
- サンプルケース1
ロボットからSlackへの通知 - サンプルのダウンロード
ここで使用したサンプルは、以下からダウンロードできます。HTTP/HTTPS通信について
HTTP/HTTPS通信を行う「HTTPリクエスト」アクティビティは、UiPath Studioにはデフォルトでは含まれておらず、自身で追加する必要があります。追加にあたっては、UiPath Studioの「デザイン」パネルより、「パッケージを管理」のボタンをクリックします。するとパッケージ管理のウィンドウが開きます。左側のペインにて、外部やローカルフォルダのパッケージフィードが選択できます。ここでは「オフィシャル」を選択し、検索窓に「web」と入力すると「UiPath.Web.Actiivties」のパッケージが現れます。こちらを選択し、「インストール」ボタン、「保存」ボタンをクリックする流れでパッケージを追加します。以上で「HTTPリクエスト」アクティビティが使用可能となります。
サンプルケース2
Slack BOTとの対話、ロボットからSlackへの通知以降の内容は初級レベルのプログラミングスキルが必要となります。続いては、「チャットボットとの対話にて入力されたデータをもとにRPAで自動化処理し、その結果をチャットボットで通知するもの」を実装して行きたいと思います。 ここではユーザがSlack BOTと対話して得られた情報をもとに、社内で稼働するロボットに見積書を作成させることを目指します。製品や数量が都度変更する業務を想定し、ユーザは必要情報をSlackのBOTに対して入力し、Slack BOTとUiPathロボットの連携により、RPAで見積書を作成します。 Slack自体に対話する機能はないので、Slackの裏でユーザと対話するプログラムを用意します。その際のポイントとして、自然言語解析的な機能を入れてプログラムを複雑化させるのではなく、Slackをあくまでも請求書作成のための入力装置とする程度のものとします。利用者側に対しては若干不親切と思われるかもしれませんが、利用者は入力規則を守ることで、SlackからRPAを呼び出せる恩恵が得られます。私個人の意見ではありますが、まずはそのような入り口からチャットボットとRPAを連携させるのが良いと考えています。 具体的には、対話は次のような対話ができるものを目指します。次に全体のアーキテクチャーを考えていくと、(1)チャットアプリがフロントエンドとなりユーザとインタラクティブに情報の入力を受け付け、(2)RPAでの処理結果を伝える機能を担い、(3)RPAがそのバックエンドとして必要な処理を実施し、結果を返す機能を担う体系が自然かと考えられます。 これはWebアプリケーション開発の現在のトレンドとして、フロントエンドをJavaScriptにてSPA(Single Page Application)で実装し、バックエンドをJavaのSprintBootといったフレームワークで実装して、その両者をREST APIで連携させるものと同じ構成です。 細かく考えると、次の一連のプロセスが、正当な順序ではないかと考えられます。上図のプロセス(6)~(8)については、下図のようにロボットからSlack APIを直接呼び出すことも可能です。それにより、実装のステップも削減されます。今回はこの簡略化したアーキテクチャーで実装を進めたいと思います。 ノード間のインターフェイス Slack、チャットボット、Orchestrator、そしてロボット、各ノードの主要なインターフェイスに関して、こちらに整理しました。Slack → チャットボット項目 区分 説明 ユーザID Slack情報 SlackのユーザID 顧客名 見積書情報 見積書に記載される顧客名 製品名 見積書情報 見積書に記載される製品名 数量 見積書情報 見積書に記載される数量チャットボット → Orchestrator → ロボット(RPA)項目 区分 説明 ユーザID Slack情報 SlackのユーザID トークン Slack情報 トークンの情報。ロボットに持たせておくことも可能 顧客名 見積書情報 見積書に記載される顧客名 製品名 見積書情報 見積書に記載される製品名 数量 見積書情報 見積書に記載される数量 環境(ネットワーク) 環境面で今回一点注意すべきこととして、Slack用チャットボットからOrchestratorへのJOB実行があります。社内のネットワークでOrchestratorをホスティングしている場合、Slack用チャットボットからOrchestratorへHTTPS(Port: 443)で通信可能にする必要があります。すなわち、Orchestrator側でインバウンドでのHTTPSを許可するものとなります。 社内でOrchestratorをホスティングしている場合、Slack用チャットボットも社内のサーバで運用するかと思いますので、その場合は大きな問題とはならないかもしれません。Slack用チャットボットをインターネット上で運用している場合などに注意が必要です。なお、Slack用チャットボットとSlackは、HTTPSのWebSokcetで通信を行います。Slack用チャットボットを社内で運用したとしても、アウトバウンドでのHTTPSが許可されていれば問題ありません。 Slack用チャットボット それでは、Slack用チャットボットの作成に取り掛かります。ここからはコーディングの知識が必要です。 私個人の考えではありますが、Windows環境での業務で単純かつ自動化できるものはWindows端末のロボットに作業を任せます。一方で、チャットボットの実装といったロジックが複雑となるものはプログラミングでサクッと開発してしまいます。チャットボットとRPAについては、現時点これがすみ分けとしてちょうど良いのではないかと考えています。 今回のサンプルでは、Ruby(Version 2以降)でslack-ruby-clientというライブラリ(Gem)を使用し、Slack BOTを作成します。こちらはSlackのReal Time Messaging APIというWebSocketでのメッセージのやり取りを実装し、簡易にSlack BOTが実装可能となるライブラリです。 Rubyは、単純に私が個人的に好きなプログラミング言語です。PythonやJavaScript(Node.js)にも同様なライブラリはあるようです。ポイントとしては、スクリプト系の言語でRPA同様にサクッと開発してしまう点です。- slack-ruby-client(https://github.com/slack-ruby/slack-ruby-client)
gem install slack-ruby-clientと入力してライブラリを追加しておきます。 Slack BOTでのSlack連携 下記のコードが、このライブラリを使用してSlack連携を実現したものとなります。これはライブラリの「RealTime Client」のサンプルコードを一部加工したものです。コードの真ん中のclient.on :messageというブロック内に、ボットでの見積書作成において必要事項を取得するロジックを実装することとなります。 require 'slack-ruby-client' token = 'xoxb-5634373235-565512315213-6dksjqvZKKvXXtGuv4muXX99' # 自身のSlack Appのトークンを指定する Slack.configure do |conf| conf.token = token end Slack::RealTime::Client.config do |config| config.websocket_ping = 30 end # RTM Clientのインスタンス生成 client = Slack::RealTime::Client.new quotations = {} client.on :hello do puts "Successfully connected, welcome '#{client.self.name}' to the '#{client.team.name}' team at https://#{client.team.domain}.slack.com." end client.on :message do |data| next if client.self.id == data.user client.typing channel: data.channel quotations[data.user] = Quotation.new(data.user) unless quotations.key? data.user quotations[data.user].reply(data.text) { |reply| client.message channel: data['channel'], text: reply } end client.on :close do |_data| puts 'Connection closing, exiting.' end client.on :closed do |_data| puts 'Connection has been disconnected.' end client.start! このコードで、Slack BOTのクライアントとして接続できます。次にclient.on :messageへ実装する対話のロジックを考えてみます。 見積のためのQuotationクラス 対話ロジックを実装するにあたり、「Quotation」というクラスを作成しました。このクラス内にユーザから取得する顧客名(client_name)、製品名(product_name)、数量(quantity)、SlackユーザID(requester)のインスタンス変数を用意します。こちらはオブジェクト指向のクラス設計で、このクラスにて1件の見積りで必要となる情報をハンドリングします。reply(message)というブロックのメソッドにて、Slack経由でのユーザとの対話処理を実装します。このメソッド内で、is_newというインスタンス変数と顧客名、製品名、数量のそれぞれの取得状況に応じて、ユーザへの入力依頼をブロックで返します。なお、すべての情報が取得でき次第、start_jobという外部のメソッドでロボットへのジョブを依頼します。 要はclient.on :messageの中で、このQuotationクラスのインスタンスを使用して、reply(message)メソッドを使用してユーザとの対話を実現するためのものとなります。 class Quotation attr_reader :client_name, :product_name, :quantity, :requester def initialize(requester) @requester = requester @is_new = true end # 対話での見積書作成用データの取得メソッド def reply(message) parsed_message = parse_message(message) if parsed_message == 'summary' yield "#{user_symbol} サマリの表示ですね" yield "情報未取得のため、表示できるサマリはありません" if @is_new elsif parsed_message == 'clear' yield "#{user_symbol} BOTで収集した情報をクリアします" clear yield "クリアしました" elsif @is_new if ['Yes', 'yes', 'はい'].include? message yield "#{user_symbol} 承知しました。それでは、、、" yield "顧客名は何? \ni.e.) ABC株式会社" @is_new = false else yield "#{user_symbol} 請求書作成BOTです。" yield "作成開始しますか? \ni.e.) #{['Yes', 'yes', 'はい'].join(', ')}" end elsif @client_name.nil? @client_name = parsed_message yield "#{user_symbol} 顧客名は *#{@client_name}* ですね" yield "製品名は何? \ni.e.) ネジ" elsif @product_name.nil? @product_name = parsed_message yield "#{user_symbol} 製品名は *#{@product_name}* ですね" yield "数量は? \ni.e.) 1000" elsif @quantity.nil? @quantity = parsed_message.to_i rescue 0 yield "#{user_symbol} 数量は *#{@quantity.to_s}* ですね" yield "UiPath Robotにて請求書を作成します!!" start_job(@requester, @client_name, @product_name, @quantity) end yield "```BOTの収集情報\n" + summary + "```" unless @is_new end # 文字列のクレンジングを実装する。 def parse_message(message) message.strip end # Slackでのユーザ表記へ変換 def user_symbol "<@#{@requester}>" end def clear @is_new = true @client_name = nil @product_name = nil @quantity = nil end def summary "顧客名: #{@client_name}\n製品名: #{@product_name}\n数量: #{@quantity}\nコマンド: summary, clear" end end こちらのクラスを工夫することで、見積書作成においてさらに必要なデータを取得したり、ユーザとのより高度な対話を実現したりもできます。一例として、入力文字列のクレンジング処理用の`parse_message(message)`メソッドを用意していますが、このメソッドの中で自然言語処理を実装したり、必要な情報のみを抽出したりすることができます。 Orchestrator REST APIの呼び出し それでは、説明ができていなかったstart_jobメソッドについて説明します。こちらでもREST APIの呼び出しに便利なrest-clientというライブラリを使用します。環境に未導入の場合、gem install rest-clientで導入しておきます。Orchestratorとのやり取りはJSON形式となりますので、jsonのライブラリをrequireしておきます。こちらはRuby標準に付属されております。 Orchestratorに関するURLやユーザ名、パスワードといった情報は今回は定数としてあらかじめ定義しています。start_jobのメソッド内では、引数からのロボット名とプロセス名の情報をもとに、APIを使用してJOB実行まで一気通貫で実行します。こちらはOrchestratorへ接続しているロボットの状況などで、適宜呼び出し方法を変更しても問題ありません。 例えば、特定のロボットで実行する必要がない場合、JOB実行のNoOfRobotsのパラメータを使用することで、ロボット一覧取得の呼び出しは不要となります。他にもRelease IDがわかっている場合、直接そのIDでJOB実行してもかまいません。- Orchestratorとの認証
- ロボット一覧取得
- プロセス一覧取得(Release ID)
- JOB実行
- Orchestrator API(https://docs.uipath.com/orchestrator/lang-ja/reference)
client.on :messageのブロックの中では、Hashクラス(ディクショナリー型)を利用して、SlackユーザIDをキーに、Quotationクラスのインスタンスを保持する仕組みとしています。quotationsのHashにメッセージを受け取ったユーザが含まれていない場合、新規にQuotationクラスのインスタンスを生成してHashに格納し、Quotationクラスのreplyブロックでユーザと対話させています。 client.on :message do |data| next if client.self.id == data.user client.typing channel: data.channel quotations[data.user] = Quotation.new(data.user) unless quotations.key? data.user quotations[data.user].reply(data.text) { |reply| client.message channel: data['channel'], text: reply } endnext if client.self.id == data.userは、ロボットでの見積書作成後の投稿に対してSlack BOT側で反応しないようにするためのものです。 UiPathロボット ロボットはOrchestratorからJOB実行されることを前提とし、その際に引数で請求書作成に必要なデータや、依頼者のSlackユーザIDを受け取ります。処理の流れは次の通りです。- 請求書用データ取得
- 請求書作成
- Slack返答
- 後処理 - 不要ファイルの削除
- Slack API files.upload(https://api.slack.com/methods/files.upload)
quotationPdfを指定します。 検証 すべての実装が完了したので、Rubyで作成したSlack BOTはプログラムを起動し、ワークフローはOrchestratorへデプロイしてロボットも稼働させておきます。Slackにて、一連の会話をチャットボットと行い、請求書がチャットボットからSlackで送られることを確認しましょう。 Slack BOTとの会話の中で、伝える情報が間違った場合、clearと入力することで、Slack BOTに蓄積されたデータをクリアできます。 サンプルのダウンロード ここで使用したサンプルは、以下からダウンロードできます。まとめ 今回のサンプル作成を通して、サンプルケース1「ロボットで実行・処理した結果を、チャットアプリへ連携し通知するもの」については、チャットアプリとの連携は、APIを使用することで簡単かつあっという間に実現できるとわかりました。 次にサンプルケース2「チャットボットとの対話にて入力されたデータをもとにRPAで自動化処理し、その結果をチャットボットで通知するもの」では、チャットアプリやRPAの既存のテクノロジーを組み合わせることで、ユーザとの対話も人手を介さずに自動化することが可能であるということがわかりました。 なお、どのような顧客、製品、数量で見積書が作成されたかをまとめて確認したいという場合、Orchestratorにすべての情報が永続的に格納されています。こちらはOrchestratorでのJOB実行の機能を利用したことで、特段そのためにロジックを作り込む必要はありません。ぜひ、チャットアプリとRPAの連携にチャレンジして、業務の自動化を促進してください。 - サンプルケース2
Slack BOTとの対話、ロボットからSlackへの通知 - UiPathロボット
- まとめ
はじめに
RPAで業務の自動化を進めていく上で、ユーザとの対話を自動化したいときに登場するのがチャットアプリです。ユーザからの問い合わせについても多くの業務で定型的なものが存在し、またそれへの対応に多くの人手が取られている現実があります。これを自動化できれば、ユーザからの問い合わせ対応にかかる人手を削減できます。
そこで今回は、チャットアプリとRPAの連携でどのようなことができるか、実際にサンプルを作成しながら理解を深めていきたいと思います。
効果的なユースケースの一例として以下を考えてみます。ユーザは営業担当者です。客先で商談を終えた直後、携帯のチャットアプリを起動します。商談の内容を踏まえて顧客情報、製品情報、その数量などをチャットボットへ伝えます。するとRPA化された自動化プロセスによって、社内にあるロボットが送られた情報をもとに見積書を作成してくれるといったものです。
チャットアプリを通して、ロボットをパーソナルアシスタントとして活用できるイメージです。
そのほか、下記のユースケースでもチャットアプリとRPAの連携が有用です。
- バッチ処理として自動化した一連のRPAのプロセス完了後、RPA運用者にチャットアプリにてその完了通知を送る
- 社内システムのアカウントのロック解除をチャットボットに依頼すると、RPA化された自動化プロセスがロックを解除する
これらはテクノロジーの観点からすると、すべて実現可能なものです。チャットアプリとUiPathといったRPA製品においては、現在のシステム連携の潮流に従いREST APIが提供されています。お互いに疎結合での相互連携が、簡易に実現可能なものとなるのです。
今回はチャットアプリとRPAの連携に焦点を当てます。
2つのサンプルケース
今回は下記の2つのサンプルケースについて、チャットアプリとRPAの連携を実現します。そしてそのアーキテクチャーや実装方法の理解を深めます。
- ロボットで実行・処理した結果を、チャットアプリへ連携し通知するもの
- UiPathのロボットからチャットアプリへメッセージを送るだけのもので、RPAの開発知識のみを必要とします。
- チャットボットとの対話で入力されたデータをもとにRPAで自動化処理し、その結果をチャットボットで通知するもの(前述の見積り作成)
- チャットボットからUiPathのロボットを起動するため、Orchestratorを必要とします。またチャットボットの実装にあたり、プログラミングの知識も必要となります。
チャットアプリは、業務での利用が多いSlackを使用します。その他のチャットアプリについても、Slackと同様の連携機能が用意されています。その他のチャットアプリを利用されている方は、適宜読み替えて参考にしてください。
SlackへBOTを登録
まず、Slackと外部のアプリケーションであるRPAが連携できるようにするために、Slack上でSlack App(BOT)を登録します。
- BOT登録ページ(https://api.slack.com/apps?new_app=1)
「Create an App」ボタンをクリックして登録作業を進めます。
「App Name」に使用するSlack Appの名称を入力します。こちらは、Slackの画面においても表示されるものです。「Development Slack Workspace」は適宜、自身の環境が指定されていることを確認します。
登録が完了すると、API Tokenが発行されます。これ以降、ロボットや外部のアプリケーションがSlackと連携する際は、このTokenを使用します。
以上で、Slack上でのBOTの登録は完了しました。ダイレクトメッセージのやり取りやチャンネルへの招待が可能となります。
サンプルケース1
ロボットからSlackへの通知
これより、「ロボットで実行・処理した結果をチャットアプリへ連携し通知するもの」を実装していきます。今回のサンプルで作成するロボットは、ユーザとインタラクティブに動作します。WebブラウザやPDFなどで気に入った文章や後で読みたい文章をSlackにリアルタイムで投稿するものです。
ロボットではイベントモニタリングの機能を使用して、「Ctrl+Up」が押されると選択中の文字列をコピーし、その文字列をSlack APIを利用してSlackへ投稿する実装とします。用途としては、Webサイト、PDF資料、メールなどにおいて、気になった文章をクリッピングするためのものです。クリッピングした文章は、Slackに全て投稿されます。
「イベントを監視」は、指定したイベントが発生すると「イベントハンドラー」内の処理を実行する機能です。ユーザの特定のキー操作やマウス操作のイベント、ファイルの新規作成・変更といったシステム上のイベントを監視できます。
イベントモニタリングの応用的な使用方法として、例えばコールセンターでのオペレーションにおいて特定のWebサイトへの入力を監視し、バックグラウンドで顧客情報を別システムへロボットに自動入力させることも可能となります。普段、複数システムへの重複入力が発生しているビジネスシーンで時間短縮となる効果的な自動化となります。
ワークフロー
それでは早速、UiPath Studioで「slack_notification」という名称の新規プロジェクトを作成します。開発するワークフローは次の通りです。
「イベントを監視」のイベントモニター機能により、「ホットキートリガー」のアクティビティにて、ユーザからの「Ctrl+Up」の操作発生を監視します。
イベント監視より、自動化が実行されると「選択されたテキストをコピー」の処理で、選択中のテキストを「message」という文字列型の変数へ保存します。「トライキャッチ」で囲んでいるのは、何も選択されていない場合など例外がスローされるためです。例外「Exception」をキャッチした場合の「message」は、.Net Framework VB.NETのNull値である「Nothing」としておきます。
その後、「条件分岐」にて、messageが「Nothing」でないという条件で場合分け処理を行います。こちらが「True」の場合、すなわちmessageにテキストが保持されている場合は、Slackへ投稿する流れとなります。
Slackへの投稿にあたって、新たに「decoratedMessage」という文字列型変数へ、下記のフォーマットでクリップしたテキストを修飾します。
"クリップされたテキスト" + DateTime.Now.ToString("yyyy/MM/dd hh:mm:ss") + Environment.NewLine + "```" + message + "```"「クリップされたテキスト」という固定の文字列と投稿時刻に続けて改行し、コピーしたテキストをボーダー付き引用段落表現にて表示するようにします。「```」はSlackのMarkdown表記です。文字の前後の行にこれを入れると、ボーダー付きの引用段落として表現されます。
その後、「HTTPリクエスト」アクティビティにて、Slack API呼び出しを行う実装とします。ここではSlackへのメッセージ投稿用に「chat.postMessage」というAPIを使用します。
「HTTPリクエスト」アクティビティが見つからない場合、次項「HTTP/HTTPS通信」を参照してください。
- Slack API chat.postMessage(https://api.slack.com/methods/chat.postMessage)
「入力」
「エンドポイント」には、下記のSlack APIのエンドポイントを指定します。
https://slack.com/api/chat.postMessage
「メソッド」(HTTP Method)には、「POST」メソッドを指定します。なお、このAPIでは「POST」メソッドが推奨されていますが、「GET」メソッドもサポートされています。
「オプション」
「パラメータ」(GETメソッドの引数)へは、以下の項目を指定します。
| 名前 | 方向 | 型 | サンプル値 / 変数 | 説明 |
|---|---|---|---|---|
| token | 入力 | String | “xoxb-5634373235-565512315213-6dksjqvZKKvXXtGuv4muXX99” | Slack API登録時に生成されたToken。左はダミーのもの |
| channel | 入力 | String | “thinkit” | Slackのチャンネル。事前にチャンネルは作成しておきます |
| text | 入力 | String | decoratedMessage | 投稿するメッセージ |
| as_user | 入力 | String | “true” | 「as_user=true」とするとTokenを発行したBot名となる |
「出力」
「状態コード」(Http Status)に、「httpStatus」という変数、「結果」(Http Response Body)に、「result」という変数を指定します。
最後に、Slack APIの応答結果を「httpStatus」と「result」で確認できますので、これらの値をログ出力しておきます。Http Statusは、数値でHTTP通信の通信結果を表現するもので、200が正常、40x、50x(xには数字が入ります)については、何かしらの問題があり、正常にHTTP通信が行われなかったことを意味します。
検証
それでは実際にロボットを動かして動作検証を実施します。なお、BOTはSlack上で事前に#thinkitというチャンネルに登録してあります。
Webブラウザで適当なWebサイトを表示し、マウスでテキストを選択した状態とします。その状態でキーボードの「Ctrl」キーと「Up」キーを同時に押します。
下図のように、選択したテキストが指定したSlackチャンネルへロボットから投稿されていれば成功です。
サンプルのダウンロード
ここで使用したサンプルは、以下からダウンロードできます。
HTTP/HTTPS通信について
HTTP/HTTPS通信を行う「HTTPリクエスト」アクティビティは、UiPath Studioにはデフォルトでは含まれておらず、自身で追加する必要があります。追加にあたっては、UiPath Studioの「デザイン」パネルより、「パッケージを管理」のボタンをクリックします。
するとパッケージ管理のウィンドウが開きます。左側のペインにて、外部やローカルフォルダのパッケージフィードが選択できます。ここでは「オフィシャル」を選択し、検索窓に「web」と入力すると「UiPath.Web.Actiivties」のパッケージが現れます。こちらを選択し、「インストール」ボタン、「保存」ボタンをクリックする流れでパッケージを追加します。
以上で「HTTPリクエスト」アクティビティが使用可能となります。
- この記事のキーワード
