【Salesforce × AI/ML】導入アプローチと具体的な実装方法をご紹介！

# はじめに
筆者らは企業の重要な情報（既存顧客情報、見込み客情報、商談情報など）を1カ所に集約し、それを展開・連携・活用できるプラットフォームであるSalesforceと、大量の情報の中から法則性や成功のカギを見つけることを得意とするAI/ML(Artificial Intelligence / Machine Learning)とは、非常に相性が良いのではないかと考えています。これらを上手く掛け合わせることができたならば、営業・マーケティング・サービスなどに大きな影響を与えるだけでなく、企業の今後を左右するような重要な意思決定にまでも大きな影響を与える可能性があると信じています。

# 第1部	導入アプローチ
第１部では、はじめにSalesforceでAI/MLを正しく活用するための前提知識について簡単にご説明し、SalesforceとAI/MLと繋ぐアプローチ例とそれぞれの特徴についてご紹介します。第2部では、Salesforceと外部AI/ML基盤とを連携する手法についてご紹介します。特に第2部の外部AI/ML基盤との連携については、ネットに公開されている情報が乏しいので、ここで具体例を1つ取り上げ、Hands-on形式でご紹介しています。是非みなさんの手で実機を動かしてSalesforce × AI/MLの大きな可能性を実感していただきたいと思っています。

## SalesforceでAI/MLを正しく活用するには？
　ここでは、SalesforceやAI/MLとはいったいどういったものなのかという前提知識について簡単にご説明します。基本を既にご存じの方は、ここを読み飛ばしていただいても問題ありません。

　SalesforceでAI/MLを正しく活用するためには、3つのステップがあります。まず1つ目のステップはSalesforceとは何か？AI/MLとは何か？を知ることです。SalesforceとAI/MLの特性を理解することで、お互いの強みを最大限に活かすことができますし、またSalesforceでAI/MLを活用する目的を明確に設定できるようになり、無駄な開発/運用コストを削減することに繋がります。2つ目のステップはSalesforceとAI/MLを繋ぐにはどのようなアプローチがあるかを知ることです。SalesforceとAI/MLを繋げる方法はいくつか存在しますが、選択するアプローチによって拡張性や開発/運用コストが大きく異なります。目的に応じた選択ができるように、各々のアプローチのメリット・デメリットを理解しておきましょう。そして３つ目のステップは実際にSalesforceとAI/MLを繋げて使ってみることです。頭の中であれこれ考えることも大切ですが、実際に使ってみて初めて得ることのできる情報もあります。是非、本記事の後半でご紹介するHands-onも参考にして使ってみてください。

＜Salesforceとは＞
Salesforceとは何か。一言でまとめるならば顧客管理システム(CRM)です。主に各企業の営業担当者やコールセンター等で活用されることが多く、顧客情報から社内ナレッジまで様々な情報を一括管理することができます。また、公式が出しているブログ内の説明が分かりやすかったので、以下に載せています。こちらも合わせてご覧ください。

私たちSalesforceは、企業と顧客の絆を深める会社です。 
私たちは、従来企業の部門間に存在するサイロ（個別最適でシステムを構築し、それらの連携が取れていない状態）をなくして顧客に関する情報を一元管理し、マーケティング、セールス、コマース、サービス、ITなどすべてのチームで共有するための、統合型の顧客管理（CRM）プラットフォームを提供しています。顧客を360度の視点で理解するためのこの仕組みを、私たちはSalesforce Customer 360と呼んでいます。この仕組みにより、従業員全員が顧客一人ひとりを包括的に把握できるため、顧客のニーズに迅速に対応したり、冗長なコミュニケーションが不要になり、顧客とより良い関係を築くためのパーソナライズされた対話が可能になります。さらに完全にデジタル化されているため、お客様のニーズにどこからでも迅速に対応することができます。
セールスフォース・ドットコムって何をしている会社？ - Salesforceブログ - Salesforceブログより

