Salesforce
デベロッパー
ブログ

LWC と Models API で、高度にカスタマイズしたAIアプリを作る

Avatar for Michikazu SugaharaMichikazu Sugahara
Lightning Web Component (LWC)と、Models API を組み合わせることで、Salesforceプラットフォーム上で、高度にカスタマイズした AI-Powered なアプリケーションを実現できます。本記事ではカスタムコンポーネント例を用いて、Models API の可能性を探ります。
LWC と Models API で、高度にカスタマイズしたAIアプリを作る
December 04, 2024

Models API とは?

高度にカスタマイズしたAIアプリケーションを実現するAPI

Models API は、Salesforce開発者がLLMを利用したアプリケーション開発で活用できる、新しいAPI です。Anthropic、Google、OpenAIなどの大規模言語モデル(LLM)、その他任意のLLM等に、Salesforceプラットフォームからは Apex で、外部アプリからは REST API 経由でアクセスします。慣れ親しんだApexを使い、既存の アプリ / コンポーネント / ビジネスロジック 等に、生成AIテクノロジーを組み込みます。

パッケージング対応

現在、 Models API は、第一世代パッケージング(1GP)、第2世代パッケージング(2GP)の両方に対応しています。ISVパートナー企業は、この Models API を活用したAIソリューションをAppExchangeマーケットプレイスで展開できます。

Einstein Trust Layer

LLMは革新的なテクノロジーである一方、ビジネス文脈で活用する観点では、データをセキュアに取り扱うことが特に重要です。Einstein Trust Layer には、LLMと連携する際、データとユーザーを保護する機能が含まれます。Models API への呼び出しは、すべてこの Einstein Trust Layer を経由します。

einstein-trust-layer

  • CRMデータに基づいたデータの信頼性
  • 機密データのマスキング
  • 生成アウトプットの有害性検出
  • 監査証跡とフィードバック
  • ゼロリテンション

Salesforce開発者向けの新しいAPIである Models API を活用し、既存のSalesforceテクノロジー Apex, LWCにより、どのようなAI-Poweredなソリューションが実現できるか? サンプルコンポーネントを���に見ていきます。

当サイトでは、最新かつ正確な情報の掲載を努めておりますが、正確性や安全性、効果等を保証するものではありません。本情報の内容(添付文書、リンク先などを含む)は、作成日時点でのものであり、予告なく変更される場合があります。また、当サイトの掲載内容によって損害等が生じた場合は、一切の責任を負いかねますので、ご利用の際はヘルプやリファレンスをご参照の上、お手元で十分検証をいただいたのち導入についてご判断くださいますようお願いいたします。

カスタムコンポーネント – SNS投稿文ジェネレーター

マーケティング担当者がSNS投稿する際の文章を生成AIに作ってもらうシーンを想定します。文章を生成するだけでなく、プレビューで確認しながら条件を調整し、投稿文をブラッシュアップできる機能を考えます。

機能

  • システム管理者がシステムプロンプトをプリセット
  • 商品(標準オブジェクト)レコードページと連動
  • ユーザーが細かな指示を出して文章を調整
  • 投稿イメージをプレビュー確認

これをフロント側はLWCで作り、組み立てたプロンプトを LLM に投げる部分は、Apex から Models API を使ってコールする構成にします。

構成

sns-post-generator-lwc

システム管理者がシステムプロンプトをプリセット

本コンポーネントをレコードページに配置する際、Lightningアプリケーションビルダーのプロパティ設定で、システムプロンプトを設定できるようにします。ここで設定した値はプロンプトの一部として組み込むことを想定しています。

*.js

systemPrompt プロパティをコンポーネント外から受け渡しができるよう、@api デコレータをセットします。

import { LightningElement, api, wire } from "lwc";

