Skip to main content

Orchestrating LLMs for Product Recommendations

This recipe demonstrates the manual orchestration of three different LLM product recommendation models. Executing this recipe grants the business user the decision-making power to determine in which circumstances each recommendation model should be used.

In this example, we're using ChatGPT prompts to mock three different product recommendation models for a grocery chain that does online ordering:

  • Products frequently purchased together, in aggregate. This requires current cart items.
  • Products frequently purchased by the customer, based on their individual purchase history. This requires customer id.
  • Products rarely purchased by the customer, based on their individual purchase history. This requires customer id and location.

We have set up three Experience Rules to represent different contexts under which each model makes sense to run:

  • Rule 1:
    • Context: Checkout page; guest user; cart items
    • Message: "Want to add on this product that a lot of people tend to buy when they've bought what you have in your cart?"
  • Rule 2:
    • Context: Checkout page; logged in user
    • Message: "Want to add on this product that you love?"
  • Rule 3:
    • Context: Checkout page; logged in user; warm sunny weather
    • Message: "Want to add on this product that you never buy - but might give a try today, because people are more likely to take chances on buying new things when the weather is warm and sunny according to our analytics?"

With this recipe, you could make further additions or adjustments for selecting recommendation models on your PDPs or in email marketing campaigns. You could take into account a variety of other contextual situations or customer behaviour as well.

There are LLM models that can handle decision-making logic, and would be capable of determining which recommendations model to use under which conditions. It will be up to your business requirements which method works best for you. There is always space for a human in the loop and sometimes that is preferable.

Mapping Out DX Engine Elements

Orchestrating LLMs Visualizer

When the frontend calls Conscia's Experience API, it will pass the following Context:

  • The location value passes the shopper's current location to the Get Current Weather Component which will set the weatherCondition Context field.
  • The pageType value represents the page where the customer is currently browsing.
  • The customerId value is either the customerId value or the String "guest". Before passing the customerId to one of the product recommendations models, you may need to make a call to a CDP for additional customer data.
  • The cartItems value passes the items currently in the shopper's cart. You may need to retrieve this information through a direct call to the commerce engine based on the current cart id; or it might come from the frontend in a format that requires some transformation before being passed to the product recommendations model. In this recipe, a simple String value is used listing the items.

An example call looks like this:

POST {{engineUrl}}/experience/components/_query
X-Customer-Code: {{customerCode}}
Authorization: Bearer {{dxEngineToken}}

{
"componentCodes": ["mapper-full-recommendations-chatgpt"],
"context": {
"cartItems" : "pumpkin puree, pie shells",
"pageType" : "checkout",
"customerId" : "guest",
"location" : "Vancouver"
}
}

Based on the context provided in this Experience API call, one of the three Experience Rules laid out above will be triggered.

  • The Model Component will look at which Experience Rule was triggered and then select the response from the appropriate recommendations model Mapper Component.
  • There is a Mapper Component for each recommendations model that will normalize each response.
  • There is a ChatGPT Recommendations Selector Component for each recommendations model.
  • Finally the Full Recommendations Mapper takes the normalized product recommendations data and stitches it together with the message that sits in each Experience Rule that will serve as a header to the recommendations section on the web page.

Assuming the weather is raining in Vancouver, an anonymous shopper would get a response like the following, depending on your model's whims:

"recommendations": {
"products": [
{
"id": 12345,
"name": "Whipped cream",
"price": 6.99,
"image": "https://www.example.com/whipped_cream.jpg"
},
{
"id": 23456,
"name": "Pumpkin spice",
"price": 8.49,
"image": "https://www.example.com/pumpkin_spice.jpg"
},
{
"id": 34567,
"name": "Cinnamon sticks",
"price": 10.25,
"image": "https://www.example.com/cinnamon_sticks.jpg"
}
]
},
"heading": "Missing one of these products?"

DX Engine Configuration Details

The topics in this section explain how to implement the elements involved in this recipe.

Context Fields

We need to create Context Fields to enable our Experience Rules to access Context values. For the purpose of this recipe, we'll be manually entering a few expected values into the Context Field configuration. For a production implementation, you would want to configure a Component to supply the expected values.

Weather Condition

To create a Context Field used to store the current weather condition, in the DX Studio UI:

  1. In the top navigation, click Settings, and then click Context Fields. The Manage Context Fields page appears.
  2. Click Add Context Field. The Create Context Field wizard appears.
  3. For Context Field Name, enter an identifier for the Secret: weatherCondition.
  4. For Display Name, enter a friendly name for the Secret: weatherCondition.
  5. Optionally, enter a Description for the Content Field.
  6. For Data Type, select String.
  7. Under Fixed List of Values, enter a single key/value pair for Sunny.
  8. Click Submit.