＜AI/MLとは＞
次にAI/MLとは何か。AI/MLと聞いて思いつくものは何かと問われると、スマートアシスタントや自動運転、Facebookなどでよく見る「ユーザひとりひとりに合わせたレコメンド機能」、そして最近話題のChatGPT。さまざまな製品や機能を思い浮かべる人が多いのではないかと思います。イメージとしては、機械がたくさんのデータを読み取って自ら学習し、学習した結果を人間に還元してくれるものといったところでしょうか。この認識は筆者らも正しい認識だと考えていますが、実際にAI/MLを導入しようとするエンジニアにとってはもう少し掘り下げた理解が必要です。
AI/MLは、コンピュータ(計算機)がデータから学習できるようにするためのアルゴリズムによって形作られています。そのアルゴリズムというのは用途や目的を意識して作成されることが多いため、作成者の意図とは異なる使い方をした時はたいてい上手く動作しません。逆に言うと、アルゴリズムの意図に合ったデータを正しく使うことができたなら、そのAI/MLは本領を発揮して人知を超えた価値を与えることができます。SalesforceとAI/MLとを組み合わせる時においても、このことを意識していただきたいと思っています。

## SalesforceとAI/MLと繋ぐアプローチ例とそれぞれの特徴
　ここでは、SalesforceとAI/MLを繋ぐアプローチについて３つ例を挙げ、筆者らが思うそれぞれの特徴も合わせて挙げています。また、それぞれのアプローチはどのような状況下において選択され得るのかについても言及しています。（各状況については、開発者レベル、保守・運用者レベル、Salesforce使用状況、組織の意向の4つの観点から定義し、ユーザに求めるレベルはどれも等しく「AI/MLについての知識はほとんどない」としています。）

### アプローチ1： Salesforce社が公式に提供しているAI/MLツール ”Einstein”
　Einsteinは、Salesforce社が公式で提供しているAI/MLツールです。専用のライセンスを契約することで、様々な種類のAI/MLを活用することができます。Einstein用のライセンスを契約することで（※）、AI/MLアルゴリズムの知識を必要とせずにSalesforce用に最適化されたAI/MLを使うことができます。またSalesforce社が公式で出しているので、Salesforceの成長とともに自動で機能更新されます。一方で、CRMもAI/MLも全てSalesforceで行おうとすると、Salesforceのリソースを圧迫してしまう可能性があります。
※場合によっては追加ライセンス不要です。

【アプローチ1が選択され得る状況例】
開発者レベル：AI/MLについての知識はほとんどない
保守・運用者レベル：AI/MLについての知識はほとんどない
Salesforceの使用状況：Salesforceを全社的に使用しており、追加ライセンスを取得することついても問わない。
組織の意向：組織内にはAI/MLに詳しい人がいないが、最新のAI/MLを使い、社内にあふれるSalesforceデータを利益に活用したいと思っている。また、AI/ML人材にあまりコストをかけたくないと思っており、定期的に行われるSalesforceのアップデートとともに自動でAI/ML機能もアップデートしてほしいと思っている。

### アプローチ2：外部AI/ML基盤との連携
　CRMとAI/MLを別々の環境で行うことで、Salesforceのリソースの圧迫を防ぐことができ、それぞれの処理速度が速くなる場合が多いです。またSalesforceの追加ライセンスについても特に考慮しなくてよく、既にAI/MLに必要なものが用意されているAI/ML基盤を使うので、AI/MLを使う技術力は必要ですが、アルゴリズムを作る技術力は不要です。とはいえ作成するにはSalesforceとAI/ML基盤を繋げる技術やAI/MLの基礎知識は必要で、Salesforceとは別に外部AI/ML基盤の使用料金がかかります。

【アプローチ2が選択され得る状況例】
開発者レベル：AI/MLを作る技術はないが、使う技術はある。
保守・運用者レベル：AI/MLを作る技術はないが、使う技術はある。
Salesforceの使用状況：現在使用しているライセンスでは、残っている計算リソースがわずか。他のデータストレージも使用しており、AI/MLを活用したいデータがSalesforce内だけではない。
組織の意向：新たにSalesforceの追加ライセンスを使用する予定はなく、現在使用しているSalesforceの性能を落とさずに（リソースを圧迫せずに）AI/MLを取り入れたいと思っている。また使用するのはSalesforceの一部のデータだけであり、場合によってはSalesforce外に保存されているデータも用いる。それらのアルゴリズムを外部AI/ML基盤によって構築できる知識を持っている。

