Models API - カスタム生成AIアプリケーション開発のための新たなAPI 

**Models API**は、Salesforceが新たに提供する、高度にカスタマイズしたLLMベースAIアプリケーションを開発するためのAPIです。どのようなことができるようになるのか？直接LLMにAPIアクセスするのと何が違うのか？開発者ドキュメントから抜粋してまとめました。

#### Einstein Generative AI - Models API
https://developer.salesforce.com/docs/einstein/genai/guide

:::note
Models APIは、2024年10月に正式版として一般提供を開始しました
:::

## Models APIとは？
Models APIは、Azure OpenAI、Open AIなどの標準サポートされる、Salesforceパートナー大規模言語モデル(LLM)やEinstein Studioで構成した独自モデル(BYOLLM)に対し、ApexクラスやREST API経由でのアクセスを提供します。つまり、Salesforce上のカスタムアプリケーションはもちろんのこと、**外部アプリケーション** にも、LLMを活用した組み込みAI、対話型AIアプリケーションの開発に大きな柔軟性をもたらします。

## Models APIでできること
テキスト生成だけでなく、チャット応答の生成、またRAGやベクトル検索に必須なEmbedding(ベクトル埋め込み)もサポートされます。

 - **テキスト生成**
単一のプロンプトからテキスト生成
 - **チャット応答**
一つのプロンプトだけでなく、会話履歴を考慮した応答メッセージを生成
 - **Embedding(ベクトル埋め込み)**
文章を高次元のベクトル数値に変換
 - **フィードバック**
Models APIが生成したテキストに対し、フィードバックを提供。フィードバックデータはData Cloudに保存される


## Models APIでサポートされるLLM
サポートされる代表的なモデルを抜粋します。

:::note warn
2024/7/1時点の内容になります。すべてのサポートモデル、最新情報は公式ドキュメントをご確認ください。
:::

> **Supported Models for Models API**
> https://developer.salesforce.com/docs/einstein/genai/guide/supported-models.html



### テキスト生成 & チャット応答
 - **Anthropic**
     - Claude 3 Haiku
 - **OpenAI** 
     - GPT 4o (Omni)
     - GPT 4 Turbo
     - GPT 3.5 Turbo

### Embedding
 - **OpenAI**
     - Ada 002


## Models APIの特徴


### 地理的ルーティング
地理的リーティング機能により、APIリクエストは適切なリージョンのLLMプロバイダーに自動的に振り分けられ、データレジデンシーやコンプライアンス要件に対応したデータ処理が可能になります。


> **Geographical Routing**
> https://developer.salesforce.com/docs/einstein/genai/guide/supported-models.html#geographical-routing

### データ不保持（ゼロリテンション）
Salesforceは各LLMプロバイダーとの間で、リクエストで使用されたデータをデータ保持しない契約を結んでいます。これにより、サードパーティのLLMプロバイダー側で個人データが保持される心配なく、生成AI機能を利用できます。

>**Zero Data Retention**
> https://developer.salesforce.com/docs/einstein/genai/guide/trust.html#zero-data-retention

### データマスキング
プロンプトに含まれる個人情報(PII)やクレジットカード会員情報(PCI)を識別してマスキングを行ってからLLMに送信されます。LLMが応答を返すと、Einstein Trust Layerはマスキングを戻す処理を行います。どのデータがどのような値にマスキングされたかどうかは、Data Cloud上に保存された監査証跡から確認できます。



> **Data Masking with Models API**
> https://developer.salesforce.com/docs/einstein/genai/guide/data-masking.html

### 有害性スコアリング
LLMはインターネット上の大量の公開データを元に学習されているため、本来、業務用途では許容できないような有害な内容や不適切な表現が応答に含まれる可能性があります。Models APIでは、これらの有害性の検出に応じた適切なポリシーアクションを実行できるよう、有害なコンテンツが含まれることを示すフラグとスコア情報を含めて応答します。

