Gemini AIでTeamsで受けた問い合わせを代行してもらう + カスタムコネクタの作成

# はじめに
問い合わせ対応って非常に手間ですよね。

特に私は最近、*Teams*で問い合わせ対応を受けるときに、
「あ、これは調べれば、すぐわかるんじゃないかな…」という内容を答えるのが億劫になる時が度々あります。

そういった状況の中で、*AI*を使ってうまくサクッと回答したい、そんな夢と希望が詰まったテーマを今回取り扱います。

*Power Automate*とこれまで使ってこなかった*Gemini AI*の機能を使って、問い合わせ対応の代行にチャレンジします。

# Geminiの準備

まずは*Gemini*の*API*の登録からスタート。

お恥ずかしながら今まで*Gemini*を使ったことがなかったので、どう登録するかなというところから調べました。
下記の記事を参考にさせていただきました🙇感謝です。

https://zenn.dev/peishim/articles/2e2e8408888f59

*Gemini*を[Web上で試すリンクがこちら](https://gemini.google.com/app)

https://gemini.google.com/app

*API*を利用する場合は[Google AI Studio](https://makersuite.google.com/app/prompts/new_freeform)にアクセスします。

アクセスするだけで、サクサクと`API キー`が取得でき、入りやすさは抜群です。

https://makersuite.google.com/app/prompts/new_freeform

`サンプルのコード`や`クイックスタート`も`APIキー`のページからアクセスできる、非常にユーザーフレンドリーな仕様になっています。

[クイックスタート ガイド](https://ai.google.dev/gemini-api/docs/get-started/tutorial?lang=python&hl=ja)を見ながら進めていきます。

# Gemini はじめの一歩
今回の検証は`フリー`プランで実施します。
*Power Automate*による実装を進める上では、まず[REST](https://ai.google.dev/gemini-api/docs/get-started/tutorial?lang=rest&hl=ja)のタブに遷移して内容を見ていきます。

https://ai.google.dev/gemini-api/docs/get-started/tutorial?lang=rest&hl=ja

*Gemini*といえば

- 圧倒的な安さ
- 使いやすさ

上記が歌われていますね。
*GPT-4o*や*Claude 3.5 Sonnet*、全て凄すぎるので、もう時代の進歩についていけません・・・。

脱線しましたが、クイックスタートを読み解くと

| 項目 | 設定値 |
|---|---|
| 方法 | POST |
| URI | https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash-latest:generateContent?key={APIキーを挿入} |

```json:ボディ
{
    "contents": [
        {
            "parts": [
                {
                    "text": "Explain how AI works"
                }
            ]
        }
    ]
}
```

*APIキー*が`クエリ文字列`に含まれることと本文の構成がほかのモデルと異なります。

*APIキー*を*Azure Key Vault*に格納し、*HTTP*アクションを実行してみると、すぐに実行が完了します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/3bbdf3da-fbfb-04e2-211d-9d4169e58c14.png)

*contents[0].parts[0].text*に指示を追加するだけで、もう簡単な*API*呼び出しは成功してしまいます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/025f06e6-511d-e863-b3e2-e06d4fc9adac.png)


これだと簡単すぎる内容になってしまいますので、`カスタムコネクタ`への加工にトライしてみます。

## カスタムコネクタの作成

1. Power Automateの左パネルからカスタムコネクターをクリック
2. 「+ カスタムコネクタの新規作成」及び「コネクタ名」を設定
3. URLとベースURLを入力
4. 要求にサンプルを入れる
5. コンテンツタイプを「application/json」に設定
6. 認証設定（基本認証、APIキーをクエリに含める）
7. JSONの値を入力してテスト

カスタムコネクタの作成、となると若干ハードルの高さを感じます。
しかし今回は非常に簡単なので、トライしていきましょう。

### 1. Power Automateの左パネルからカスタムコネクターをクリック
*Power Automate*の画面左側のパネルから`カスタムコネクタ`をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/a1c8b3d8-4182-f27e-40ec-1cb79e8070e7.png)

画面右上の「+ カスタムコネクタの新規作成」をクリックし、選択肢の中から「一から作成」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/331cd39a-05a7-378a-d3d6-30c714a9fda9.png)