### アプローチ3：ApexにAI/MLエンジンをハードコーディング
　Salesforceの追加ライセンスも外部AI/ML基盤の使用料金もかからない最も運用コストの低い手法です。しかし自分でAI/MLアルゴリズムを作成できる技術力が必要であったり、複雑なAI/MLロジックを構築する場合、Salesforceのガバナ制約に抵触する可能性があったり、日々Open Sourceで開発されていく新たなアルゴリズムを取り込めないなど、理論的には実現可能かもしれませんが、企業に導入することを考えると現実的には不可能に近いと考えています。そのため今回はこの手法に関しては章立てて言及しないこととします。

【アプローチ3が選択され得る状況例】
開発者レベル：AI/MLを作る技術が‘ある。
保守・運用者レベル：AI/MLを作る技術が‘ある。
Salesforceの使用状況：小規模なグループで使用している。またSalesforceの計算リソースにも十分な空きがあり、活用したいAI/MLもApexのリソースで実現できる範囲の単純なロジックになっている。
組織の意向：組織内に1からAI/MLエンジンを作ることができるAI/MLエンジニアがおり、その人材を活かしたいと思っている。また可能な限りライセンス費用を抑える必要がある。

第2部では、アプローチ2で紹介したSalesforceと外部のAI/ML基盤との連携についてHands-on形式でご紹介します。また、今回筆者らは外部のAI/ML基盤としてAmazon SageMakerを使用しています。Amazon SageMakerとは、AI/MLを使用する時に必要なもの（計算機やAI/MLエンジンなど）をまとめてレンタルできるサービスです。公式の説明では以下のように書かれています。

Amazon SageMakerは、フルマネージド型の機械学習サービスです。SageMakerを使用すると、データ科学者や開発者は、迅速かつ容易に機械学習モデルを構築して訓練し、本番環境に直接デプロイすることができます。Jupyterオーサリングノートブックのインスタンスが統合されており、データソースに簡単にアクセスして探索や分析ができるため、サーバーを管理する必要がありません。また、分散環境において非常に大きなデータに対して効率的に実行できるように最適化された一般的な機械学習アルゴリズムも提供します。SageMakerは、Bring-your-own-algorithmsとフレームワークのネイティブサポートにより、特定のワークフローに適応する柔軟な分散学習オプションを提供します。SageMaker Studio または SageMaker コンソールから数回クリックするだけでモデルを起動し、安全でスケーラブルな環境にデプロイすることができます。
What Is Amazon SageMaker? - Amazon SageMakerをwww.DeepL.com/Translator（無料版）で翻訳。
 
# 第2部	実装手順
## 実装機能概要
今回は、住宅の適正価格をAI/MLで算出する機能をSalesforceに実装します。
不動産業者が住宅を査定する際に、物件の条件を入力すれば、AI/MLが適正価格を算出してくれる、、そんなイメージです。（Einsteinで同様の機能を実現しようとする場合、Einstein予測ビルダーが利用できそうです。）

アーキテクチャは下図の通りです。SageMakerで作成した学習済みモデルをApexから呼び出します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636007/c4c8ed1a-fa3b-e769-2ef7-d48f5be70987.png)


この機能の検証のため、AI/MLの学習においてよく使用されているBoston Housingという住宅価格データセットを使用します。これは、1970年代後半におけるボストンの住宅について、町別の犯罪率、1戸あたりの平均部屋数などの住宅価格に関係するパラメータと住宅価格の中央値を格納した表形式のデータセットで、今回使用する説明変数と目的変数は以下の通りです。

説明変数
|変数名|意味|
|----|----|
|DIS|主要施設への距離|
|RAD|主要道路へのアクセス性|	
|AGE|古い家の割合|	
|TAX|固定資産税率|	
|INDUS|非小売業の割合|	

目的変数
|変数名|意味|
|----|----|
|MEDV|住宅価格の平均値|

機能の開発は以下の手順で行います。
1.	S3への学習データ格納とSageMakerでのモデル構築
2.	Postmanを用いた疎通確認
3.	Salesforceのオブジェクト作成とデータ投入
4.	指定ログイン情報の設定
5.	SalesforceからSageMakerを呼び出すApexクラスの作成
6.	LWCの作成

## 実装手順
### 【手順1】 S3への学習データ格納とSageMakerでのモデル構築
まず初めに、Boston Housingデータセットを、Amazon S3に配置します。

