Hierarchical LUIS Dispatch sample

New sample to demonstrate how to use a LUIS dispatcher from the Dispatch
tool in hierarchical mode
This commit is contained in:
Denise Mak 2018-04-19 10:11:50 -07:00
Родитель d1f661fcc2
Коммит 3a0fdee7ef
6 изменённых файлов: 311 добавлений и 1 удалений

Просмотреть файл

@ -1,6 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26730.12
VisualStudioVersion = 15.0.27130.2010
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libraries", "Libraries", "{4269F3C3-6B42-419B-B64A-3E6DC0F1574A}"
EndProject
@ -96,6 +96,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Samples.Dialo
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Dialogs.Tests", "tests\Microsoft.Bot.Builder.Dialogs.Tests\Microsoft.Bot.Builder.Dialogs.Tests.csproj", "{2F77CA1D-E6F0-4DEA-96BB-8A039F4D0FF8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Samples.Ai.Luis.Dispatch.Hierarchical", "samples\Microsoft.Bot.Samples.Ai.Luis.Dispatch.Hierarchical\Microsoft.Bot.Samples.Ai.Luis.Dispatch.Hierarchical.csproj", "{1A5ED921-4613-4DCB-9AE3-1F93EFCC1F65}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug - NuGet Packages|Any CPU = Debug - NuGet Packages|Any CPU
@ -409,6 +411,14 @@ Global
{2F77CA1D-E6F0-4DEA-96BB-8A039F4D0FF8}.Documentation|Any CPU.Build.0 = Debug|Any CPU
{2F77CA1D-E6F0-4DEA-96BB-8A039F4D0FF8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2F77CA1D-E6F0-4DEA-96BB-8A039F4D0FF8}.Release|Any CPU.Build.0 = Release|Any CPU
{1A5ED921-4613-4DCB-9AE3-1F93EFCC1F65}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
{1A5ED921-4613-4DCB-9AE3-1F93EFCC1F65}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
{1A5ED921-4613-4DCB-9AE3-1F93EFCC1F65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1A5ED921-4613-4DCB-9AE3-1F93EFCC1F65}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1A5ED921-4613-4DCB-9AE3-1F93EFCC1F65}.Documentation|Any CPU.ActiveCfg = Debug|Any CPU
{1A5ED921-4613-4DCB-9AE3-1F93EFCC1F65}.Documentation|Any CPU.Build.0 = Debug|Any CPU
{1A5ED921-4613-4DCB-9AE3-1F93EFCC1F65}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1A5ED921-4613-4DCB-9AE3-1F93EFCC1F65}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -458,6 +468,7 @@ Global
{0F639EB4-FB64-4909-8A10-FB93E7BE3AFB} = {4269F3C3-6B42-419B-B64A-3E6DC0F1574A}
{B71A123F-09FE-45D7-9644-4EE3E1E221AE} = {3ADFB27A-95FA-4330-B211-1D66A29A17AB}
{2F77CA1D-E6F0-4DEA-96BB-8A039F4D0FF8} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
{1A5ED921-4613-4DCB-9AE3-1F93EFCC1F65} = {3ADFB27A-95FA-4330-B211-1D66A29A17AB}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {7173C9F3-A7F9-496E-9078-9156E35D6E16}

Просмотреть файл

