【UiPath】Apps&コネクションで生成AIモバイルアプリを作成する

# はじめに
- 本記事ではUiPath Appsの新機能であるコネクション連携を使って生成AIアプリを作成してみたいと思います。出来上がりは ↓ このような感じです。
    <img width="350" alt="35.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/bd315f8e-010f-c13f-1e0a-92bc1245fcec.jpeg">

- 質問文を入力してボタンをクリックすると生成AIサービスからの回答が表示されるというシンプルなものですが、**UiPath Appsを利用することによってローコードかつ自前でサーバーを用意せずにWebアプリの開発および運用が可能** です。

## UiPath Appsとは？
- [UiPath Apps](https://docs.uipath.com/ja/apps/automation-cloud/latest/user-guide/introduction) は、ユーザーエクスペリエンスに優れたエンタープライズレベルのカスタム アプリケーションを構築・共有できる、ローコードアプリケーション開発プラットフォームで UiPath Automation Cloudの一部として利用することができます。AppsではUI要素のコンポーネントを配置し、ボタンクリックなどをトリガーとして自動化プロセス実行することもできます。
- まだプレビュー段階ですが [アプリのコネクション](https://docs.uipath.com/ja/apps/automation-cloud/latest/user-guide/connections-in-apps) によってAppsからIntegration Serviceを呼び出すことができるようになりました。[Integration Service](https://docs.uipath.com/ja/integration-service/automation-cloud/latest/user-guide/introduction) はいわゆるiPaaS (Integration Platform as a Service) で様々なWebサービスと容易に連携できます。**UiPath GenAIアクティビティ** などを利用すれば生成AIサービスを呼び出すこともできます。コネクション連携ではAppsからIntegration Service経由でWebサービスをコールするため、実行環境としてのUiPath Robotは不要になります。
:::note warn
UiPath GenAI アクティビティを利用するにはAIユニットが必要となります。プレビュー段階では無料でご利用いただけていましたが、2024年7月に一般提供(GA)されてからはアクティビティ実行ごとにAIユニットが消費されます。
:::
- Appsでこのように開発されたWebアプリはRobotが不要なためモバイル端末でも実行することができます。今回はモバイル対応の生成AIアプリをAppsで作成してみたいと思います。

# Appsによる生成アプリ作成手順

## Integration Serviceのコネクタを作成する
- [Automation Cloud](https://cloud.uipath.com) に管理者アカウントにてサインインし、Integration Serviceメニューをクリックします。
    ![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/8c4c9c0c-dad7-bfa3-35b2-930618868377.png)

- **UiPath GenAIアクティビティ** のコネクタを作成します。OpenAIなどその他の生成AIサービスとのコネクタを作成する手順については [こちらの記事](https://qiita.com/hidecha/items/8adb863b4ea336997c9e) をご参照ください。
    ![10a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/87e6420a-6591-5f9a-69e2-bd8351ab6f27.png)

## Appsでアプリを作成する
- 次にAppsでアプリを作成します。[Automation Cloud](https://cloud.uipath.com) にてAppsメニューをクリックします。
![01a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/3f618303-04a6-662a-5b70-0c6703177813.png)

- [新しいアプリを作成] をクリックし、アプリケーション名として `ChatApps` と入力し [作成] をクリックします。
![02a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/dee3e2b1-8bdb-a943-30a4-3f3e4c1247fc.png)

- テンプレートは **空のページ** をダブルクリックして選択します。
![03a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/59016334-bc38-614b-c6cb-1079b1d0ac92.png)

### UIの作成
- 生成AIアプリのシンプルなUIを作成します。[コントロールを追加] をクリックし、入力 > テキストボックス をドラッグ&ドロップしてMainPageに追加します。
![04a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/55e2ac1d-9269-fa29-e037-6c7fb9192d3e.png)
    - このテキストボックスはユーザーが質問を入力するために使用します。モバイル用にUI領域を節約するために 全般 > ラベルの既定値 "Label" を削除します。続いて スタイル > サイズ > 幅をひとまず `370px` に設定します。モバイル端末に合わせて調整する方法については後ほど説明します。
    ![05a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/e2d3c097-fbe3-688f-c629-049812ba9eaa.png)

- [コントロールを追加] をクリックし、入力 > ボタン をドラッグ&ドロップしてMainPageに追加します。テキストを "Query" に変更します。ユーザーがクリックした時に質問内容を生成AIに問い合わせするように後ほどイベントルールを実装します。
    ![06a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/e4aebb57-abfb-8c87-3b2d-826031618363.png)

- 再び [コントロールを追加] をクリックし、入力 > カスタムHTML をドラッグ&ドロップしてMainPageに追加します。カスタムHTMLは生成AIサービスからの応答を表示します。スタイル > サイズ > 幅を `370 px` に指定します。
    ![07a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/e6ab2bc0-9aa6-bf31-7048-0b290c6507b8.png)

- アプリのコネクションを追加します。[コントロールを追加] をクリックし、**コネクション** を選択します。
    ![08a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/77a1f3b4-c8f5-e024-23b1-e2f9cfc18292.png)
    - コネクションを追加して **UiPath GenAI Activities** を選択し、フォルダー配下に作成されたコネクタを選択します。[追加] をクリックします。
        ![09a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/d07a0536-1c9d-408a-9ade-e064fcd4ca33.png)

- 生成AIサービスからの応答を格納する変数を作成します。左メニューの **アプリの変数** > (+) をクリックし、変数名 `query_response`、型 `Text` を選択して [作成] をクリックします。
    ![18a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/33e09b03-d4bc-11fa-f5e2-2b1db4d6dd3b.png)

### イベントルールの作成
ボタンクリック時にコネクションを利用して生成AIサービスに問い合わせするようにイベントルールを実装します。
- ボタン > イベント > [ルールを作成] をクリックします。
    ![11a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/8e46e18a-b6bf-9d76-3255-fd19624dd984.png)

- 新しいルールとして **UiPath GenAI Activities** > **Content Generation** を選択します。
    ![12a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/be55e5b1-a74d-0faa-04ea-de25ce7f14d2.png)
- **Content Generation** (コンテンツ生成) のパラメーターは下記のように設定します。
    - **Model name**: `"gpt-4o-2024-05-13"`
    - **Stream**: `false`
    - **Prompt**: `MainPage.Text.Value` (※ コントロール名を変更している場合は `Text` 部分を置き換えます)
    - その他のパラメーターは [アクティビティガイド](https://docs.uipath.com/ja/activities/other/latest/integration-service/uipath-uipath-airdk-content-generation) をご参照ください。
    ![13b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/c715bc5b-b5a4-e440-fc5a-dc1115389ebf.png)

- Content Generation アクティビティ実行の状態が分かるようにスピナーを追加します。
    ![14a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/baf93ef1-be0e-3a59-0bf7-456d79b0c94a.png)
    - 開始時 > **スピナーを表示/非表示** をクリックし、スピナーの表示設定を `true` (既定値) にします。
    - 完了時 > **スピナーを表示/非表示** をクリックし、スピナーの表示設定を `false` に変更します。
    ![15a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/d5fdac81-d4df-1282-2346-0ce0b0594f44.png)

- アクティビティ実行の戻り値を受け取るため、完了時のルールを (+) をクリックして追加し、 **値を設定** を選択します。
    ![19a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/6c8c7721-bb54-411f-3886-33a5b6a24c33.png)
    - 設定する項目: アプリの変数として `query_response` をセットします。
    - 値: 式として `Newtonsoft.Json.Linq.JToken.Parse(MainPage.Button.ContentGeneration.Response.RawResponse)("text").ToString` をセットします。
        - [Webガイド](https://docs.uipath.com/ja/apps/automation-cloud/latest/user-guide/connections-faq#how-can-i-get-a-raw-response-from-the-api%3F) に記載の通り、生の戻り値は `<PageName>.<ControlName>.<RuleName>.Response.RawResponse` で受け取ります。それをJSONオブジェクトとしてパースし、応答部分のみを取り出しています。
    ![22a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/2d850d33-eea5-c8b9-ae53-d353f02c85af.png)

### カスタムHTMLコントロールの設定
カスタムHTMLの外観を設定し、生成AIサービスからの応答を表示するようコードを記述します。
- カスタムHTML > 全般 > **コードエディターを開く** をクリックします。
    ![23a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/3a2d469b-bb66-e563-1bf4-1a0adb4c50e6.png)
- コードエディターにてそれぞれ次のように設定して [保存] をクリックします。
    ```html: HTML
    <div id="textContainer">
    </div>
    ```

    ```css: CSS
    @import url("https://fonts.googleapis.com/css2?family=Noto+Sans+JP");
    
    div {
      background-color: #ffffff;
      font-family: 'Noto Sans JP';
      font-size: 13px;
      color: #333333;  
      display: grid;
    }
    
    code {
      font-family: 'Courier New', Courier, monospace;
      font-size: small;
      background-color: #f8f8f8;
      border: 1px solid #dddddd;
      border-radius: 4px;
      padding: 2px 4px;
      color: #333333;
    }
    ```

    ```Javascript: JAVASCRIPT
    async function init() {
      const text_container = document.getElementById('textContainer');
    
      App.onVariableChange("query_response", value => {
        console.log("Response: ", value);
        text_container.innerHTML = value;
      })
    }
    init();
    ```
    ![35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/09992e3c-9ea3-4823-41db-ac5858fe25db.png)

## 実行確認とデバック・微調整
- これで基本部分は実装できましたので動作確認してみましょう。[プレビュー] をクリックすると別タブにてアプリが起動します。
    ![36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/0eca98e9-7fda-9740-a3c1-8ba66adebc54.png)
    - **コネクションを更新** が表示される場合には、コネクタを選択して [実行] をクリックします。
    ![25a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/5fa85272-c889-ddf4-61a8-271d4be1a7ab.png)
- UIが表示されましたらテキストボックスに質問文 (例: `UiPath Automation Cloudについて教えて`) を入力して [Query] ボタンをクリックします。30秒ほどで応答が表示されます。
    ![26a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/2daea5ec-f5df-853c-9768-9737dfe7e0d9.png)
- 現段階では見栄えはあまり良くありませんので後ほど調整します。

### デバッグとモバイル対応
- もし応答が正常に表示されない場合にはF12を押下して開発者ツールを起動し、**Console** タブを開きます。
    - **Selected context only** をオンにします。
    - 上部のドロップダウンを top → `html-control-base.html` に変更します。JavaScript コード `console.log(変数)` によってセットされた変数の値をコンソール出力してデバッグに役立てることができます。 
    ![27a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/cd159129-43ca-554d-60b3-481c9dfedae3.png)

- モバイル端末でのUI微調整も開発者ツールで行うことができます。Elements タブ左のモバイルアイコンをクリックし、画面左上部で端末の種類を選択します。見栄えが良くなるようにテキストコントロールやカスタムHTMLのサイズやマージン(余白)を調整します。
    ![28a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/688fa52e-2285-0fc4-e3a9-f9c31fe46ead.png)
    - モバイル対応のデザインに関する詳細は [こちらのガイド](https://docs.uipath.com/ja/apps/automation-cloud/latest/user-guide/build-a-mobile-friendly-app) もご参照ください。

### Markdown→HTML変換
- 現段階ではカスタムHTMLにて生成AIサービスの応答をそのまま表示していますが、改行などがされておらず可読性があまり良くありません。応答は主にMarkdown形式であるため、既存コードに少し手を加えてHTMLに変換し見栄えを改善してみましょう。
- Markdown→HTML変換のJavaScriptライブラリはいくつかありますが、今回は [Showdown](https://github.com/showdownjs/showdown) を使用したいと思います。
    - カスタムHTMLのコードエディターを開き、外部リソースをクリックし、JavaScriptのソースとして `https://unpkg.com/showdown/dist/showdown.min.js` を指定し [保存] をクリックします。
    ![37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/a1e1f4c1-079e-21c5-55b6-4fb5d31b4827.png)

- コードエディターを再度開き、JavaScriptを次のように変更して [保存] をクリックします。
    ```Javascript: JAVASCRIPT:
    async function init() {
      const text_container = document.getElementById('textContainer');
      const converter = new showdown.Converter();
    
      App.onVariableChange("query_response", value => {
        let answer_html = converter.makeHtml(value);
        console.log("HTML: ", answer_html);
        text_container.innerHTML = answer_html;
      })
    }
    init();
    ```
    
    ![38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/0e5e3f6f-a9e5-d223-7a9a-20891c5cec5b.png)

- 再度プレビュー実行すると、応答がHTML変換され読みやすくなっていることを確認します。
    ![29a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/95c4ee1b-51e0-f5ff-fb64-b5d399ce2378.png)

## アプリのデプロイ
- アプリをデプロイするには [パブリッシュ] をクリックします。
    ![30a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/83f7493f-e619-71d9-d594-26cff3327127.png)
- 必要に応じて説明を入力して [パブリッシュ] をクリックします。次の手順にて [今すぐデプロイ] をクリックします。
    ![31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/f31841c8-eeef-0aad-5f26-a9c6f73b6766.png)
- アプリはOrchestratorフォルダーごとにデプロイします。利用ユーザーが割り当てられているフォルダーを選択し、 オートメーション > アプリ > [アプリをデプロイ] をクリックします。
    ![32a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/03d6a474-37f9-a6a9-3fe4-e4a4a35f70de.png)
    - アプリとして `ChatApps` を選択し [デプロイ] をクリックします。
    ![33a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/23a51da4-be80-4da9-a871-3f5dfac0c111.png)
    - デプロイされたアプリの縦三点 > URLをコピー をクリックし、このURLをモバイル端末に共有します。
    ![34a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/f128c0a3-bf7f-6049-c9d4-2e54da9ca0b5.png)

- モバイル端末でURLを開きます。まずAutomation Cloudへの認証が求められますので権限のないユーザーはアクセスできません。Automation Cloudへのサインイン後、質問文を入力してQueryボタンをクリックし、応答が表示されることを確認します。
    <img width="350" alt="35.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178312/bd315f8e-010f-c13f-1e0a-92bc1245fcec.jpeg">

# おわりに
本記事ではUiPath Appsのコネクション連携機能を使用してモバイル端末に対応した生成AIアプリを作成してみました。今回紹介したコネクション・アクティビティ以外にも様々なサービスとの連携が利用可能ですし、UIデザインもカスタマイズできます。[Appsユーザーガイド](https://docs.uipath.com/ja/apps/automation-cloud/latest/user-guide/introduction) を参照して皆さんのニーズに合わせたアプリ開発をお試しいただければと思います！