Amazon S3を開いてバケットを作成し、Boston Housingのデータファイルをアップロードします。
今回は上記の説明変数と目的変数のみの列に絞ったcsvファイルを使用します。1列目に目的変数、2列目以降に説明変数を並べます。
AI/MLの学習と推論では通常は異なるデータを使用しますが、今回は全てのデータで学習をさせます。（今回はあくまでSalesforceからSageMakerによる推論を利用する機能の検証に主眼を置いているため、このあたりは簡素化しています。）

アップロードしたファイルのs3 URIをメモします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636007/3164bccc-0dbc-adfa-3792-2185871fd1b6.png)
次に、SageMakerを使用してモデルを構築していきます。
SageMakerを開き、「トレーニング」＞「トレーニングジョブ」から「トレーニングジョブの作成」をクリックします。その後、ジョブ名とIAMロールを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636007/1b027de3-fedb-d8c0-404a-13a8390c076b.png)
AI/MLモデルは「Tabular - XGBoost : v1.3」とします。XGBoostは決定木ベースの回帰モデルです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636007/bcdda0a1-95be-f620-f18a-52ad7b216aeb.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636007/e67c9678-e81b-17aa-56bf-4d6fad00fa17.png)
ハイパーパラメータは以下のように設定します。ほとんどデフォルト値です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636007/d08989e3-f162-676b-b223-b362ea1bea19.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636007/98ca625d-6f27-b38b-3ccc-771371638e97.png)
入力データ設定で、先ほどS3に格納したデータファイルのs3 URIを入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636007/dde63847-bf30-04fd-6b07-b7cb4751caa1.png)
「トレーニングジョブの作成」をクリックします。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636007/5f37eacb-da5f-b5cf-a6c9-46466b383d44.png)
Completedになったことを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636007/baaf2c80-fd36-ac2e-59ef-975b441a1fa1.png)
作成したトレーニングジョブを開き、「モデルの作成」をクリックします。
その後、任意のモデル名を入力してモデルを作成します。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636007/76e29258-b31a-5e97-466a-c0df3a0a2b7e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636007/561c464c-a367-b721-1ce5-78bd7557ebfb.png)
出来上がったモデルを開き、「エンドポイントの作成」をクリックします。
その後、以下の通り入力し、「エンドポイント設定の作成」＞「エンドポイントの作成」をクリックします。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636007/06d4f82e-2de4-b371-f829-38dfed0c34a7.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636007/645803c6-5c4c-1430-0ca7-17b69f436f80.png)
エンドポイントが立ち上がったことを確認し、URLをメモします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636007/0e1e7cc3-b1c9-4808-fae3-f5bf2e2366e7.png)
### 【手順2】 Postmanを用いた疎通確認
PostmanというアプリでHTTPリクエストを投げてSageMakerの学習済みモデルに推論を行わせることができるか確認します。

準備として、AWSでIAMユーザを作成し、アクセスキーとシークレットキーをメモします。
（参考：IAM の準備作業>管理ユーザーを作成する、管理ユーザーを作成する）

Postmanのデスクトップアプリを起動し、エンドポイントのURLを入力します。
また、「Authorization」タブからAWSの認証情報を設定します。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636007/e5927fb3-916e-03dc-d0f6-0c1d980dabac.png)
ヘッダーを以下のように設定します。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636007/9494f47b-795c-9c35-3d89-722d765eff76.png)
ボディには説明変数を順番にカンマ区切りで記載します。
例えば、1行目のデータでは、以下のようになります。その後、「Send」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636007/d1a9f161-539e-93db-a365-55fe270d63c4.png)
レスポンスが返ってきました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636007/6546dbeb-8b52-7123-1563-9a006f6ba55b.png)
実際の値（24.0）と照らし合わせても妥当な値ですね。
以上で、HTTPリクエストでSageMakerのモデルに推論させることができると確認できました。

### 【手順3】 Salesforceのオブジェクト作成とデータ投入
続いて、Salesforce側に賃貸住宅のオブジェクトを作成します。
Salesforceに「賃貸物件」（API名：Rental__c）というオブジェクトを作成し、下表の項目を作成します。
（Bostonの住宅価格のデータセットの対象は賃貸物件ではないですが、思い込みで賃貸物件としてしまいました、、）

|表示ラベル|項目名（API名）型|型|
|----|----|----|
|主要施設への距離|DIS__c|数値(2,2)|
|主要高速道路へのアクセス性|RAD__c|数値(2,0)|
|古い家の割合|AGE__c|パーセント(3,1)|
|固定資産税率|TAX__c|数値(4,0)|
|平均部屋数|RM__c|数値(2,3)|
|非小売業の割合|INDUS__c|パーセント(3,2)|
|住宅価格|MEDV__c|数値(4,1)|
|住宅価格（予測値）|MEDV_PRED__c|数値(4,1)|

