2017-12-28 5 views
2

Ich verwende das Bot-Framework von Microsoft, um einen Bot für die Befragung des Benutzers zu erstellen und dann die Antwort zu verstehen. Der Benutzer wird mithilfe der FormFlow-API im Bot-Framework befragt und die Antworten werden abgerufen. Hier ist der Code für die Formflow:Rufen Sie LUIS aus FormFlow in C#

public enum Genders { none, Male, Female, Other}; 

[Serializable] 
public class RegisterPatientForm 
{ 

    [Prompt("What is the patient`s name?")] 
    public string person_name; 

    [Prompt("What is the patients gender? {||}")] 
    public Genders gender; 

    [Prompt("What is the patients phone number?")] 
    [Pattern(@"(<Undefined control sequence>\d)?\s*\d{3}(-|\s*)\d{4}")] 
    public string phone_number; 

    [Prompt("What is the patients Date of birth?")] 
    public DateTime DOB; 

    [Prompt("What is the patients CNIC number?")] 
    public string cnic; 


    public static IForm<RegisterPatientForm> BuildForm() 
    { 
     OnCompletionAsyncDelegate<RegisterPatientForm> processHotelsSearch = async (context, state) => 
     { 
      await context.PostAsync($"Patient {state.person_name} registered"); 
     }; 

     return new FormBuilder<RegisterPatientForm>() 
      .Field(nameof(person_name), 
      validate: async (state, value) => 
      { 
       //code here for calling luis 
      }) 
      .Field(nameof(gender)) 
      .Field(nameof(phone_number)) 
      .Field(nameof(DOB)) 
      .Field(nameof(cnic)) 
      .OnCompletion(processHotelsSearch) 
      .Build(); 
    } 

} 

Der Benutzer eingeben kann, wenn für Namen gefragt:

mein Name ist James Bond

Auch der Name von variabler Länge sein könnte. Ich wäre besser, Luis von hier aus anzurufen und die Entität (Name) für die Absicht zu bekommen. Mir ist momentan nicht bekannt, wie ich einen luis-Dialog aus dem Formularfluss aufrufen könnte.

+0

'FormFlow' nicht wirklich die beste Lösung sein, wenn Sie einige benutzerdefinierte Behandlungen –

+0

@NicolasR tun wollen, was getan werden sollte? –

+0

Implementieren Sie einen Dialog, anstatt beispielsweise FormFlow zu verwenden. Es ist länger, aber Sie können tun, was Sie wollen –

Antwort

4

Sie die API-Methode von LUIS verwenden können, anstelle des Dialogmethode.

Code wäre - RegisterPatientForm Klasse:

public enum Genders { none, Male, Female, Other }; 

[Serializable] 
public class RegisterPatientForm 
{ 

    [Prompt("What is the patient`s name?")] 
    public string person_name; 

    [Prompt("What is the patients gender? {||}")] 
    public Genders gender; 

    [Prompt("What is the patients phone number?")] 
    [Pattern(@"(<Undefined control sequence>\d)?\s*\d{3}(-|\s*)\d{4}")] 
    public string phone_number; 

    [Prompt("What is the patients Date of birth?")] 
    public DateTime DOB; 

    [Prompt("What is the patients CNIC number?")] 
    public string cnic; 


    public static IForm<RegisterPatientForm> BuildForm() 
    { 
     OnCompletionAsyncDelegate<RegisterPatientForm> processHotelsSearch = async (context, state) => 
     { 
      await context.PostAsync($"Patient {state.person_name} registered"); 
     }; 

     return new FormBuilder<RegisterPatientForm>() 
      .Field(nameof(person_name), 
      validate: async (state, response) => 
      { 
       var result = new ValidateResult { IsValid = true, Value = response }; 

       //Query LUIS and get the response 
       LUISOutput LuisOutput = await GetIntentAndEntitiesFromLUIS((string)response); 

       //Now you have the intents and entities in LuisOutput object 
       //See if your entity is present in the intent and then retrieve the value 
       if (Array.Find(LuisOutput.intents, intent => intent.Intent == "GetName") != null) 
       { 
        LUISEntity LuisEntity = Array.Find(LuisOutput.entities, element => element.Type == "name"); 

        if (LuisEntity != null) 
        { 
         //Store the found response in resut 
         result.Value = LuisEntity.Entity; 
        } 
        else 
        { 
         //Name not found in the response 
         result.IsValid = false; 
        } 
       } 
       else 
       { 
        //Intent not found 
        result.IsValid = false; 
       } 
       return result; 
      }) 
      .Field(nameof(gender)) 
      .Field(nameof(phone_number)) 
      .Field(nameof(DOB)) 
      .Field(nameof(cnic)) 
      .OnCompletion(processHotelsSearch) 
      .Build(); 
    } 

