我正在开发的漫游器替代了公司希望与之联系的潜在客户的联系表,因此用户输入必须保存在数据库中。我已成功将Cosmos DB连接到我的机器人,该机器人在使用机器人时会收集状态数据。我有一个对话框堆栈,每个用户输入(姓名,电子邮件和用户要离开的消息)只有一个对话框。
我找不到任何有关如何保存用C#编写的机器人的对话历史记录的有用文档。谁能帮我吗?我仍然是Bot Framework和C#的初学者。
这是我的global.asax文件:
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
var uri = new Uri(ConfigurationManager.AppSettings["DocumentDbUrl"]);
var key = ConfigurationManager.AppSettings["DocumentDbKey"];
var store = new DocumentDbBotDataStore(uri, key);
Conversation.UpdateContainer(
builder =>
{
builder.Register(c => store)
.Keyed<IBotDataStore<BotData>>(AzureModule.Key_DataStore)
.AsSelf()
.SingleInstance();
builder.Register(c => new CachingBotDataStore(store, CachingBotDataStoreConsistencyPolicy.ETagBasedConsistency))
.As<IBotDataStore<BotData>>()
.AsSelf()
.InstancePerLifetimeScope();
});
}
}
这是我的NameDialog,用于收集用户名:(其他对话框与此几乎相同)
[Serializable]
public class NameDialog : IDialog<string>
{
private int attempts = 3;
public async Task StartAsync(IDialogContext context)
{
await context.PostAsync("What's your name?");
context.Wait(this.MessageReceivedAsync);
}
private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> result)
{
var message = await result;
if ((message.Text != null) && (message.Text.Trim().Length > 0))
{
context.Done(message.Text);
}
else
{
--attempts;
if (attempts > 0)
{
await context.PostAsync("I couldn't understand, can you try again?");
context.Wait(this.MessageReceivedAsync);
}
else
{
context.Fail(new TooManyAttemptsException("This is not a valid input"));
}
}
}
}
答案 0 :(得分:1)
我提交了几条评论,要求您对所要查找的内容进行澄清,但我想我还是可以提供一个无所不包的答案。
如果您的机器人是新机器人,只需使用BotBuilder / BotFramework的V4。它更容易,功能更多,支持更好。无论如何,我都会提供答案。
参考:
对于自定义存储,您可以在其中指定用户ID:
// Create Cosmos Storage
private static readonly CosmosDbStorage _myStorage = new CosmosDbStorage(new CosmosDbStorageOptions
{
AuthKey = CosmosDBKey,
CollectionId = CosmosDBCollectionName,
CosmosDBEndpoint = new Uri(CosmosServiceEndpoint),
DatabaseId = CosmosDBDatabaseName,
});
// Write
var userData = new { Name = "xyz", Email = "xyz@email.com", Message = "my message" };
var changes = Dictionary<string, object>();
{
changes.Add("UserId", userData);
};
await _myStorage.WriteAsync(changes, cancellationToken);
// Read
var userDataFromStorage = await _myStorage.read(["UserId"]);
对于机器人处理ID的用户数据:
关键部分:
public class GreetingState
{
public string Name { get; set; }
public string City { get; set; }
}
private readonly IStatePropertyAccessor<GreetingState> _greetingStateAccessor;
[...]
_greetingStateAccessor = _userState.CreateProperty<GreetingState>(nameof(GreetingState));
[...]
Dialogs.Add(new GreetingDialog(_greetingStateAccessor));
Save UserState at the end of OnTurnAsync:
await _userState.SaveChangesAsync(turnContext);
Greeting Dialog to Get and Set User Data
var greetingState = await UserProfileAccessor.GetAsync(stepContext.Context, () => null);
[...]
greetingState.Name = char.ToUpper(lowerCaseName[0]) + lowerCaseName.Substring(1);
await UserProfileAccessor.SetAsync(stepContext.Context, greetingState);
参考文献:
只需阅读文档并查看此示例。复制/粘贴的代码太多。
参考:
为了后代,我将从this good answer to a similar question on StackOverflow复制/粘贴代码:
public class WebChatController : Controller
{
public ActionResult Index()
{
var connectionString = ConfigurationManager.ConnectionStrings["StorageConnectionString"].ConnectionString;
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionString);
CloudTableClient tableClient = storageAccount.CreateCloudTableClient();
CloudTable table = tableClient.GetTableReference("BotStore");
string userId = Guid.NewGuid().ToString();
TableQuery<BotDataRow> query = new TableQuery<BotDataRow>().Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, userId));
var dataRow = table.ExecuteQuery(query).FirstOrDefault();
if(dataRow != null)
{
dataRow.Data = Newtonsoft.Json.JsonConvert.SerializeObject(new
{
UserName = "This user's name",
Email = "whatever@email.com",
GraphAccessToken = "token",
TokenExpiryTime = DateTime.Now.AddHours(1)
});
dataRow.Timestamp = DateTimeOffset.UtcNow;
table.Execute(TableOperation.Replace(dataRow));
}
else
{
var row = new BotDataRow(userId, "userData");
row.Data = Newtonsoft.Json.JsonConvert.SerializeObject(new
{
UserName = "This user's name",
Email = "whatever@email.com",
GraphAccessToken = "token",
TokenExpiryTime = DateTime.Now.AddHours(1)
});
row.Timestamp = DateTimeOffset.UtcNow;
table.Execute(TableOperation.Insert(row));
}
var vm = new WebChatModel();
vm.UserId = userId;
return View(vm);
}
public class BotDataRow : TableEntity
{
public BotDataRow(string partitionKey, string rowKey)
{
this.PartitionKey = partitionKey;
this.RowKey = rowKey;
}
public BotDataRow() { }
public bool IsCompressed { get; set; }
public string Data { get; set; }
}
}
保存用户数据:
参考:
基本上,您想首先使用IActivityLogger
捕获所有活动,就像上面的示例中一样:
创建DebugActivityLogger
public class DebugActivityLogger : IActivityLogger
{
public async Task LogAsync(IActivity activity)
{
Debug.WriteLine($"From:{activity.From.Id} - To:{activity.Recipient.Id} - Message:{activity.AsMessageActivity()?.Text}");
// Add code to save in whatever format you'd like using "Saving Custom Data in V3" section
}
}
将以下内容添加到Global.asax.cs
:
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
var builder = new ContainerBuilder();
builder.RegisterType<DebugActivityLogger>().AsImplementedInterfaces().InstancePerDependency();
builder.Update(Conversation.Container);
GlobalConfiguration.Configure(WebApiConfig.Register);
}
}