共用方式為


管理狀態

適用於: SDK v4

Bot 內的狀態會遵循與新式 Web 應用程式相同的架構,而 Bot Framework SDK 會提供一些抽象概念,讓狀態管理變得更容易。

如同 Web 應用程式,Bot 原本是無狀態的;不同的 Bot 執行個體可處理任何指定的交談回合。 對於某些機器人而言,這種簡便性受到偏好—機器人可以在無需額外資訊的情況下運行,或保證所需的資訊在該傳入訊息中。 對某些人來說,了解狀態(例如,交談中斷的地方或先前收到的用戶相關數據)對於機器人進行有意義的交談是必需的。

為什麼我需要這個狀態?

維護狀態可讓您的 Bot 記住使用者或交談的某些事項,以取得更有意義的交談。 例如,如果您先前已與使用者交談,您可以儲存先前的相關信息,因此您不需要再次要求。 狀態也會讓數據保持超過目前回合的時間,讓 Bot 在多回合交談過程中保留資訊。

與 Bot 相關,使用狀態有幾個層:儲存層、狀態管理(包含在下圖中的 Bot 狀態中),以及狀態屬性存取子。 此圖示說明這些層之間互動序列的部分,其中實線箭頭代表方法呼叫,而虛線箭頭代表回應(包含或不包含回傳值)。

說明如何載入、快取和儲存每個回合狀態的循序圖。

下圖的流程會在下列各節中說明,其中每個圖層都有詳細數據。

儲存層

從實際儲存狀態資訊的後端開始,就是 儲存層。 這可視為您的實體記憶體,例如記憶體內部、Azure 或第三方伺服器。

Bot Framework SDK 包含儲存層的一些實作:

  • 記憶體儲存 實作記憶體儲存,以供測試之用。 記憶體內部數據記憶體僅適用於本機測試,因為此記憶體是揮發性和暫時性的。 每次重新啟動 Bot 時,都會清除數據。
  • Azure Blob 記憶體 會連線到 Azure Blob 記憶體物件資料庫。
  • Azure Cosmos DB 分割記憶體 會連線到分割的 Cosmos DB NoSQL 資料庫。

這很重要

Cosmos DB 記憶體類別已被取代。 原本使用 CosmosDbStorage 建立的容器沒有分割區索引鍵集,而且會獲得預設分割區索引鍵 “/_partitionKey”。

使用 Cosmos DB 記憶體 建立的容器可以搭配 Cosmos DB 分割記憶體使用。 如需詳細資訊,請參閱 Azure Cosmos DB 中的數據分割。

另請注意,與舊版 Cosmos DB 記憶體不同,Cosmos DB 分割記憶體不會自動在您的 Cosmos DB 帳戶內建立資料庫。 您必須 手動建立新的資料庫,但請略過手動建立容器,因為 CosmosDbPartitionedStorage 會為您建立容器。

如需如何連線到其他記憶體選項的指示,請參閱 直接寫入記憶體

狀態管理

狀態管理 會將 Bot 狀態的讀取和寫入自動化至基礎儲存層。 狀態會儲存為 狀態屬性,這實際上是 Bot 可以透過狀態管理物件讀取和寫入的索引鍵/值組,而不必擔心特定的基礎實作。 這些狀態屬性會定義該資訊儲存的方式。 例如,當您擷取定義為特定類別或對象的屬性時,您會知道該數據的結構。

這些狀態屬性被歸類為具範圍的「集合」,用於幫助整理這些屬性。 SDK 包含下列三個「分組」:

  • 用戶狀態
  • 交談狀態
  • 私人交談狀態

所有這些貯體都是 Bot 狀態 類別的子類別,其可衍生為定義具有不同範圍的其他類型的貯體。

根據貯體而定,這些預先定義的貯體會限定為特定可見性:

  • 無論交談內容如何,Bot 都會在與該頻道上的用戶進行對話的任何回合中可用用戶狀態。
  • 不論用戶為何,交談狀態都可以在任何回合中取得,例如在群組交談中
  • 私人交談狀態的範圍限於特定交談以及特定使用者

小提示

使用者和對話狀態都是依頻道來限制的。 同一個人使用不同管道來存取 Bot,會被顯示為不同的使用者,每個管道各有一個使用者,每個使用者有不同的使用者狀態。

每個預先定義貯體所使用的索引鍵都是使用者和交談專用的,或兩者皆專屬。 設定狀態屬性值時,系统會為您內部定義索引鍵,其中包含回合內容中的資訊,以確保每個使用者或交談都被分配到正確的分類和屬性值。 具體來說,金鑰的定義如下:

  • 用戶狀態會使用 通道標識碼來源標識碼 建立金鑰。 例如{Activity.ChannelId}/users/{Activity.From.Id}#YourPropertyName
  • 交談狀態會使用 通道標識碼交談標識碼來建立密鑰。 例如{Activity.ChannelId}/conversations/{Activity.Conversation.Id}#YourPropertyName
  • 私人交談狀態會使用 通道標識碼從標識符交談標識碼建立密鑰。 例如 ,{Activity.ChannelId}/conversations/{Activity.Conversation.Id}/users/{Activity.From.Id}#YourPropertyName

