2016-06-22 14 views
4

So haben sie dieses schönes Beispiel in der EchoBot Probe KettenKette mit LUIS Intents

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(); 
} 

jedoch zu demonstrieren, anstatt eine REGEX der Verwendung meines Gesprächspfad bestimmen würde ich viel lieber ein Intent LUIS verwenden. Ich verwende dieses nette Stück Code, um den LUIS Intent zu extrahieren.

Jetzt leider, weil dies async ist, spielt es nicht gut mit der LINQ-Abfrage, um die case-Anweisung auszuführen. Kann mir jemand einen Code zur Verfügung stellen, der es mir ermöglicht, in meiner LUIS Intent-Kette eine Case-Anweisung zu erstellen?

+0

Warum nicht context.call und context.Forward verwenden, um Ihren Dialog (innerhalb des Dialogs) statt "Kette Dialog" im Bot-Framework zu verketten? – OmG

Antwort

0

Omg ist richtig in seinem Kommentar.

Denken Sie daran, dass IDialogs haben einen Typ, das heißt, iDialog kann ein Objekt eines Typs selbst angegeben zurück:

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); 
    } 
} 

der Aufruf von context.Done() das Objekt zurückgibt, das Ihr Dialog gemeint zurückgeben. Whever Sie eine Klassendeklaration für jede Art von iDialog gerade lesen

public class TodoItemDialog : LuisDialog<TodoItem> 

Es, es zu lesen hilft als:

„TodoItemDialog ein Dialog-Klasse ist, die eine TodoItem zurückgibt, wenn es fertig ist“ Statt

Verkettungstag, können Sie context.Forward() verwenden, die im Grunde die gleiche messageActivity zu einem anderen Dialogklasse leitet ..

der Unterschied zwischen context.Forward() und context.Call() ist essencially dass context.Forward() können Sie einen messageActivity weiterleiten, die unmittelbar durch den Dialog behandelt wird aufgerufen, während context.Call() einfach eine neue beginnt Dialog, ohne etwas zu übergeben.

Von Ihrem „Root“ Dialog, wenn Sie LUIS verwenden müssen, um eine Absicht zu bestimmen und ein bestimmtes Objekt zurückgeben, können Sie einfach vorwärts die messageActivity ihn von nach vorne und anschließend Umgang mit dem Ergebnis in dem angegebenen Rückruf:

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

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

    // Continue conversation 
} 

Und schließlich könnte Ihre LuisDialog Klasse wie folgt aussehen:

[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); 
     } 
    } 
} 

(Aus Gründen der Kürze, ich habe keine ELSE Positionspapier ts in dem Beispiel, was Sie natürlich hinzufügen müssen)