1

ボットを構築しようとしています。最初はNode.jsを使用していましたが、クライアントには c# の方が適していることが明らかだったので、C# で Bot の作成を開始しました。LUIS アプリケーションも作成しました。

このボットの背後にある考え方は、最後に結果を組み合わせて回答に基づいて解決策を選択する前に、一連の質問をするというものです。私が抱えている問題は、それを行うためにボットを設定する方法がわからないことです. nodeではウォーターフォールについて話していましたが、c#版ではそのようなものは見当たりません。また、注意を向けるべき場所が LUIS にあるかどうかもわかりません。

例として、ユーザーにオブジェクトを選択してもらい、そのオブジェクトに基づいて次のような 3 つの質問をするとします。

  1. 小さいですか?
  2. 軽いですか?
  3. あなたは何色が好きですか?

そして最後に「黒くて小さくて軽いカメラが欲しい」と言ってください。私はそれを機能させることができないようです。FormFlow を使用すると言う方もいらっしゃると思いますが、質問は動的であり、オブジェクトも動的であるため、LUIS を使用しました。

LUIS を使用してそれに似たフローを作成する方法についての良い記事をどこで見つけることができるか知っている人はいますか?

4

2 に答える 2

1

FormFlow の制限が厳しすぎる場合は、ダイアログの使用を検討する必要があります。よりオープンな会話が可能になります。

私は次のことをします:

1) ユーザーにカテゴリを選択してもらいます。

可能であれば、ボタンを使用して選択できるカテゴリのリストをユーザーに提供します。つまり、ユーザーが選択したカテゴリについて LUIS に問い合わせる必要はありません。

それ以外の場合は、ユーザーがカテゴリを入力して LUIS に渡すことができるようにします。LUIS からの応答にはエンティティが含まれます。エンティティはカテゴリの名前を保持します。

2) そのカテゴリのダイアログに転送

LUIS から返されたエンティティに応じて、次の質問を担当する適切なダイアログに転送します。

[LuisIntent("AskQuestionAboutCategory")]
    public async Task AskQuestion(IDialogContext context, LuisResult result)
    {
       //get Entity from LUIS response
        string category = result.Entities.FirstOrDefault(e => e.Type == "Category")?.Entity;

        switch (category)
        {
            case "Category 1":

                //forward to Dialog for Category1

                await
                    context.Forward(new Category1Dialog(), ResumeAfter,
                        new Activity {Text = result.Query}, CancellationToken.None);
                break;

            case "Category 2":

                //forward to Dialog for Category2

                await
                    context.Forward(new Category2Dialog(), ResumeAfter,
                        new Activity {Text = result.Query}, CancellationToken.None);
                break;

        }
    }

    private async Task ResumeAfter(IDialogContext context, IAwaitable<object> result)
    {
        context.Wait(MessageReceived);
    }

3) ダイアログ内で質問する

ダイアログ内で、PromptDialog を使用して質問 1 を尋ねます。質問 1 の回答のスイッチを使用して、質問 2 の質問内容を決定します。このように会話を続けます。

[Serializable]
public class Category1Dialog : IDialog<object>
{
    public async Task StartAsync(IDialogContext context)
    {
        context.Wait(MessageReceivedAsync);
    }

    public virtual async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> argument)
    {

        var prompt = "what is the answer to question 1 ?";

        //ASK QUESTION 1
        PromptDialog.Text(context, ResumeAfterQuestion1, prompt);
    }

    private async Task ResumeAfterQuestion1(IDialogContext context, IAwaitable<string> result)
    {
        var input = await result;

        switch (input)
        {
            //ASK QUESTION 2, DEPENDING ON WHAT WAS ANSWERED FOR QUESTION 1
            case "Answer A":
                PromptDialog.Text(context, ResumeAfterQuestion2, "what is the answer to question 2 ?");
                break;
            case "Answer B":
                PromptDialog.Text(context, ResumeAfterQuestion2, "what is the answer to question 2 ?");
                break;
        }
    }


    private async Task ResumeAfterQuestion2(IDialogContext context, IAwaitable<string> result)
    {
        var input = await result;

        switch (input)
        {
            //ASK QUESTION 3
            case "Answer C":
                PromptDialog.Text(context, ResumeAfterQuestion3, "what is the answer to next question after Answer C ?");
        break;
            case "Answer D":
                PromptDialog.Text(context, ResumeAfterQuestion3, "what is the answer to next question after Answer D ?");
        break;
    }
    }

次に質問する内容を決定するには、switch ステートメントを使用する必要があるようです。

ダイアログの詳細については、ここをクリックしてください

于 2016-11-15T06:13:29.080 に答える
1

別の方法があります。これを手動で処理する場合は、質問ごとに異なる context.Wait メソッドを設定して、一種のウォーターフォール アプローチを使用できます。

では、ChooseCategory インテントを持つ LuisDialog があるとします。そのメソッドでは、カテゴリを決定し、いくつかのカスタム ロジックに基づいて、新しい質問をします。

PromptDialog/ResumeAfter または手動の context.PostAsync/ context.Wait (基本的に、次のメッセージをリッスンするメソッドを定義します)。

カスタム ロジックがどのようになっているのかはわかりませんが、次のメッセージをリッスンする次のメソッドを動的に決定できるはずです。

[LuisIntent("Choose category")]
public async Task ChooseCategory(IDialogContext context, LuisResult result)
{
    // get category logic..

    await context.PostAsync("This is my first question?");
    context.Wait(CaptureFirstQuestionAnswerAsync);
}

public async Task CaptureFirstQuestionAnswerAsync(IDialogContext context, IAwaitable<IMessageActivity> argument)
{
    IMessageActivity message = await argument;
    switch (message.Text.ToLower())
    {
        case "answer 1":
            // do something
            break;
        case "answer 2":
           // do something different
            break;
        default:
           // do something ...
            break;
    }

    await context.PostAsync($"This is my second question?");

    context.Wait(CaptureSecondQuestionAnswerAsync);
}

public async Task CaptureSecondQuestionAnswerAsync(IDialogContext context, IAwaitable<IMessageActivity> argument)
{
  //...
}
于 2016-11-14T20:38:41.803 に答える