使用每種狀態類型的時機

交談狀態很適合追蹤交談的內容,例如:

  • Bot 是否詢問用戶問題,以及哪一個問題
  • 交談的目前主題是什麼,或最後一個主題是什麼

使用者狀態適用於追蹤使用者的相關信息,例如:

  • 非重要用戶資訊,例如名稱和喜好設定、警示設定或警示喜好設定
  • 他們與 Bot 上次交談的相關信息
    • 例如,產品支援 Bot 可能會追蹤使用者詢問的產品。

私人化的對話狀態適用於支援群組交談的頻道,但同時也在您想要追蹤使用者及對話特定資訊的情況下使用。 例如,如果您有一個教學用點名器機器人:

  • Bot 可以匯總並顯示給定問題的學生回應。
  • Bot 能夠匯總每個學生的表現,並在課程結束時私下回傳給他們。

如需使用這些預先定義的儲存桶的詳細資訊,請參閱狀態操作指南文章

連接到多個資料庫

如果您的 Bot 需要連線到多個資料庫,請為每個資料庫建立儲存層。 如果您的 Bot 收集具有不同安全性、並行或資料位置需求的資訊,您可以選擇使用多個資料庫。

針對每個儲存層,建立支援狀態屬性所需的狀態管理物件。

State 屬性存取子

狀態屬性存取子 用於讀取或寫入您的狀態屬性,並在回合過程中提供 取得設定刪除 方法來存取狀態屬性。 若要建立存取子,您必須提供屬性名稱,這通常會在初始化 Bot 時發生。 然後,您可以使用該存取子來取得並操作機器人狀態的該屬性。

存取子可讓 SDK 從基礎記憶體取得狀態,併為您更新 Bot 的狀態快取 。 狀態快取是由 Bot 維護的本機快取,可為您儲存狀態對象,允許讀取和寫入作業,而不需要存取基礎記憶體。 如果尚未在快取中,則呼叫存取子的 get 方法會擷取狀態,並將它放在快取中。 擷取之後,就可以像局部變數一樣操控狀態屬性。

存取子的 delete 方法會從快取中移除 屬性,也會從基礎記憶體中刪除它。

這很重要

在第一次呼叫存取子的get方法時,如果該物件尚不存在於您的狀態中,您必須提供一個 Factory 方法來建立該物件。 如果沒有提供 Factory 方法,您將會收到例外狀況。 如需如何使用工廠方法的詳細資訊,請參閱 狀態指南文章

若要保存您對存取子取得之狀態屬性所做的任何變更,狀態快取中的 屬性必須更新。 您可以透過呼叫 存取子 set 方法來完成此動作,此方法會將您的屬性值設置在快取中,並可在稍後需要讀取或更新時使用。 若要實際保存該數據至基礎記憶體(因此在目前回合之後可供使用),您必須儲存 狀態

狀態屬性存取器方法的工作原理

存取方法是您的 bot 與狀態互動的主要方式。 每個工作的方式,以及基礎層的互動方式,如下所示:

  • 存取子的 get 方法:
    • 取用器從狀態快取中請求屬性。
    • 如果屬性位於快取中,請傳回它。 否則,請從狀態管理物件取得它。 (如果尚未處於狀態,請使用存取子 取得 呼叫中提供的 Factory 方法。
  • 存取器的 set 方法:
    • 使用新的 屬性值更新狀態快取。
  • 狀態管理物件的 儲存變更 方法:
    • 檢查狀態快取中屬性的變更。
    • 將該屬性寫入記憶體。

對話框中的狀態

對話框庫使用定義在 Bot 交談狀態上的對話狀態屬性存取器,以維持對話在交談中的位置。 對話框狀態屬性也允許每個對話在回合之間儲存暫時性資訊。

調適型對話具有更細緻的記憶體範圍結構,可讓您更輕鬆地存取組態和辨識結果等等。 對話管理員會使用使用者和交談狀態管理物件來提供這些記憶體範圍。

如需對話框連結庫的相關信息,請參閱 對話框連結庫 一文。

儲存狀態

當您呼叫存取器的設置方法來記錄更新的狀態時,該狀態屬性尚未儲存到持久儲存中,而只會儲存到 Bot 的狀態快取。 若要將狀態快取中的任何變更儲存到保存的狀態,您必須呼叫狀態管理對象的 儲存變更 方法,這可在上述 Bot 狀態類別的實作上取得(例如用戶狀態或交談狀態)。

針對狀態管理物件呼叫存儲變更方法(例如上述的桶)會將您已針對該桶設定至目前的所有屬性儲存在狀態快取中,但不會適用於機器人狀態中可能存在的任何其他桶。

小提示

Bot 狀態執行「最後寫入優先」的行為,其中最後一個寫入會覆蓋掉先前寫入的狀態。 這可能適用於許多應用程式,但會產生影響,特別是在延展性方案中,其中可能存在一定程度的並發或延遲。

如果您的自定義中間件可能會在回合處理程式完成之後更新狀態,請考慮 在中間件中處理狀態

其他資源