Page Type

To create a Context Field used to store the current page a shopper is browsing, in the DX Studio UI:

  1. In the top navigation, click Settings, and then click Context Fields. The Manage Context Fields page appears.
  2. Click Add Context Field. The Create Context Field wizard appears.
  3. For Context Field Name, enter an identifier for the Secret: pageType.
  4. For Display Name, enter a friendly name for the Secret: pageType.
  5. Optionally, enter a Description for the Content Field.
  6. For Data Type, select String.
  7. Under Fixed List of Values, enter a single key/value pair for checkout.
  8. Click Submit.

Customer Id

To create a Context Field used to store the customer id of the current shopper, in the DX Studio UI:

  1. In the top navigation, click Settings, and then click Context Fields. The Manage Context Fields page appears.
  2. Click Add Context Field. The Create Context Field wizard appears.
  3. For Context Field Name, enter an identifier for the Secret: customerId.
  4. For Display Name, enter a friendly name for the Secret: customerId.
  5. Optionally, enter a Description for the Content Field.
  6. For Data Type, select String.
  7. Under Fixed List of Values, enter a single key/value pair for guest.
  8. Click Submit.

Secrets

WeatherAPI Secret

To create a Secret used to store the WeatherAPI API Key, in the DX Studio UI:

  1. In the top navigation, click Settings, and then click Secrets. The Manage Secrets page appears.
  2. Click Add Secret. The Create Secret wizard appears.
  3. For Secret Code, enter an identifier for the Secret: weatherapi-key.
  4. For Name, enter a friendly name for the Secret: WeatherAPI Key.
  5. Optionally, enter a Description for the Secret.
  6. For Secret Value, enter your WeatherAPI API key.
  7. Click Submit.

ChatGPT Secret

To create a Secret used to store the ChatGPT API Key, in the DX Studio UI:

  1. In the top navigation, click Settings, and then click Secrets. The Manage Secrets page appears.
  2. Click Add Secret. The Create Secret wizard appears.
  3. For Secret Code, enter an identifier for the Secret: chatgpt-key.
  4. For Name, enter a friendly name for the Secret: ChatGPT Key.
  5. Optionally, enter a Description for the Secret.
  6. For Secret Value, enter your ChatGPT API key.
  7. Click Submit.

Connections

Connection to WeatherAPI

  • Navigate to the Connections page (Settings --> Connections).
  • Click the + Add Connection button.
  • Enter the following and click Submit:
FieldValue
Connection Codeweatherapi-connection
Connection NameWeatherAPI Connection
ConnectorUniversal API Connector
Base URLGet value from: Literal
http://api.weatherapi.com/v1
Query ParametersParameter: key
Value:
Get value from: Secret
WeatherAPI Key

Connection to ChatGPT

  • Navigate to the Connections page (Settings --> Connections).
  • Click the + Add Connection button.
  • Enter the following and click Submit:
FieldValue
Connection Codechatgpt-connection
Connection NameChatGPT Connection
ConnectorUniversal API Connector
Base URLGet value from: Literal
https://api.openai.com/v1
Base HeadersHeader: Authorization
Value:
Get value from: JS Expression
`Bearer ` + secret('chatgpt-personalaccount') Key
Base HeadersHeader: OpenAI-Organization
Value:
Get value from: Literal
{your organization id}
Base HeadersHeader: content-type
Value:
Get value from: Literal
application/json

Components

Component to retrieve current weather conditions

  • Navigate to the Experience Components page (Manage Experiences --> Components).
  • Click the + Add Component button.
  • Enter the following and click Submit.
FieldForm TabValue
Component CodeMainget-current-weather
Component NameMainGet Current Weather
No RulesMainChecked
Component TypeMainConscia - Universal API Connector
ConnectionMainWeather API Connection
Webservice PathMainGet value from: Literal
/current.json
MethodMainGET
Query ParametersMainParameter: q
Value:
Get value from: JS Expression
`${contextField('location')}`
Context Field EnrichmentsUpdate ContextContext Field: weatherCondition
Expression: response.current.condition.text

Component to retrieve Frequently Purchased Together recommendations

  • Navigate to the Experience Components page (Manage Experiences --> Components).
  • Click the + Add Component button.
  • Enter the following and click Submit.
