
Salesforceプロンプトビルダー入門
こんにちは木村です。
今回はSalesforceが現在激推しの生成AI機能 Einstein GPTの構成要素であるプロンプトビルダーを解説していきたいと思います。概要、試せる環境の紹介、実際どう使うのかを紹介していきます。
長くなってしまいましたが、半分以上チュートリアルですので、そこは必要に応じて読み飛ばして、怖気づかず読んでもらえるとうれしいです。
なお、この記事は以下のイベントで発表した内容です。定期開催しているので、ぜひご参加ください。
1. プロンプトビルダーでできること
プロンプトビルダーとは
プロンプトビルダーはプロンプトテンプレートを作るツールです。
以下のように左上にプロンプトテンプレートを記入し、画面下でそのテンプレートを実際のデータで試すことができるようになっています。

プロンプトテンプレートとは
プロンプトはChatGPTなどでも馴染み深いと思いますが、プロンプトテンプレートとは何でしょう?
プロンプトテンプレートは変数を含む再利用可能なプロンプトのことです。Salesforceではレコードやフローの結果の値をプロンプトテンプレートに動的に差し込んで、具体的なプロンプトを生成して実行することができます。このプロンプトの具体化、つまり変数に実際の値を入れることをグラウンディングと呼びます。
以下が実際のプロンプトテンプレートの例です。色がついている箇所が変数(差し込み項目)になっています。

何をグラウンディングできるのか
Salesforceから動的にプロンプトテンプレートに差し込める(グラウンディング)データは以下の通りです。
レコード差し込み項目 {!$Input:Account.Name}
関連リスト差し込み項目 {!$RelatedList:Case.CaseComments}
Data Cloud DMO差し込み項目
フロー {!$Flow.Get_Contact_Interest_Summary}
Apex {!Apex:GetActivityHistories.Prompt}
Salesforceのレコードの項目値や関連リストを差し込める他、Data Cloudのデータ、またフローやApexで作った動的なテキストを差し込むこともできます。フローで外部APIを呼んでその結果を差し込むなんてことも可能です。

詳しくはGround Prompt Templates with Salesforce Resourcesをご覧ください。
プロンプトテンプレートはどう使われるのか
例えば、プロンプトテンプレートの1種であるセールスメールテンプレートは、以下のようにメール作成画面から利用されます。
メール作成画面を開く
Draft with Einsteinボタンを押す
プロンプトテンプレートを選ぶ
メール文面が自動生成される