export default class DemoSnsPostGenerator extends LightningElement {
    @api systemPrompt;

*.js-meta.xml

Lightningアプリケーションビルダーのプロパティ設定から systemPrompt を編集できるよう targetConfig を設定します。

<targets>
    <target>lightning__RecordPage</target>
</targets>
<targetConfigs>
    <targetConfig targets="lightning__RecordPage">
        <property name="systemPrompt" type="String" label="システムプロンプト" default="あなたはSNS投稿文章を生成するプロのライターです。あなたは企業のソーシャルアカウントからお届けする魅力的なSNS投稿文章を作成するのが得意です。" />
    </targetConfig>
</targetConfigs>

Lightningアプリケーションビルダーでコンポーネントを配置すると、システムプロンプト という設定項目が現れます。ここで入力された値は、LWCのJavascriptから systemPrompt プロパティでアクセスできるようになります。

lightning-app-builder

商品(標準オブジェクト)レコードページと連動

商品オブジェクト Product2 のレコード情報をプロンプトで扱えるよう、データ連携させます。

*.js-meta.xml

商品オブジェクト Product2 のレコードページで機能するコンポーネントであることを定義します。

<targetConfigs>
    <targetConfig targets="lightning__RecordPage">
        <objects>
            <object>Product2</object>
        </objects>
    </targetConfig>
</targetConfigs>

*.js

@wire デコレータと recordId プロパティを使い、商品オブジェクト Product2 の商品説明項目 Description を含むレコード情報を取得するようにします。

import { getRecord } from "lightning/uiRecordApi";
const FIELDS = ["Product2.Description"];

export default class DemoSnsPostGenerator extends LightningElement {
    @api recordId;
    @wire(getRecord, { recordId: "$recordId", fields: FIELDS }) product2;

これで、以下のような商品説明項目の値をコンポーネントから扱うことが出来るようになります。

product2-description

ユーザーが細かな指示を出して文章を調整

UI上で以下項目を設定できるようにします。

  • トピック: 自由入力
  • 言語: 日本語 / 英語
  • スタイル: カジュアル / フォーマル / ボエム風 / クイズ形式
  • 文字数の目安: 0-400
  • ハッシュタグ数: 0-10
  • 文章生成に使うLLM: GPT-4 Omni / Claude 3 Haiku

*.html

LWCの標準部品を使っています。ユーザーがUI上で設定した各値を取得できるよう、各項目に ref を設定しています。

<lightning-textarea lwc:ref="topic" label="トピック"></lightning-textarea>
<lightning-radio-group lwc:ref="language" label="言語" options={writingLanguages} type="button"></lightning-radio-group>
<lightning-radio-group lwc:ref="style" label="スタイル" options={writingStyles} type="button"></lightning-radio-group>
<lightning-slider lwc:ref="length" label="文章量(文字数)" max="400" step="10"></lightning-slider>
<lightning-slider lwc:ref="hashTags" label="ハッシュタグ" value={hashTags} max="10"></lightning-slider>
<lightning-radio-group lwc:ref="llm" label="LLM" options={modelOptions} type="button"></lightning-radio-group>

以下のようなUIになります。

ui-configure

これでプロンプトを組み立てる準備が整いました。

プロンプトの組み立て

プロンプトに必要な各情報を取得し、プロンプトを組み立てます。

*.js

それぞれプロンプトにバインドします。