@ -0,0 +1,181 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Ai.LUIS;
using Microsoft.Bot.Builder.Ai.QnA;
using Microsoft.Bot.Schema;
namespace Microsoft.Bot.Samples.Ai.Luis.Dispatch.Hierarchical
{
/// <summary>
/// This bot demonstrates how to use a LUIS model generated by the Dispatch tool in hierarchical mode.
///
/// See https://aka.ms/bot-dispatch for more information on Dispatch.
///
/// This example assumes the LUIS app from Dispatch is generated from two LUIS apps and one QnAMaker service:
/// * A LUIS app named "homeautomation", for handling messages about turning lights and appliances on and off
/// * A LUIS app named "weather", for handling requests for weather forecasts and conditions
/// * A QnAMaker service named "faq", for answering questions about using the hypothetical home automation system.
///
/// Generate the LUIS app from Dispatch with the -hiearchical flag set to true. This will create one intent for each of the
/// constituent LUIS apps and QnAMaker services: "l_homeautomation", "l_weather", "q_faq". The bot can use the intents
/// to route the user messages to the appropriate LUIS app or QnA maker.
///
/// Dispatching the messages to the original LUIS apps allows the bot to get entities from the original apps.
/// The LUIS app from dispatcher doesn't contain entity information.
/// </summary>
public class LuisDispatchBot : IBot
{
public LuisDispatchBot() { }
private static QnAMakerOptions qnaOptions = new QnAMakerOptions
{
// add subscription key for QnA and knowledge base ID
SubscriptionKey = "<QNAMAKER-KB-ID>",
KnowledgeBaseId = "<YOUR-QNAMAKER-SUBSCRIPTION-KEY>"
};
// App ID for a LUIS model named "homeautomation"
private static LuisModel luisModel1 =
new LuisModel("<YOUR-APP-ID>", "<YOUR-LUIS-SUBSCRIPTION-KEY>", new System.Uri("https://westus.api.cognitive.microsoft.com/luis/v2.0/apps/"));
// App ID for a LUIS model named "weather"
private static LuisModel luisModel2 =
new LuisModel("YOUR-APP-ID", "<YOUR-LUIS-SUBSCRIPTION-KEY>", new System.Uri("https://westus.api.cognitive.microsoft.com/luis/v2.0/apps/"));
public async Task OnTurn(ITurnContext context)
{
if (context.Activity.Type is ActivityTypes.Message)
{
var message = context.Activity.AsMessageActivity();
// Get the intent recognition result from the context object.
var dispatchResult = context.Services.Get<RecognizerResult>(LuisRecognizerMiddleware.LuisRecognizerResultKey) as RecognizerResult;
var topIntent = dispatchResult?.GetTopScoringIntent();
LuisRecognizer luisRecognizer1, luisRecognizer2;
RecognizerResult recognizerResult;
var intentsList = new List<string>();
var entitiesList = new List<string>();
if (topIntent == null)
{
await context.SendActivity("Unable to get the top intent.");
}
else
{
if (topIntent.Value.score < 0.3)
{
await context.SendActivity("I'm not very sure what you want but will try to send your request.");
}
switch (topIntent.Value.key.ToLowerInvariant())
{
case "l_homeautomation":
await context.SendActivity("Sending your request to the home automation system ...");
luisRecognizer1 = new LuisRecognizer(luisModel1);
var luisResults = await luisRecognizer1.CallAndRecognize(message.Text, System.Threading.CancellationToken.None);
recognizerResult = luisResults.recognizerResult;
// list the intents
foreach (var intent in recognizerResult.Intents)
{
intentsList.Add($"'{intent.Key}', score {intent.Value}");
}
await context.SendActivity($"Intents detected by the weather app {string.Join("\n\n", intentsList)}");
// list the entities
entitiesList = new List<string>();
foreach (var entity in recognizerResult.Entities)
{
if (!entity.Key.ToString().Equals("$instance"))
{
entitiesList.Add($"{entity.Key}: {entity.Value.First}");
}
}
if (entitiesList.Count > 0)
{
await context.SendActivity($"The following entities were found the message:\n\n{string.Join("\n\n", entitiesList)}");
}
// Here, you can add code for calling the hypothetical home automation service, passing in any entity information that you need
break;
case "l_weather":
await context.SendActivity("Sending your request to the weather system ...");
luisRecognizer2 = new LuisRecognizer(luisModel2);
luisResults = await luisRecognizer2.CallAndRecognize(message.Text, System.Threading.CancellationToken.None);
recognizerResult = luisResults.recognizerResult;
// list the intents
var intentsResult2 = new List<string>();
foreach (var intent in recognizerResult.Intents)
{
intentsResult2.Add($"'{intent.Key}', score {intent.Value}");
}
await context.SendActivity($"Intents detected by the weather app {string.Join("\n\n", intentsResult2)}");
// list the entities
entitiesList = new List<string>();
foreach (var entity in recognizerResult.Entities)
{
if (!entity.Key.ToString().Equals("$instance"))
{
entitiesList.Add($"{entity.Key}: {entity.Value.First}");
}
}
if (entitiesList.Count > 0)
{
await context.SendActivity($"The following entities were found in the message:\n\n{string.Join("\n\n", entitiesList)}");
}
// Here, you can add code for calling the hypothetical weather service, passing in any entity information that you need
break;
case "none":
// You can provide logic here to handle the known None intent (none of the above).
// In this example we fall through to the QnA intent.
case "q_faq":
QnAMaker qnaMaker = new QnAMaker(qnaOptions);
var messageActivity = context.Activity.AsMessageActivity();
if (!string.IsNullOrEmpty(messageActivity.Text))
{
var results = await qnaMaker.GetAnswers(messageActivity.Text.Trim()).ConfigureAwait(false);
if (results.Any())
{
await context.SendActivity(results.First().Answer);
}
else
{
await context.SendActivity("Couldn't find an answer in the FAQ.");
}
}
break;
default:
// The intent didn't match any case, so just display the recognition results.
await context.SendActivity($"Dispatch intent: {topIntent.Value.key} ({topIntent.Value.score}).");
break;
}
}
}
else if (context.Activity.Type is ActivityTypes.ConversationUpdate)
{
foreach (var newMember in context.Activity.MembersAdded)
{
if (newMember.Id != context.Activity.Recipient.Id)
{
await context.SendActivity("Hello and welcome to the LUIS Dispatch sample bot. This bot dispatches messages to LUIS apps and QnA, using a LUIS model generated by the Dispatch tool in hierarchical mode.");
}
}
}
}
}
}

