共用方式為


儲存使用者和對話資料

適用於: SDK v4

Bot 本質上是無狀態的。 部署 Bot 之後,它可能不會在相同進程中執行,或從一個回合到下一個回合在同一部電腦上執行。 不過,您的 Bot 可能需要追蹤交談的內容,才能管理其行為,並記住先前問題的解答。 Bot Framework SDK 的狀態和儲存功能可讓您將狀態新增至 Bot。 Bot 會使用狀態管理和儲存物件來管理和保存狀態。 狀態管理員提供抽象層,可讓您使用屬性存取子來存取狀態屬性,與基礎記憶體類型無關。

注意

Bot Framework JavaScript、C# 和 Python SDK 將會繼續受到支援,不過,Java SDK 即將淘汰,最終長期支援將於 2023 年 11 月結束。

使用 Java SDK 建置的現有 Bot 將繼續運作。

針對新的 Bot 建置,請考慮使用 Microsoft Copilot Studio ,並閱讀 選擇正確的 Copilot 解決方案

如需詳細資訊,請參閱 Bot 建置的未來。

必要條件

關於此範例

收到使用者輸入時,此範例會檢查儲存的交談狀態,以查看此使用者先前是否已提示您提供其名稱。 如果沒有,則會要求使用者的名稱,且該輸入會儲存在用戶狀態內。 如果是的話,儲存在用戶狀態內的名稱會用來與使用者及其輸入數據進行交談,以及接收的時間和輸入通道標識碼,會傳回給使用者。 時間與通道標識碼值會從使用者交談數據擷取,然後儲存至交談狀態。 下圖顯示 Bot、使用者配置檔和交談數據類別之間的關聯性。

定義類別

設定狀態管理的第一個步驟是定義類別,其中包含在使用者和交談狀態中管理的資訊。 本文中使用的範例會定義下列類別:

  • UserProfile.cs中,您會為 Bot 將收集的使用者資訊定義類別 UserProfile
  • ConversationData.cs中,您會定義類別 ConversationData ,以在收集用戶資訊時控制我們的交談狀態。

下列程式代碼範例顯示和 ConversationData 類別的定義UserProfile

UserProfile.cs

public class UserProfile
{
    public string Name { get; set; }
}

ConversationData.cs

public class ConversationData
{
    // The time-stamp of the most recent incoming message.
    public string Timestamp { get; set; }

    // The ID of the user's channel.
    public string ChannelId { get; set; }

    // Track whether we have already asked the user's name
    public bool PromptedUserForName { get; set; } = false;
}

建立交談和用戶狀態物件

接下來,您會註冊 MemoryStorage 用來建立 UserStateConversationState 物件的 。 使用者和交談狀態物件會在 中 Startup 建立,並將相依性插入 Bot 建構函式中。 已註冊 Bot 的其他服務包括:認證提供者、配接器和 Bot 實作。

Startup.cs

// {
//     TypeNameHandling = TypeNameHandling.All,
// var storage = new BlobsStorage("<blob-storage-connection-string>", "bot-state");

// With a custom JSON SERIALIZER, use this instead.
// var storage = new BlobsStorage("<blob-storage-connection-string>", "bot-state", jsonSerializer);

/* END AZURE BLOB STORAGE */

Bots/StateManagementBot.cs

private BotState _conversationState;
private BotState _userState;

public StateManagementBot(ConversationState conversationState, UserState userState)
{
    _conversationState = conversationState;
    _userState = userState;
}

新增狀態屬性存取子

現在,您可以使用 方法建立屬性存取子 CreateProperty ,以提供 物件的句柄 BotState 。 每個狀態屬性存取子都可讓您取得或設定相關聯狀態屬性的值。 使用狀態屬性之前,請先使用每個存取子從記憶體載入屬性,並從狀態快取中取得屬性。 若要取得與 state 屬性相關聯的適當範圍索引鍵,您可以呼叫 GetAsync 方法。

Bots/StateManagementBot.cs

var conversationStateAccessors = _conversationState.CreateProperty<ConversationData>(nameof(ConversationData));
var userStateAccessors = _userState.CreateProperty<UserProfile>(nameof(UserProfile));

從 Bot 存取狀態