つまり、ChatGPTなどの対話型AIと比べると、対話なしに一発でテキストを生成することがプロンプトテンプレートの特徴と言えます。
プロンプトデザイン
一発で確実に適切なテキストを生成する必要があるため、プロンプトをよく練る必要があります。これをプロンプトデザインと呼びます。
具体的には、送信者/受信者のロール、背景情報、出力したい内容、関連情報、指示、語調、ハルシネーションの防止などをプロンプトに含めることで、生成結果をより理想に近づけることが推奨されています。
例えば、以下のようにするとよいと言われています。
よくない例
以下の商談において次に顧客に送るべきメール文面を作成してください。
商談情報:
"""
商談名: {!$Input:opportunity.Name}
取引先名: {!$Input:opportunity.Account.Name}
説明: {!$Input:opportunity.Description}
商談金額: {!$Input:opportunity.Amount}
フェーズ: {!$Input:opportunity.StageName}
次のステップ: {!$Input:opportunity.NextStep}
期待収益: {!$Input:opportunity.ExpectedRevenue}
"""
活動履歴:
"""
{!$Apex:GetActivityHistories.Prompt}
"""
出力例
NovaDynamics株式会社 御中
拝啓 時下ますますご清祥のこととお慶び申し上げます。平素は格別のお引き立てを賜り、誠にありがとうございます。
「SkyCanvas 導入プロジェクト」に関しまして、これまでの商談の進捗についてご報告申し上げます。これまでの活動を通じて、貴社のご要望やフィードバックを収集し、製品の最終調整に努めてまいりました。特に、デモンストレーション後のフィードバック収集や改善点についての議論、さらには技術詳細の説明会など、貴社との密接なコミュニケーションを重視してきました。
次のステップとして、フィードバックに基づく製品の最終調整を行い、その成果をもってクライアントとの最終プレゼンテーションの準備を進めております。このプレゼンテーションをもって、SkyCanvasの導入に向けた貴社のご期待に応えられるよう、全力を尽くして参ります。
プレゼンテーションの日程につきましては、貴社のご都合を伺いながら調整させていただきたく存じます。ご都合の良い日程がございましたら、ご一報いただけますと幸いです。
この度のプロジェクトが、貴社にとって真に価値あるものとなるよう尽力して参ります。今後とも変わらぬご支援とご協力を賜りますようお願い申し上げます。
敬具
[あなたの名前]
[あなたの役職]
[あなたの連絡先]
何も指示しなくてもある程度生成してくれますが、「拝啓」「敬具」や「時下ますますご清祥のこととお慶び申し上げます。」のようになかなかメールで使わない言い回しをしてしまっています。
そこで語調の指定などを行うとよりよい結果を返すようになります。
改善例
以下の商談において次に顧客に送るべきメール文面を作成してください。
送信者情報:
"""
- 役職: 営業担当者
- 名前: {!$User.Name}
- 拝啓: 送信者は以下の活動履歴をすべて行っています。
"""
受信者情報:
"""
{!$RelatedList:opportunity.OpportunityContactRoles.Records}
"""
メールの目的:
"""
- 商談を前進させる。
- 相手の次の行動を促す。
"""
メールの語調と指示:
"""
- 語調: プロフェッショナルでありながら親しみやすく、信頼を感じさせる。過度な敬語は避け、親近感を持たせる表現を使う。
- 「拝啓」「敬具」のフレーズは不要。メールの結びは、相手に次の行動を促す形で。
"""
追加情報と指示:
"""
- 具体的なデータや事実のみを使用し、仮定に基づく表現や不確かな情報は避ける。
"""
商談情報:
"""
商談名: {!$Input:opportunity.Name}
取引先名: {!$Input:opportunity.Account.Name}
説明: {!$Input:opportunity.Description}
商談金額: {!$Input:opportunity.Amount}
フェーズ: {!$Input:opportunity.StageName}
次のステップ: {!$Input:opportunity.NextStep}
期待収益: {!$Input:opportunity.ExpectedRevenue}
"""
活動履歴:
"""
{!$Apex:GetActivityHistories.Prompt}
"""
出力例
佐藤 一郎様
いつも大変お世話になっております。貴社のSkyCanvas 導入プロジェクトに関するご協力に心より感謝申し上げます。
これまでの商談の進捗につきまして、私どもは貴社からの貴重なフィードバックを基に製品の最終調整を進めております。また、最終プレゼンテーションの準備も着々と進行中でございます。これにより、貴社のニーズに最適なソリューションを提供できることを確信しております。
次のステップとして、貴社のご都合に合わせて最終プレゼンテーションの日程を調整させていただきたく存じます。貴社のご意見をお聞かせいただければ、さらに具体的な提案へと進めて参ります。
また、これまでの商談の中で何かご不明な点や追加でご要望等がございましたら、お気軽にお申し付けください。貴社の事業成功に貢献できるよう、全力を尽くしてまいります。
最後に、貴社とのこのプロジェクトを通じて、より一層の信頼関係を築いていけることを楽しみにしております。ご多忙のところ恐縮ですが、最終プレゼンテーションのご希望日程について、ご連絡いただけますと幸いです。
何卒よろしくお願い申し上げます。
営業担当者
プロンプトビルダーにはプレビュー機能があるため、プレビューと修正を繰り返し、プロンプトを練り上げていきます。
詳しくはTrailheadのプロンプト入門、プロンプトテンプレートを確認して修正し、保存するをご覧ください。
4種類のプロンプトテンプレート
セールスメール、項目生成、レコードの概要、Flexテンプレートの4つの種類があります。それぞれで使用箇所、入力に使える情報が決まっています。
セールスメール: メール文面を自動生成する
項目生成: 項目の値を自動生成する
レコードの概要: レコードの要約を生成する
Flex: 他3つ以外の用途をカバーするテンプレート
以下のスライドにまとまっていますが、詳しくは後述します。

どこから利用できるのか
まず、何の設定もせずに呼び出すことができるパターンとして、以下のテンプレート種類ごとに標準の利用方法があります。
セールスメール: メール作成画面
項目生成: レコードページ
レコードの概要: Einstein Copilotアクション
それ以外に以下のような利用方法があります。これらは追加の設定や開発が必要になります。
カスタムCopilotアクションとしてEinstein Copilotから呼ぶ
呼び出し可能アクション(Invocable Action)としてフローから呼ぶ
Connect REST API
Connect in Apex
テンプレートタイプによって利用可能な方法が異なり、まとめると以下の図のようになります。

詳細はIntegrate Prompt Templates with Salesforce Featuresをご覧ください。
2. プロンプトビルダーを試せる環境
Trailheadの以下のプロジェクトにプロンプトビルダーを試せる環境を作成するためのリンクがあります。文中の「5-day trial org with Einstein Generative AI」の箇所です。
こちらから、プロンプトビルダーを無料で試せる組織を作成できます。(5日と書いていますが、私が作った組織は1ヶ月半ほど使えました。)
3. セールスメール
ここからはプロンプトのそれぞれの種類について、どうやって使うかを解説していきます。残念ながらセールスメールは上記環境では動かないので、試せていません。
ただ、デモ動画を見ると、普通のメール作成画面の左下の「Draft with Einstein」ボタンからプロンプトテンプレートを選択できるようになることがわかります。

