Flowのみで実装するChatGPT・SalesforceのAPI連携

# 1. Introduction
本記事は非エンジニア向けにSalesforce上でもChatGPTを利用する機能を構築を説明しております。
Apex等プログラミング言語を用いず、ノンコードでAPI連携を構築できるので、これからSalesforceの開発に取り組む方の一助になればと思います。

:::note info
Winter'24で実装されたFlowの最新機能を用いて実装します！
[HTTP コールアウトを介してコードなしで Salesforce データを外部サーバーに送信 (正式リリース)](https://help.salesforce.com/s/articleView?id=release-notes.rn_automate_flow_builder_http_callout_post.htm&release=246&type=5)	
:::
# 2. 目次
以下の流れでSalesforceからChatGPTのAPIを呼び出す機能を構築します。

| No. | 章 |
|:-:|:--------------------|
| 1 | [3_1. API(OpenAI)の仕様書の確認](#3_1-API(OpenAI)の仕様書の確認) |
| 2 | [3_2_1. 外部ログイン情報の構築](#3_2_1-外部ログイン情報の構築) |
| 3 | [3_2_2. 指定ログイン情報の構築](#3_2_2-指定ログイン情報の構築) |
| 4 | [3_3. 画面フローの構築](#3_3-画面フローの構築) |

# 3. 手順
Winter'24で実装された機能の為、参考となるドキュメントが一切ありませんでした…
ただ、本記事の実装方法をマスターすると、Apexで実装するよりも1/2の工数(筆者体感…)で実装できるため、触ってみて良かった！となるはずです…

## 3_1. API(OpenAI)の仕様書の確認
タイトルにある通り、Flowを使ってSalesforceから**ChatGPT**を呼び出す機能を構築する為、呼び出し先のChatGPTのAPIドキュメントを見てみましょう。

[Chat Completions API](https://platform.openai.com/docs/guides/text-generation/chat-completions-api)に記載の通り、以下のURLがAPIを呼び出すエンドポイントの様です。
本ドキュメントにはJavaScriptやPythonで呼び出すサンプルコードが記載されてますね。

```js:サンプルコード（Node.js、抜粋)
const response = await openai.chat.completions.create({
    model: "gpt-3.5-turbo",
    messages: [{"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Who won the world series in 2020?"},
        {"role": "assistant", "content": "The Los Angeles Dodgers won the World Series in 2020."},
        {"role": "user", "content": "Where was it played?"}],
  });
```

上記記載の通り、今回はChatGPTのバージョン「gpt-3.5-turbo」を利用する為、[Chat Completions API](https://platform.openai.com/docs/guides/text-generation/chat-completions-api)をエンドポイントとして指定します。
APIのリファレンスは[こちら](https://platform.openai.com/docs/api-reference/chat/create)。

```html:エンドポイント(Chat Completions API)
https://api.openai.com/v1/chat/completions
```

:::note info
[Continuous model upgrades](https://platform.openai.com/docs/models/continuous-model-upgrades)にも記載の通り、ChatGPTには「gpt-4」等様々なバージョンが存在します。利用するバージョンによってChatGPTの性能が異なるようです。
:::

:::note alert
ChatGPTはエンドポイントとして[Completions API](https://platform.openai.com/docs/guides/text-generation/completions-api)がありますが、今年中に廃止される機能の為、**絶対**に使用しないでください。
:::

## 3_2_1. 外部ログイン情報の構築
Salesforceの画面を開き、ChatGPTのAPIを利用する為の認証情報を追加します。
設定画面を表示し、セキュリティ＞指定ログイン情報＞**外部ログイン情報**を選択し、以下の画面から「新規」ボタンをクリックしてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/c536dcea-4935-1baf-5a19-67a54e0e71bc.png)

以下の通り、「新規外部ログイン情報」を作成する画面が表示されるので、任意の名称を入力の上、「認証プロトコル」を「カスタム」に設定の上、「保存」ボタンをクリックしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/d61a89ee-4b3a-732e-156a-490b1c46fae7.png)

保存すると以下のとおり詳細設定画面が表示されるので、Chat GPTを呼び出すために必要な情報を設定していきます。
※赤枠部分が設定する箇所になります！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/dbf6e57f-ddc8-bbd2-46f4-ec8e231ddec0.png)

### 3_2_1_1. プリンシパルの設定
Salesforceにおける「プリンシパル」は、一般的にユーザー、グループ、またはシステムなど、リソースにアクセスする権限を持つエンティティを指します。
Chat GPTを呼び出す際に必要な情報をパラメーターとして定義するもの、とここでは理解ください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/5de5f3f7-b05f-7100-2103-874cb561839d.png)

![タイトルなし.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/ff5d75c9-676d-a042-179e-7052d1077374.png)

上記の通り、必要なパラメーターは「API Key」「Org」のみです。
早速Chat GPTのパラメーターを設定していきましょう。

:::note info
パラメーターの名称は任意で設定できます。
お好きな名称で設定ください。
:::

[OpenAI developer platform](https://platform.openai.com/docs/overview)よりログインし、以下の画面を表示してください。
画面サブの「Setting」をクリックし、「Organization ID」に表示されている文字列をコピーします。 - ①

![スクリーンショット 2023-11-16 214054.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/33246fa7-982b-ead6-3dc6-ff7d5c8cf73d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/00bc09e4-26e0-0a82-246a-dd43247f5f50.png)

次に、「API keys」を選択し、「Create new secret key」をクリックします。

![API-keys-OpenAI-API.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/6f4d9b9c-599b-82c6-b7bb-7abaeb0c047a.png)

任意の名前を入力し、「Create secret key」を選択してください。
APIを呼び出すための**Key**が発行されるので、生成された文字列をコピーしてください - ②

![API-keys-OpenAI-API (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/aa2e1919-fc6c-69c9-fd85-2ee9747c2e1b.png)
![API-keys-OpenAI-API (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/37ca4625-bf78-7f0d-9b87-eaff3f996eb0.png)

::: note alert
一度生成されたAPI Keyは**再度表示する事が出来ません**。
生成されたAPI Keyを忘れた場合は再度生成する必要があるので、忘れないように控えておいてください。
:::

## 3_2_2. 指定ログイン情報の構築
外部ログイン情報の時と同様に、設定画面を表示しセキュリティ＞指定ログイン情報を選択し、以下の画面から「新規」ボタンをクリックしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/691864bc-f1ab-5f2c-c9e7-77b97fc090a5.png)

以下赤枠部分に必要な情報を入力し、「保存」ボタンをクリックしてください
・入力前
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/00ff9777-4021-bc9e-13a5-96a1de9f50c8.png)

・入力後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/f3d4be96-9add-aec0-8494-f55e6132c3ed.png)

:::note info
項目「URL」には[Text generation model](https://platform.openai.com/docs/guides/text-generation/text-generation-models)に記載の通り、「https://api.openai.com/v1/completions
」を入力し、項目「外部ログイン情報」には[3_2_1. 外部ログイン情報の構築](#3_2_1-外部ログイン情報の構築)で作成した外部ログイン情報を設定する。
:::

### 3_3. 画面フローの構築
これでSalesforceからChatGPTを呼び出す準備が整いました！
上記で作成した認証情報を元に、画面フローからChatGPTを呼び出しましょう。

設定画面を表示し、プロセスの自動化＞フローを選択し、以下の画面から「新規」ボタンをクリックしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/bea4b33f-0c76-5e50-3487-9d682bc4860c.png)

完成したフローは以下になります。
今回は、開発に際しポイントとなる下図①「ChatGPT入力画面」②「HTTPリクエストの作成」③「HTTPリクエストの実行」④「HTTPレスポンスの処理」を解説します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/6477b514-30e0-0947-de97-9fb92e75cc9e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/b54bfd55-b561-71ed-2ac0-e32ac24ea6b4.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/dcfb7f75-9566-1366-8838-9b117ebbf71c.png)

#### ①「ChatGPT入力画面」
下記の通り、Salesforceの画面（今回はケースレコード詳細画面を想定）にて、ChatGPTへの命令文（プロンプト）を入力する画面を作成しました。
特筆すべき事項はないですが、赤枠部分の「SelectCaseRecord.Description」は、表示したケースの項目値をプリセットするために用意しております。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/2a43631d-8edd-f6d9-3f7d-fd84abfc8cc8.png)

#### ②「HTTPリクエストの作成」
ChatGPTに対するHTTPリクエストを作成しております。
[The message object](https://platform.openai.com/docs/api-reference/messages/object)にも記載の通り、最低限パラメーター「Message」の「role」「content」に値を入力する必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/2d9cf458-cb23-e9af-fa3e-b05332775e69.png)

また、以下の画面の通り、上記で作成した変数をパラメータ「Message」に、パラメーター「model」に今回利用するChatGPTのモデル（今回は「gpt-3.5-turbo」を利用）を設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/94d09f80-9076-0e1c-7696-b8aa0f94bf07.png)

::: note alert
HTTPリクエストを作成するにあたり、2つのフローの変数を作成しました。
　１．Apex定義「RequestBody」：実際に送信するHTTPリクエスト
 　　┗ExternalService__（外部サービス名）_（外部サービスの操作）**_IN_body**
　２．Apex定義「RequestBodyMessage」：１内のパラメーター「Message」の定義
 　　┗ExternalService__（外部サービス名）_（外部サービスの操作）**_IN_body_messages**

なお、詳細な内容は割愛しますが、上記外部サービスは[3_2_1. 外部ログイン情報の構築](#3_2_1-外部ログイン情報の構築)[3_2_2. 指定ログイン情報の構築](#3_2_2-指定ログイン情報の構築)にて外部ログイン情報及び、指定ログイン情報が作成されると同時に自動的に作成される資材で、併せて動的なApexクラスも作成されます。

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/ff747ddc-0449-b24d-7f54-3150373caf7a.png)

上記変数１．Apex定義「RequestBody」２．Apex定義「RequestBodyMessage」については、下記の通り自動的に作成されたApexクラスを元に変数を作成し、利用してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/e87f164d-9d77-6b5b-c857-4a17ae1e49c4.png)

:::

#### ③「HTTPリクエストの実行」
今度は作成したHTTPリクエストを実行するアクションを作成します。

アクションの作成画面から、右下の「HTTPコールアウトを作成」を押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/37c3d3bf-82bc-ec5b-d6b2-39331a1889db.png)

任意の名称を入力し、項目「指定ログイン情報」に[3_2_2. 指定ログイン情報の構築](#3_2_2-指定ログイン情報の構築)で作成した指定ログイン情報を入力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/442bd967-541f-8b14-6028-ce5731c62078.png)

次に表示された画面から、項目「メソッド」に「POST」と入力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/da65cbed-4138-9795-c93b-2fbb3ce1cada.png)

画面をスクロールすると、HTTPリクエストおよびHTTPレスポンスの形式を定義するボタンが表示されます。
サンプルとなるJSONを入力する必要があるので、[The message object](https://platform.openai.com/docs/api-reference/messages/object)に記載の下記コードを入力してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/a36b75e8-b8ad-47e8-a942-1f2bbf0e9146.png)

```json:サンプルリクエスト（JSON)
{
  "id": "msg_abc123",
  "object": "thread.message",
  "created_at": 1698983503,
  "thread_id": "thread_abc123",
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": {
        "value": "Hi! How can I help you today?",
        "annotations": []
      }
    }
  ],
  "file_ids": [],
  "assistant_id": "asst_abc123",
  "run_id": "run_abc123",
  "metadata": {}
}
```

```json:サンプルレスポンス（JSON)
{
  "id": "msg_abc123",
  "object": "thread.message",
  "created_at": 1699017614,
  "thread_id": "thread_abc123",
  "role": "user",
  "content": [
    {
      "type": "text",
      "text": {
        "value": "How does AI work? Explain it in simple terms.",
        "annotations": []
      }
    }
  ],
  "file_ids": [],
  "assistant_id": null,
  "run_id": null,
  "metadata": {}
}

```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/6bda5ee1-63d4-e085-7a69-4497c6b911c1.png)

最後まで設定が完了すると、以下の通りアクションの編集画面が表示されます。
ここまでくれば作業完了です！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/15ca8a34-1938-0f6a-7d96-577520db31a9.png)

#### ④「HTTPレスポンスの処理」
HTTPリクエストの結果を処理する機能を構築します。
別途作成した以下のような変数に、HTTPレスポンスの値が**自動的**に格納されます。

::: note alert
HTTPレスポンスも同様に、フローの変数を作成する必要がある。
　Apex定義「ResponseBody」：実際に受信するHTTPレスポンス
 　　┗ExternalService__（外部サービス名）_（外部サービスの操作）**_OUT_2XX**
   
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/66d491cf-188c-f0a9-e119-c0e1096d67d5.png)

:::

下図の通り、HTTPレスポンスの「responseCode」が「200」の場合（つまり、リクエストが成功した場合）、条件分岐させます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/a4b531b0-a093-4967-0093-e1f1ac79c136.png)