    public static async Task<LUISOutput> GetIntentAndEntitiesFromLUIS(string Query) 
    { 
     Query = Uri.EscapeDataString(Query); 
     LUISOutput luisData = new LUISOutput(); 
     try 
     { 
      using (HttpClient client = new HttpClient()) 
      { 
       string RequestURI = WebConfigurationManager.AppSettings["LuisModelEndpoint"] + Query; 
       HttpResponseMessage msg = await client.GetAsync(RequestURI); 
       if (msg.IsSuccessStatusCode) 
       { 
        var JsonDataResponse = await msg.Content.ReadAsStringAsync(); 
        luisData = JsonConvert.DeserializeObject<LUISOutput>(JsonDataResponse); 
       } 
      } 
     } 
     catch (Exception ex) 
     { 

     } 
     return luisData; 
    } 
} 

Hier GetIntentAndEntitiesFromLUIS Methode funktioniert die Abfrage zu LUIS den Endpunkt von Ihrem Luis App ausgesetzt werden. Fügen Sie den Endpunkt Ihrer Web.config mit Schlüssel LuisModelEndpoint

Finden Sie Ihr luis Endpunkt von bis gehen Veröffentlichen Tab in Ihrem luis App

Ihre web.config aussehen würde wie folgt

<appSettings> 
    <!-- update these with your BotId, Microsoft App Id and your Microsoft App Password--> 
    <add key="BotId" value="YourBotId" /> 
    <add key="MicrosoftAppId" value="" /> 
    <add key="MicrosoftAppPassword" value="" /> 
    <add key="LuisModelEndpoint" value="https://westus.api.cognitive.microsoft.com/luis/v2.0/apps/YOUR_MODEL_ID?subscription-key=YOUR_SUBSCRIPTION_KEY&amp;verbose=true&amp;timezoneOffset=0&amp;q="/> 
</appSettings> 

Ich habe eine LUISOutput-Klasse zum Deserialisieren der Antwort erstellt:

public class LUISOutput 
{ 
    public string query { get; set; } 
    public LUISIntent[] intents { get; set; } 
    public LUISEntity[] entities { get; set; } 
} 
public class LUISEntity 
{ 
    public string Entity { get; set; } 
    public string Type { get; set; } 
    public string StartIndex { get; set; } 
    public string EndIndex { get; set; } 
    public float Score { get; set; } 
} 
public class LUISIntent 
{ 
    public string Intent { get; set; } 
    public float Score { get; set; } 
} 

Emulator Antwort enter image description here

+0

Überprüfen Sie das gleiche ist [Git Hub] (https://github.com/Kumar-Ashwin-Hubert/LuisInsideFormFlow) –

2

In dieser Situation ist es möglicherweise am besten, eine luis-Absicht außerhalb von formflow aufzurufen. Die gesuchte Funktionalität existiert nicht genau. Sie könnten einen „Name“ Absicht rufen dann rufen Sie wie folgt bilden:

[LuisIntent("Name")] 
public async Task Name(IDialogContext context, LuisResult result) 
{ 
    //save result in variable 
    var name = result.query 
    //call your form 
    var pizzaForm = new FormDialog<PizzaOrder>(new PizzaOrder(), this.MakePizzaForm, FormOptions.PromptInStart, entities); 
    context.Call<PizzaOrder>(pizzaForm, PizzaFormComplete); 
    context.Wait(this.MessageReceived); 
} 
Verwandte Themen