4. 項目生成
したがって、最初は「項目生成(Field Generation)」です。項目生成は特定の項目の値を自動生成する機能です。
商談の活動を要約するプロンプトテンプレートを作っていきます。ここでは、フローの情報を差し込み項目として使用する方法も合わせて見てみましょう。
差し込むためのフローを作成
最初にテンプレートに差し込むための活動情報を作成するフローを作成します。
(1) フローを作成し、「テンプレートトリガープロンプトフロー」を選択
(2) プロンプトテンプレート種別機能「項目生成テンプレート機能」、オブジェクト「商談」を選択

(3) 後は省略しますが、以下のようなフローを作ります。商談に紐づくTaskレコードを取得して、ループの中で「プロンプト手順を追加」アクションを呼びます。

(4) フローは「GetOpportunityTasks」というAPI名で保存してください。
プロンプトテンプレートを作成
(1) 商談に項目「活動の要約(TaskSummary__c)」を作成します。
(2) 設定画面からプロンプトビルダーを開き「新規プロンプトテンプレート」をクリック

(3) 種別を「項目生成」、プロンプトテンプレート名「OpportunityTaskSummary」、オブジェクト「商談」、項目「活動の要約」と入力します。

(4) プロンプトテンプレートに以下を入力し、モデル「Open AI GPT 4 Turbo」を選択。
商談「{!$Input:Opportunity.Name}」に対する以下の活動履歴の要約を作成してください。
{!$Flow:GetOpportunityTasks.Prompt}
指示:
"""
500文字以内で1段落で作成してください。
収まらない場合は新しい情報を優先してください。
"""
上記をコピペすると差し込み項目が展開されますが、通常は「リソース」から差し込みます。先ほど追加したフローが表示されるようになっていると思います。

(5) 商談レコードを選択し、「保存&プレビュー」をクリックすると、以下のように応答結果を見ることができます。

(6) 問題なければ「有効化」をクリック
レコードページに配置
(1) 商談レコードページで詳細コンポーネントを動的フォームに変更します。
(2) 「活動の要約」を選択し、Prompt Template「OpportunityTaskSummary」を選択します。

(3) 「保存」し「有効化」します。
(4) 商談編集画面で「活動の要約」項目の横にキラッとしたアイコンがあるのでクリックすると、Einstein Copilotで先ほどのプロンプトテンプレートが動作し、テキストを生成します。

(5) 下部の「Use」ボタンをクリックすると、「活動の要約」項目に生成されたテキストが挿入されます。

5. レコードの概要
「レコードの概要(Record Summary)」は特定のレコードの概要を作成する機能です。Einstein Copilotから使用できます。
実はこの機能はプロンプトテンプレートを作らなくても以下のように動作します。プロンプトテンプレートを作るとこのときに別のプロンプトで結果を生成することができるようになります。

上記のようにCopilotは日本語対応していないので、今回はとりあえずプロンプトテンプレートを使うことで日本語を返すようにしてみましょう。
ここからはチュートリアルの説明は雑に書きますので、適時補完して読んでください。
(1) 「レコードの概要」種別のプロンプトテンプレートを作成する。

(2) なぜか日本語テンプレートが「An issue occurred while processing your request. Please try again later or contact your Salesforce system administrator for assistance.」とエラーになるので、英語テンプレートを書きます。
Please summarize the following sales opportunity.
Opportunity Details:
"""
Opportunity Name: {!$Input:opportunity.Name}
Account Name: {!$Input:opportunity.Account.Name}
Description: {!$Input:opportunity.Description}
Opportunity Amount: {!$Input:opportunity.Amount}
Stage: {!$Input:opportunity.StageName}
Next Step: {!$Input:opportunity.NextStep}
Expected Revenue: {!$Input:opportunity.ExpectedRevenue}
"""
Products
"""
{!$RelatedList:Opportunity.OpportunityLineItems.Records}
"""
Roles of Account Contacts
"""
{!$RelatedList:Opportunity.OpportunityContactRoles.Records}
"""
Activity History:
"""
{!$Flow:GetOpportunityTodosRecordSummary.Prompt}
"""
「GetOpportunityTodosRecordSummary」というテンプレートトリガーフローは項目生成のときと同じように作成してください。
(3) 有効化して、Copilotで「Summarize opportunity」を実行すると、日本語の要約が得られます。

