開始使用 Azure AI 個人化服務工具的多插槽
重要
從 2023 年 9 月 20 日起,您將無法建立新的個人化工具資源。 個人化工具服務將于 2026 年 10 月 1 日淘汰。
多位置個人化 (預覽) 可讓您以網頁版面配置、浮動切換和清單為目標,其中一個以上的動作(例如產品或內容片段)會向使用者顯示。 透過個人化工具多位置 API,您可以在個人化工具中讓 AI 模型瞭解哪些使用者內容和產品會驅動特定行為,並考慮並學慣用戶介面中的位置。 例如,個人化工具可能會瞭解某些產品或內容會以提要欄或頁尾的點擊次數,而不是頁面上的主要醒目提示。
在本指南中,您將瞭解如何使用個人化工具多重位置 API。
參考檔 | 程式庫原始程式碼 | 套件 (NuGet) | 多位置概念範例 |
必要條件
- Azure 訂用帳戶 - 免費建立一個訂用帳戶
- .NET Core 的 目前版本。
- 擁有 Azure 訂用帳戶之後, 請在Azure 入口網站中建立個人化工具資源 ,以取得您的金鑰和端點。 部署之後,請選取 [移至資源 ]。
- 您需要從您建立的資源取得金鑰和端點,才能將應用程式連線到個人化工具 API。 將金鑰和端點貼到快速入門稍後的程式碼中。
- 您可以使用免費定價層 (
F0
) 來試用服務,稍後再升級至生產環境的付費層。
設定
將個人化工具實例升級至多位置
注意
多位置個人化 (預覽) 會影響個人化工具服務的其他功能。 無法復原此變更。 啟用多位置個人化之前,請參閱 多位置個人化 (預覽) 。
- 停用自動優化 在Azure 入口網站中,在個人化工具資源中, 于 [資源管理 ] 底下的 [模型和學習設定 ] 頁面上,關閉 [自動優化] 並儲存。
注意
除非您停用自動優化,否則多位置個人化將無法運作。 未來將支援多重位置個人化自動優化。
- 將個人化服務工具更新為多插槽。在 Azure 入口網站的個人化服務工具資源中,於 [資源管理] 下的 [模型和學習設定] 頁面上,選取 [匯出學習設定]。 下載 json 檔案中的引數 欄位會以 --cb_explore_adf 開頭 。 將此變更為 --ccb_explore_adf 並儲存檔案。 CB(關聯式強盜)和 CCB(條件式關聯式強盜)是個人化工具分別用於單一位置和多位置個人化的演算法。 ADF(動作相依特徵)表示動作會以特徵表示/識別。
在入口網站的相同索引標籤中,在 [匯入學習設定 ] 下 ,流覽以尋找您最近修改過的 json 檔案並上傳它。 這會將您的個人化工具實例更新為「多位置」個人化工具,現在將支援多位置排名和獎勵呼叫。
變更模型更新頻率
在 Azure 入口網站中,前往個人化服務工具資源的 [設定] 頁面,將 [模型更新頻率] 變更為 30 秒。 這個較短的時間將會快速定型模型,讓您可以查看建議的動作會如何針對每個反覆項目變更。
變更獎勵等候時間
在 Azure 入口網站中,前往個人化服務工具資源的 [設定] 頁面,將 [奬勵等待時間] 變更為 10 分鐘。 這會決定模型在傳送建議之後等候的時間長度,以接收來自該建議的獎勵意見反應。 直到獎勵等候時間過後,才會進行定型。
建立新的 C# 應用程式
在慣用的編輯器或 IDE 中建立新的 .NET Core 應用程式。
在主控台視窗中(例如 cmd、PowerShell 或 Bash),使用 dotnet new
命令建立名稱為 personalizer-quickstart
的新主控台應用程式。 此命令會建立簡單的 "Hello World" C# 專案,內含單一原始程式檔:Program.cs
。
dotnet new console -n personalizer-quickstart
將您的目錄變更為新建立的應用程式資料夾。 您可以使用下列專案建置應用程式:
dotnet build
組建輸出不應包含警告或錯誤。
...
Build succeeded.
0 Warning(s)
0 Error(s)
...
安裝用戶端程式庫
在應用程式目錄中,使用下列命令安裝適用于 .NET 的個人化工具用戶端程式庫:
dotnet add package Azure.AI.Personalizer --version 2.0.0-beta.2
從專案目錄,在慣用的編輯器或 IDE 中開啟 Program.cs
檔案。 新增下列 using 指示詞:
using System;
using Azure;
using Azure.AI.Personalizer;
using System.Collections.Generic;
using System.Linq;
物件模型
個人化工具用戶端是 個人化工具Client 物件,可使用包含金鑰的 Azure.AzureKeyCredential 向 Azure 進行驗證。
若要要求每個位置內容的單一最佳專案,請建立 PersonalizerRankMultiSlotOptions 物件,然後將它傳遞至 PersonalizerClient.RankMultiSlot 。 RankMultiSlot 方法會 傳回 PersonalizerMultiSlotRankResult 。
若要將獎勵分數傳送給個人化工具,請建立 個人化工具RewardMultiSlotOptions ,然後將它 傳遞給個人化工具Client.RewardMultiSlot 方法以及對應的事件識別碼。
本快速入門中的獎勵分數非常簡單。 在生產系統中,決定哪些專案會影響獎勵分數 ,以及複雜程式可能有多少 ,而您可能會決定隨著時間而變更。 此設計決策應該是個人化工具架構中的主要決策之一。
程式碼範例
這些程式碼片段示範如何使用適用于 .NET 的個人化工具用戶端程式庫來執行下列工作:
驗證用戶端
在本節中,您將執行兩件事:
- 指定您的金鑰和端點
- 建立個人化工具用戶端
首先,將下列幾行新增至您的 Program 類別。 請務必從個人化工具資源新增金鑰和端點。
重要
前往 Azure 入口網站。 如果您在部署成功的必要條件 一節中 建立的個人化工具資源,請按一下 [後續步驟 ] 底下的 [移至資源 ] 按鈕。 您可以在資源 管理的 [金鑰和端點] 頁面中 ,找到您的金鑰和端點 。
當您完成時,請記得從程式碼中移除金鑰,且絕不會公開發布。 針對生產環境,請考慮使用安全的方式來儲存和存取您的認證。 例如, Azure 金鑰保存庫 。
private const string ServiceEndpoint = "https://REPLACE-WITH-YOUR-PERSONALIZER-RESOURCE-NAME.cognitiveservices.azure.com";
private const string ResourceKey = "<REPLACE-WITH-YOUR-PERSONALIZER-KEY>";
接下來,建構排名和獎勵 URL。
static PersonalizerClient InitializePersonalizerClient(Uri url)
{
return new PersonalizerClient(url, new AzureKeyCredential(ResourceKey));
}
取得以動作表示的內容選擇
動作代表您想要個人化工具從中選取最佳內容專案的內容選擇。 將下列方法新增至 Program 類別,以代表一組動作及其功能。
private static IList<PersonalizerRankableAction> GetActions()
{
IList<PersonalizerRankableAction> actions = new List<PersonalizerRankableAction>
{
new PersonalizerRankableAction(
id: "Red-Polo-Shirt-432",
features:
new List<object>() { new { onSale = "true", price = "20", category = "Clothing" } }
),
new PersonalizerRankableAction(
id: "Tennis-Racket-133",
features:
new List<object>() { new { onSale = "false", price = "70", category = "Sports" } }
),
new PersonalizerRankableAction(
id: "31-Inch-Monitor-771",
features:
new List<object>() { new { onSale = "true", price = "200", category = "Electronics" } }
),
new PersonalizerRankableAction(
id: "XBox-Series X-117",
features:
new List<object>() { new { onSale = "false", price = "499", category = "Electronics" } }
)
};
return actions;
}
取得位置
位置會組成使用者將與其互動的頁面。 個人化工具會決定要在每個定義位置中顯示的動作。 動作可以從特定位置排除,如下所示 ExcludeActions
。 BaselineAction
是位置的預設動作,該位置已顯示而不使用個人化工具。
本快速入門具有簡單的位置功能。 在生產系統中,判斷和 評估 功能 可能是一件非簡單的事情。
private static IList<PersonalizerSlotOptions> GetSlots()
{
IList<PersonalizerSlotOptions> slots = new List<PersonalizerSlotOptions>
{
new PersonalizerSlotOptions(
id: "BigHeroPosition",
features: new List<object>() { new { size = "large", position = "left" } },
excludedActions: new List<string>() { "31-Inch-Monitor-771" },
baselineAction: "Red-Polo-Shirt-432"
),
new PersonalizerSlotOptions(
id: "SmallSidebar",
features: new List<object>() { new { size = "small", position = "right" } },
excludedActions: new List<string>() { "Tennis-Racket-133" },
baselineAction: "XBox-Series X-117"
),
};
return slots;
}
取得內容的使用者喜好設定
將下列方法新增至 Program 類別,以從命令列取得使用者在一天中的時間輸入,以及使用者開啟的裝置類型。 這些方法將用作內容功能。
static string GetTimeOfDayForContext()
{
string[] timeOfDayFeatures = new string[] { "morning", "afternoon", "evening", "night" };
Console.WriteLine("\nWhat time of day is it (enter number)? 1. morning 2. afternoon 3. evening 4. night");
if (!int.TryParse(GetKey(), out int timeIndex) || timeIndex < 1 || timeIndex > timeOfDayFeatures.Length)
{
Console.WriteLine("\nEntered value is invalid. Setting feature value to " + timeOfDayFeatures[0] + ".");
timeIndex = 1;
}
return timeOfDayFeatures[timeIndex - 1];
}
static string GetDeviceForContext()
{
string[] deviceFeatures = new string[] { "mobile", "tablet", "desktop" };
Console.WriteLine("\nWhat is the device type (enter number)? 1. Mobile 2. Tablet 3. Desktop");
if (!int.TryParse(GetKey(), out int deviceIndex) || deviceIndex < 1 || deviceIndex > deviceFeatures.Length)
{
Console.WriteLine("\nEntered value is invalid. Setting feature value to " + deviceFeatures[0] + ".");
deviceIndex = 1;
}
return deviceFeatures[deviceIndex - 1];
}
這兩種方法都會使用 GetKey
方法,從命令列讀取使用者的選取範圍。
private static string GetKey()
{
return Console.ReadKey().Key.ToString().Last().ToString().ToUpper();
}
private static IList<object> GetContext(string time, string device)
{
return new List<object>()
{
new { time = time },
new { device = device }
};
}
建立學習迴圈
個人化工具學習迴圈是 RankMultiSlot 和 RewardMultiSlot 呼叫的 迴圈。 在本快速入門中,每個排名呼叫,為了個人化內容,接著是獎勵呼叫,告知個人化工具服務的執行程度。
下列程式碼會迴圈透過命令列詢問使用者其喜好設定,並將該資訊傳送至個人化工具,以選取每個位置的最佳動作,向客戶呈現從清單中選擇的選項,然後將獎勵分數傳送給個人化工具,表示服務在其選取範圍中的表現。
static void Main(string[] args)
{
Console.WriteLine($"Welcome to this Personalizer Quickstart!\n" +
$"This code will help you understand how to use the Personalizer APIs (multislot rank and multislot reward).\n" +
$"Each iteration represents a user interaction and will demonstrate how context, actions, slots, and rewards work.\n" +
$"Note: Personalizer AI models learn from a large number of user interactions:\n" +
$"You won't be able to tell the difference in what Personalizer returns by simulating a few events by hand.\n" +
$"If you want a sample that focuses on seeing how Personalizer learns, see the Python Notebook sample.");
int iteration = 1;
bool runLoop = true;
IList<PersonalizerRankableAction> actions = GetActions();
IList<PersonalizerSlotOptions> slots = GetSlots();
PersonalizerClient client = InitializePersonalizerClient(new Uri(ServiceEndpoint));
do
{
Console.WriteLine("\nIteration: " + iteration++);
string timeOfDayFeature = GetTimeOfDayForContext();
string deviceFeature = GetDeviceForContext();
IList<object> currentContext = GetContext(timeOfDayFeature, deviceFeature);
string eventId = Guid.NewGuid().ToString();
var multiSlotRankOptions = new PersonalizerRankMultiSlotOptions(actions, slots, currentContext, eventId);
PersonalizerMultiSlotRankResult multiSlotRankResult = client.RankMultiSlot(multiSlotRankOptions);
for (int i = 0; i < multiSlotRankResult.Slots.Count(); ++i)
{
string slotId = multiSlotRankResult.Slots[i].SlotId;
Console.WriteLine($"\nPersonalizer service decided you should display: { multiSlotRankResult.Slots[i].RewardActionId} in slot {slotId}. Is this correct? (y/n)");
string answer = GetKey();
if (answer == "Y")
{
client.RewardMultiSlot(eventId, slotId, 1f);
Console.WriteLine("\nGreat! The application will send Personalizer a reward of 1 so it learns from this choice of action for this slot.");
}
else if (answer == "N")
{
client.RewardMultiSlot(eventId, slotId, 0f);
Console.WriteLine("\nYou didn't like the recommended item. The application will send Personalizer a reward of 0 for this choice of action for this slot.");
}
else
{
client.RewardMultiSlot(eventId, slotId, 0f);
Console.WriteLine("\nEntered choice is invalid. Service assumes that you didn't like the recommended item.");
}
}
Console.WriteLine("\nPress q to break, any other key to continue:");
runLoop = !(GetKey() == "Q");
} while (runLoop);
}
請仔細查看下列各節中的排名和獎勵呼叫。 新增下列方法,在 執行程式碼檔案之前,先取得內容選擇 、 取得位置 ,以及 傳送多位置排名和獎勵要求 :
GetActions
GetSlots
GetTimeOfDayForContext
GetDeviceForContext
GetKey
GetContext
要求最佳動作
為了完成排名要求,程式會要求使用者的喜好設定來建立 Context
內容的選擇。 要求包含內容、動作和位置及其各自的功能和唯一事件識別碼,以接收回應。
本快速入門具有一天時間與使用者裝置的簡單內容功能。 在生產系統中,判斷和 評估 動作和功能 可能是非微不足道的問題。
string timeOfDayFeature = GetTimeOfDayForContext();
string deviceFeature = GetDeviceForContext();
IList<object> currentContext = GetContext(timeOfDayFeature, deviceFeature);
string eventId = Guid.NewGuid().ToString();
var multiSlotRankOptions = new PersonalizerRankMultiSlotOptions(actions, slots, currentContext, eventId);
PersonalizerMultiSlotRankResult multiSlotRankResult = client.RankMultiSlot(multiSlotRankOptions);
傳送獎勵
若要取得 Reward 要求的獎勵分數,程式會透過命令列取得每個位置的使用者選取專案、將數值(獎勵分數)指派給選取專案,然後將每個位置的唯一事件識別碼、位置識別碼和獎勵分數,作為獎勵 API 的數值。 每個位置不需要定義獎勵。
本快速入門會將簡單的數位指派為獎勵分數,可以是零或 1。 在生產系統中,根據您的特定需求,判斷傳送給 Reward 呼叫的時機和內容可能是非簡單事項。
for (int i = 0; i < multiSlotRankResult.Slots.Count(); ++i)
{
string slotId = multiSlotRankResult.Slots[i].SlotId;
Console.WriteLine($"\nPersonalizer service decided you should display: { multiSlotRankResult.Slots[i].RewardActionId} in slot {slotId}. Is this correct? (y/n)");
string answer = GetKey();
if (answer == "Y")
{
client.RewardMultiSlot(eventId, slotId, 1f);
Console.WriteLine("\nGreat! The application will send Personalizer a reward of 1 so it learns from this choice of action for this slot.");
}
else if (answer == "N")
{
client.RewardMultiSlot(eventId, slotId, 0f);
Console.WriteLine("\nYou didn't like the recommended item. The application will send Personalizer a reward of 0 for this choice of action for this slot.");
}
else
{
client.RewardMultiSlot(eventId, slotId, 0f);
Console.WriteLine("\nEntered choice is invalid. Service assumes that you didn't like the recommended item.");
}
}
執行程式
從應用程式目錄使用 dotnet run
命令執行應用程式。
dotnet run
本快速入門 的原始程式碼可供使用。
必要條件
- Azure 訂用帳戶 - 免費建立一個訂用帳戶
- 安裝 Node.js 和 NPM (使用 Node.js v14.16.0 和 NPM 6.14.11 驗證)。
- 擁有 Azure 訂用帳戶之後, 請在Azure 入口網站中建立個人化工具資源 ,以取得您的金鑰和端點。 部署之後,請選取 [移至資源 ]。
- 您需要從您建立的資源取得金鑰和端點,才能將應用程式連線到個人化工具 API。 將金鑰和端點貼到快速入門稍後的程式碼中。
- 您可以使用免費定價層 (
F0
) 來試用服務,稍後再升級至生產環境的付費層。
設定
將個人化工具實例升級至多位置
注意
多位置個人化 (預覽) 會影響個人化工具服務的其他功能。 無法復原此變更。 啟用多位置個人化之前,請參閱 多位置個人化 (預覽) 。
- 停用自動優化 在Azure 入口網站中,在個人化工具資源中, 于 [資源管理 ] 底下的 [模型和學習設定 ] 頁面上,關閉 [自動優化] 並儲存。
注意
除非您停用自動優化,否則多位置個人化將無法運作。 未來將支援多重位置個人化自動優化。
- 將個人化服務工具更新為多插槽。在 Azure 入口網站的個人化服務工具資源中,於 [資源管理] 下的 [模型和學習設定] 頁面上,選取 [匯出學習設定]。 下載 json 檔案中的引數 欄位會以 --cb_explore_adf 開頭 。 將此變更為 --ccb_explore_adf 並儲存檔案。 CB(關聯式強盜)和 CCB(條件式關聯式強盜)是個人化工具分別用於單一位置和多位置個人化的演算法。 ADF(動作相依特徵)表示動作會以特徵表示/識別。
在入口網站的相同索引標籤中,在 [匯入學習設定 ] 下 ,流覽以尋找您最近修改過的 json 檔案並上傳它。 這會將您的個人化工具實例更新為「多位置」個人化工具,現在將支援多位置排名和獎勵呼叫。
變更模型更新頻率
在 Azure 入口網站中,前往個人化服務工具資源的 [設定] 頁面,將 [模型更新頻率] 變更為 30 秒。 這個較短的時間將會快速定型模型,讓您可以查看建議的動作會如何針對每個反覆項目變更。
變更獎勵等候時間
在 Azure 入口網站中,前往個人化服務工具資源的 [設定] 頁面,將 [奬勵等待時間] 變更為 10 分鐘。 這會決定模型在傳送建議之後等候的時間長度,以接收來自該建議的獎勵意見反應。 直到獎勵等候時間過後,才會進行定型。
建立新的 Node.js 應用程式
在主控台視窗中(例如 cmd、PowerShell 或 Bash),為您的應用程式建立新的目錄,然後流覽至它。
mkdir myapp && cd myapp
npm init -y
執行 命令以建立 package.json
檔案。
npm init -y
在慣用的編輯器或 IDE 中建立名為 sample.js
的新 Node.js 應用程式,並為資源的端點和訂用帳戶金鑰建立變數。
重要
前往 Azure 入口網站。 如果您在部署成功的必要條件 一節中 建立的個人化工具資源,請按一下 [後續步驟 ] 底下的 [移至資源 ] 按鈕。 您可以在資源 管理的 [金鑰和端點] 頁面中 ,找到您的金鑰和端點 。
當您完成時,請記得從程式碼中移除金鑰,且絕不會公開發布。 針對生產環境,請考慮使用安全的方式來儲存和存取您的認證。 例如, Azure 金鑰保存庫 。
const axios = require('axios');
const { v4: uuidv4 } = require('uuid');
const readline = require('readline-sync');
// The endpoint specific to your personalization service instance;
// e.g. https://<your-resource-name>.cognitiveservices.azure.com
const PersonalizationBaseUrl = '<REPLACE-WITH-YOUR-PERSONALIZER-ENDPOINT>';
// The key specific to your personalization service instance; e.g. "0123456789abcdef0123456789ABCDEF"
const ResourceKey = '<REPLACE-WITH-YOUR-PERSONALIZER-KEY>';
安裝 NPM 套件以取得快速入門
npm install readline-sync uuid axios --save
物件模型
若要要求每個位置內容的單一最佳專案,請建立 rankRequest ,然後將張貼要求傳送至 multislot/rank 。 然後,回應會剖析成 rankResponse 。
若要將獎勵分數傳送給個人化工具,請建立 獎勵 ,然後將張貼要求傳送至 multislot/events/{eventId}/reward 。
判斷獎勵分數,在本快速入門中是微不足道的。 在生產系統中,決定哪些專案會影響獎勵分數 ,以及複雜程式可能有多少 ,而您可能會決定隨著時間而變更。 此設計決策應該是個人化工具架構中的主要決策之一。
程式碼範例
這些程式碼片段示範如何藉由傳送 NodeJS 的 HTTP 要求來執行下列工作:
建立基底 URL
在本節中,您將使用基底 URL 和使用資源金鑰的要求標頭來建構排名/獎勵 URL。
const MultiSlotRankUrl = PersonalizationBaseUrl.concat('personalizer/v1.1-preview.1/multislot/rank');
const MultiSlotRewardUrlBase = PersonalizationBaseUrl.concat('personalizer/v1.1-preview.1/multislot/events/');
const Headers = {
'ocp-apim-subscription-key': ResourceKey,
'Content-Type': 'application/json'
};
取得以動作表示的內容選擇
動作代表您想要個人化工具從中選取最佳內容專案的內容選擇。 將下列方法新增至腳本,以代表一組動作及其功能。
function getActions() {
return [
{
'id': 'Red-Polo-Shirt-432',
'features': [
{
'onSale': 'true',
'price': 20,
'category': 'Clothing'
}
]
},
{
'id': 'Tennis-Racket-133',
'features': [
{
'onSale': 'false',
'price': 70,
'category': 'Sports'
}
]
},
{
'id': '31-Inch-Monitor-771',
'features': [
{
'onSale': 'true',
'price': 200,
'category': 'Electronics'
}
]
},
{
'id': 'XBox-Series X-117',
'features': [
{
'onSale': 'false',
'price': 499,
'category': 'Electronics'
}
]
}
];
}
取得內容的使用者喜好設定
將下列方法新增至腳本,以在一天中的時間從命令列取得使用者的輸入,以及使用者開啟的裝置類型。 這些會作為內容功能使用。
function getContextFeatures() {
const timeOfDayFeatures = ['morning', 'afternoon', 'evening', 'night'];
const deviceFeatures = ['mobile', 'tablet', 'desktop'];
let answer = readline.question('\nWhat time of day is it (enter number)? 1. morning 2. afternoon 3. evening 4. night\n');
let selection = parseInt(answer);
const timeOfDay = selection >= 1 && selection <= 4 ? timeOfDayFeatures[selection - 1] : timeOfDayFeatures[0];
answer = readline.question('\nWhat type of device is the user on (enter number)? 1. mobile 2. tablet 3. desktop\n');
selection = parseInt(answer);
const device = selection >= 1 && selection <= 3 ? deviceFeatures[selection - 1] : deviceFeatures[0];
console.log('Selected features:\n');
console.log('Time of day: ' + timeOfDay + '\n');
console.log('Device: ' + device + '\n');
return [
{
'time': timeOfDay
},
{
'device': device
}
];
}
取得位置
位置會組成使用者將與其互動的頁面。 個人化工具會決定要在每個定義位置中顯示的動作。 動作可以從特定位置排除,如下所示 ExcludeActions
。 BaselineAction
是位置的預設動作,該位置在未使用個人化工具的情況下顯示。
本快速入門具有簡單的位置功能。 在生產系統中,判斷和 評估 功能 可能是一件非簡單的事情。
function getSlots() {
return [
{
'id': 'BigHeroPosition',
'features': [
{
'size': 'large',
'position': 'left',
}
],
'excludedActions': ['31-Inch-Monitor-771'],
'baselineAction': 'Red-Polo-Shirt-432'
},
{
'id': 'SmallSidebar',
'features': [
{
'size': 'small',
'position': 'right',
}
],
'excludedActions': ['Tennis-Racket-133'],
'baselineAction': 'XBox-Series X-117'
}
];
}
提出 HTTP 要求
新增這些函式,以將要求傳送至個人化工具端點,以進行多位置排名和獎勵呼叫。
async function sendMultiSlotRank(rankRequest) {
try {
let response = await axios.post(MultiSlotRankUrl, rankRequest, { headers: Headers })
return response.data;
}
catch (err) {
if(err.response)
{
throw err.response.data
}
console.log(err)
throw err;
}
}
async function sendMultiSlotReward(rewardRequest, eventId) {
try {
let rewardUrl = MultiSlotRewardUrlBase.concat(eventId, '/reward');
let response = await axios.post(rewardUrl, rewardRequest, { headers: Headers })
}
catch (err) {
console.log(err);
throw err;
}
}
取得個人化工具決策的意見反應
將下列方法新增至腳本。 如果個人化工具透過命令列提示,為每個位置做出良好的決策,您將會發出訊號。
function getRewardForSlot() {
let answer = readline.question('\nIs this correct? (y/n)\n').toUpperCase();
if (answer === 'Y') {
console.log('\nGreat! The application will send Personalizer a reward of 1 so it learns from this choice of action for this slot.\n');
return 1;
}
else if (answer === 'N') {
console.log('\nYou didn\'t like the recommended item.The application will send Personalizer a reward of 0 for this choice of action for this slot.\n');
return 0;
}
console.log('\nEntered choice is invalid. Service assumes that you didn\'t like the recommended item.\n');
return 0;
}
建立學習迴圈
個人化工具學習迴圈是排名 和 獎勵 呼叫的 迴圈。 在本快速入門中,每個排名呼叫,為了個人化內容,接著是獎勵呼叫,告知個人化工具服務的執行程度。
下列程式碼會迴圈透過命令列詢問使用者其喜好設定,並將該資訊傳送至個人化工具,以選取每個位置的最佳動作,向客戶呈現從清單中選擇的選項,然後將獎勵分數傳送給個人化工具,表示服務在其選取範圍中的表現。
let runLoop = true;
(async () => {
do {
let multiSlotRankRequest = {};
// Generate an ID to associate with the request.
multiSlotRankRequest.eventId = uuidv4();
// Get context information from the user.
multiSlotRankRequest.contextFeatures = getContextFeatures();
// Get the actions list to choose from personalization with their features.
multiSlotRankRequest.actions = getActions();
// Get the list of slots for which Personalizer will pick the best action.
multiSlotRankRequest.slots = getSlots();
multiSlotRankRequest.deferActivation = false;
try {
//Rank the actions for each slot
let multiSlotRankResponse = await sendMultiSlotRank(multiSlotRankRequest);
let multiSlotrewards = {};
multiSlotrewards.reward = [];
for (let i = 0; i < multiSlotRankResponse.slots.length; i++) {
console.log('\nPersonalizer service decided you should display: '.concat(multiSlotRankResponse.slots[i].rewardActionId, ' in slot ', multiSlotRankResponse.slots[i].id, '\n'));
let slotReward = {};
slotReward.slotId = multiSlotRankResponse.slots[i].id;
// User agrees or disagrees with Personalizer decision for slot
slotReward.value = getRewardForSlot();
multiSlotrewards.reward.push(slotReward);
}
// Send the rewards for the event
await sendMultiSlotReward(multiSlotrewards, multiSlotRankResponse.eventId);
let answer = readline.question('\nPress q to break, any other key to continue:\n').toUpperCase();
if (answer === 'Q') {
runLoop = false;
}
}
catch (err) {
console.log(err);
throw err;
}
} while (runLoop);
})()
請仔細查看下列各節中的排名和獎勵呼叫。
新增下列方法來 取得內容選擇 、 取得內容 的使用者喜好設定、取得位置 、 提出 HTTP 要求 、 取得每個位置 的獎勵, 再執行程式碼檔案:
- getActions
- getCoNtextFeatures
- getSlots
- sendRank
- sendReward
- getRewardForSlot
要求最佳動作
若要完成排名要求,程式會要求使用者的喜好設定來建立內容選擇。 要求本文包含內容、動作和位置及其各自的功能。 方法 sendMultiSlotRank
會採用 rankRequest,並執行多位置排名要求。
本快速入門具有一天時間與使用者裝置的簡單內容功能。 在生產系統中,判斷和 評估 動作和功能 可能是非微不足道的問題。
let multiSlotRankRequest = {};
// Generate an ID to associate with the request.
multiSlotRankRequest.eventId = uuidv4();
// Get context information from the user.
multiSlotRankRequest.contextFeatures = getContextFeatures();
// Get the actions list to choose from personalization with their features.
multiSlotRankRequest.actions = getActions();
// Get the list of slots for which Personalizer will pick the best action.
multiSlotRankRequest.slots = getSlots();
multiSlotRankRequest.deferActivation = false;
//Rank the actions for each slot
try {
let multiSlotRankResponse = await sendMultiSlotRank(multiSlotRankRequest);
}
catch (err) {
console.log(err);
throw err;
}
傳送獎勵
若要取得 Reward 要求的獎勵分數,程式會透過命令列取得每個位置的使用者選取專案、將數值(獎勵分數)指派給選取專案,然後將每個位置的唯一事件識別碼、位置識別碼和獎勵分數傳送至 sendMultiSlotReward
方法。 不需要為每個位置定義獎勵。
本快速入門會將簡單的數位指派為獎勵分數,可以是零或 1。 在生產系統中,根據您的特定需求,判斷傳送給 Reward 呼叫的時機和內容可能是非簡單事項。
let multiSlotrewards = {};
multiSlotrewards.reward = [];
for (i = 0; i < multiSlotRankResponse.slots.length; i++) {
console.log('\nPersonalizer service decided you should display: '.concat(multiSlotRankResponse.slots[i].rewardActionId, ' in slot ', multiSlotRankResponse.slots[i].id, '\n'));
let slotReward = {};
slotReward.slotId = multiSlotRankResponse.slots[i].id;
// User agrees or disagrees with Personalizer decision for slot
slotReward.value = getRewardForSlot();
multiSlotrewards.reward.push(slotReward);
}
// Send the rewards for the event
await sendMultiSlotReward(multiSlotrewards, multiSlotRankResponse.eventId);
執行程式
從您的應用程式目錄使用 Node.js 執行應用程式。
node sample.js
本快速入門 的原始程式碼可供使用。
必要條件
- Azure 訂用帳戶 - 免費建立一個訂用帳戶
- Python 3.x
- 擁有 Azure 訂用帳戶之後, 請在Azure 入口網站中建立個人化工具資源 ,以取得您的金鑰和端點。 部署之後,請選取 [移至資源 ]。
- 您需要從您建立的資源取得金鑰和端點,才能將應用程式連線到個人化工具 API。 將金鑰和端點貼到快速入門稍後的程式碼中。
- 您可以使用免費定價層 (
F0
) 來試用服務,稍後再升級至生產環境的付費層。
設定
將個人化工具實例升級至多位置
注意
多位置個人化 (預覽) 會影響個人化工具服務的其他功能。 無法復原此變更。 啟用多位置個人化之前,請參閱 多位置個人化 (預覽) 。
- 停用自動優化 在Azure 入口網站中,在個人化工具資源中, 于 [資源管理 ] 底下的 [模型和學習設定 ] 頁面上,關閉 [自動優化] 並儲存。
注意
除非您停用自動優化,否則多位置個人化將無法運作。 未來將支援多重位置個人化自動優化。
- 將個人化服務工具更新為多插槽。在 Azure 入口網站的個人化服務工具資源中,於 [資源管理] 下的 [模型和學習設定] 頁面上,選取 [匯出學習設定]。 下載 json 檔案中的引數 欄位會以 --cb_explore_adf 開頭 。 將此變更為 --ccb_explore_adf 並儲存檔案。 CB(關聯式強盜)和 CCB(條件式關聯式強盜)是個人化工具分別用於單一位置和多位置個人化的演算法。 ADF(動作相依特徵)表示動作會以特徵表示/識別。
在入口網站的相同索引標籤中,在 [匯入學習設定 ] 下 ,流覽以尋找您最近修改過的 json 檔案並上傳它。 這會將您的個人化工具實例更新為「多位置」個人化工具,現在將支援多位置排名和獎勵呼叫。
變更模型更新頻率
在 Azure 入口網站中,前往個人化服務工具資源的 [設定] 頁面,將 [模型更新頻率] 變更為 30 秒。 這個較短的時間將會快速定型模型,讓您可以查看建議的動作會如何針對每個反覆項目變更。
變更獎勵等候時間
在 Azure 入口網站中,前往個人化服務工具資源的 [設定] 頁面,將 [奬勵等待時間] 變更為 10 分鐘。 這會決定模型在傳送建議之後等候的時間長度,以接收來自該建議的獎勵意見反應。 直到獎勵等候時間過後,才會進行定型。
建立新的 Python 應用程式
建立新的 Python 檔案,並為資源的端點和訂用帳戶金鑰建立變數。
重要
前往 Azure 入口網站。 如果您在部署成功的必要條件 一節中 建立的個人化工具資源,請按一下 [後續步驟 ] 底下的 [移至資源 ] 按鈕。 您可以在資源 管理的 [金鑰和端點] 頁面中 ,找到您的金鑰和端點 。
當您完成時,請記得從程式碼中移除金鑰,且絕不會公開發布。 針對生產環境,請考慮使用安全的方式來儲存和存取您的認證。 例如, Azure 金鑰保存庫 。
import json, uuid, requests
# The endpoint specific to your personalization service instance;
# e.g. https://<your-resource-name>.cognitiveservices.azure.com
PERSONALIZATION_BASE_URL = "<REPLACE-WITH-YOUR-PERSONALIZER-ENDPOINT>"
# The key specific to your personalization service instance; e.g. "0123456789abcdef0123456789ABCDEF"
RESOURCE_KEY = "<REPLACE-WITH-YOUR-PERSONALIZER-KEY>"
物件模型
若要要求每個位置內容的單一最佳專案,請建立 rank_request ,然後將張貼要求傳送至 multislot/rank 。 然後,回應會剖析成 rank_response 。
若要將獎勵分數傳送給個人化工具,請建立 獎勵 ,然後將張貼要求傳送至 multislot/events/{eventId}/reward 。
在本快速入門中,判斷獎勵分數是微不足道的。 在生產系統中,決定哪些影響 獎勵分數 ,以及您可以決定隨著時間變更的複雜程式。 此設計決策應該是個人化工具架構中的主要決策之一。
程式碼範例
這些程式碼片段示範如何藉由傳送 Python 的 HTTP 要求來執行下列工作:
建立基底 URL
在本節中,您將使用基底 URL 和使用資源金鑰的要求標頭來建構排名/獎勵 URL。
MULTI_SLOT_RANK_URL = '{0}personalizer/v1.1-preview.1/multislot/rank'.format(PERSONALIZATION_BASE_URL)
MULTI_SLOT_REWARD_URL_BASE = '{0}personalizer/v1.1-preview.1/multislot/events/'.format(PERSONALIZATION_BASE_URL)
HEADERS = {
'ocp-apim-subscription-key': RESOURCE_KEY,
'Content-Type': 'application/json'
}
取得以動作表示的內容選擇
動作代表您想要個人化工具從中選取最佳內容專案的內容選擇。 將下列方法新增至腳本,以代表一組動作及其功能。
def get_actions():
return [
{
"id": "Red-Polo-Shirt-432",
"features": [
{
"onSale": "true",
"price": 20,
"category": "Clothing"
}
]
},
{
"id": "Tennis-Racket-133",
"features": [
{
"onSale": "false",
"price": 70,
"category": "Sports"
}
]
},
{
"id": "31-Inch-Monitor-771",
"features": [
{
"onSale": "true",
"price": 200,
"category": "Electronics"
}
]
},
{
"id": "XBox-Series X-117",
"features": [
{
"onSale": "false",
"price": 499,
"category": "Electronics"
}
]
}
]
取得內容的使用者喜好設定
將下列方法新增至腳本,以在一天中的時間從命令列取得使用者的輸入,以及使用者開啟的裝置類型。 這些會作為內容功能使用。
def get_context_features():
time_features = ["morning", "afternoon", "evening", "night"]
time_pref = input("What time of day is it (enter number)? 1. morning 2. afternoon 3. evening 4. night\n")
try:
parsed_time = int(time_pref)
if(parsed_time <=0 or parsed_time > len(time_features)):
raise IndexError
time_of_day = time_features[parsed_time-1]
except (ValueError, IndexError):
print("Entered value is invalid. Setting feature value to", time_features[0] + ".")
time_of_day = time_features[0]
device_features = ['mobile', 'tablet', 'desktop']
device_pref = input("What type of device is the user on (enter number)? 1. mobile 2. tablet 3. desktop\n")
try:
parsed_device = int(device_pref)
if(parsed_device <=0 or parsed_device > len(device_features)):
raise IndexError
device = device_features[parsed_device-1]
except (ValueError, IndexError):
print("Entered value is invalid. Setting feature value to", device_features[0]+ ".")
device = device_features[0]
return [
{'time': time_of_day},
{'device': device}
]
取得位置
位置會組成使用者將與其互動的頁面。 個人化工具會決定要在每個定義位置中顯示的動作。 動作可以從特定位置排除,如下所示 ExcludeActions
。 BaselineAction
是位置的預設動作,該位置在未使用個人化工具的情況下顯示。
本快速入門具有簡單的位置功能。 在生產系統中,判斷和 評估 功能 可能是一件非簡單的事情。
def get_slots():
return [
{
"id": "BigHeroPosition",
"features": [
{
"size": "large",
"position": "left",
}
],
"excludedActions": ["31-Inch-Monitor-771"],
"baselineAction": "Red-Polo-Shirt-432"
},
{
"id": "SmallSidebar",
"features": [
{
"size": "small",
"position": "right",
}
],
"excludedActions": ["Tennis-Racket-133"],
"baselineAction": "XBox-Series X-117"
}
]
提出 HTTP 要求
新增這些函式,以將要求傳送至個人化工具端點,以進行多位置排名和獎勵呼叫。
def send_multi_slot_rank(rank_request):
multi_slot_response = requests.post(MULTI_SLOT_RANK_URL, data=json.dumps(rank_request), headers=HEADERS)
if multi_slot_response.status_code != 201:
raise Exception(multi_slot_response.text)
return json.loads(multi_slot_response.text)
def send_multi_slot_reward(reward_request, event_id):
reward_url = '{0}{1}/reward'.format(MULTI_SLOT_REWARD_URL_BASE, event_id)
requests.post(reward_url, data=json.dumps(reward_request), headers=HEADERS)
取得個人化工具決策的意見反應
將下列方法新增至腳本。 如果個人化工具透過命令列提示,為每個位置做出良好的決策,您將會發出訊號。
def get_reward_for_slot():
answer = input('\nIs this correct? (y/n)\n').upper()
if (answer == 'Y'):
print('\nGreat! The application will send Personalizer a reward of 1 so it learns from this choice of action for this slot.\n')
return 1
elif (answer == 'N'):
print('\nYou didn\'t like the recommended item.The application will send Personalizer a reward of 0 for this choice of action for this slot.\n')
return 0
print('\nEntered choice is invalid. Service assumes that you didn\'t like the recommended item.\n')
return 0
建立學習迴圈
個人化工具學習迴圈是排名 和 獎勵 呼叫的 迴圈。 在本快速入門中,每個排名呼叫,為了個人化內容,接著是獎勵呼叫,告知個人化工具服務的執行程度。
下列程式碼會迴圈透過命令列詢問使用者其喜好設定,並將該資訊傳送至個人化工具,以選取每個位置的最佳動作,向客戶呈現從清單中選擇的選項,然後將獎勵分數傳送給個人化工具,表示服務在其選取範圍中的表現。
run_loop = True
while run_loop:
eventId = str(uuid.uuid4())
context = get_context_features()
actions = get_actions()
slots = get_slots()
rank_request = {
"eventId": eventId,
"contextFeatures": context,
"actions": actions,
"slots": slots,
"deferActivation": False
}
#Rank the actions for each slot
multi_slot_rank_response = send_multi_slot_rank(rank_request)
multi_slot_rewards = {"reward": []}
for i in range(len(multi_slot_rank_response['slots'])):
print('\nPersonalizer service decided you should display: {0} in slot {1}\n'.format(multi_slot_rank_response['slots'][i]['rewardActionId'], multi_slot_rank_response['slots'][i]['id']))
slot_reward = {'slotId': multi_slot_rank_response['slots'][i]['id']}
# User agrees or disagrees with Personalizer decision for slot
slot_reward['value'] = get_reward_for_slot()
multi_slot_rewards['reward'].append(slot_reward)
# Send the rewards for the event
send_multi_slot_reward(multi_slot_rewards, multi_slot_rank_response['eventId'])
answer = input('\nPress q to break, any other key to continue:\n').upper()
if (answer == 'Q'):
run_loop = False
請仔細查看下列各節中的排名和獎勵呼叫。
新增下列方法來 取得內容選擇 、 取得內容 的使用者喜好設定、取得位置 、 提出 HTTP 要求 、 取得每個位置 的獎勵, 再執行程式碼檔案:
- get_actions
- get_coNtext_features
- get_slots
- send_rank
- send_reward
- get_reward_for_dsot
要求最佳動作
若要完成排名要求,程式會要求使用者的喜好設定來建立內容選擇。 要求本文包含內容、動作和位置及其各自的功能。 方法 send_multi_slot_rank
會採用 rankRequest,並執行多位置排名要求。
本快速入門具有一天時間與使用者裝置的簡單內容功能。 在生產系統中,判斷和 評估 動作和功能 可能是非微不足道的問題。
eventId = str(uuid.uuid4())
context = get_context_features()
actions = get_actions()
slots = get_slots()
rank_request = {
"eventId": eventId,
"contextFeatures": context,
"actions": actions,
"slots": slots,
"deferActivation": False
}
#Rank the actions for each slot
multi_slot_rank_response = send_multi_slot_rank(rank_request)
傳送獎勵
若要取得 Reward 要求的獎勵分數,程式會透過命令列取得每個位置的使用者選取專案、將數值(獎勵分數)指派給選取專案,然後將每個位置的唯一事件識別碼、位置識別碼和獎勵分數傳送至 send_multi_slot_reward
方法。 不需要為每個位置定義獎勵。
本快速入門會將簡單的數位指派為獎勵分數,可以是零或 1。 在生產系統中,根據您的特定需求,判斷傳送給 Reward 呼叫的時機和內容可能是非簡單事項。
multi_slot_rewards = {"reward": []}
for i in range(len(multi_slot_rank_response['slots'])):
print('\nPersonalizer service decided you should display: {0} in slot {1}\n'.format(multi_slot_rank_response['slots'][i]['rewardActionId'], multi_slot_rank_response['slots'][i]['id']))
slot_reward = {'slotId': multi_slot_rank_response['slots'][i]['id']}
# User agrees or disagrees with Personalizer decision for slot
slot_reward['value'] = get_reward_for_slot()
multi_slot_rewards['reward'].append(slot_reward)
# Send the rewards for the event
send_multi_slot_reward(multi_slot_rewards, multi_slot_rank_response['eventId'])
執行程式
從您的應用程式目錄使用 Python 執行應用程式。
python sample.py
本快速入門 的原始程式碼可供使用。