下図の通り、取得したHTTPレスポンスの「choice」要素をループさせ、その要素内の「message.content」のみ抽出します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/c05a7c65-a7cd-cc43-a66a-177385a9adcf.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/9c9f303f-0c2a-89db-9527-ba46bd931bef.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/7d4da880-14a6-235a-26e1-88049762a2c4.png)

この要素「message.content」こそ、普段我々が目にしているChatGPTの返答内容です。

# 4. 完成形
お疲れ様でした！
今まで開発した内容を実際に挙動させると以下の通りになります。

①配置した画面フロー内に、ChatGPTに聞きたい内容を入力

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/34279fd3-0bc5-c808-e0e6-3d73014682cb.png)

②入力した内容を確認する画面が表示される

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/4c61ed6c-9da3-d205-37af-c7f962539177.png)

③（処理中）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/cafa0f00-aade-28a2-a645-35be7ee3a416.png)

④ChatGPTの出力結果が表示される！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644257/1849c9d1-bfaa-d697-9766-102e5866f2a9.png)

# 5. おわりに
今までSalesforceから外部システムへ接続する為にはApexなどのプログラミングが必須でした。
しかし、今回こちらの記事で紹介した通り、フローを利用したノンコードでも機能実装が可能です！

今後、フローで出来る事がますます増えそうですね。