LUIS配额超限时避免Bot返回错误消息的技术求助
解决LUIS配额超限时机器人不回复的问题
看起来你遇到的核心问题是外层的try/catch捕获不到LUIS的配额异常,因为Conversation.SendAsync内部会处理对话框的异常流程,不会把异常冒泡到MessageController的Post方法里。要实现超限时不回复,得在LuisDialog内部做异常拦截。
我给你两个可行的方案:
方案1:重写LuisDialog的OnExceptionAsync方法
这是最直接的方式,专门处理对话框内的所有异常,我们可以在这里判断是否是LUIS配额超标的403错误,然后跳过回复操作:
[LuisModel("---", "---", domain: "westeurope.api.cognitive.microsoft.com")] [Serializable] public class DefaultDialog : LuisDialog<object> { // ... 你的意图处理方法 ... protected override async Task OnExceptionAsync(IDialogContext context, Exception exception) { // 精准判断LUIS配额超出的403错误 bool isQuotaExceeded = false; if (exception is HttpRequestException httpEx) { // 检查内部异常是否包含Forbidden状态和配额提示 if (httpEx.InnerException is WebException webEx) { if (webEx.Response is HttpWebResponse response && response.StatusCode == HttpStatusCode.Forbidden && webEx.Message.Contains("Quota Exceeded")) { isQuotaExceeded = true; } } // 有些环境下异常信息可能直接包含"403 Quota Exceeded",加个兜底判断 else if (httpEx.Message.Contains("403 Quota Exceeded")) { isQuotaExceeded = true; } } if (isQuotaExceeded) { // 不发送任何回复,直接等待用户下一条消息 context.Wait(MessageReceived); } else { // 其他异常按默认逻辑处理(比如记录日志或提示用户) await base.OnExceptionAsync(context, exception); } } }
方案2:重写GetLuisResultAsync方法拦截LUIS调用异常
这个方法是LuisDialog用来获取LUIS识别结果的入口,我们可以在这里提前捕获配额异常,避免异常进入后续的意图处理流程:
[LuisModel("---", "---", domain: "westeurope.api.cognitive.microsoft.com")] [Serializable] public class DefaultDialog : LuisDialog<object> { // ... 你的意图处理方法 ... protected override async Task<LuisResult> GetLuisResultAsync(IDialogContext context, IMessageActivity message) { try { return await base.GetLuisResultAsync(context, message); } catch (HttpRequestException ex) { // 判断是否是配额超标的403错误 if (ex.Message.Contains("403 Quota Exceeded") || (ex.InnerException is WebException webEx && (webEx.Response as HttpWebResponse)?.StatusCode == HttpStatusCode.Forbidden && webEx.Message.Contains("Quota Exceeded"))) { // 返回空的LuisResult,后续意图处理会走到None方法 return new LuisResult(); } else { // 非配额异常继续抛出,让上层处理 throw; } } } // 配合方案2,确保None方法里也不回复 [LuisIntent("")] public async Task None(IDialogContext context, LuisResult result) { // 直接等待下一条消息,不做任何回复 context.Wait(MessageReceived); } }
为什么原来的try/catch没用?
Conversation.SendAsync内部维护了对话框的生命周期,当对话框内发生异常时,Bot Framework的对话系统会自动捕获并处理(比如默认会给用户发错误提示),不会把异常抛到外层的MessageController中,所以你在Post方法里加的try/catch根本捕获不到这个异常。
内容的提问来源于stack exchange,提问作者Jo David
相关产品推荐
相关产品推荐