#### 有害性スコアリングの応答例
```json
{
"generatedText": "Once upon a time in sunny San Diego, there lived a diligent and experienced financial advisor named James Lee. With a passion for numbers and a knack for helping others achieve their financial goals, James had built a reputation as a trusted advisor in the community.\n\nJames had always been fascinated by the world of finance. From a young age, he would spend hours poring over financial newspapers and studying the stock market. As he grew older, his passion only intensified, leading him to pursue a degree in finance from a prestigious university...",
    "contentQuality": {
      "scanToxicity": {
        "isDetected": false,
        "categories": [
          {
            "categoryName": "identity",
            "score": 2.0e-5,
          },
          {
            "categoryName": "hate",
            "score": 0.0,
          },
          {
            "categoryName": "profanity",
            "score": 3.0e-5,
          },
          {
            "categoryName": "violence",
            "score": 2.0e-5,
          },
          {
            "categoryName": "sexual",
            "score": 1.5e-4,
          },
          {
            "categoryName": "physical",
            "score": 0.0,
          }
        ]
      }
    }
}
```


> **Toxicity Scoring with Models API**
> https://developer.salesforce.com/docs/einstein/genai/guide/toxicity-scoring.html



## Models APIの使い方

### Apexでの使い方
Models API対応のApexメソッドを使用します。

> **Access Models API with Apex**
> https://developer.salesforce.com/docs/einstein/genai/guide/access-models-api-with-apex.html


#### テキスト生成
サンプルコード
```apex
aiplatform.ModelsAPI.createGenerations_Request request = new aiplatform.ModelsAPI.createGenerations_Request();
request.modelName = 'sfdc_ai__DefaultOpenAIGPT4Omni';
aiplatform.ModelsAPI_GenerationRequest requestBody = new aiplatform.ModelsAPI_GenerationRequest();
request.body = requestBody;
requestBody.prompt = 'プロンプト文章';
try {
    // 成功時
    aiplatform.ModelsAPI modelsAPI = new aiplatform.ModelsAPI();
    aiplatform.ModelsAPI.createGenerations_Response response = modelsAPI.createGenerations(request);
    System.debug('Models API response: ' + response.Code200.generation.generatedText);
} catch(aiplatform.ModelsAPI.createGenerations_ResponseException e) {
    // エラー発生時
    System.debug('Response code: ' + e.responseCode);
    System.debug('The following exception occurred: ' + e);
}
```

#### チャット応答
サンプルコード
```apex
aiplatform.ModelsAPI.createChatGenerations_Request request = new aiplatform.ModelsAPI.createChatGenerations_Request();
request.modelName = 'sfdc_ai__DefaultOpenAIGPT4Omni';
aiplatform.ModelsAPI_ChatGenerationsRequest body = new aiplatform.ModelsAPI_ChatGenerationsRequest();
request.body = body;
List <aiplatform.ModelsAPI_ChatMessageRequest> messagesList = new List <aiplatform.ModelsAPI_ChatMessageRequest> ();
aiplatform.ModelsAPI_ChatMessageRequest systemMessage = new aiplatform.ModelsAPI_ChatMessageRequest();
systemMessage.content = 'LLMの発言';
systemMessage.role = 'system';
messagesList.add(systemMessage);
aiplatform.ModelsAPI_ChatMessageRequest userMessage = new aiplatform.ModelsAPI_ChatMessageRequest();
userMessage.content = 'ユーザの発言';
userMessage.role = 'user';
messagesList.add(userMessage);
body.messages = messagesList;
try {
    // 成功時
    aiplatform.ModelsAPI modelsAPI = new aiplatform.ModelsAPI();
    aiplatform.ModelsAPI.createChatGenerations_Response response = modelsAPI.createChatGenerations(request);
    System.debug('Models API response: ' + response.Code200.generationDetails.generations);
} catch(aiplatform.ModelsAPI.createChatGenerations_ResponseException e) {
    // エラー発生時
    System.debug('Response code: ' + e.responseCode);
    System.debug('The following exception occurred: ' + e);
}
```


#### Embedding(ベクトル埋め込み)
サンプルコード

