在 C# 中从 FormFlow 调用 LUIS
Call LUIS from FormFlow in C#
我正在使用 Microsoft 机器人框架创建一个机器人来提问用户然后理解答案。使用机器人框架中的 FormFlow API 询问用户并检索答案。这是表单流的代码:
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();
}
}
用户可以在询问姓名时输入:
my name is James Bond
名称也可以是可变长度的。我最好从这里打电话给 luis 并获取意图的实体(名称)。我目前不知道如何从表单流中调用 luis 对话框。
在这种情况下,最好在 formflow 之外调用 luis 意图。您正在寻找的功能并不完全存在。您可以调用 "Name" 意图,然后这样调用您的表单:
[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);
}
您可以使用 LUIS 的 API 方法,而不是对话框方法。
您的代码将是 - RegisterPatientForm Class :
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;
}
}
此处 GetIntentAndEntitiesFromLUIS
方法使用您的 Luis 应用公开的端点对 LUIS 进行查询。使用密钥 LuisModelEndpoint
将端点添加到您的 Web.config
Find your luis endpoint by going to Publish tab in your luis app
你的 web.config 看起来像这样
<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&verbose=true&timezoneOffset=0&q="/>
</appSettings>
我创建了一个 LUISOutput class 来反序列化响应:
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; }
}
模拟器响应
我正在使用 Microsoft 机器人框架创建一个机器人来提问用户然后理解答案。使用机器人框架中的 FormFlow API 询问用户并检索答案。这是表单流的代码:
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();
}
}
用户可以在询问姓名时输入:
my name is James Bond
名称也可以是可变长度的。我最好从这里打电话给 luis 并获取意图的实体(名称)。我目前不知道如何从表单流中调用 luis 对话框。
在这种情况下,最好在 formflow 之外调用 luis 意图。您正在寻找的功能并不完全存在。您可以调用 "Name" 意图,然后这样调用您的表单:
[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);
}
您可以使用 LUIS 的 API 方法,而不是对话框方法。
您的代码将是 - RegisterPatientForm Class :
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;
}
}
此处 GetIntentAndEntitiesFromLUIS
方法使用您的 Luis 应用公开的端点对 LUIS 进行查询。使用密钥 LuisModelEndpoint
Find your luis endpoint by going to Publish tab in your luis app
你的 web.config 看起来像这样
<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&verbose=true&timezoneOffset=0&q="/>
</appSettings>
我创建了一个 LUISOutput class 来反序列化响应:
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; }
}
模拟器响应