`コネクタ名`を命名して「続行」をクリックしてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/971df748-8874-11e8-b508-17e0e0b26bd4.png)

コチラが「カスタムコネクタの`全般情報`」を設定する画面です。
アイコンや背景色も設定できますが、今回は割愛します。

肝心な部分は赤枠`rgba(255,0,0,1)`の部分

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/eff74074-0c84-79e2-f9ec-6f4bd811d64b.png)

 - スキーマ `HTTPS`
 - ホスト `generativelanguage.googleapis.com`
 - ベース URL `/v1beta`

上記を選択し、`2. セキュリティ`に移ります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/fda7c470-98d0-e66f-95b6-dfbf64f574dd.png)

こちらで`認証タイプ`を選択します。
`認証タイプ`は`API キー`です。

として`API キー`の設定は
- パラメーターのラベル `key`
- パラメーター名 `key`
- パラメーターの場所 `クエリ`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/0454cbd4-bb8d-5ae5-e17e-a20d3a19740a.png)

上記を選択してください。
完了次第、`3. 定義`に移ります。

ここで、一度画面右上の`✓コネクタの作成`をする必要があります。
`保存`するようなイメージです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/111c3fe4-ec97-ec9d-dff0-ebd615f2a09b.png)

成功すると下記のようなメッセージがでます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/39d586ff-061e-e2c1-77d0-7caf0de8726c.png)

次に「+ 新しいアクション」をクリックして、実際のコネクタの動作を定義します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/636d2d67-3f70-54ca-e3bc-dfcbd5c4256a.png)

`アクション名`やアクションの`概要`、`ID`を設定します。
今回は`GeminiCall`と雑につけました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/8a59022d-47cd-9e24-d9ed-3e72f2ab8365.png)

次に「要求」の部分で「+ サンプルからのインポート」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/30fea206-8770-15ad-10d2-32a4e2d15775.png)

こちらで
- 動詞 `POST`
- URL `https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash-latest:generateContent`
- ヘッダー `Content-Type application/json`

上記を設定します。

`本文`は最初に登場したプロンプトの*JSON*を設定し、`インポート`をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/2a238377-a809-5a1b-2a33-aca7b515d3e1.png)

インポートが成功すると下記のような画面になります。
この中で`カスタムコネクタ`を呼び出すとき`Content-Type`と`body`が設定すべき値となります。
`Content-Type`は固定なので、値を固定にしましょう。`Content-Type`をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/cae57828-1c96-fefc-3123-83a1fe0da527.png)

`既定値`を`application/json`に設定し、必須項目に設定。表示を`internal`します。
これで固定的に設定される値になりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/1fffbbf5-fc74-65ab-56ca-fec8d5283a54.png)

`body`は必須をオンにする以外はほとんど変更していません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/52114d11-7cbe-f247-5515-9bd23c070803.png)

ここから一気に「6.テスト」まで移ります。
ここでテストを実行するために一度`✓コネクタの作成`をする必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/7b607df4-98a0-482f-bc95-3bd9ecbf281a.png)

更新後、`テスト操作`のための接続作成が必要になります。`+ 新しい接続`をクリックしましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/2c7558b1-c698-31e3-4dfc-34de387d5d36.png)

*Gemini*の*API キー*を設定してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/cdd0119a-c84b-209a-161a-807ec0e60ad3.png)

接続を作成すると、赤枠のような情報が出ます。
即時に反映されるわけではないので、適宜リフレッシュボタンを押して状態を見ましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/dc65b9ca-5207-ba3d-99e8-35cd50746b95.png)

いよいよテストです。`Content-Type`は自動的に設定されます。
`未加工の本文`を`オン`にして前述の*JSON*を本文にテストを実行すると、おそらく成功するでしょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/38fbc46d-9e03-aaa1-33c5-583fd076378e.png)

上手くいくと回答が返ってきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/7ed21431-d8ce-6991-fe9a-23102e4b5d2f.png)

### フローの作成
フローでは、`アクション`で`ランタイム`が`カスタム`の部分に作成したコネクタが反映されていることがわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/845774cb-c7fc-875b-b182-53db8eef1e66.png)

GUIでプロンプトを設定できることが魅力です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/aad2e1be-9de4-babf-4a6f-c1bc9c364aba.png)