FieldForm TabValue
Component CodeMainchatgpt-rec1
Component NameMainChatGPT - Frequently Purchased Recs (Aggregate)
No RulesMainChecked
Component TypeMainConscia - Universal API Connector
ConnectionMainChatGPT Connection
Webservice PathMainGet value from: Literal
/chat/completions
MethodMainPOST
BodyMainGet value from: JS Expression
`{
"model": "gpt-3.5-turbo",
"response_format": { "type": "json_object" },
"messages": [{"role": "user", "content": "A person has the following items in their online grocery store shopping cart: ${contextField('cartItems')}. Provide me with a JSON list of 3 grocery store products that people often buy that are complementary to the items in the cart. Each JSON product object should have a numeric id of 5 digits; a name; a price between $5 and $25; and a placeholder url link to a generic image of this product."}],
"temperature": 0.9
}`

Component to retrieve Frequently Purchased recommendations

  • Navigate to the Experience Components page (Manage Experiences --> Components).
  • Click the + Add Component button.
  • Enter the following and click Submit.
FieldForm TabValue
Component CodeMainchatgpt-rec2
Component NameMainChatGPT - Frequently Purchased Recs (Individual)
No RulesMainChecked
Component TypeMainConscia - Universal API Connector
ConnectionMainChatGPT Connection
Webservice PathMainGet value from: Literal
/chat/completions
MethodMainPOST
BodyMainGet value from: JS Expression
`{
"model": "gpt-3.5-turbo",
"response_format": { "type": "json_object" },
"messages": [{"role": "user", "content": "Provide me with a list of 3 grocery store products that people would buy in a weekly online order. Each JSON product object should have a numeric id of 5 digits; a name; a price between $5 and $25; and a placeholder url link to a generic image of this product. The products should be in fruit, chocolate, candy, chips, or dip categories."}],
"temperature": 0.9
}`

Component to retrieve Never Purchased recommendations

  • Navigate to the Experience Components page (Manage Experiences --> Components).
  • Click the + Add Component button.
  • Enter the following and click Submit.
FieldForm TabValue
Component CodeMainchatgpt-rec3
Component NameMainChatGPT - Never Purchased Recs (Individual)
No RulesMainChecked
Component TypeMainConscia - Universal API Connector
ConnectionMainChatGPT Connection
Webservice PathMainGet value from: Literal
/chat/completions
MethodMainPOST
BodyMainGet value from: JS Expression
`{
"model": "gpt-3.5-turbo",
"response_format": { "type": "json_object" },
"messages": [{"role": "user", "content": "Provide me with a JSON list of 3 grocery store products that people rarely buy in a weekly online order. They should be foods people generally enjoy. Each JSON product object should have a numeric id of 5 digits; a name; a price between $5 and $25; and a placeholder url link to a generic image of this product."}],
"temperature": 0.9
}`

Mapper Components to transform recommendations responses

Because each of our product recommendations models is providing the same output instructions to the ChatGPT prompt, the Mapper Components are virtually identical in this recipe. We'll only show the configuration for the first model. It's likely specific LLMs will have varying response structures, so you would need to create separate Mappers for each of them in your implementation.

  • Navigate to the Experience Components page (Manage Experiences --> Components).
  • Click the + Add Component button.
  • Enter the following and click Submit.
FieldForm TabValue
Component CodeMainchatgpt-rec1-mapper
Component NameMainMapper - Frequently Purchased Recs (Aggregate) - ChatGPT
No RulesMainChecked
Component TypeMainConscia - Data Transformation Script
Data to modifyMainGet value from: Component Response
ChatGPT - Frequently Purchased Recs (Aggregrate)
ScriptMainThis script's main purpose is to extract JSON from the String message ChatGPT returns in its API response.
let recs = data.choices[0].message.content; 

function extractJSON(str) {
var firstOpen, firstClose, candidate;
firstOpen = str.indexOf('{', firstOpen + 1);
do {
firstClose = str.lastIndexOf('}');
console.log('firstOpen: ' + firstOpen, 'firstClose: ' + firstClose);
if(firstClose <= firstOpen) {
return null;
}
do {
candidate = str.substring(firstOpen, firstClose + 1);
console.log('candidate: ' + candidate);
try {
var res = JSON.parse(candidate);
return res;
}
catch(e) {
console.log('...failed');
}
firstClose = str.substr(0, firstClose).lastIndexOf('}');
} while(firstClose > firstOpen);
firstOpen = str.indexOf('{', firstOpen + 1);
} while(firstOpen != -1);
}

var result = extractJSON(recs);
result

Component to allow users to select source LLM for product recommendations

The Experience Rules will be created on this Component. You could choose to define default Metadata here. In this recipe we depend on the existence of a default Rule.

  • Navigate to the Experience Components page (Manage Experiences --> Components).
  • Click the + Add Component button.
  • Enter the following and click Submit.
