簡體   English   中英

在 Azure 中檢索聊天機器人對話數據

[英]Retrieving Chat Bot conversation data in Azure

首先簡要介紹一下背景:Bot 框架將對話數據存儲在 Azure 表/Cosmos DB(在我的案例中為 Azure 表)的存儲中。 對於每個對話,在 Azure 表中都有一個條目,其中包含時間戳、用戶 ID、對話消息和其他詳細信息。

我正在嘗試使用 C# 中的自定義代碼從 Azure 表存儲中檢索對話詳細信息,如下所示。

Microsoft.WindowsAzure.Storage.CloudStorageAccount storageAccount = Microsoft.WindowsAzure.Storage.CloudStorageAccount.Parse(connectionString);
Microsoft.WindowsAzure.Storage.Table.CloudTableClient tableClient = storageAccount.CreateCloudTableClient();
CloudTable table = tableClient.GetTableReference("botdata");
TableQuery<DynamicTableEntity> projectionQuery = new TableQuery<DynamicTableEntity>().Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "directline:user"));
var dataRow = table.ExecuteQuery(projectionQuery).Where(q => q.RowKey == "souvik").FirstOrDefault();
var conversation = Encoding.UTF8.GetString(dataRow.Properties["Data"].BinaryValue);
Console.WriteLine(conversation);

當我檢索時,我收到了一些亂碼,類似於這樣的 - \ \\b\\0\\0\\0\\0\\0\\\0 \\\0C \\\0\\0\\0以二進制格式存儲在 Azure 表存儲中的數據。 數據在 Azure 存儲資源管理器中如下所示 -

在此處輸入圖片說明

我對每個對話都進行了嘗試和測試,我發現每次我鍵入並向機器人發送數據並獲得響應時,都會將新記錄添加到 Azure 表中,並帶有正確的時間戳。 這是檢索數據的正確方法還是我做錯了什么? 如果我可以添加更多詳細信息,請告訴我。

更新 1:

我已經提到了這個 - 如何在 Azure (Tablelogger) 中檢索保存的對話數據,但對我的問題沒有太大幫助。

更新 2

基於 Fei 在下面的回答,我剛剛注意到當我使用PartitionKey作為directline:userdirectline:conversation我得到反序列化的值作為{}但如果我使用directline:private我得到這樣的東西 -