サクっと`カスタムコネクタ`が作成できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/0e28c83e-c4d8-fa0c-6d8b-5db49496b8c4.png)

# 問い合わせ代行のためのPower Automateの設定
いよいよ本題に移ります。

1. 「選択したメッセージの場合」を選択
2. プロンプトを設定
3. `Gemini`を呼び出す
3. 返答を投稿する

:::note info
2024.06.23時点では、`選択したメッセージの場合`はクラシックデザイナーにのみ対応しています
:::

プロンプトは下記のように設定しました。

```plaintext:プロンプト
あなたは非常に丁寧で知識豊富なアシスタントです。ユーザーからの問い合わせに対して、以下のガイドラインに従って回答してください。

1. 丁寧な対応: ユーザーに対して常に丁寧な言葉遣いを心がけ、敬意を持って対応してください。相手を尊重し、親しみやすさを感じさせるトーンで返答します。
2. 要点をかいつまむ: 回答は簡潔に、かつユーザーが必要とする情報を漏れなく提供してください。詳細すぎる説明は避け、わかりやすい例や具体的なポイントを挙げることを心がけます。
3. 追加の情報提供: ユーザーがさらに詳細な情報を求める場合に備えて、追加のリソースや参考リンクを提案することも検討してください。
4. 質問の明確化: ユーザーの質問が不明瞭な場合は、明確化のための追加の質問を行い、正確な情報を提供できるよう努めてください。
5. 積極的なフォローアップ: 回答後もユーザーが満足しているか確認し、必要に応じて追加のサポートを提供する意向を示してください。

以下のユーザーからの質問に対応してください：

質問: 「@{triggerBody()?['teamsFlowRunContext']?['messagePayload']?['body']?['plainText']}」
```

ユーザーへの返答は`チャットまたはチャネルでメッセージを投稿する`アクションを使います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/4e52bf9c-a7a3-7346-6473-9e1494509b4c.png)

- 投稿者 - `ユーザー`
- 投稿先 - `Group Chat`
- Group Chat - `triggerBody()?['teamsFlowRunContext']?['conversation']?['id']`

一対一の会話も`Group Chat`で設定します。
この会話のIDを取得するために`会話ID triggerBody()?['teamsFlowRunContext']?['conversation']?['id']`を`選択したメッセージの場合`のトリガーから取得しています。

`['conversation']?['id']`が会話IDです。

投稿するメッセージは`body('Generate_Content')?['candidates'][0]?['content']?['parts'][0]?['text']`を設定します


### 例：「Outlookの使い方がわかんないんだけど」
ユーザーからこのような質問が来たとします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/0109aaeb-bbf5-3e2e-421f-a00fd52fba6c.png)

ちょっとイラっとしなくもないですが・・・、このメッセージを右クリックし、Power Automateフローを起動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/b64d5f51-4d40-38f9-df23-36e088a50cd5.png)

:::note warn
ラグが発生しているのか、初期段階の雑な名前がそのまま残ってしまっています💦
:::

*Gemini*の回答がコチラ！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/f025531b-863a-50b3-d281-6cae80ffc984.png)

```plaintext:Geminiの回答
Outlook の使い方が変わって戸惑っていらっしゃるんですね、お気持ちお察しします。ファイル添付ができないとのことですが、具体的にどのような状況でしょうか？ 例えば、 * 以前はファイル添付ができたのに、最近できなくなった * 特定のファイルだけ添付できない * 添付しようとした時にエラーメッセージが出る など、状況によって原因と解決策が異なります。 もし可能でしたら、もう少し詳しく教えていただけますか？そうすれば、より的確なアドバイスができます。 もし、他に何か困っていることがあれば、遠慮なくお申し付けください。
```

素晴らしい！！

非常に丁寧な返信が返ってきました。この返信を使用し、カンバセーションIDを利用して適切なスレッドに返信します。

## おわりに
常に親切丁寧対応ができたら嬉しいですが、現実的には難しい場面もありますよね。
*Gemini*を使える場合は、コスト面の強さも含めて簡素化したいものです。

本日も読んでいただき、ありがとうございました。​​​​​​​​​​​​​​​​