  • システム管理者が設定したシステムプロンプト: ${this.systemPrompt}
  • 商品ページの商品説明項目: ${this.product2.data.fields.Description.value}
  • ユーザーが設定した各パラメーター値: ${this.refs.[各パラメーターのref値].value}
createPrompt() {
    const prompt = `
${this.systemPrompt}
以下の商品情報、ユーザーからのリクエストに応じたコンテンツを作成します。

商品情報: """
${this.product2.data.fields.Description.value}
"""

ユーザーからのリクエスト: """
- トピック: ${this.refs.topic.value} 
- コンテンツの言語: ${this.refs.language.value}
- 文章の文字数の目安: ${this.refs.length.value}
- 文体: ${this.refs.style.value}
- ハッシュタグの数(この数だけハッシュタグを文末につけて): ${this.refs.hashTags.value}
"""

コンテンツ:
`;
    return prompt;
}

プロンプトの実行

組み立てたプロンプトをModels API経由でLLMにコールします。

*.js

文章生成ボタン押下時、組み立てたプロンプトを prompt 、ユーザーが指定したLLMを
modelName を引数とし、Apexメソッド getGeneratedText を呼び出します。生成したテキストは content に格納されます。

import getGeneratedText from "@salesforce/apex/DemoSnsPostGeneratorController.getGeneratedText";

const modelName = this.refs.llm.value;
const prompt = this.createPrompt();
const payload = { prompt, modelName };
this.content = await getGeneratedText(payload);

Apex

Apexでは、promptmodelName を引数として受け取り、Models API を介し、LLM にプロンプトを投げます。

@AuraEnabled
public static string getGeneratedText(String prompt, String modelName) {
    aiplatform.ModelsAPI.createGenerations_Request request = new aiplatform.ModelsAPI.createGenerations_Request();
    request.modelName = modelName;
    aiplatform.ModelsAPI_GenerationRequest requestBody = new aiplatform.ModelsAPI_GenerationRequest();
    request.body = requestBody;
    requestBody.prompt = prompt;
    try {
        aiplatform.ModelsAPI modelsAPI = new aiplatform.ModelsAPI();
        aiplatform.ModelsAPI.createGenerations_Response response = modelsAPI.createGenerations(request);
        return response.Code200.generation.generatedText;
    } catch (aiplatform.ModelsAPI.createGenerations_ResponseException ex) {
        System.debug('The following exception occurred: ' + ex);
    }
    return null;
}

投稿イメージをプレビュー表示

生成した文章はそのまま表示せず、ハッシュタグ部分をリンク形式に変換して表示します。

*.js

プロンプトから返ってきた値 content を、リッチテキスト形式の文字列に変換するgetter関数 formattedContent を定義しておきます。

get formattedContent() {
    if (this.content) {
      return this.content.replace(/#/, "<br/><br/>#").replace(/(#\S+)/g, '<a href="">$1</a> ');
    }
    return "";
}

すると、以下のように表示されます。

ui-preview

デモ

コンフィグ調整しながら何度もSNS投稿文をプレビュー確認することができます。

lwc-demo-01

lwc-demo-02

lwc-demo-03

まとめ

Models API により、既存Salesforceテクノロジー(LWC、フロー、Apex 等)で、より高度にカスタマイズされたAIアプリケーションを作成できます。また、プロンプトに必要なデータは安全かつ柔軟にバインドされ、かつEinstein Trust Layerを介すことで、信頼性の高いAIを実現します。本記事で紹介したLWCはサンプルコードも公開してます。是非お試しください。

参考資料

Get the latest Salesforce Developer blog posts and podcast episodes via Slack or RSS.

(英語のみです)

Add to Slack Subscribe to RSS

その他の関連記事

TrailblazerDX '24 Developer Recap

TrailblazerDX '24 Developer Recap

Explore a recap of TrailblazerDX 2024, with highlights from Einstein 1 Studio, Data Cloud, and more generative AI features.March 19, 2024

Connecting Google Cloud Storage and Salesforce with Data Cloud

Connecting Google Cloud Storage and Salesforce with Data Cloud

Start ingesting data from your Google Cloud Storage buckets into Data Cloud to keep building a single source of truth for your customers.March 26, 2024

How to Use Data Cloud AI Model Predictions in Flow

How to Use Data Cloud AI Model Predictions in Flow

Streamline the delivery of AI insights with Flow Builder and Slack. Trigger your Einstein Studio model's endpoint directly from Flow Builder, capturing predictions and feeding them straight into your Slack channels.August 06, 2024