また、データローダ等でデータを投入しておきます。

### 【手順4】 指定ログイン情報の設定
SalesforceにAWSのアクセス情報を設定します。
（参考：Salesforce の指定ログイン情報 (Named Credential) を利用した AWS へのリクエスト）

「新規」の右の▼から「新規（従来）」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636007/48e8c308-5e87-5bb9-2551-1f3f870c9cd8.png)
以下のように設定し保存します。「AWS アクセスキーID」と「AWS シークレットアクセスキー」にはAWSのIAMユーザの情報を入力します。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636007/26c43a3f-c08a-083e-333f-b26629d49e49.png)
### 【手順5】 SalesforceからSageMakerを呼び出すApexクラスの作成
初めに疎通確認用のApexクラスを作成します。

```TestCallout.cls
public class TestCallout {
    public void callout(String body){
        // リクエストを作成する。
        HttpRequest req = new HttpRequest();
        req.setEndpoint('callout:AmazonSageMaker/endpoints/boston-endpoint-2/invocations');
        req.setMethod('POST');
        req.setHeader('Content-Type', 'text/csv');
        req.setHeader('Accept', '*/*');
        req.setBody(body);

        // リクエストを投げる。
        Http http = new Http();
        HTTPResponse res = http.send(req);

        // 結果を出力する。
        System.debug(res.getBody());
    }
}
```
開発者コンソールの「Open Execute Anonymous Window」から以下のコードを実行します。
```
TestCallout caller = new TestCallout();
caller.callout('2.31,6.575,65.2,4.09,1,296');
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636007/48909cf5-1d26-4554-4e01-d9a13bc6d958.png)
 
24.04...という値が返ってきているので、疎通成功です。
※タイムアウトすることがありますが、その場合は再度実行します。（エンドポイントのタイプをサーバーレスにしているためです。）

疎通の確認が取れたので、続いて、SageMakerに説明変数を送信し、予測値を受信するためのApexクラスを作成します。

```PriceCallout.cls
public with sharing class PriceCallout {
    @AuraEnabled
    public static decimal callout(ID recordId, String INDUS, String RM, String AGE, String DIS, String RAD, String TAX){
        // リクエストを作成する。
        HttpRequest req = new HttpRequest();
        req.setEndpoint('callout:AmazonSageMaker/endpoints/boston-endpoint-2/invocations');
        req.setMethod('POST');
        req.setHeader('Content-Type', 'text/csv');
        req.setHeader('Accept', '*/*');
        req.setBody(INDUS + ',' + RM + ',' + AGE + ',' + DIS + ',' + RAD + ',' + TAX);

        // リクエストを投げる。
        Http http = new Http();
        HTTPResponse res = http.send(req);

        // 文字列で返ってくる予測値をdecimal型に変換し、小数第二位を四捨五入する。
        Decimal MEDV_PRED = decimal.valueOf(res.getBody().replace('\n','')).setScale(1, System.RoundingMode.HALF_UP);

        // 賃貸物件レコードを更新する。
        Rental__c rent = [SELECT Id, MEDV_PRED__c FROM Rental__c WHERE Id = :recordId];
        rent.MEDV_PRED__c = MEDV_PRED;
        update rent;

        // 予測値を返す。
        return MEDV_PRED;
    }
}
```

### 【手順6】 LWCの作成
callSagemakerという名前でLWCを作成します。以下がHTMLファイルです。
``` callSagemaker.html 
<template>
  <lightning-card title="住宅適正価格のAI予測" icon-name="custom:custom14">
     <lightning-button label='計算' onclick={callSageMaker} slot="actions"></lightning-button>
     <div class="slds-m-around_medium">
        <div if:true={MEDV_PRED}>
           <p>この条件の物件の価格中央値は<font size="30">{MEDV_PRED}</font>です。（単位：1000ドル）</p>
        </div>
        <div if:false={MEDV_PRED}>
           <p>この条件の物件の価格中央値は計算されていません。</p>
        </div>
     </div>
  </lightning-card>