FieldForm TabValue
Component CodeMainchatgpt-recs-source
Component NameMainChatGPT - Recommendations Source
No RulesMainNot Checked
Component TypeMainConscia - Metadata

Model Component to retrieve model recommendations based on triggered Experience Rule

  • Navigate to the Experience Components page (Manage Experiences --> Components).
  • Click the + Add Component button.
  • Enter the following and click Submit.
FieldForm TabValue
Component CodeMainmodel-chatgpt-recs
Component NameMainModel - ChatGPT Recs
No RulesMainChecked
Component TypeMainConscia - Metadata
Response TransformMain(see below)
componentResponse('chatgpt-recs-source').source[0] === 'recs1' ? componentResponse('chatgpt-rec1-mapper') : componentResponse('chatgpt-recs-source').source[0] === 'recs2' ? componentResponse('chatgpt-rec2-mapper') : componentResponse('chatgpt-recs-source').source[0] === 'recs3' ? componentResponse('chatgpt-rec3-mapper') : {}

Mapper Component to merge message header with recommendations data

  • Navigate to the Experience Components page (Manage Experiences --> Components).
  • Click the + Add Component button.
  • Enter the following and click Submit.
FieldForm TabValue
Component CodeMainchatgpt-full-recommendations-mapper
Component NameMainMapper - Full Recommendations - ChatGPT
No RulesMainChecked
Component TypeMainConscia - Property Mapper
  • Create two Property Maps as follows and click Submit.
FieldValue
Source DataGet value from: Component Response Model - ChatGPT Recs
Expression TypeJavascript
MappingsTarget property: recommendations
Source expression: data
FieldValue
Source DataGet value from: Component Response ChatGPT - Recommendations Source
Expression Typejavascript
MappingsTarget property: heading
Source expression: data.message[0]

Experience Rules

Experience Rule to use the Frequently Purchased Together LLM

  • Navigate to the Omnichannel Experience Rules page (Manage Experiences --> Experience).
  • Navigate to your ChatGPT - Recommendations Source Component under All Components.
  • Click the + Add Experience Rule button.
  • Enter the following and click Submit.
FieldForm TabValue
Rule IDMainfrequently-purchased-all
Rule NameMainFrequently Purchased Together (Aggregate)
PriorityMain999
Is DefaultMainChecked
FieldForm TabValue
ActiveExperienceChecked
DatesExperienceOptional
  • Under Real-time Context Evaluation, construct the following logic:

    pageType is equal to (=) checkout AND customerId is equal to (=) guest

  • Under Target Experience, add two instruction key/value pairs then click Submit.

FieldValue
InstructionsKey: source
Value: recs1
InstructionsKey: message
Value: Missing one of these products?

Experience Rule to use the Frequently Purchased by an Individual LLM

  • Navigate to the Omnichannel Experience Rules page (Manage Experiences --> Experience).
  • Navigate to your ChatGPT - Recommendations Source Component under All Components.
  • Click the + Add Experience Rule button.
  • Enter the following and click Submit.
FieldForm TabValue
Rule IDMainfrequently-purchased
Rule NameMainFrequently Purchased (Individual)
PriorityMain900
Is DefaultMainNot Checked
FieldForm TabValue
ActiveExperienceChecked
DatesExperienceOptional
  • Under Real-time Context Evaluation, construct the following logic:

    pageType is equal to (=) checkout AND customerId is not equal to (=/=) guest

  • Under Target Experience, add two instruction key/value pairs then click Submit.

FieldValue
InstructionsKey: source
Value: recs2
InstructionsKey: message
Value: Did you forget something?

Experience Rule to use the Never Purchased by an Individual LLM

  • Navigate to the Omnichannel Experience Rules page (Manage Experiences --> Experience).
  • Navigate to your ChatGPT - Recommendations Source Component under All Components.
  • Click the + Add Experience Rule button.
  • Enter the following and click Submit.
FieldForm TabValue
Rule IDMainnever-purchased
Rule NameMainNever Purchased (Individual)
PriorityMain800
Is DefaultMainNot Checked
FieldForm TabValue
ActiveExperienceChecked
DatesExperienceOptional
  • Under Real-time Context Evaluation, construct the following logic:

    pageType is equal to (=) checkout AND customerId is not equal to (=/=) guest AND weatherCondition is equal to (=) Sunny

  • Under Target Experience, add two instruction key/value pairs then click Submit.

FieldValue
InstructionsKey: source
Value: recs3
InstructionsKey: message
Value: Ready for Adventure? Try something new!

References