6. Flexテンプレート
Flexテンプレートは上記3つのテンプレートでは実現できないユースケースのときに使います。他のテンプレートとは違い、5つのレコードを入力に指定できることが特徴的です。
記事が長くなりすぎたので、チュートリアルは割愛します。中の人が一週間ほど前にいい記事を書いていますので、以下をご覧ください。
こちらの記事では差し込み項目にApexを使用する例も紹介されているので、そちらも参考になります。
7. いろいろなところからプロンプトテンプレートを呼ぶ
今まで標準機能から呼ぶ例を紹介してきましたが、フローやApexからも呼ぶことができます。
フローから呼ぶ
先ほど作成した項目生成テンプレート「OpportunityTaskSummary」をフローから呼んでいる例です。項目生成テンプレートの通常の使い方だといきなり値を更新してくれませんので、フローを使うことでいきなりレコードを更新しています。

レコードアクション「活動の要約を更新」をクリックするといきなり「活動の要約」項目に値が入ります。

Apexから呼ぶ
Apexからも呼べます。
// 入力を作成
ConnectApi.EinsteinPromptTemplateGenerationsInput promptGenerationsInput = new ConnectApi.EinsteinPromptTemplateGenerationsInput();
promptGenerationsInput.isPreview = false;
// 入力として商談IDを指定
Map<String,ConnectApi.WrappedValue> valueMap = new Map<String,ConnectApi.WrappedValue>();
Map<String, String> relatedEntityRecordIdMap = new Map<String, String>();
relatedEntityRecordIdMap.put('id', '006Hn00001RGRVzIAP');
ConnectApi.WrappedValue relatedEntityWrappedValue = new ConnectApi.WrappedValue();
relatedEntityWrappedValue.value = relatedEntityRecordIdMap;
valueMap.put('Input:Opportunity', relatedEntityWrappedValue);
promptGenerationsInput.inputParams = valueMap;
// additionalConfigは設定しなくても動くが、必須とドキュメントには書いてある
promptGenerationsInput.additionalConfig = new ConnectApi.EinsteinLlmAdditionalConfigInput();
promptGenerationsInput.additionalConfig.applicationName = 'PromptTemplateGenerationsInvocable';
// プロンプトテンプレートを実行
ConnectApi.EinsteinPromptTemplateGenerationsRepresentation generationsOutput =
ConnectApi.EinsteinLLM.generateMessagesForPromptTemplate('OpportunityTaskSummary', promptGenerationsInput);
// プロンプトテンプレートの実行結果を出力
for (ConnectApi.EinsteinLLMGenerationItemOutput generation : generationsOutput.generations) {
System.debug('Generation: ' + generation.text);
}
プロンプト実行結果が出力される。でも、23秒かかりました。

8. おわりに
けっこう柔軟に使えてなかなかおもしろいです。フローやApexの結果を入力にも使えるし、プロンプトを実行した結果をApexでごにょごにょすることもできちゃいます。
ただ、Prompt Builder Limitationsには不思議な制限や怖い制限が書かれているので、実際に使う際は最初に一読することをお勧めします。特にFlexテンプレートをパッケージに入れる場合はちゃんと検証しないと怖そうな制限が書かれていました。
9. よくありそうな質問
最後に疑問に思いそうなところをまとめて書いておきます。
日本語で使えるの?
使えます。プロンプトは日本語で書いても英語で書いても動きます。出力はユーザの言語に依存します。つまり、プロンプトが英語でもユーザの言語が日本語ならそのユーザが操作したときは日本語で結果が取得できます。
関連リストで活動履歴を入れても差し込まれないんだけど?
制限で活動履歴はサポートされていないようです。ドキュメントに以下のように書いていますが、Accountじゃなくてもだめでした。
The Activities related list on the Account object isn’t supported, due to a limitation involving the behavior of polymorphic related lists.
プロンプトテンプレートで作成したカスタム項目が選択できないよ?
ドキュメントに制限として書いてありました。そういう場合は一度ログアウト/ログインすると出てくるようになります。
When you create a custom object or custom field, it isn’t available for use in Prompt Builder immediately. To use a new custom object or field immediately, log out and log back in.
プロンプトビルダーのプレビューと実際の結果が全然違うのですが?
ね。私もわかりません。困ります。プレビューの意味とは…
プロンプトテンプレートのメタデータは取得できる?
GenAiPromptTemplateという名前でメータデータを取得できます。@salesforce/cliのバージョンやAPIバージョンが古いとエラーになるので要注意。
sf project retrieve start --metadata GenAiPromptTemplate
参考リンク
Ground Your Prompt Templates with Data Using Flow or Apex | Salesforce Developers Blog
Create Trusted Generative AI Apps with Prompt Builder - YouTube
Create a Copilot Action Using a Prompt Builder Template | TrailblazerDX 2024 - YouTube
codeLive: A Deep Dive into Apex for Prompt Builder - YouTube
Prompt Builder: Ask Me Anything with Salesforce Developers - YouTube
Prompt Template Types | Prompt Builder for Developers - YouTube
Grounding Prompt Templates | Prompt Builder for Developers - YouTube