Просмотреть файл

@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\libraries\integration\Microsoft.Bot.Builder.Integration.AspNet.Core\Microsoft.Bot.Builder.Integration.AspNet.Core.csproj" />
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Builder.Ai.LUIS\Microsoft.Bot.Builder.Ai.LUIS.csproj" />
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Builder.Ai.QnA\Microsoft.Bot.Builder.Ai.QnA.csproj" />
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Builder.Core\Microsoft.Bot.Builder.Core.csproj" />
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Builder\Microsoft.Bot.Builder.csproj" />
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Connector\Microsoft.Bot.Connector.csproj" />
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Schema\Microsoft.Bot.Schema.csproj" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace Microsoft.Bot.Samples.Ai.Luis.Dispatch.Hierarchical
{
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
}
}

Просмотреть файл

@ -0,0 +1,62 @@
using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Bot.Builder.BotFramework;
using Microsoft.Bot.Builder.Integration.AspNet.Core;
using Microsoft.Bot.Builder.Ai.LUIS;
using Microsoft.Cognitive.LUIS;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace Microsoft.Bot.Samples.Ai.Luis.Dispatch.Hierarchical
{
public class Startup
{
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddBot<LuisDispatchBot>(options =>
{
options.CredentialProvider = new ConfigurationCredentialProvider(Configuration);
string luisModelId = "<Your LUIS app ID from Dispatch here>";
string luisSubscriptionKey = "<Your LUIS Subscription Key here>";
Uri luisUri = new Uri("https://westus.api.cognitive.microsoft.com/luis/v2.0/apps/");
var luisModel = new LuisModel(luisModelId, luisSubscriptionKey, luisUri);
// If you want to get all intents scorings, add verbose in luisOptions
var luisOptions = new LuisRequest { Verbose = true };
var middleware = options.Middleware;
middleware.Add(new LuisRecognizerMiddleware(luisModel, luisOptions: luisOptions));
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseDefaultFiles()
.UseStaticFiles()
.UseBotFramework();
}
}
}

Просмотреть файл

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
Hi, I'm an example bot showing you how a LUIS app that is generated by the Dispatch tool can combine multiple LUIS apps and services.
</body>
</html>