```apex
aiplatform.ModelsAPI.createEmbeddings_Request request = new aiplatform.ModelsAPI.createEmbeddings_Request();
request.modelName = 'sfdc_ai__DefaultOpenAITextEmbeddingAda_002';
aiplatform.ModelsAPI_EmbeddingRequest body = new aiplatform.ModelsAPI_EmbeddingRequest();
request.body = body;
List <String> inputList = new List <String> ();
inputList.add('文章1');
inputList.add('文章2');
inputList.add('文章3');
body.input = inputList;
try {
    // 成功時
    aiplatform.ModelsAPI modelsAPI = new aiplatform.ModelsAPI();
    aiplatform.ModelsAPI.createEmbeddings_Response response = modelsAPI.createEmbeddings(request);
    System.debug('Models API response: ' + response.Code200.embeddings);
} catch(aiplatform.ModelsAPI.createEmbeddings_ResponseException e) {
    // エラー発生時
    System.debug('Response code: ' + e.responseCode);
    System.debug('The following exception occurred: ' + e);
}
```

#### フィードバック
サンプルコード

```apex
aiplatform.ModelsAPI.submitFeedback_Request request = new aiplatform.ModelsAPI.submitFeedback_Request();
aiplatform.ModelsAPI_FeedbackRequest feedbackRequest = new aiplatform.ModelsAPI_FeedbackRequest();
feedbackRequest.id = '78w60870345-2335840385-4857348-803483';
feedbackRequest.generationId = '89t608-46756v66y-23r4wqxe43-096mi';
feedbackRequest.feedback = 'GOOD';
feedbackRequest.feedbackText = 'このテキスト生成は期待された内容でした';
feedbackRequest.source = 'HUMAN';
feedbackRequest.appGenerationId = 'appGenerationId';
feedbackRequest.appGeneration = 'appGeneration';
request.body = feedbackRequest;
try {
    // 成功時
    aiplatform.ModelsAPI modelsAPI = new aiplatform.ModelsAPI();
    aiplatform.ModelsAPI.submitFeedback_Response response = modelsAPI.submitFeedback(request);
    System.debug('Models API response: ' + response.Code202.message);
} catch(aiplatform.ModelsAPI.submitFeedback_ResponseException e) {
    // エラー発生時
    System.debug('Response code: ' + e.responseCode);
    System.debug('The following exception occurred: ' + e);
}
```

### REST APIでの使い方

> **Access Models API with REST**
> https://developer.salesforce.com/docs/einstein/genai/guide/access-models-api-with-rest.html

接続アプリケーションを作成し、JWT(JSON Web Token)を発効し、取得したアクセストークンを用いてREST APIにアクセスします。

#### エンドポイント

 - テキスト生成
     - https://api.salesforce.com/einstein/platform/v1/models/[モデル名]/generations
 - チャット応答
     - https://api.salesforce.com/einstein/platform/v1/models/[モデル名]/chat-generations
 - Embedding
     - https://api.salesforce.com/einstein/platform/v1/models/[モデル名]/embeddings
 - フィードバック
     - https://api.salesforce.com/einstein/platform/v1/models/[モデル名]/feedback

#### リクエスト例
`GPT4Omni`モデルに対し、`テキスト生成`をリクエストする場合

##### curlでの呼び出しサンプル
```shell
curl --location 'https://api.salesforce.com/einstein/platform/v1/models/sfdc_ai__DefaultOpenAIGPT4Omni/generations' \
--header 'Authorization: Bearer [JWT]' \
--header 'Content-Type: application/json' \
--header 'x-sfdc-app-context: EinsteinGPT' \
--header 'x-client-feature-id: ai-platform-models-connected-app' \
--data '{
    "prompt": "プロンプト文章",
}'
```
## Models API の活用例

https://qiita.com/misu007/items/39608a8c0c8385681df3



## おわりに
生成AI分野の技術革新は目まぐるしいですが、業務アプリケーションでいかにLLMを活用し、価値を生み出せられるか？開発柔軟性がとても重要です。同時に、データセキュリティ、コンプライアンス要件への対応も求められます。これらを両立し、信頼できるAIを実現する手段として、Models APIが重要な役割を果たします。
  
以下Trailheadから有効期限5日のEinstein生成AIが有効化されたDeveloper Edition組織を取得できます。Einstein Generative AIに興味ある方は、是非お試しください。  

https://trailhead.salesforce.com/ja/content/learn/projects/quick-start-prompt-builder