</template>
```
予測値が既に計算されているか否かによって表示を切り替えるようにしています。

以下がJavaScriptのコードです。

``` callSagemaker.js
import { LightningElement, api, wire } from 'lwc';
import { getRecord } from 'lightning/uiRecordApi';
import callout from '@salesforce/apex/PriceCallout.callout';

const fields = [
    'Rental__c.INDUS__c',
    'Rental__c.RM__c',
    'Rental__c.AGE__c',
    'Rental__c.DIS__c',
    'Rental__c.RAD__c',
    'Rental__c.TAX__c',
    'Rental__c.MEDV_PRED__c'
];

export default class CallSagemaker extends LightningElement {
    @api recordId;
    INDUS; // 非小売業の割合
    RM; // 平均部屋数
    AGE; // 古い家の割合
    DIS; // 主要施設への距離
    RAD; // 主要道路へのアクセス性
    TAX; // 固定資産税率
    MEDV_PRED; // MEDVの予測値

    // 賃貸物件レコードの情報を読み込む。
    @wire(getRecord, { recordId: '$recordId', fields} )
    loadRecord ({error, data}) {
        if (data) {
            this.INDUS = data.fields.INDUS__c.value;
            this.RM = data.fields.RM__c.value;
            this.AGE = data.fields.AGE__c.value;
            this.DIS = data.fields.DIS__c.value;
            this.RAD = data.fields.RAD__c.value;
            this.TAX = data.fields.TAX__c.value;
            this.MEDV_PRED = data.fields.MEDV_PRED__c.value;
        } else if (error) {
            console.error('Error in loadRecord:', error.body.message);
        }
    }

    // PriceCallout.clsで定義したcallout関数によってSageMakerを呼び出す。
    callSageMaker(){
        callout({recordId: this.recordId,
            INDUS: this.INDUS.toString(),
            RM: this.RM.toString(),
            AGE: this.AGE.toString(),
            DIS: this.DIS.toString(),
            RAD: this.RAD.toString(),
            TAX: this.TAX.toString()
        }).then(response =>{
            this.MEDV_PRED = response;
        }).catch(error =>{
            console.error('Error in callout:', error.body.message);
        });
    }
}
```
## 完成
こちらが予測値が登録されていないレコードの詳細画面です。右に作成したLWCを配置しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636007/20a1cfe2-f0ee-396b-d9a2-333e12a5fe59.png)
「計算」ボタンをクリックすると予測値が表示されます。予測値（20.1）は実際の値（20.2）とほぼ一致しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636007/f2d3b654-97a9-a3c1-a7d4-8b9084dc6b9d.png)
※エンドポイントのタイプをサーバーレスにしているため、時間を空けてSageMakerの呼び出しを実行するとランタイムエラーが発生します。今回はその場合の処理まで実装していないので、再度実行することで対処します。

# さいごに
以上、SalesforceとAI/MLを繋ぐアプローチ例と、SalesforceからAmazon SageMakerを呼び出す機能の実装手順をご紹介しました。

Salesforce にしても、AI/ML にしても、使いこなすには並々ならない知識が必要となりますが、その苦難を乗り越えるだけの価値は十分にあると思っています。この記事をいろいろな人に活用してもらえると嬉しいです。この記事をいろいろな人に活用してもらえると嬉しいです。また、この記事を執筆中にEinstein GPTが発表されました。Salesforceの進化はとても速いですね！これからもAI/MLの機能の拡充に期待します。


第1部執筆：山岸善治（yoshiharu.yamagishi）
第2部執筆：西井俊貴（shunki.nishii）
2023年9月21日

# 参考文献

・Salesforceの引用
She.WITI."SALESFORCEって何をしている会社？".Salesforceって何をしている会社？ - WITI & Salesforce Working Together.2021-02-08T18:48:34+00:00.https://she.witi.com/ja/she-leads-jp/salesforce%e3%81%a3%e3%81%a6%e4%bd%95%e3%82%92%e3%81%97%e3%81%a6%e3%81%84%e3%82%8b%e4%bc%9a%e7%a4%be%ef%bc%9f/, (参照2023-09-11)

・SageMakerの引用
Amazon Web Services, Inc. or its affiliates."What is Amazon SageMaker?".What is Amazon SageMaker? - Amazon SageMaker.2023.https://docs.aws.amazon.com/sagemaker/latest/dg/whatis.html, (参照2023-09-11)