Несколько услуг QnA в одном боте с использованием C # - PullRequest
0 голосов
/ 02 мая 2018

У меня есть 3 QnA Service. Я хочу, чтобы они использовались в одном BOT одновременно. Как это можно реализовать с помощью C #. Моя первоначальная идея состоит в том, чтобы поместить идентификатор базы данных и дополнительный ключ в массив (как реализовать это или будет работать массив?) .. Я видел некоторый код в Node.JS, но не могу понять, как преобразовать код в C # ,

public class QnaDialog : QnAMakerDialog
{
    public QnaDialog() : base(
        new QnAMakerService(new QnAMakerAttribute(ConfigurationManager.AppSettings["QnaSubscriptionKey1"],
        ConfigurationManager.AppSettings["QnaKnowledgebaseId1"], "Hmm, I wasn't able to find an article about that. Can you try asking in a different way?", 0.5)),

        new QnAMakerService(new QnAMakerAttribute(ConfigurationManager.AppSettings["QnaSubscriptionKey2"],
        ConfigurationManager.AppSettings["QnaKnowledgebaseId2"], "Hmm, I wasn't able to find an article about that. Can you try asking in a different way?", 0.5)),

        new QnAMakerService(new QnAMakerAttribute(ConfigurationManager.AppSettings["QnaSubscriptionKey3"],
        ConfigurationManager.AppSettings["QnaKnowledgebaseId4"], "Hmm, I wasn't able to find an article about that. Can you try asking in a different way?", 0.5))
        )
    {
    }
}

1 Ответ

0 голосов
/ 02 мая 2018

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

Базовая реализация с использованием QnAMakerDialog из пакета Nuget BotBuilder.CognitiveServices будет выглядеть так:

[Serializable]
[QnAMaker("QnaSubscriptionKey1", "QnaKnowledgebaseId1", "Hmm, I wasn't able to find an article about that. Can you try asking in a different way?", 0.50, 3)]
[QnAMaker("QnaSubscriptionKey2", "QnaKnowledgebaseId2", "Hmm, I wasn't able to find an article about that. Can you try asking in a different way?", 0.5, 3)]
[QnAMaker("QnaSubscriptionKey3", "QnaKnowledgebaseId3", "Hmm, I wasn't able to find an article about that. Can you try asking in a different way?", 0.5, 3)]
public class RootDialog : QnAMakerDialog
{
}

НО (да, есть «но»), в некоторых случаях вы можете столкнуться с исключением во время обработки ваших сообщений. Поскольку QnAMakerDialog имеет открытый исходный код (источники здесь ), вы можете легко обнаружить, что проблема заключается в реализации возврата вызовов служб, в MessageReceivedAsync:

var sendDefaultMessageAndWait = true;
qnaMakerResults = tasks.FirstOrDefault(x => x.Result.ServiceCfg != null)?.Result;
if (tasks.Count(x => x.Result.Answers?.Count > 0) > 0)
{
    var maxValue = tasks.Max(x => x.Result.Answers[0].Score);
    qnaMakerResults = tasks.First(x => x.Result.Answers[0].Score == maxValue).Result;

    if (qnaMakerResults != null && qnaMakerResults.Answers != null && qnaMakerResults.Answers.Count > 0)
    {
        if (this.IsConfidentAnswer(qnaMakerResults))
        {
            await this.RespondFromQnAMakerResultAsync(context, message, qnaMakerResults);
            await this.DefaultWaitNextMessageAsync(context, message, qnaMakerResults);
        }
        else
        {
            feedbackRecord = new FeedbackRecord { UserId = message.From.Id, UserQuestion = message.Text };
            await this.QnAFeedbackStepAsync(context, qnaMakerResults);
        }

        sendDefaultMessageAndWait = false;
    }
}

if (sendDefaultMessageAndWait)
{
    await context.PostAsync(qnaMakerResults.ServiceCfg.DefaultMessage);
    await this.DefaultWaitNextMessageAsync(context, message, qnaMakerResults);
}

В этом коде эта строка кода прервется, если не все ваши службы будут иметь ответ на ваш вопрос (т. Е. Если хотя бы один из ваших KB QnAMaker не ответит на ваш вопрос)

tasks.Max(x => x.Result.Answers[0].Score);

Обходной путь: вы можете реализовать свой собственный QnAMakerDialog, получив источники и исправив метод, например, такой:

public async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> argument)
{
    var message = await argument;

    if (message != null && !string.IsNullOrEmpty(message.Text))
    {
        var tasks = this.services.Select(s => s.QueryServiceAsync(message.Text)).ToArray();
        await Task.WhenAll(tasks);

        if (tasks.Any())
        {
            var sendDefaultMessageAndWait = true;
            qnaMakerResults = tasks.FirstOrDefault(x => x.Result.ServiceCfg != null)?.Result;

            var qnaMakerFoundResults = tasks.Where(x => x.Result.Answers.Any()).ToList();
            if (qnaMakerFoundResults.Any())
            {
                var maxValue = qnaMakerFoundResults.Max(x => x.Result.Answers[0].Score);
                qnaMakerResults = qnaMakerFoundResults.First(x => x.Result.Answers[0].Score == maxValue).Result;

                if (qnaMakerResults?.Answers != null && qnaMakerResults.Answers.Count > 0)
                {
                    if (this.IsConfidentAnswer(qnaMakerResults))
                    {
                        await this.RespondFromQnAMakerResultAsync(context, message, qnaMakerResults);
                        await this.DefaultWaitNextMessageAsync(context, message, qnaMakerResults);
                    }
                    else
                    {
                        feedbackRecord = new FeedbackRecord { UserId = message.From.Id, UserQuestion = message.Text };
                        await this.QnAFeedbackStepAsync(context, qnaMakerResults);
                    }

                    sendDefaultMessageAndWait = false;
                }
            }

            if (sendDefaultMessageAndWait)
            {
                await context.PostAsync(qnaMakerResults.ServiceCfg.DefaultMessage);
                await this.DefaultWaitNextMessageAsync(context, message, qnaMakerResults);
            }
        }
    }
}
...