Azure Bot State Data Store in Azure Cosmos db

In previous post here explained how bot manage state data in memory cache.Now I have extended this example here to store state data in azure cosmos db.

Few changes in code are required.Just add few  c#  lines  in StateDialog.cs

//Set conversion data
dialogContext.UserData.SetValue("patientname", patiantName.Text);

//Set conversion  data
dialogContext.ConversationData.SetValue("address", patiantAddress.Text);

//Set PrivateConversationData  data
dialogContext.PrivateConversationData.SetValue("patientMedicalHistory", medicalHistory.Text);

  1. Add nuget package ref of Microsoft.Bot.Builder.Azure in project
  2. Create Azure cosmos db instance here https://portal.azure.com

Then click on create Cosmos Db and fill some details ….

Fire Create button and it will create cosmos db instance for you ..

Write down URI and key strings as shown in above pic and save somewhere so we need to update these key as a DocumentDbAuthKey and URI  as DocumentDbServiceEndpoint in web.config.

<add key=”DocumentDbServiceEndpoint” value=”https://xxxxxxxx.documents.azure.com:443/” />
<add key=”DocumentDbAuthKey” value=”cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx” />

3.Change the Global.asax.cs  

Add the below code there to connect the azure cosmos db :

protected void Application_Start()
{
   //GlobalConfiguration.Configure(WebApiConfig.Register);
   Uri docDbServiceEndpoint = new Uri(ConfigurationManager.AppSettings["DocumentDbServiceEndpoint"]);
   string docDbEmulatorKey = ConfigurationManager.AppSettings["DocumentDbAuthKey"];
   var builder = new ContainerBuilder();
   builder.RegisterModule(new AzureModule(Assembly.GetExecutingAssembly()));
   var store = new DocumentDbBotDataStore(docDbServiceEndpoint, docDbEmulatorKey);
   builder.Register(c => store).Keyed<IBotDataStore<BotData>>(AzureModule.Key_DataStore)
     .AsSelf()
     .SingleInstance();
   builder.Update(Conversation.Container);
   GlobalConfiguration.Configure(WebApiConfig.Register);
}

4.Build the solution and run bot in emulator and reply to bot messages ..

Emulator messages

5.Here we are saving patient name as a user data ,address info as public conversation info and Medical history as private conversation info. Lets check all these information stored in cosmos db..

Public state data(address) stored in cosmos document:

Private state data(Patient Medical History) stored in cosmos document:

 

 

User state data(Patient name) stored in cosmos document:

User bot state

 

Find working code here  Download

Just replace cosmos db key and Uri and code should work……….

Good luck!!

Azure Chatbot State Management example

Prerequisite  for bot development using .net code

Below  tools and SDKs are required:

1. Visual Studio 2015/2017

2.Visual Studio Bot Application Template for C#

3.Download the bot application template from http://aka.ms/bf-bc-vstemplate

the download contains a zip file named  BotApplication.zip

4.Copy the zip to the Visual Studio Templates folder for C#. The
default location for templates is %USERPROFILE%\Documents\
Visual Studio 2015\Templates\ProjectTemplates\Visual C#\. (This
path is for VS 2015; for other version like VS 2017, use the Visual
Studio 2017 Templates folder path will be %USERPROFILE%\Documents\Visual Studio 2017\Templates\ProjectTemplates\Visual C#).
• Open Visual Studio as Administrator and click on New Project.
Search for “Bot Application” using the search section at the top
right corner. You should now be able to see the project template
for bots in the Templates section.

5.Download and install Bot Emulator from here

6.The Azure Bot framework provides three stores that you can use to store state, as follows:

  • User data state
  • Conversation data state
  • Private conversation state

7.The Conversation and the Private Conversation data stores are available for the lifetime of a conversation within a session.User data continues to be available even if the user switches or creates a new conversation.By default, Azure  Bot framework stores the state in cache using the CachingBotDataStore Object.