{"ResumptionContext":{"locale":"en-US","isTrustedServiceUrl":true}, "DialogState":"H4sIAAAAAAAEAO1a328iVRRmYGYKbTfbdZtNzLq7GM26DWS2FGi7MVUptUrcVi1VYxrSvcCFjh1mmrl3quyjb74YEx+N/hW+uzFxE/8KX9fsH6HnzAxQ7A8GhHpZoemBDs O953znO+d+99KQFAqF/oIHPuNjNgzm8y29YlvMqnFt3YJfRzeq1E7GP6U20y1zLa2llrQlLZOM5x2DOzZdM6nDbWIk4x85ZUOvfECbu9YhhTtT5Vp6NbtMqunlDE1nFZznF+nM8bWCyaltEoNpm 3oZpvKeHqX29s6+f0MnhlVnJz7nXdkl7DAZH1kMpVIEglAYJ5VDtWaTBmXKl0TnLCLLT8LFJuO0oeUtw6AVDjMx7T1qUluvaA91xs+P5lT0hU0cW8DwRzo4CYhOESAlhv6YIMaJIrdsWjAhJ2aF rjd3m0e06Ni2VSecJj4sfwGp2KE1alN4Gxl+ObPgbwzJEpPRKGBk/HPCkmFUoLqvA4ZM2Wf6YxrdP/aGBaR/DdpfhMVur4TUiUZjqs8i5I8iXwpxsUPLeEfkjs/ST0ydN7sGfN/CWV16T4GRFN /FWBTMFDodkvxL8pOxz4YbZwzNNJgrYRlj7gUOMlTeIJzE3DsQ0NkcY7RRNprbEKcUkqLqDNz0NPBqiPBskgrksikgSphsdXak6kFy6YXzXAHzW1DgPoPFWWzcYoibEutLGwlcLHKD2Icyai JZvpyV9odwH1x4tCQaask9v5t4oSXjDVaxbEMvd0bPaIv403vw8soKyVayy6kH6QxdXH3gpcTtYVfRzGFzxkbmdrRraF7CS1dbPfw6cnFuAmpvUGWbMi6blFZlOTBYO/CZ/yNYiYD4bAOcbcb OIxefw/60n0+j9Jg6JoZD9/dD0bAvRhSk+tNxp3T32HnLNCkubFphizJG6jQHu4lj0Bv/9KJ95xC7/An2B8ZVVPYLhOtAhXIDWf4nFMpz/zBHwqZ+rf3Ws5NvXW/JqJdDfeyWth3DcMtCPNHR 0VDz/axbopJxlK3Y3Zdw0FMqJ3adcrVB+YFVjcg9t3s/nUOUi3BK7B445iHg7HhiddSLzH1/AhCH/sGKtgVbLmoXzJp13hb2JppX0NxCCt3oZ50QlUKC9LPB2fb7ENgmCAgDE/M2mjto4ti2b 7ba9quTJndxK+isB1jWojcuXJNV251K/qaHr55HuRr3vhi5lG3ja1jEtwYgMZJVxsOurpOvWN4gjLmvinrdJOjWdPvV0rQ3JG755/wz8Zxdh6BNziR8hCLRK74jeNNeSX0d50GeuzlX745BztU 3wMmvI604DmxKqrpZ19AP5lrwIOjBqa/K+o+4VIojbPcCn9D6X8gNMNM5zWSQBnSGYwVAEfzqyhhMeQrePJ4nGYbLUTc1C+o9SMQz5eJE9JsJwZrtaL+LGYxCYwLRcPk50pYSiO54gj4t3W4piY WJ1h2azOuIDpRsL5B+PalPfu5PnwgSQVvKJFBHo5hGOaMmu3WD9mKlTb0P8fw4kRjDbeFBkxtQfSxCjr5XJ+pjoj4uQX0I0piCCxUFt54CbYkHP876tkcQ+QOim4mHlnXkXRH2sDSFZglNGsxsBs zax2YOYur4lQrql+kYhoJr8njKisHpcLfbryJpHBlU83DUdiyLe4FnBs1SFs0ymhVUPKmW3l8Vq546khkZJVqNoO6dzkE3rdAqNbncR9LCLfyldEtsvglmxseWNc2KpznXBIxbfQuc+k66QJTET8 RxztrbXrm8F1B5nH7Fe65zOfyvIVI26KnTnAX1bXDrj//erZFi72/Qs62CfWdsm2OntrEOAtYO3BnC+pFWWmWzDmbe93wHKlE/plU3wWr+Xy896kZwz9R33UxcxL6zvBwdDQNvRBbUTdxkhMVxXRSKesU28zeNVmRMBTMAAA=="}

感覺上面JSON中的DialogState數據需要解密?

對於我輸入的每條消息和收到的響應,Azure 表中插入了三條記錄,每條記錄都有不同的PartitionKey ,分別是 - directline:privatedirectline:userdirectline:conversation

Azure Table Storage二進制數據存儲為Base64 encoded string 您需要做的是先將此字符串轉換為字節,然后從這些字節中獲取字符串。

類似的東西:

var conversation = Encoding.UTF8.GetString(Convert.FromBase64String(dataRow.Properties["Data"].BinaryValue));

如果您想使用WindowsAzure.Storage 客戶端庫從表存儲中檢索實體並從Data屬性中提取數據,您可以參考以下代碼。

CloudStorageAccount storageAccount = CloudStorageAccount.Parse("DefaultEndpointsProtocol=https;AccountName={your_account_name};AccountKey={your_account_key};EndpointSuffix=core.windows.net");

CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

CloudTable table = tableClient.GetTableReference("botdata");

TableQuery<MessageEntity> query = new TableQuery<MessageEntity>().Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "emulator:user"));

foreach (MessageEntity entity in table.ExecuteQuery(query))
{
    string mydata = "";
    using (var msi = new MemoryStream(entity.Data))
    using (var mso = new MemoryStream())
    {
        using (var gs = new GZipStream(msi, CompressionMode.Decompress))
        {
            gs.CopyTo(mso);
        }
        mydata = Encoding.UTF8.GetString(mso.ToArray());
    }

    object data = JsonConvert.DeserializeObject(mydata);

    //.....
}

MessageEntity

public class MessageEntity : TableEntity
{
    public MessageEntity(string pk, string rk)
    {
        this.PartitionKey = pk;
        this.RowKey = rk;
    }

    public MessageEntity() { }

    public string BotId { get; set; }
    public string ChannelId { get; set; }
    public string ConversationId { get; set; }
    public byte[] Data { get; set; }
    public string UserId { get; set; }
}

測試結果:

在此處輸入圖片說明

注意:

  • 源代碼中,您可以在BotDataEntity類中找到定義為byte[]Data屬性。
  • 在 Jason Sowers 的回復中,他分享了關於Data屬性的序列化和反序列化的信息。

我假設您正在使用 botbuilder-azure 包

不要在對話框中執行此操作,因為您只能訪問context對象中的相同數據。 它恰好是我寫代碼的地方

其實就這么簡單:

private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
{
    var activity = await result as Activity;

    IBotDataStore<BotData> table = new TableBotDataStore(ConfigurationManager.ConnectionStrings["StorageConnectionString"].ConnectionString);

//use the type of state data you need
    var userData = await table.LoadAsync(Address.FromActivity(activity), BotStoreType.BotUserData, CancellationToken.None );
    var privateConvoData = await table.LoadAsync(Address.FromActivity(activity), BotStoreType.BotPrivateConversationData, CancellationToken.None );
    var convoData = await table.LoadAsync(Address.FromActivity(activity), BotStoreType.BotConversationData, CancellationToken.None);

//in this case I am just replying with the data, but do what you need with it here
    var reply = activity.CreateReply(userData.Data.ToString());
    var reply2 = activity.CreateReply(privateConvoData.Data.ToString());
    var reply3 = activity.CreateReply(convoData.Data.ToString());

    await context.PostAsync(reply);
    await context.PostAsync(reply2);
    await context.PostAsync(reply3);

    context.Wait(MessageReceivedAsync);
}

如果您在botbuilder-azure的源代碼中注意到有一個序列化和反序列化方法。 發生這種情況的地方:

private byte[] Serialize(object data)
{
    using (var cmpStream = new MemoryStream())
    using (var stream = new GZipStream(cmpStream, CompressionMode.Compress))
    using (var streamWriter = new StreamWriter(stream))
    {
        var serializedJSon = JsonConvert.SerializeObject(data, serializationSettings);
        streamWriter.Write(serializedJSon);
        streamWriter.Close();
        stream.Close();
        return cmpStream.ToArray();
    }
}

所以你需要的數據被壓縮成你看到的“亂碼”。 當通過LoadAsync方法訪問數據時,它也被解壓縮,如下所示:

private object Deserialize(byte[] bytes)
{
    using (var stream = new MemoryStream(bytes))
    using (var gz = new GZipStream(stream, CompressionMode.Decompress))
    using (var streamReader = new StreamReader(gz))
    {
        return JsonConvert.DeserializeObject(streamReader.ReadToEnd());
    }
}

返回語句中LoadAsync方法內部調用反序列化return new BotData(entity.ETag, entity.GetData()); 它的GetData()方法如下所示:

internal ObjectT GetData<ObjectT>()
{
    return ((JObject)Deserialize(this.Data)).ToObject<ObjectT>();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM