Как перенаправить сообщение в соответствующее приложение LUIS

У меня есть бот с корневым LuisDialog и еще 4 LuisDialogs каждый с другой моделью LUIS. После разговора, начатого здесь, я реализовал аналогичную стратегию DialogFactory.

Когда пользователь отправляет вопрос, который соответствует намерению "Нет", в моем корневом диалоговом окне, я оцениваю остальные диалоговые окна, пока не найду совпадение, а затем отправлю сообщение "победителю".

Проблема, с которой я сталкиваюсь, заключается в том, что при запросе LUIS (класс BaseDialog) я получаю ошибку http: 429 (слишком много запросов).

Есть идеи о том, как с этим бороться?

"Нет" намерение в моем корневом диалоге:

    [LuisIntent("None")]
public async Task None(IDialogContext context, IAwaitable<IMessageActivity> message, LuisResult result)
{
    var activity = await message;

    var factory = new DialogFactory();
    BaseDialog<object> dialog = await factory.Create(result.Query);
    if (dialog != null)
    {
        await context.Forward(dialog, EndDialog, activity, CancellationToken.None);
    }
    else
    {
        await context.PostAsync("No results!");
    }
}

public static async Task EndDialog(IDialogContext context, IAwaitable<object> result)
{
    //...
}

Класс DialogFactory:

    using System;
using System.Collections.Generic;
using System.Configuration;
using System.Threading.Tasks;

namespace CodeBot.Dialogs
{
    public class DialogFactory
    {
        private static object _lock = new object();
        private static List<BaseDialog<object>> Dialogs { get; set; }

        public async Task<BaseDialog<object>> Create(string query)
        {
            query = query.ToLowerInvariant();
            EnsureDialogs();
            foreach (var dialog in Dialogs)
            {
                if (await dialog.CanHandle(query))
                {
                    return dialog;
                }
            }
            return null;
        }

        private void EnsureDialogs()
        {
            if (Dialogs == null || (Dialogs.Count != 4))
            {
                lock (_lock)
                {
                    if (Dialogs == null)
                    {
                        Dialogs = new List<BaseDialog<object>>();
                    }
                    else if (Dialogs.Count != 4)
                    {
                        Dialogs.Clear();
                    }

                    Dialogs.Add((BaseDialog<object>)Activator.CreateInstance(typeof(Dialog1));
                    Dialogs.Add((BaseDialog<object>)Activator.CreateInstance(typeof(Dialog2));
                    Dialogs.Add((BaseDialog<object>)Activator.CreateInstance(typeof(Dialog3));
                    Dialogs.Add((BaseDialog<object>)Activator.CreateInstance(typeof(Dialog4));
                }
            }
        }
    }
}

И, наконец, класс BaseDialog (где я получаю сообщение об ошибке):

    using Microsoft.Bot.Builder.Dialogs;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Bot.Builder.Luis;
using System;

namespace CodeBot.Dialogs
{
    [Serializable]
    public class BaseDialog<R> : LuisDialog<R>
    {
        public LuisModelAttribute Luis_Model { get; private set; }

        public BaseDialog(LuisModelAttribute luisModel) : base(new LuisService(luisModel))
        {
            Luis_Model = luisModel;
        }

        public async Task<bool> CanHandle(string query)
        {
            try
            {
                var tasks = services.Select(s => s.QueryAsync(query, CancellationToken.None)).ToArray();
                var results = await Task.WhenAll(tasks);  <-- Error!!!

                var winners = from result in results.Select((value, index) => new { value, index })
                              let resultWinner = BestIntentFrom(result.value)
                              where resultWinner != null
                              select new LuisServiceResult(result.value, resultWinner, this.services[result.index]);

                var winner = this.BestResultFrom(winners);

                return winner != null && !winner.BestIntent.Intent.Equals(Constants.NONE, StringComparison.InvariantCultureIgnoreCase);
            }
            catch(Exception e)
            {
                System.Diagnostics.Debug.WriteLine($"CanHandle error: {e.Message}");
                return false;
            }
        }
    }
}

1 ответ

Решение

Ошибка 429 вызвана тем, что ваше приложение (ключ) слишком сильно ударило по LUIS API.

Вам нужно либо ограничить свои запросы, чтобы убедиться, что вы остаетесь ниже порога бесплатного уровня, либо перейти на базовый план, который позволяет 50 запросов в секунду.

Другие вопросы по тегам