如何为用作Cortana技能的Microsoft Bot添加延迟以支持输入交互?
嘿,针对你这个基于LUIS的Cortana技能Bot需求,我整理了几个实用的实现思路,刚好之前做过类似的场景,应该能帮到你:
实现核心思路:异步延迟+用户中断监听
核心是在Bot对话流程中同时处理「后台模拟延迟任务」和「用户实时输入监听」,结合LUIS的意图识别来判断用户是否要中断,再分支处理逻辑。
1. 用异步任务+Task.WhenAny实现双等待逻辑
你可以在对话的特定步骤里,启动一个模拟后台活动的延迟任务,同时监听用户输入,用Task.WhenAny来等待其中一个任务先完成,以此判断是用户中断还是延迟结束。
举个C#代码示例(适配Bot Framework v3,v4逻辑类似):
private async Task StartBackgroundTaskAsync(IDialogContext context) { // 先给用户反馈,告知正在处理且可中断 await context.PostAsync("我正在处理后台任务,大概需要10秒~你随时可以打断我提问哦!"); var delayCts = new CancellationTokenSource(); // 存储取消令牌到会话私有数据,避免多用户冲突 context.PrivateConversationData.SetValue("DelayCts", delayCts); try { // 模拟10秒后台活动 var delayTask = Task.Delay(10000, delayCts.Token); // 监听用户输入 var inputWaitTask = context.Wait(OnUserInputReceivedAsync); // 等待延迟完成或用户输入 var completedTask = await Task.WhenAny(delayTask, inputWaitTask); if (completedTask == delayTask) { // 延迟结束,无用户中断,发送自动消息并等待输入 await context.PostAsync("后台任务完成啦!现在可以告诉我你的需求了~"); await context.Wait(OnUserInputReceivedAsync); } } catch (TaskCanceledException) { // 延迟任务被取消,说明用户中断了,直接处理用户提问 await context.PostAsync("好的,你有什么问题?"); } finally { delayCts.Dispose(); context.PrivateConversationData.RemoveValue("DelayCts"); } }
2. 结合LUIS识别用户中断意图
因为是LUIS驱动的Bot,你可以在LUIS模型里新增一个中断类意图(比如命名为InterruptQuery),添加常见的触发词,比如「等等」「我想问个问题」「先别弄了」这类用户可能用来中断的表述。
然后在用户输入的处理方法里,先调用LUIS识别意图,如果命中InterruptQuery,就取消之前的延迟任务:
private async Task OnUserInputReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> result) { var activity = await result; // 调用LUIS识别意图 var luisResult = await _luisRecognizer.RecognizeAsync(activity.Text, CancellationToken.None); // 判断是否是中断意图 if (luisResult.TopIntent().Intent == "InterruptQuery") { // 从会话数据中取出取消令牌,终止延迟任务 if (context.PrivateConversationData.TryGetValue<CancellationTokenSource>("DelayCts", out var cts)) { cts.Cancel(); } // 跳转到用户提问的处理逻辑 await HandleUserQuestionAsync(context, activity); return; } // 其他正常意图的处理逻辑... }
3. 适配Cortana技能的特殊细节
- 会话超时处理:Cortana默认会话有超时限制,10秒延迟可能接近超时,你可以在启动延迟前发送一条轻量消息(比如上面的提示语)来延长会话有效期。
- 语音交互体验:因为是Cortana技能,用户大概率用语音交互,所以提示语要口语化,比如「我正在处理后台任务,大概10秒,你随时喊我提问就行~」,符合语音场景的用户习惯。
- 会话状态隔离:一定要用
PrivateConversationData存储取消令牌这类会话相关数据,不能用全局变量,否则多用户同时使用时会出现逻辑混乱。
内容的提问来源于stack exchange,提问作者user1944013
相关产品推荐
相关产品推荐