Step1.Create new botapplication in visual studio

 

Step2 :add new class StateDialog.cs

using Microsoft.Bot.Builder.Dialogs;

using Microsoft.Bot.Connector;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Threading.Tasks;

using System.Web;




namespace Bot_State_Application.Dialogs

{

[Serializable]

public class StateDialog: IDialog<object>

{
public async Task StartAsync(IDialogContext dialogContext)

{

await dialogContext.PostAsync("Provide some details to help you");

dialogContext.Wait(ConversationStart);

}
public async Task ConversationStart(IDialogContext dialogContext, IAwaitable<IMessageActivity> result)

{

var patiantName = await result;

//Set user  data

await dialogContext.PostAsync("Please provide patient name");

dialogContext.Wait(GetPatientName);

}




public async Task GetPatientName(IDialogContext dialogContext, IAwaitable<IMessageActivity> result)

{

var patiantName = await result;

//Set conversion  data

dialogContext.UserData.SetValue("patientname", patiantName.Text);

await dialogContext.PostAsync("Please provide patient address");

dialogContext.Wait(GetPatientAddress);

}

public async Task GetPatientAddress(IDialogContext dialogContext, IAwaitable<IMessageActivity> result)

{

var patiantAddress = await result;

//Set conversion  data

dialogContext.ConversationData.SetValue("address", patiantAddress.Text);

await dialogContext.PostAsync("Please provide patient medicalHistory");

dialogContext.Wait(GetPatientMedicalHistory);

}




public async Task GetPatientMedicalHistory(IDialogContext dialogContext, IAwaitable<IMessageActivity> result)

{

var medicalHistory = await result;

//Set PrivateConversationData  data

dialogContext.PrivateConversationData.SetValue("patientMedicalHistory", medicalHistory.Text);

await dialogContext.PostAsync("Do you want to see all patient info");

dialogContext.Wait(ShowPatientData);

}




public async Task ShowPatientData(IDialogContext dialogContext, IAwaitable<IMessageActivity> result)

{

var yes = await result;

//get data

//get userdata

var name = dialogContext.UserData.GetValue<string>("patientname");

var address = dialogContext.ConversationData.GetValue<string>("address");

var medicalHistory = dialogContext.PrivateConversationData.GetValue<string>("patientMedicalHistory");

var data = $"Details retrieved from Bot state  >> Patient Name: {name}, Address: {address}, MedicalHistory: {medicalHistory} ";

await dialogContext.PostAsync(data);

dialogContext.Wait(ConversationStart);

}




}

}

Step 3:MessagesController.cs changes

Comment the line  >>  await Conversation.SendAsync(activity, () => new Dialogs.RootDialog());

And add line  await Conversation.SendAsync(activity, () => new Dialogs.StateDialog());

Code changes show here. ..

public async Task<HttpResponseMessage> Post([FromBody]Activity activity)

{

if (activity.Type == ActivityTypes.Message)

{

// await Conversation.SendAsync(activity, () => new Dialogs.RootDialog());

await Conversation.SendAsync(activity, () => new Dialogs.StateDialog());

}

else

{

HandleSystemMessage(activity);

}

var response = Request.CreateResponse(HttpStatusCode.OK);

return response;

}

 

Step 4:Build project and add bot api url in emulator.

Keep application Id and password blank.

Test chatbot in here. Emulator Bot responses shows the state data :

You can download working code here

QnA azure chatbot Architecture evaluation

Developed QnA chatbot its working fine.
But sometimes bot responses with irrelevant and vague answers . If I type question which contains word e. g mango then bot throws responses in answer which contains mango word. Sometimes its weird. Feels my bot behaved like look up dictionary.
Thoughts came in the mind. How can I improve her.Decided to take help of intelligence Sister LUIS.so Luis would help to evaluate user intents and pass to QnA engine n it worked exactly. Now QnA bot responses with 96% relevant answers.
Implemented flow…