Skip to content

Commit b57bf88

Browse files
authored
Orchestrator entities sample (#6340)
* Orchestrator reorganization 1. Moved ModelTuning from botbuilder-samples repo 2. Delete OrchestratorDispatch Composer sample (moved to botbuilder-samples repo) * Update FAQ.md * Orchestrator with entities sample
1 parent 2362e4f commit b57bf88

17 files changed

+1243
-0
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Assets generated by luis:build, luis:cross-train
2+
**/model
3+
**/[Gg]enerated
4+
**/*.blu
5+
*.json
6+
**/*.targets
7+
**/*.props
8+
**/*.cache
9+
*.dgspec.json
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using System;
5+
using Microsoft.Bot.Builder;
6+
using Microsoft.Bot.Builder.Integration.AspNet.Core;
7+
using Microsoft.Bot.Builder.TraceExtensions;
8+
using Microsoft.Extensions.Configuration;
9+
using Microsoft.Extensions.Logging;
10+
11+
namespace Microsoft.BotBuilderSamples
12+
{
13+
public class AdapterWithErrorHandler : BotFrameworkHttpAdapter
14+
{
15+
public AdapterWithErrorHandler(IConfiguration configuration, ILogger<BotFrameworkHttpAdapter> logger, ConversationState conversationState = null)
16+
: base(configuration, logger)
17+
{
18+
OnTurnError = async (turnContext, exception) =>
19+
{
20+
// Log any leaked exception from the application.
21+
logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}");
22+
23+
// Send a message to the user
24+
await turnContext.SendActivityAsync("The bot encountered an error or bug.");
25+
await turnContext.SendActivityAsync("To run this sample make sure you have the LUIS and QnA models deployed.");
26+
await turnContext.SendActivityAsync("To continue to run this bot, please fix the bot source code.");
27+
28+
if (conversationState != null)
29+
{
30+
try
31+
{
32+
// Delete the conversationState for the current conversation to prevent the
33+
// bot from getting stuck in a error-loop caused by being in a bad state.
34+
// ConversationState should be thought of as similar to "cookie-state" in a Web pages.
35+
await conversationState.DeleteAsync(turnContext);
36+
}
37+
catch (Exception e)
38+
{
39+
logger.LogError(e, $"Exception caught on attempting to Delete ConversationState : {e.Message}");
40+
}
41+
}
42+
43+
// Send a trace activity, which will be displayed in the Bot Framework Emulator
44+
await turnContext.TraceActivityAsync("OnTurnError Trace", exception.Message, "https://www.botframework.com/schemas/error", "TurnError");
45+
};
46+
}
47+
}
48+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using Microsoft.Bot.Builder.AI.Luis;
5+
using Microsoft.Bot.Builder.AI.Orchestrator;
6+
using Microsoft.Bot.Builder.AI.QnA;
7+
using Microsoft.Extensions.Configuration;
8+
9+
namespace Microsoft.BotBuilderSamples
10+
{
11+
public class BotServices : IBotServices
12+
{
13+
public BotServices(IConfiguration configuration, OrchestratorRecognizer dispatcher)
14+
{
15+
// Read the setting for cognitive services (LUIS, QnA) from the appsettings.json
16+
// If includeApiResults is set to true, the full response from the LUIS api (LuisResult)
17+
// will be made available in the properties collection of the RecognizerResult
18+
LuisHomeAutomationRecognizer = CreateLuisRecognizer(configuration, "LuisHomeAutomationAppId");
19+
LuisWeatherRecognizer = CreateLuisRecognizer(configuration, "LuisWeatherAppId");
20+
21+
Dispatch = dispatcher;
22+
23+
SampleQnA = new QnAMaker(new QnAMakerEndpoint
24+
{
25+
KnowledgeBaseId = configuration["QnAKnowledgebaseId"],
26+
EndpointKey = configuration["QnAEndpointKey"],
27+
Host = configuration["QnAEndpointHostName"]
28+
});
29+
}
30+
31+
public OrchestratorRecognizer Dispatch { get; private set; }
32+
33+
public QnAMaker SampleQnA { get; private set; }
34+
35+
public LuisRecognizer LuisHomeAutomationRecognizer { get; private set; }
36+
37+
public LuisRecognizer LuisWeatherRecognizer { get; private set; }
38+
39+
private LuisRecognizer CreateLuisRecognizer(IConfiguration configuration, string appIdKey)
40+
{
41+
var luisApplication = new LuisApplication(
42+
configuration[appIdKey],
43+
configuration["LuisAPIKey"],
44+
configuration["LuisAPIHostName"]);
45+
46+
// Set the recognizer options depending on which endpoint version you want to use.
47+
// More details can be found in https://docs.microsoft.com/en-gb/azure/cognitive-services/luis/luis-migration-api-v3
48+
var recognizerOptions = new LuisRecognizerOptionsV2(luisApplication)
49+
{
50+
IncludeAPIResults = true,
51+
PredictionOptions = new LuisPredictionOptions()
52+
{
53+
IncludeAllIntents = true,
54+
IncludeInstanceData = true
55+
}
56+
};
57+
58+
return new LuisRecognizer(recognizerOptions);
59+
}
60+
}
61+
}
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using Microsoft.Azure.CognitiveServices.Language.LUIS.Runtime.Models;
9+
using Microsoft.Bot.Builder;
10+
using Microsoft.Bot.Builder.Dialogs;
11+
using Microsoft.Bot.Schema;
12+
using Microsoft.Extensions.Logging;
13+
14+
namespace Microsoft.BotBuilderSamples
15+
{
16+
public class DispatchBot : ActivityHandler
17+
{
18+
private ILogger<DispatchBot> _logger;
19+
private IBotServices _botServices;
20+
21+
public DispatchBot(IBotServices botServices, ILogger<DispatchBot> logger)
22+
{
23+
_logger = logger;
24+
_botServices = botServices;
25+
}
26+
27+
protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
28+
{
29+
var dc = new DialogContext(new DialogSet(), turnContext, new DialogState());
30+
// Top intent tell us which cognitive service to use.
31+
var allScores = await _botServices.Dispatch.RecognizeAsync(dc, (Activity)turnContext.Activity, cancellationToken);
32+
var topIntent = allScores.Intents.First().Key;
33+
34+
// Detected entities which could be used to help with intent dispatching, for example, when top intent score is too low or
35+
// when there are multiple top intents with close scores.
36+
var entities = allScores.Entities.Children().Where(t => t.Path != "$instance");
37+
38+
// Next, we call the dispatcher with the top intent.
39+
await DispatchToTopIntentAsync(turnContext, topIntent, cancellationToken);
40+
}
41+
42+
protected override async Task OnMembersAddedAsync(IList<ChannelAccount> membersAdded, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
43+
{
44+
const string WelcomeText = "Type a greeting, or a question about the weather to get started.";
45+
46+
foreach (var member in membersAdded)
47+
{
48+
if (member.Id != turnContext.Activity.Recipient.Id)
49+
{
50+
await turnContext.SendActivityAsync(MessageFactory.Text($"Welcome to Dispatch bot {member.Name}. {WelcomeText}"), cancellationToken);
51+
}
52+
}
53+
}
54+
55+
private async Task DispatchToTopIntentAsync(ITurnContext<IMessageActivity> turnContext, string intent, CancellationToken cancellationToken)
56+
{
57+
switch (intent)
58+
{
59+
case "HomeAutomation":
60+
await ProcessHomeAutomationAsync(turnContext, cancellationToken);
61+
break;
62+
case "Weather":
63+
await ProcessWeatherAsync(turnContext, cancellationToken);
64+
break;
65+
case "QnAMaker":
66+
await ProcessSampleQnAAsync(turnContext, cancellationToken);
67+
break;
68+
default:
69+
_logger.LogInformation($"Dispatch unrecognized intent: {intent}.");
70+
await turnContext.SendActivityAsync(MessageFactory.Text($"Dispatch unrecognized intent: {intent}."), cancellationToken);
71+
break;
72+
}
73+
}
74+
75+
private async Task ProcessHomeAutomationAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
76+
{
77+
_logger.LogInformation("ProcessHomeAutomationAsync");
78+
79+
// Retrieve LUIS result for HomeAutomation.
80+
var recognizerResult = await _botServices.LuisHomeAutomationRecognizer.RecognizeAsync(turnContext, cancellationToken);
81+
var result = recognizerResult.Properties["luisResult"] as LuisResult;
82+
83+
var topIntent = result.TopScoringIntent.Intent;
84+
85+
await turnContext.SendActivityAsync(MessageFactory.Text($"HomeAutomation top intent {topIntent}."), cancellationToken);
86+
await turnContext.SendActivityAsync(MessageFactory.Text($"HomeAutomation intents detected:\n\n{string.Join("\n\n", result.Intents.Select(i => i.Intent))}"), cancellationToken);
87+
if (result.Entities.Count > 0)
88+
{
89+
await turnContext.SendActivityAsync(MessageFactory.Text($"HomeAutomation entities were found in the message:\n\n{string.Join("\n\n", result.Entities.Select(i => i.Entity))}"), cancellationToken);
90+
}
91+
}
92+
93+
private async Task ProcessWeatherAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
94+
{
95+
_logger.LogInformation("ProcessWeatherAsync");
96+
97+
// Retrieve LUIS result for Weather.
98+
var recognizerResult = await _botServices.LuisWeatherRecognizer.RecognizeAsync(turnContext, cancellationToken);
99+
var result = recognizerResult.Properties["luisResult"] as LuisResult;
100+
var topIntent = result.TopScoringIntent.Intent;
101+
102+
await turnContext.SendActivityAsync(MessageFactory.Text($"ProcessWeather top intent {topIntent}."), cancellationToken);
103+
await turnContext.SendActivityAsync(MessageFactory.Text($"ProcessWeather Intents detected::\n\n{string.Join("\n\n", result.Intents.Select(i => i.Intent))}"), cancellationToken);
104+
if (result.Entities.Count > 0)
105+
{
106+
await turnContext.SendActivityAsync(MessageFactory.Text($"ProcessWeather entities were found in the message:\n\n{string.Join("\n\n", result.Entities.Select(i => i.Entity))}"), cancellationToken);
107+
}
108+
}
109+
110+
private async Task ProcessSampleQnAAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
111+
{
112+
_logger.LogInformation("ProcessSampleQnAAsync");
113+
114+
var results = await _botServices.SampleQnA.GetAnswersAsync(turnContext);
115+
if (results.Any())
116+
{
117+
await turnContext.SendActivityAsync(MessageFactory.Text(results.First().Answer), cancellationToken);
118+
}
119+
else
120+
{
121+
await turnContext.SendActivityAsync(MessageFactory.Text("Sorry, could not find an answer in the Q and A system."), cancellationToken);
122+
}
123+
}
124+
}
125+
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
2+
> LUIS application information
3+
> !# @app.name = Home Automation
4+
> !# @app.desc = Home Automation LUIS application - Bot Builder Samples
5+
> !# @app.versionId = 0.1
6+
> !# @app.culture = en-us
7+
> !# @app.luis_schema_version = 4.0.0
8+
> !# @app.tokenizerVersion = 1.0.0
9+
10+
11+
> # Intent definitions
12+
13+
## ControlDevice
14+
- {@Room=breezeway} on please
15+
- change {@deviceProperty=temperature} to seventy two degrees
16+
- {@Device=coffee bar} on please
17+
- decrease {@deviceProperty=temperature} for me please
18+
- dim {@Room=kitchen} {@Device=lights} to 25 .
19+
- {@Device=fish pond} off please
20+
- {@Device=fish pond} on please
21+
- {@Device=illuminate} please
22+
- {@Room=living room} {@Device=lamp} on please
23+
- {@Room=living room} {@Device=lamps} off please
24+
- lock the {@Device=doors} for me please
25+
- lower your {@deviceProperty=volume}
26+
- make {@Device=camera 1} off please
27+
- make some {@Device=coffee}
28+
- play {@Device=dvd}
29+
- set {@Device=lights} out in {@Room=bedroom}
30+
- set {@Device=lights} to {@deviceProperty=bright}
31+
- set {@Device=lights} to {@deviceProperty=concentrate}
32+
- shut down my work {@Device=computer}
33+
- snap switch {@Device=fan} fifty percent
34+
- start {@Room=master bedroom} {@Device=light}.
35+
- {@Room=theater} on please
36+
- turn {@Device=dimmer} off
37+
- turn off {@Device=ac} please
38+
- turn off {@Room=foyer} {@Device=lights}
39+
- turn off {@Room=living room} {@Device=light}
40+
- turn off {@Device=staircase}
41+
- turn off venice {@Device=lamp}
42+
- turn on {@Room=bathroom} {@Device=heater}
43+
- turn on {@Device=external speaker}
44+
- turn on {@Room=kitchen} {@Device=faucet}
45+
- turn on {@Device=light} in {@Room=bedroom}
46+
- turn on my {@Room=bedroom} {@Device=lights}.
47+
- turn on the {@Room=furnace room} {@Device=lights}
48+
- turn on the internet in my {@Room=bedroom} please
49+
- turn on {@Device=thermostat} please
50+
- turn the {@Device=fan} to high
51+
- turn {@Device=thermostat} on 70.
52+
- {@Device_PatternAny} off [please]
53+
- {@Device_PatternAny} in {Room_PatternAny} on [please]
54+
- turn on {@Device_PatternAny} in {Room_PatternAny}
55+
- turn off {@Device_PatternAny} in {Room_PatternAny}
56+
- {@Device_PatternAny} in {Room_PatternAny} off [please]
57+
- {@Device_PatternAny} on [please]
58+
- turn on {@Device_PatternAny}
59+
60+
61+
## None
62+
63+
64+
> # Entity definitions
65+
66+
@ ml Device
67+
68+
@ ml deviceProperty
69+
70+
@ ml Room
71+
72+
73+
> # PREBUILT Entity definitions
74+
75+
@ prebuilt number
76+
77+
78+
> # Phrase list definitions
79+
80+
81+
> # List entities
82+
83+
@ list Operation =
84+
- off :
85+
- turn off
86+
- switch off
87+
- lock
88+
- out
89+
- shut down
90+
- stop
91+
- on :
92+
- turn on
93+
- switch on
94+
- unlock
95+
- un lock
96+
- boot up
97+
- start
98+
99+
100+
> # RegEx entities
101+
102+
103+
> # Pattern.Any entities
104+
105+
@ patternany Device_PatternAny
106+
@ patternany Room_PatternAny
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# ? hi
2+
```
3+
hello
4+
```
5+
6+
# ? greetings
7+
- good morning
8+
- good evening
9+
```
10+
Hello!
11+
```
12+
13+
# ? What are you?
14+
- What?
15+
- What do you do?
16+
- Who are you?
17+
- What is your name?
18+
- What should I call you?
19+
```
20+
I am the LUIS-QnAMaker Dispatch bot! This sample demonstrates using several LUIS applications and QnA Maker knowledge base using Orchestrator.
21+
```

0 commit comments

Comments
 (0)