Saturday 16 March 2024

Einstein Prompt Grounding with Apex

Image generated by DALL-E 3 in response to a prompt from Bob Buzzard

Introduction

A couple of weeks ago I published my initial experience and thoughts on Einstein Prompt Builder, and one of my findings was that I couldn't get grounding with Apex to work, even using the example code in the help. Thanks to some help from Claudio Moraes from the Salesforce Partner team, that is no longer the case and I can pull information into my prompt via an Apex class. 

Example Scenario

The prompt I've created is following up on a lead where we have a pretty good idea what product they are interested in. Using standard prompting I can get the user to select the product in questions, but I also want to include the standard price to give the lead an idea of what it might cost them. I can pull the PricebookEntries related list from the product into the prompt, but that is all or nothing, whereas I just want the a single entry from the standard price book.

The Apex Code

In order to be considered for use in a Sales Email Prompt Template, I need a method with the following signature:

@InvocableMethod(label='Price for Lead' 
                 description='Gets the price of a product for a lead' 
                 CapabilityType='PromptTemplateType://einstein_gpt__salesEmail')
public static List<Response> getProductStandardPrices(List<Request> requests) 

The key aspects of this are:

It must be an invocable method

Which simply means it needs the @InvocableMethod annotation. Without this, the Apex class will never be considered by Prompt Builder.

It has to have the CapabilityType attribute on the @InvocableMethod annotation

This identifies the type of Prompt Template that the method can be used with. As this is for a Sales Email, I specify :

     PromptTemplateType://einstein_gpt__salesEmail

It must take a list of Request class instances

Request is an inner class that I have to define, with the format:

 public class Request {
    @InvocableVariable(required=true)
    public User Sender;

    @InvocableVariable(required=true)
    public Lead Recipient;

    @InvocableVariable(required=true)
    public Product2 RelatedObject;
}

The variable names must be exactly as shown here - including the capitalisation (thanks Claudio!). These match the properties of the Prompt Template.

It must return a list of Response class instances

Again, Response is an inner class that I define, with the format:

 public class Response {
    @InvocableVariable(required=true)
    public String prompt;
}


The body of the method itself is pretty straightforward:

@InvocableMethod(label='Price for Lead' 
                 description='Gets the price of a product for a lead' 
                 CapabilityType='PromptTemplateType://einstein_gpt__salesEmail')
public static List<Response> getProductStandardPrices(List<Request> requests) 
{
    Request req=requests[0];
    Id productId=req.RelatedObject.Id;
    Response resp=new Response();
    PricebookEntry entry=[
            select Id, UnitPrice, CurrencyISOCode from PricebookEntry
            where Product2.Id=:productId
            and   Pricebook2.IsStandard = true];

    resp.prompt=entry.CurrencyISOCode + ' ' + entry.UnitPrice;
        
    return new List<Response>{resp};
}

Note that while the method has to take a list of requests and return a list of responses, there's only ever one element present.

Putting it Together

If I deploy my class and it doesn't show up in Prompt Builder because I've got the capitalisation wrong, it doesn't appear to be possible to recover it. Instead, I have to delete the class and try the next attempt with a new one (thanks again, Claudio!).  

Once I have the correct breed of chicken and the right colour chalk for the pentangle, Apex appears in the resource picker :


And clicking into the Apex option shows me the name of my enclosing class and the label attribute from the @InvocableMethod annotation :

And selecting this adds it to my prompt, helpfully highlighted to show me that it is a reference rather than plaintext :

The Prompt and Response

I've added this to a pretty simple prompt - I doubt it would make much difference to a potential customer, but the point of this blog is to show the Apex, not what makes a great prompt! Note that as I didn't ground the prompt with any details of the user, they are expected to add that themselves :


and the response from the LLM:

Subject:

Thank You for Your Interest in Solar Panels

Body:

Dear Lauren Reynolds, 

Thank you for your interest in our solar panels. We are pleased to share the price with you. The cost for a single panel is USD 1725.00. Please note that discounts are available for larger orders, but this price already reflects an excellent value for such a high-quality product. 

We hope this information is helpful to you, and we look forward to the possibility of working with you. 

Should you have any further questions or require additional details, please do not hesitate to reach out. 

Warm regards,
[Your Name]
Credera Sales Team


More Information





No comments:

Post a Comment