上一節涵蓋將狀態屬性存取子新增至 Bot 的初始化時間步驟。 現在,您可以在運行時間使用這些存取子來讀取和寫入狀態資訊。 下列範例程式代碼會使用下列邏輯流程:

  • 如果 userProfile.Name 為空白且 conversationData.PromptedUserForNametrue,則您會擷取所提供的用戶名稱,並將它儲存在用戶狀態內。
  • 如果 userProfile.Name 是空的,且 conversationData.PromptedUserForNamefalse,則您要求用戶的名稱。
  • 如果 userProfile.Name 先前已儲存,您會從使用者輸入擷取訊息時間和通道標識碼、將所有數據回顯回給使用者,並將擷取的數據儲存在交談狀態中。

Bots/StateManagementBot.cs

protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
    // Get the state properties from the turn context.

    var conversationStateAccessors = _conversationState.CreateProperty<ConversationData>(nameof(ConversationData));
    var conversationData = await conversationStateAccessors.GetAsync(turnContext, () => new ConversationData());

    var userStateAccessors = _userState.CreateProperty<UserProfile>(nameof(UserProfile));
    var userProfile = await userStateAccessors.GetAsync(turnContext, () => new UserProfile());

    if (string.IsNullOrEmpty(userProfile.Name))
    {
        // First time around this is set to false, so we will prompt user for name.
        if (conversationData.PromptedUserForName)
        {
            // Set the name to what the user provided.
            userProfile.Name = turnContext.Activity.Text?.Trim();

            // Acknowledge that we got their name.
            await turnContext.SendActivityAsync($"Thanks {userProfile.Name}. To see conversation data, type anything.");

            // Reset the flag to allow the bot to go through the cycle again.
            conversationData.PromptedUserForName = false;
        }
        else
        {
            // Prompt the user for their name.
            await turnContext.SendActivityAsync($"What is your name?");

            // Set the flag to true, so we don't prompt in the next turn.
            conversationData.PromptedUserForName = true;
        }
    }
    else
    {
        // Add message details to the conversation data.
        // Convert saved Timestamp to local DateTimeOffset, then to string for display.
        var messageTimeOffset = (DateTimeOffset)turnContext.Activity.Timestamp;
        var localMessageTime = messageTimeOffset.ToLocalTime();
        conversationData.Timestamp = localMessageTime.ToString();
        conversationData.ChannelId = turnContext.Activity.ChannelId.ToString();

        // Display state data.
        await turnContext.SendActivityAsync($"{userProfile.Name} sent: {turnContext.Activity.Text}");
        await turnContext.SendActivityAsync($"Message received at: {conversationData.Timestamp}");
        await turnContext.SendActivityAsync($"Message received from: {conversationData.ChannelId}");
    }
}

結束回合處理程式之前,您會使用狀態管理物件的 SaveChangesAsync() 方法來將所有狀態變更寫回記憶體。

Bots/StateManagementBot.cs

public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
{
    await base.OnTurnAsync(turnContext, cancellationToken);

    // Save any state changes that might have occurred during the turn.
    await _conversationState.SaveChangesAsync(turnContext, false, cancellationToken);
    await _userState.SaveChangesAsync(turnContext, false, cancellationToken);
}

測試您的機器人

  1. 下載並安裝最新的 Bot Framework 模擬器
  2. 在本機電腦上執行範例。 如果您需要指示,請參閱 C#JavaScriptJavaPython 的自述檔。
  3. 使用模擬器來測試範例 Bot。

其他資訊

本文說明如何將狀態新增至 Bot。 如需相關主題的詳細資訊,請參閱下表。

主題 備註
隱私權 如果您想要儲存使用者的個人資料,您應該確保符合 一般數據保護規定
狀態管理 所有狀態管理呼叫都是異步的,而且預設為最後寫入器獲勝。 在實務上,您應該盡可能在 Bot 中取得、設定和儲存狀態。 如需如何實作開放式鎖定的討論,請參閱 為您的 Bot 實作自定義記憶體。
關鍵商務數據 使用 Bot 狀態來儲存喜好設定、使用者名稱或他們訂購的最後一件事,但不要使用它來儲存重要的商務數據。 對於重要數據,請建立您自己的記憶體元件,或直接寫入記憶體
辨識器-文字 此範例會使用 Microsoft/Recognizers-Text 連結庫來剖析及驗證用戶輸入。 如需詳細資訊,請參閱概 頁面。

下一步

瞭解如何詢問使用者一系列問題、驗證答案,以及儲存其輸入。