4

所以他们在 EchoBot 样本中有这个很好的例子来演示链

 public static readonly IDialog<string> dialog = Chain.PostToChain()
        .Select(msg => msg.Text)
        .Switch(
            new Case<string, IDialog<string>>(text =>
                {
                    var regex = new Regex("^reset");
                    return regex.Match(text).Success;
                }, (context, txt) =>
                {
                    return Chain.From(() => new PromptDialog.PromptConfirm("Are you sure you want to reset the count?",
                    "Didn't get that!", 3)).ContinueWith<bool, string>(async (ctx, res) =>
                    {
                        string reply;
                        if (await res)
                        {
                            ctx.UserData.SetValue("count", 0);
                            reply = "Reset count.";
                        }
                        else
                        {
                            reply = "Did not reset count.";
                        }
                        return Chain.Return(reply);
                    });
                }),
            new RegexCase<IDialog<string>>(new Regex("^help", RegexOptions.IgnoreCase), (context, txt) =>
                {
                    return Chain.Return("I am a simple echo dialog with a counter! Reset my counter by typing \"reset\"!");
                }),
            new DefaultCase<string, IDialog<string>>((context, txt) =>
                {
                    int count;
                    context.UserData.TryGetValue("count", out count);
                    context.UserData.SetValue("count", ++count);
                    string reply = string.Format("{0}: You said {1}", count, txt);
                    return Chain.Return(reply);
                }))
        .Unwrap()
        .PostToUser();
}

但是,与其使用 REGEX 来确定我的对话路径,我更愿意使用 LUIS Intent。我正在使用这段漂亮的代码来提取 LUIS Intent。

public static async Task<LUISQuery> ParseUserInput(string strInput)
    {
        string strRet = string.Empty;
        string strEscaped = Uri.EscapeDataString(strInput);

        using (var client = new HttpClient())
        {
            string uri = Constants.Keys.LUISQueryUrl + strEscaped;
            HttpResponseMessage msg = await client.GetAsync(uri);

            if (msg.IsSuccessStatusCode)
            {
                var jsonResponse = await msg.Content.ReadAsStringAsync();
                var _Data = JsonConvert.DeserializeObject<LUISQuery>(jsonResponse);
                return _Data;
            }
        }
        return null;
    }

现在不幸的是,因为这是异步的,它不能很好地与 LINQ 查询一起运行 case 语句。任何人都可以提供一些代码,允许我在我的链中基于 LUIS 意图有一个案例陈述吗?

4

1 回答 1

0

Omg 在他的评论中是正确的。

记住IDialogs有一个TYPE,意思是IDialog可以返回一个自己指定类型的对象:

public class TodoItemDialog : IDialog<TodoItem>
{
   // Somewhere, you'll call this to end the dialog
   public async Task FinishAsync(IDialogContext context, IMessageActivity activity)
   {
      var todoItem = _itemRepository.GetItemByTitle(activity.Text);
      context.Done(todoItem);
   }
}

对context.Done()的调用返回您的 Dialog 打算返回的对象。无论您正在阅读任何类型的 IDialog 的类声明

public class TodoItemDialog : LuisDialog<TodoItem>

它有助于将其阅读为:

“TodoItemDialog 是一个对话框类,它在完成时返回一个 TodoItem”

您可以使用context.Forward()而不是链接,它基本上将相同的 messageActivity 转发到另一个对话框类..

context.Forward()context.Call()之间的区别本质上是context.Forward()允许您转发由调用的对话框立即处理的messageActivity,而context.Call()只是启动一个新对话框,无需交出任何东西。

在您的“根”对话框中,如果您需要使用 LUIS 来确定意图并返回特定对象,您只需使用Forward将 messageActivity 转发给它然后在指定的回调中处理结果:

await context.Forward(new TodoItemDialog(), AfterTodoItemDialogAsync, messageActivity, CancellationToken.None);

private async Task AfterTodoItemDialogAsync(IDialogContext context, IAwaitable<TodoItem> result)
{
    var receivedTodoItem = await result;

    // Continue conversation
}

最后,您的 LuisDialog 类可能如下所示:

[Serializable, LuisModel("[ModelID]", "[SubscriptionKey]")]
public class TodoItemDialog : LuisDialog<TodoItem>
{
    [LuisIntent("GetTodoItem")]
    public async Task GetTodoItem(IDialogContext context, LuisResult result)
    {
        await context.PostAsync("Working on it, give me a moment...");
        result.TryFindEntity("TodoItemText", out EntityRecommendation entity);
        if(entity.Score > 0.9)
        {
            var todoItem = _todoItemRepository.GetByText(entity.Entity);
            context.Done(todoItem);
        }
    }
}

(为简洁起见,我在示例中没有 ELSE 语句,这是您当然需要添加的内容)

于 2017-04-30T08:24:54.143 回答