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
This commit is contained in:
Родитель
2362e4f1f9
Коммит
b57bf88069
|
@ -0,0 +1,9 @@
|
|||
# Assets generated by luis:build, luis:cross-train
|
||||
**/model
|
||||
**/[Gg]enerated
|
||||
**/*.blu
|
||||
*.json
|
||||
**/*.targets
|
||||
**/*.props
|
||||
**/*.cache
|
||||
*.dgspec.json
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Integration.AspNet.Core;
|
||||
using Microsoft.Bot.Builder.TraceExtensions;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples
|
||||
{
|
||||
public class AdapterWithErrorHandler : BotFrameworkHttpAdapter
|
||||
{
|
||||
public AdapterWithErrorHandler(IConfiguration configuration, ILogger<BotFrameworkHttpAdapter> logger, ConversationState conversationState = null)
|
||||
: base(configuration, logger)
|
||||
{
|
||||
OnTurnError = async (turnContext, exception) =>
|
||||
{
|
||||
// Log any leaked exception from the application.
|
||||
logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}");
|
||||
|
||||
// Send a message to the user
|
||||
await turnContext.SendActivityAsync("The bot encountered an error or bug.");
|
||||
await turnContext.SendActivityAsync("To run this sample make sure you have the LUIS and QnA models deployed.");
|
||||
await turnContext.SendActivityAsync("To continue to run this bot, please fix the bot source code.");
|
||||
|
||||
if (conversationState != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Delete the conversationState for the current conversation to prevent the
|
||||
// bot from getting stuck in a error-loop caused by being in a bad state.
|
||||
// ConversationState should be thought of as similar to "cookie-state" in a Web pages.
|
||||
await conversationState.DeleteAsync(turnContext);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.LogError(e, $"Exception caught on attempting to Delete ConversationState : {e.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
// Send a trace activity, which will be displayed in the Bot Framework Emulator
|
||||
await turnContext.TraceActivityAsync("OnTurnError Trace", exception.Message, "https://www.botframework.com/schemas/error", "TurnError");
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Microsoft.Bot.Builder.AI.Luis;
|
||||
using Microsoft.Bot.Builder.AI.Orchestrator;
|
||||
using Microsoft.Bot.Builder.AI.QnA;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples
|
||||
{
|
||||
public class BotServices : IBotServices
|
||||
{
|
||||
public BotServices(IConfiguration configuration, OrchestratorRecognizer dispatcher)
|
||||
{
|
||||
// Read the setting for cognitive services (LUIS, QnA) from the appsettings.json
|
||||
// If includeApiResults is set to true, the full response from the LUIS api (LuisResult)
|
||||
// will be made available in the properties collection of the RecognizerResult
|
||||
LuisHomeAutomationRecognizer = CreateLuisRecognizer(configuration, "LuisHomeAutomationAppId");
|
||||
LuisWeatherRecognizer = CreateLuisRecognizer(configuration, "LuisWeatherAppId");
|
||||
|
||||
Dispatch = dispatcher;
|
||||
|
||||
SampleQnA = new QnAMaker(new QnAMakerEndpoint
|
||||
{
|
||||
KnowledgeBaseId = configuration["QnAKnowledgebaseId"],
|
||||
EndpointKey = configuration["QnAEndpointKey"],
|
||||
Host = configuration["QnAEndpointHostName"]
|
||||
});
|
||||
}
|
||||
|
||||
public OrchestratorRecognizer Dispatch { get; private set; }
|
||||
|
||||
public QnAMaker SampleQnA { get; private set; }
|
||||
|
||||
public LuisRecognizer LuisHomeAutomationRecognizer { get; private set; }
|
||||
|
||||
public LuisRecognizer LuisWeatherRecognizer { get; private set; }
|
||||
|
||||
private LuisRecognizer CreateLuisRecognizer(IConfiguration configuration, string appIdKey)
|
||||
{
|
||||
var luisApplication = new LuisApplication(
|
||||
configuration[appIdKey],
|
||||
configuration["LuisAPIKey"],
|
||||
configuration["LuisAPIHostName"]);
|
||||
|
||||
// Set the recognizer options depending on which endpoint version you want to use.
|
||||
// More details can be found in https://docs.microsoft.com/en-gb/azure/cognitive-services/luis/luis-migration-api-v3
|
||||
var recognizerOptions = new LuisRecognizerOptionsV2(luisApplication)
|
||||
{
|
||||
IncludeAPIResults = true,
|
||||
PredictionOptions = new LuisPredictionOptions()
|
||||
{
|
||||
IncludeAllIntents = true,
|
||||
IncludeInstanceData = true
|
||||
}
|
||||
};
|
||||
|
||||
return new LuisRecognizer(recognizerOptions);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Azure.CognitiveServices.Language.LUIS.Runtime.Models;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples
|
||||
{
|
||||
public class DispatchBot : ActivityHandler
|
||||
{
|
||||
private ILogger<DispatchBot> _logger;
|
||||
private IBotServices _botServices;
|
||||
|
||||
public DispatchBot(IBotServices botServices, ILogger<DispatchBot> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
_botServices = botServices;
|
||||
}
|
||||
|
||||
protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
|
||||
{
|
||||
var dc = new DialogContext(new DialogSet(), turnContext, new DialogState());
|
||||
// Top intent tell us which cognitive service to use.
|
||||
var allScores = await _botServices.Dispatch.RecognizeAsync(dc, (Activity)turnContext.Activity, cancellationToken);
|
||||
var topIntent = allScores.Intents.First().Key;
|
||||
|
||||
// Detected entities which could be used to help with intent dispatching, for example, when top intent score is too low or
|
||||
// when there are multiple top intents with close scores.
|
||||
var entities = allScores.Entities.Children().Where(t => t.Path != "$instance");
|
||||
|
||||
// Next, we call the dispatcher with the top intent.
|
||||
await DispatchToTopIntentAsync(turnContext, topIntent, cancellationToken);
|
||||
}
|
||||
|
||||
protected override async Task OnMembersAddedAsync(IList<ChannelAccount> membersAdded, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
|
||||
{
|
||||
const string WelcomeText = "Type a greeting, or a question about the weather to get started.";
|
||||
|
||||
foreach (var member in membersAdded)
|
||||
{
|
||||
if (member.Id != turnContext.Activity.Recipient.Id)
|
||||
{
|
||||
await turnContext.SendActivityAsync(MessageFactory.Text($"Welcome to Dispatch bot {member.Name}. {WelcomeText}"), cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DispatchToTopIntentAsync(ITurnContext<IMessageActivity> turnContext, string intent, CancellationToken cancellationToken)
|
||||
{
|
||||
switch (intent)
|
||||
{
|
||||
case "HomeAutomation":
|
||||
await ProcessHomeAutomationAsync(turnContext, cancellationToken);
|
||||
break;
|
||||
case "Weather":
|
||||
await ProcessWeatherAsync(turnContext, cancellationToken);
|
||||
break;
|
||||
case "QnAMaker":
|
||||
await ProcessSampleQnAAsync(turnContext, cancellationToken);
|
||||
break;
|
||||
default:
|
||||
_logger.LogInformation($"Dispatch unrecognized intent: {intent}.");
|
||||
await turnContext.SendActivityAsync(MessageFactory.Text($"Dispatch unrecognized intent: {intent}."), cancellationToken);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ProcessHomeAutomationAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.LogInformation("ProcessHomeAutomationAsync");
|
||||
|
||||
// Retrieve LUIS result for HomeAutomation.
|
||||
var recognizerResult = await _botServices.LuisHomeAutomationRecognizer.RecognizeAsync(turnContext, cancellationToken);
|
||||
var result = recognizerResult.Properties["luisResult"] as LuisResult;
|
||||
|
||||
var topIntent = result.TopScoringIntent.Intent;
|
||||
|
||||
await turnContext.SendActivityAsync(MessageFactory.Text($"HomeAutomation top intent {topIntent}."), cancellationToken);
|
||||
await turnContext.SendActivityAsync(MessageFactory.Text($"HomeAutomation intents detected:\n\n{string.Join("\n\n", result.Intents.Select(i => i.Intent))}"), cancellationToken);
|
||||
if (result.Entities.Count > 0)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ProcessWeatherAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.LogInformation("ProcessWeatherAsync");
|
||||
|
||||
// Retrieve LUIS result for Weather.
|
||||
var recognizerResult = await _botServices.LuisWeatherRecognizer.RecognizeAsync(turnContext, cancellationToken);
|
||||
var result = recognizerResult.Properties["luisResult"] as LuisResult;
|
||||
var topIntent = result.TopScoringIntent.Intent;
|
||||
|
||||
await turnContext.SendActivityAsync(MessageFactory.Text($"ProcessWeather top intent {topIntent}."), cancellationToken);
|
||||
await turnContext.SendActivityAsync(MessageFactory.Text($"ProcessWeather Intents detected::\n\n{string.Join("\n\n", result.Intents.Select(i => i.Intent))}"), cancellationToken);
|
||||
if (result.Entities.Count > 0)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ProcessSampleQnAAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.LogInformation("ProcessSampleQnAAsync");
|
||||
|
||||
var results = await _botServices.SampleQnA.GetAnswersAsync(turnContext);
|
||||
if (results.Any())
|
||||
{
|
||||
await turnContext.SendActivityAsync(MessageFactory.Text(results.First().Answer), cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
await turnContext.SendActivityAsync(MessageFactory.Text("Sorry, could not find an answer in the Q and A system."), cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
|
||||
> LUIS application information
|
||||
> !# @app.name = Home Automation
|
||||
> !# @app.desc = Home Automation LUIS application - Bot Builder Samples
|
||||
> !# @app.versionId = 0.1
|
||||
> !# @app.culture = en-us
|
||||
> !# @app.luis_schema_version = 4.0.0
|
||||
> !# @app.tokenizerVersion = 1.0.0
|
||||
|
||||
|
||||
> # Intent definitions
|
||||
|
||||
## ControlDevice
|
||||
- {@Room=breezeway} on please
|
||||
- change {@deviceProperty=temperature} to seventy two degrees
|
||||
- {@Device=coffee bar} on please
|
||||
- decrease {@deviceProperty=temperature} for me please
|
||||
- dim {@Room=kitchen} {@Device=lights} to 25 .
|
||||
- {@Device=fish pond} off please
|
||||
- {@Device=fish pond} on please
|
||||
- {@Device=illuminate} please
|
||||
- {@Room=living room} {@Device=lamp} on please
|
||||
- {@Room=living room} {@Device=lamps} off please
|
||||
- lock the {@Device=doors} for me please
|
||||
- lower your {@deviceProperty=volume}
|
||||
- make {@Device=camera 1} off please
|
||||
- make some {@Device=coffee}
|
||||
- play {@Device=dvd}
|
||||
- set {@Device=lights} out in {@Room=bedroom}
|
||||
- set {@Device=lights} to {@deviceProperty=bright}
|
||||
- set {@Device=lights} to {@deviceProperty=concentrate}
|
||||
- shut down my work {@Device=computer}
|
||||
- snap switch {@Device=fan} fifty percent
|
||||
- start {@Room=master bedroom} {@Device=light}.
|
||||
- {@Room=theater} on please
|
||||
- turn {@Device=dimmer} off
|
||||
- turn off {@Device=ac} please
|
||||
- turn off {@Room=foyer} {@Device=lights}
|
||||
- turn off {@Room=living room} {@Device=light}
|
||||
- turn off {@Device=staircase}
|
||||
- turn off venice {@Device=lamp}
|
||||
- turn on {@Room=bathroom} {@Device=heater}
|
||||
- turn on {@Device=external speaker}
|
||||
- turn on {@Room=kitchen} {@Device=faucet}
|
||||
- turn on {@Device=light} in {@Room=bedroom}
|
||||
- turn on my {@Room=bedroom} {@Device=lights}.
|
||||
- turn on the {@Room=furnace room} {@Device=lights}
|
||||
- turn on the internet in my {@Room=bedroom} please
|
||||
- turn on {@Device=thermostat} please
|
||||
- turn the {@Device=fan} to high
|
||||
- turn {@Device=thermostat} on 70.
|
||||
- {@Device_PatternAny} off [please]
|
||||
- {@Device_PatternAny} in {Room_PatternAny} on [please]
|
||||
- turn on {@Device_PatternAny} in {Room_PatternAny}
|
||||
- turn off {@Device_PatternAny} in {Room_PatternAny}
|
||||
- {@Device_PatternAny} in {Room_PatternAny} off [please]
|
||||
- {@Device_PatternAny} on [please]
|
||||
- turn on {@Device_PatternAny}
|
||||
|
||||
|
||||
## None
|
||||
|
||||
|
||||
> # Entity definitions
|
||||
|
||||
@ ml Device
|
||||
|
||||
@ ml deviceProperty
|
||||
|
||||
@ ml Room
|
||||
|
||||
|
||||
> # PREBUILT Entity definitions
|
||||
|
||||
@ prebuilt number
|
||||
|
||||
|
||||
> # Phrase list definitions
|
||||
|
||||
|
||||
> # List entities
|
||||
|
||||
@ list Operation =
|
||||
- off :
|
||||
- turn off
|
||||
- switch off
|
||||
- lock
|
||||
- out
|
||||
- shut down
|
||||
- stop
|
||||
- on :
|
||||
- turn on
|
||||
- switch on
|
||||
- unlock
|
||||
- un lock
|
||||
- boot up
|
||||
- start
|
||||
|
||||
|
||||
> # RegEx entities
|
||||
|
||||
|
||||
> # Pattern.Any entities
|
||||
|
||||
@ patternany Device_PatternAny
|
||||
@ patternany Room_PatternAny
|
|
@ -0,0 +1,21 @@
|
|||
# ? hi
|
||||
```
|
||||
hello
|
||||
```
|
||||
|
||||
# ? greetings
|
||||
- good morning
|
||||
- good evening
|
||||
```
|
||||
Hello!
|
||||
```
|
||||
|
||||
# ? What are you?
|
||||
- What?
|
||||
- What do you do?
|
||||
- Who are you?
|
||||
- What is your name?
|
||||
- What should I call you?
|
||||
```
|
||||
I am the LUIS-QnAMaker Dispatch bot! This sample demonstrates using several LUIS applications and QnA Maker knowledge base using Orchestrator.
|
||||
```
|
|
@ -0,0 +1,71 @@
|
|||
|
||||
> LUIS application information
|
||||
> !# @app.name = Weather
|
||||
> !# @app.desc = Weather LUIS application - Bot Builder Samples
|
||||
> !# @app.versionId = 0.1
|
||||
> !# @app.culture = en-us
|
||||
> !# @app.luis_schema_version = 4.0.0
|
||||
|
||||
|
||||
> # Intent definitions
|
||||
|
||||
## Get Weather Condition
|
||||
- current weather ?
|
||||
- do {@Location=florida} residents usually need ice scrapers
|
||||
- get {@Location=florence} temperature in september
|
||||
- get for me the weather conditions in {@Location=sonoma county}
|
||||
- get the daily temperature {@Location=greenwood indiana}
|
||||
- get the weather at {@Location=saint george utah}
|
||||
- how much rain does {@Location=chambersburg} get a year
|
||||
- show average rainfall for {@Location=boise}
|
||||
- temperature of {@Location=delhi} in celsius please
|
||||
- was last year about this time as wet as it is now in the {@Location=south} ?
|
||||
- what is the rain volume in {@Location=sonoma county} ?
|
||||
- what to wear in march in {@Location=california}
|
||||
- what's the weather like in {@Location=minneapolis}
|
||||
- weather in {@Location_PatternAny}
|
||||
- how's the weather in {@Location_PatternAny}
|
||||
- current weather in {@Location_PatternAny}
|
||||
|
||||
|
||||
## Get Weather Forecast
|
||||
- forecast in celcius
|
||||
- get the forcast for me
|
||||
- i want to know the temperature at {@Location=death valley}
|
||||
- provide me by {@Location=toronto} weather please
|
||||
- show me the forecast at {@Location=alabama}
|
||||
- soliciting today's weather
|
||||
- what is the weather in {@Location=redmond} ?
|
||||
- what is the weather today at 10 day {@Location=durham} ?
|
||||
- what will the weather be tomorrow in {@Location=new york} ?
|
||||
- what's the weather going to be like in {@Location=hawaii} ?
|
||||
- will it be raining in {@Location=ranchi}
|
||||
- will it rain this weekend
|
||||
- will it snow today
|
||||
- what's the forecast for next week in {@Location_PatternAny}
|
||||
- show me the forecast for {@Location_PatternAny}
|
||||
- what's the forecast for {@Location_PatternAny}
|
||||
|
||||
|
||||
## None
|
||||
|
||||
|
||||
> # Entity definitions
|
||||
|
||||
@ ml Location
|
||||
|
||||
|
||||
> # PREBUILT Entity definitions
|
||||
|
||||
|
||||
> # Phrase list definitions
|
||||
|
||||
|
||||
> # List entities
|
||||
|
||||
> # RegEx entities
|
||||
|
||||
|
||||
> # Pattern.Any entities
|
||||
|
||||
@ patternany Location_PatternAny
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Integration.AspNet.Core;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples
|
||||
{
|
||||
[Route("api/messages")]
|
||||
[ApiController]
|
||||
public class BotController : ControllerBase
|
||||
{
|
||||
private IBotFrameworkHttpAdapter _adapter;
|
||||
private IBot _bot;
|
||||
|
||||
public BotController(IBotFrameworkHttpAdapter adapter, IBot bot)
|
||||
{
|
||||
_adapter = adapter;
|
||||
_bot = bot;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task PostAsync()
|
||||
{
|
||||
// Delegate the processingg of the HTTP POST to the adapter.
|
||||
// The adapter will invoke the bot.
|
||||
await _adapter.ProcessAsync(Request, Response, _bot);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Microsoft.Bot.Builder.AI.Luis;
|
||||
using Microsoft.Bot.Builder.AI.Orchestrator;
|
||||
using Microsoft.Bot.Builder.AI.QnA;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples
|
||||
{
|
||||
public interface IBotServices
|
||||
{
|
||||
LuisRecognizer LuisHomeAutomationRecognizer { get; }
|
||||
|
||||
LuisRecognizer LuisWeatherRecognizer { get; }
|
||||
|
||||
OrchestratorRecognizer Dispatch { get; }
|
||||
|
||||
QnAMaker SampleQnA { get; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
namespace Microsoft.BotBuilderSamples
|
||||
{
|
||||
public class OrchestratorConfig
|
||||
{
|
||||
public string SnapshotFile { get; set; }
|
||||
|
||||
public string ModelFolder { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Microsoft.AspNetCore;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
CreateWebHostBuilder(args).Build().Run();
|
||||
}
|
||||
|
||||
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
||||
WebHost.CreateDefaultBuilder(args)
|
||||
.ConfigureLogging((logging) =>
|
||||
{
|
||||
logging.AddDebug();
|
||||
logging.AddConsole();
|
||||
})
|
||||
.UseStartup<Startup>();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:3978/",
|
||||
"sslPort": 0
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"10.EchoBot": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"applicationUrl": "http://localhost:3978/"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,138 @@
|
|||
# NLP with Orchestrator
|
||||
|
||||
Bot Framework v4 NLP with Orchestrator (with entity recognition) bot sample
|
||||
|
||||
This bot has been created using [Bot Framework](https://dev.botframework.com), it shows how to create a bot that relies on multiple [LUIS.ai](https://www.luis.ai) and [QnAMaker.ai](https://www.qnamaker.ai) models for natural language processing (NLP).
|
||||
|
||||
Use the Orchestrator dispatch model in cases when:
|
||||
|
||||
- Your bot consists of multiple language modules (LUIS + QnA) and you need assistance in routing user's utterances to these modules in order to integrate the different modules into your bot.
|
||||
- Create a text classification model from text files.
|
||||
|
||||
## Overview
|
||||
|
||||
This bot uses Orchestrator to route user utterances to multiple LUIS models and QnA maker services to support multiple conversational scenarios. This bot sample also demonstrates using Orchestrator for entity recognition.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
| OS | Version | Architectures |
|
||||
| ------- | ------------------- | --------------- |
|
||||
| Windows | 10 (1607+) | ia32 (x86), x64 |
|
||||
| MacOS | 10.14+ | x64 |
|
||||
| Linux | Ubuntu 18.04, 20.04 | x64 |
|
||||
|
||||
This sample **requires** prerequisites in order to run.
|
||||
- Install latest supported version of [Visual C++ Redistributable](https://support.microsoft.com/en-gb/help/2977003/the-latest-supported-visual-c-downloads)
|
||||
|
||||
- Install latest [Bot Framework Emulator](https://github.com/microsoft/BotFramework-Emulator/releases)
|
||||
|
||||
- [.NET Core SDK](https://aka.ms/dotnet-core-applaunch?framework=Microsoft.AspNetCore.App&framework_version=3.1.0&arch=x64&rid=win10-x64) version 3.1
|
||||
|
||||
```bash
|
||||
> dotnet --version
|
||||
```
|
||||
|
||||
- Node v14
|
||||
|
||||
```bash
|
||||
> node -v
|
||||
```
|
||||
|
||||
- Install BF CLI with Orchestrator plugin
|
||||
|
||||
```bash
|
||||
> npm i -g @microsoft/botframework-cli
|
||||
```
|
||||
Make sure bf orchestrator command is working and shows all available orchestrator commands
|
||||
```bash
|
||||
> bf orchestrator
|
||||
```
|
||||
|
||||
## To try this bot sample
|
||||
|
||||
- Clone the repository
|
||||
```bash
|
||||
> git clone https://github.com/microsoft/botbuilder-samples.git
|
||||
```
|
||||
|
||||
- CD Orchestrator\Samples\dotnet\nlp-with-entities
|
||||
```bash
|
||||
> cd Orchestrator\Samples\dotnet\nlp-with-entities
|
||||
```
|
||||
|
||||
- Configure the LUIS applications (HomeAutomation and Weather) required for this sample.
|
||||
- Get your [LUIS authoring key](https://docs.microsoft.com/en-us/azure/cognitive-services/LUIS/luis-concept-keys)
|
||||
```bash
|
||||
> bf luis:build --in CognitiveModels --authoringKey <YOUR-KEY> --botName <YOUR-BOT-NAME>
|
||||
```
|
||||
- Update application settings in `./appsettings.json`.
|
||||
|
||||
- Configure the QnA Maker KB required for this sample.
|
||||
- Get your [QnA Maker Subscription key](https://docs.microsoft.com/en-us/azure/cognitive-services/QnAMaker/how-to/set-up-qnamaker-service-azure#create-a-new-qna-maker-service)
|
||||
```bash
|
||||
> bf qnamaker:build --in CognitiveModels --subscriptionKey <YOUR-KEY> --botName <YOUR-BOT-NAME>
|
||||
```
|
||||
- Update kb information in `./appsettings.json`
|
||||
|
||||
- Configure Orchestrator to route utterances to LUIS/QnA language services set up above
|
||||
- Download Orchestrator intent and entity base models
|
||||
```bash
|
||||
> mkdir model
|
||||
> bf orchestrator:basemodel:get --out ./model
|
||||
> bf orchestrator:basemodel:get --versionId pretrained.20210218.microsoft.dte.00.06.bert_example_ner.en.onnx --out ./model/entity
|
||||
```
|
||||
- Create the Orchestrator snapshot
|
||||
```bash
|
||||
> mkdir generated
|
||||
> bf orchestrator:create --hierarchical --in ./CognitiveModels --out ./generated --model ./model --entityModel ./model/entity
|
||||
```
|
||||
The *hierarchical* flag creates top level intents in the snapshot file derived from the .lu/.qna file names in the input folder. As a result, the example utterances are mapped to *HomeAutomation*, *QnAMaker* and *Weather* intents/labels.
|
||||
The optional *entityModel* parameter provides path to a pretrained base model for named entity recognition and will be used to compute entity embeddings for Orchestrator snapshot file.
|
||||
|
||||
- Verify appsettings.json has the following:
|
||||
|
||||
```
|
||||
"Orchestrator": {
|
||||
"ModelFolder": ".\\model",
|
||||
"SnapshotFile": ".\\generated\\orchestrator.blu"
|
||||
}
|
||||
```
|
||||
|
||||
- Run the bot from a terminal or from Visual Studio, choose option A or B.
|
||||
A) From a terminal
|
||||
|
||||
```bash
|
||||
> cd samples\csharp_dotnetcore\14.nlp-with-orchestrator
|
||||
> dotnet run
|
||||
```
|
||||
B) Or from Visual Studio
|
||||
- Launch Visual Studio
|
||||
- File -> Open -> Project/Solution
|
||||
- Navigate to `Orchestrator` folder
|
||||
- Select `OrchestratorSamples.sln` file
|
||||
- Right click on `01.dispatch-bot` project in the solution and 'Set as Startup Project'
|
||||
- Press `F5` to run the project
|
||||
|
||||
## Connect to the bot using Bot Framework Emulator
|
||||
|
||||
- Launch Bot Framework Emulator
|
||||
- File -> Open Bot
|
||||
- Enter a Bot URL of `http://localhost:3978/api/messages`
|
||||
- Try entering several utterances related to home automation, weather or some chit chat. Some examples:
|
||||
- set lights to bright
|
||||
- good morning
|
||||
- how is the weather in seattle
|
||||
|
||||
## Further reading
|
||||
- [Dispatch Migration Example](https://github.com/microsoft/botframework-sdk/blob/main/Orchestrator/docs/DispatchMigrationExample.md)
|
||||
- [Bot Framework Documentation](https://docs.botframework.com)
|
||||
- [BF Orchestrator Command Usage](https://github.com/microsoft/botframework-sdk/blob/main/Orchestrator/docs/BFOrchestratorUsage.md)
|
||||
- [Bot Basics](https://docs.microsoft.com/azure/bot-service/bot-builder-basics?view=azure-bot-service-4.0)
|
||||
- [Activity processing](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-concept-activity-processing?view=azure-bot-service-4.0)
|
||||
- [Azure Bot Service Introduction](https://docs.microsoft.com/azure/bot-service/bot-service-overview-introduction?view=azure-bot-service-4.0)
|
||||
- [Azure Bot Service Documentation](https://docs.microsoft.com/azure/bot-service/?view=azure-bot-service-4.0)
|
||||
- [.NET Core CLI tools](https://docs.microsoft.com/en-us/dotnet/core/tools/?tabs=netcore2x)
|
||||
- [Azure CLI](https://docs.microsoft.com/cli/azure/?view=azure-cli-latest)
|
||||
- [Azure Portal](https://portal.azure.com)
|
||||
- [Channels and Bot Connector Service](https://docs.microsoft.com/en-us/azure/bot-service/bot-concepts?view=azure-bot-service-4.0)
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.IO;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.AI.Orchestrator;
|
||||
using Microsoft.Bot.Builder.Integration.AspNet.Core;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
public Startup(IConfiguration configuration)
|
||||
{
|
||||
OrchestratorConfig = configuration.GetSection("Orchestrator").Get<OrchestratorConfig>();
|
||||
}
|
||||
|
||||
public OrchestratorConfig OrchestratorConfig { get; }
|
||||
|
||||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Latest);
|
||||
|
||||
// Create the Bot Framework Adapter with error handling enabled.
|
||||
services.AddSingleton<IBotFrameworkHttpAdapter, AdapterWithErrorHandler>();
|
||||
|
||||
services.AddSingleton<OrchestratorRecognizer>(InitializeOrchestrator());
|
||||
|
||||
// Create the bot services (LUIS, QnA) as a singleton.
|
||||
services.AddSingleton<IBotServices, BotServices>();
|
||||
|
||||
// Create the bot as a transient.
|
||||
services.AddTransient<IBot, DispatchBot>();
|
||||
}
|
||||
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||
{
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
|
||||
app.UseDefaultFiles()
|
||||
.UseStaticFiles()
|
||||
.UseWebSockets()
|
||||
.UseRouting()
|
||||
.UseAuthorization()
|
||||
.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapControllers();
|
||||
});
|
||||
}
|
||||
|
||||
private OrchestratorRecognizer InitializeOrchestrator()
|
||||
{
|
||||
string modelFolder = Path.GetFullPath(OrchestratorConfig.ModelFolder);
|
||||
string snapshotFile = Path.GetFullPath(OrchestratorConfig.SnapshotFile);
|
||||
OrchestratorRecognizer orc = new OrchestratorRecognizer()
|
||||
{
|
||||
ModelFolder = modelFolder,
|
||||
SnapshotFile = snapshotFile
|
||||
};
|
||||
return orc;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"MicrosoftAppId": "",
|
||||
"MicrosoftAppPassword": "",
|
||||
|
||||
"QnAKnowledgebaseId": "",
|
||||
"QnAEndpointKey": "",
|
||||
"QnAEndpointHostName": "",
|
||||
|
||||
"LuisHomeAutomationAppId": "",
|
||||
"LuisWeatherAppId": "",
|
||||
"LuisAPIKey": "",
|
||||
"LuisAPIHostName": "",
|
||||
|
||||
"AllowedHosts": "*",
|
||||
|
||||
"Orchestrator": {
|
||||
"ModelFolder": ".\\model",
|
||||
"SnapshotFile": ".\\generated\\orchestrator.blu"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Platforms>x64</Platforms>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Content Remove="orchestrator.json" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="generated\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Bot.Builder.AI.Luis" Version="4.14.0" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder.AI.Orchestrator" Version="4.14.0" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder.AI.QnA" Version="4.14.0" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder.Integration.AspNet.Core" Version="4.14.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Update="appsettings.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="model\*">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="**\*.lu">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="**\*.dialog">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="**\*.lg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1,417 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Dispatch bot sample with Orchestrator</title>
|
||||
<style>
|
||||
body {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
font-family: Segoe UI;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
header {
|
||||
background-image: url("data:image/svg+xml,%3Csvg version='1.1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 4638.9 651.6' style='enable-background:new 0 0 4638.9 651.6;' xml:space='preserve'%3E%3Cstyle type='text/css'%3E .st0%7Bfill:%2355A0E0;%7D .st1%7Bfill:none;%7D .st2%7Bfill:%230058A8;%7D .st3%7Bfill:%23328BD8;%7D .st4%7Bfill:%23B6DCF1;%7D .st5%7Bopacity:0.2;fill:url(%23SVGID_1_);enable-background:new ;%7D%0A%3C/style%3E%3Crect y='1.1' class='st0' width='4640' height='646.3'/%3E%3Cpath class='st1' d='M3987.8,323.6L4310.3,1.1h-65.6l-460.1,460.1c-17.5,17.5-46.1,17.5-63.6,0L3260.9,1.1H0v646.3h3660.3 L3889,418.7c17.5-17.5,46.1-17.5,63.6,0l228.7,228.7h66.6l-260.2-260.2C3970.3,369.8,3970.3,341.1,3987.8,323.6z'/%3E%3Cpath class='st2' d='M3784.6,461.2L4244.7,1.1h-983.9l460.1,460.1C3738.4,478.7,3767.1,478.7,3784.6,461.2z'/%3E%3Cpath class='st3' d='M4640,1.1h-329.8l-322.5,322.5c-17.5,17.5-17.5,46.1,0,63.6l260.2,260.2H4640L4640,1.1L4640,1.1z'/%3E%3Cpath class='st4' d='M3889,418.8l-228.7,228.7h521.1l-228.7-228.7C3935.2,401.3,3906.5,401.3,3889,418.8z'/%3E%3ClinearGradient id='SVGID_1_' gradientUnits='userSpaceOnUse' x1='3713.7576' y1='438.1175' x2='3911.4084' y2='14.2535' gradientTransform='matrix(1 0 0 -1 0 641.3969)'%3E%3Cstop offset='0' style='stop-color:%23FFFFFF;stop-opacity:0.5'/%3E%3Cstop offset='1' style='stop-color:%23FFFFFF'/%3E%3C/linearGradient%3E%3Cpath class='st5' d='M3952.7,124.5c-17.5-17.5-46.1-17.5-63.6,0l-523,523h1109.6L3952.7,124.5z'/%3E%3C/svg%3E%0A");
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100%;
|
||||
background-position: right;
|
||||
background-color: #55A0E0;
|
||||
width: 100%;
|
||||
font-size: 44px;
|
||||
height: 120px;
|
||||
color: white;
|
||||
padding: 30px 0 40px 0px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.header-icon {
|
||||
background-image: url("data:image/svg+xml;utf8,%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20xmlns%3Axlink%3D%22http%3A//www.w3.org/1999/xlink%22%20x%3D%220px%22%20y%3D%220px%22%0A%09%20viewBox%3D%220%200%20150.2%20125%22%20style%3D%22enable-background%3Anew%200%200%20150.2%20125%3B%22%20xml%3Aspace%3D%22preserve%22%3E%0A%3Cstyle%20type%3D%22text/css%22%3E%0A%09.st0%7Bfill%3Anone%3B%7D%0A%09.st1%7Bfill%3A%23FFFFFF%3B%7D%0A%3C/style%3E%0A%3Crect%20x%3D%220.5%22%20class%3D%22st0%22%20width%3D%22149.7%22%20height%3D%22125%22/%3E%0A%3Cg%3E%0A%09%3Cpath%20class%3D%22st1%22%20d%3D%22M59%2C102.9L21.8%2C66c-3.5-3.5-3.5-9.1%2C0-12.5l37-36.5l2.9%2C3l-37%2C36.4c-1.8%2C1.8-1.8%2C4.7%2C0%2C6.6l37.2%2C37L59%2C102.9z%22%0A%09%09/%3E%0A%3C/g%3E%0A%3Cg%3E%0A%09%3Cpath%20class%3D%22st1%22%20d%3D%22M92.5%2C102.9l-3-3l37.2-37c0.9-0.9%2C1.4-2%2C1.4-3.3c0-1.2-0.5-2.4-1.4-3.3L89.5%2C20l2.9-3l37.2%2C36.4%0A%09%09c1.7%2C1.7%2C2.6%2C3.9%2C2.6%2C6.3s-0.9%2C4.6-2.6%2C6.3L92.5%2C102.9z%22/%3E%0A%3C/g%3E%0A%3Cg%3E%0A%09%3Cpath%20class%3D%22st1%22%20d%3D%22M90.1%2C68.4c-4.5%2C0-8-3.5-8-8.1c0-4.5%2C3.5-8.1%2C8-8.1c4.4%2C0%2C8%2C3.7%2C8%2C8.1C98.1%2C64.7%2C94.4%2C68.4%2C90.1%2C68.4z%0A%09%09%20M90.1%2C56.5c-2.2%2C0-3.8%2C1.7-3.8%2C3.9c0%2C2.2%2C1.7%2C3.9%2C3.8%2C3.9c1.9%2C0%2C3.8-1.6%2C3.8-3.9S91.9%2C56.5%2C90.1%2C56.5z%22/%3E%0A%3C/g%3E%0A%3Cg%3E%0A%09%3Cpath%20class%3D%22st1%22%20d%3D%22M61.4%2C68.4c-4.5%2C0-8-3.5-8-8.1c0-4.5%2C3.5-8.1%2C8-8.1c4.4%2C0%2C8%2C3.7%2C8%2C8.1C69.5%2C64.7%2C65.8%2C68.4%2C61.4%2C68.4z%0A%09%09%20M61.4%2C56.5c-2.2%2C0-3.8%2C1.7-3.8%2C3.9c0%2C2.2%2C1.7%2C3.9%2C3.8%2C3.9c1.9%2C0%2C3.8-1.6%2C3.8-3.9S63.3%2C56.5%2C61.4%2C56.5z%22/%3E%0A%3C/g%3E%0A%3C/svg%3E%0A");
|
||||
background-repeat: no-repeat;
|
||||
float: left;
|
||||
height: 140px;
|
||||
width: 140px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.header-text {
|
||||
padding-left: 1%;
|
||||
color: #FFFFFF;
|
||||
font-family: "Segoe UI";
|
||||
font-size: 72px;
|
||||
font-weight: 300;
|
||||
letter-spacing: 0.35px;
|
||||
line-height: 96px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.header-inner-container {
|
||||
min-width: 480px;
|
||||
max-width: 1366px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.header-inner-container::after {
|
||||
content: "";
|
||||
clear: both;
|
||||
display: table;
|
||||
}
|
||||
|
||||
.main-content-area {
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
.content-title {
|
||||
color: #000000;
|
||||
font-family: "Segoe UI";
|
||||
font-size: 46px;
|
||||
font-weight: 300;
|
||||
line-height: 62px;
|
||||
}
|
||||
|
||||
.main-text {
|
||||
color: #808080;
|
||||
font-size: 24px;
|
||||
font-family: "Segoe UI";
|
||||
font-size: 24px;
|
||||
font-weight: 200;
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
.main-text-p1{
|
||||
padding-top: 48px;
|
||||
padding-bottom: 28px;
|
||||
}
|
||||
|
||||
.endpoint {
|
||||
height: 32px;
|
||||
width: 571px;
|
||||
color: #808080;
|
||||
font-family: "Segoe UI";
|
||||
font-size: 24px;
|
||||
font-weight: 200;
|
||||
line-height: 32px;
|
||||
padding-top: 28px;
|
||||
}
|
||||
|
||||
.how-to-build-section {
|
||||
padding-top: 20px;
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
.how-to-build-section>h3 {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.35px;
|
||||
line-height: 22px;
|
||||
margin: 0 0 24px 0;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.step-container {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.step-container dl {
|
||||
border-left: 1px solid #A0A0A0;
|
||||
display: block;
|
||||
padding: 0 24px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.step-container dl>dt::before {
|
||||
background-color: white;
|
||||
border: 1px solid #A0A0A0;
|
||||
border-radius: 100%;
|
||||
content: '';
|
||||
left: 47px;
|
||||
height: 11px;
|
||||
position: absolute;
|
||||
width: 11px;
|
||||
}
|
||||
|
||||
.step-container dl>.test-bullet::before {
|
||||
background-color: blue;
|
||||
}
|
||||
|
||||
.step-container dl>dt {
|
||||
display: block;
|
||||
font-size: inherit;
|
||||
font-weight: bold;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.step-container dl>dd {
|
||||
font-size: inherit;
|
||||
line-height: 20px;
|
||||
margin-left: 0;
|
||||
padding-bottom: 32px;
|
||||
}
|
||||
|
||||
.step-container:last-child dl {
|
||||
border-left: 1px solid transparent;
|
||||
}
|
||||
|
||||
.ctaLink {
|
||||
background-color: transparent;
|
||||
border: 1px solid transparent;
|
||||
color: #006AB1;
|
||||
cursor: pointer;
|
||||
font-weight: 600;
|
||||
padding: 0;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.ctaLink:focus {
|
||||
outline: 1px solid #00bcf2;
|
||||
}
|
||||
|
||||
.ctaLink:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.step-icon {
|
||||
display: flex;
|
||||
height: 38px;
|
||||
margin-right: 15px;
|
||||
width: 38px;
|
||||
}
|
||||
|
||||
.step-icon>div {
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.ms-logo-container {
|
||||
min-width: 580px;
|
||||
max-width: 980px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
left: 0;
|
||||
right: 0;
|
||||
transition: bottom 400ms;
|
||||
}
|
||||
|
||||
.ms-logo {
|
||||
float: right;
|
||||
background-image: url("data:image/svg+xml;utf8,%0A%3Csvg%20version%3D%221.1%22%20id%3D%22MS-symbol%22%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20xmlns%3Axlink%3D%22http%3A//www.w3.org/1999/xlink%22%20x%3D%220px%22%20y%3D%220px%22%0A%09%20viewBox%3D%220%200%20400%20120%22%20style%3D%22enable-background%3Anew%200%200%20400%20120%3B%22%20xml%3Aspace%3D%22preserve%22%3E%0A%3Cstyle%20type%3D%22text/css%22%3E%0A%09.st0%7Bfill%3Anone%3B%7D%0A%09.st1%7Bfill%3A%23737474%3B%7D%0A%09.st2%7Bfill%3A%23D63F26%3B%7D%0A%09.st3%7Bfill%3A%23167D3E%3B%7D%0A%09.st4%7Bfill%3A%232E76BC%3B%7D%0A%09.st5%7Bfill%3A%23FDB813%3B%7D%0A%3C/style%3E%0A%3Crect%20x%3D%220.6%22%20class%3D%22st0%22%20width%3D%22398.7%22%20height%3D%22119%22/%3E%0A%3Cpath%20class%3D%22st1%22%20d%3D%22M171.3%2C38.4v43.2h-7.5V47.7h-0.1l-13.4%2C33.9h-5l-13.7-33.9h-0.1v33.9h-6.9V38.4h10.8l12.4%2C32h0.2l13.1-32H171.3%0A%09z%20M177.6%2C41.7c0-1.2%2C0.4-2.2%2C1.3-3c0.9-0.8%2C1.9-1.2%2C3.1-1.2c1.3%2C0%2C2.4%2C0.4%2C3.2%2C1.3c0.8%2C0.8%2C1.3%2C1.8%2C1.3%2C3c0%2C1.2-0.4%2C2.2-1.3%2C3%0A%09c-0.9%2C0.8-1.9%2C1.2-3.2%2C1.2s-2.3-0.4-3.1-1.2C178%2C43.8%2C177.6%2C42.8%2C177.6%2C41.7z%20M185.7%2C50.6v31h-7.3v-31H185.7z%20M207.8%2C76.3%0A%09c1.1%2C0%2C2.3-0.3%2C3.6-0.8c1.3-0.5%2C2.5-1.2%2C3.6-2v6.8c-1.2%2C0.7-2.5%2C1.2-4%2C1.5c-1.5%2C0.3-3.1%2C0.5-4.9%2C0.5c-4.6%2C0-8.3-1.4-11.1-4.3%0A%09c-2.9-2.9-4.3-6.6-4.3-11c0-5%2C1.5-9.1%2C4.4-12.3c2.9-3.2%2C7-4.8%2C12.4-4.8c1.4%2C0%2C2.7%2C0.2%2C4.1%2C0.5c1.4%2C0.4%2C2.5%2C0.8%2C3.3%2C1.2v7%0A%09c-1.1-0.8-2.3-1.5-3.4-1.9c-1.2-0.5-2.4-0.7-3.6-0.7c-2.9%2C0-5.2%2C0.9-7%2C2.8c-1.8%2C1.9-2.7%2C4.4-2.7%2C7.6c0%2C3.1%2C0.8%2C5.6%2C2.5%2C7.3%0A%09C202.6%2C75.4%2C204.9%2C76.3%2C207.8%2C76.3z%20M235.7%2C50.1c0.6%2C0%2C1.1%2C0%2C1.6%2C0.1s0.9%2C0.2%2C1.2%2C0.3v7.4c-0.4-0.3-0.9-0.5-1.7-0.8%0A%09c-0.7-0.3-1.6-0.4-2.7-0.4c-1.8%2C0-3.3%2C0.8-4.5%2C2.3c-1.2%2C1.5-1.9%2C3.8-1.9%2C7v15.6h-7.3v-31h7.3v4.9h0.1c0.7-1.7%2C1.7-3%2C3-4%0A%09C232.2%2C50.6%2C233.8%2C50.1%2C235.7%2C50.1z%20M238.9%2C66.6c0-5.1%2C1.4-9.2%2C4.3-12.2c2.9-3%2C6.9-4.5%2C12.1-4.5c4.8%2C0%2C8.6%2C1.4%2C11.3%2C4.3%0A%09c2.7%2C2.9%2C4.1%2C6.8%2C4.1%2C11.7c0%2C5-1.4%2C9-4.3%2C12c-2.9%2C3-6.8%2C4.5-11.8%2C4.5c-4.8%2C0-8.6-1.4-11.4-4.2C240.3%2C75.3%2C238.9%2C71.4%2C238.9%2C66.6z%0A%09%20M246.5%2C66.3c0%2C3.2%2C0.7%2C5.7%2C2.2%2C7.4c1.5%2C1.7%2C3.6%2C2.6%2C6.3%2C2.6c2.7%2C0%2C4.7-0.9%2C6.1-2.6c1.4-1.7%2C2.1-4.2%2C2.1-7.6c0-3.3-0.7-5.8-2.2-7.5%0A%09c-1.4-1.7-3.4-2.5-6-2.5c-2.7%2C0-4.7%2C0.9-6.2%2C2.7C247.2%2C60.5%2C246.5%2C63%2C246.5%2C66.3z%20M281.5%2C58.8c0%2C1%2C0.3%2C1.9%2C1%2C2.5%0A%09c0.7%2C0.6%2C2.1%2C1.3%2C4.4%2C2.2c2.9%2C1.2%2C5%2C2.5%2C6.1%2C3.9c1.2%2C1.5%2C1.8%2C3.2%2C1.8%2C5.3c0%2C2.9-1.1%2C5.3-3.4%2C7c-2.2%2C1.8-5.3%2C2.7-9.1%2C2.7%0A%09c-1.3%2C0-2.7-0.2-4.3-0.5c-1.6-0.3-2.9-0.7-4-1.2v-7.2c1.3%2C0.9%2C2.8%2C1.7%2C4.3%2C2.2c1.5%2C0.5%2C2.9%2C0.8%2C4.2%2C0.8c1.6%2C0%2C2.9-0.2%2C3.6-0.7%0A%09c0.8-0.5%2C1.2-1.2%2C1.2-2.3c0-1-0.4-1.9-1.2-2.5c-0.8-0.7-2.4-1.5-4.6-2.4c-2.7-1.1-4.6-2.4-5.7-3.8c-1.1-1.4-1.7-3.2-1.7-5.4%0A%09c0-2.8%2C1.1-5.1%2C3.3-6.9c2.2-1.8%2C5.1-2.7%2C8.6-2.7c1.1%2C0%2C2.3%2C0.1%2C3.6%2C0.4c1.3%2C0.2%2C2.5%2C0.6%2C3.4%2C0.9v6.9c-1-0.6-2.1-1.2-3.4-1.7%0A%09c-1.3-0.5-2.6-0.7-3.8-0.7c-1.4%2C0-2.5%2C0.3-3.2%2C0.8C281.9%2C57.1%2C281.5%2C57.8%2C281.5%2C58.8z%20M297.9%2C66.6c0-5.1%2C1.4-9.2%2C4.3-12.2%0A%09c2.9-3%2C6.9-4.5%2C12.1-4.5c4.8%2C0%2C8.6%2C1.4%2C11.3%2C4.3c2.7%2C2.9%2C4.1%2C6.8%2C4.1%2C11.7c0%2C5-1.4%2C9-4.3%2C12c-2.9%2C3-6.8%2C4.5-11.8%2C4.5%0A%09c-4.8%2C0-8.6-1.4-11.4-4.2C299.4%2C75.3%2C297.9%2C71.4%2C297.9%2C66.6z%20M305.5%2C66.3c0%2C3.2%2C0.7%2C5.7%2C2.2%2C7.4c1.5%2C1.7%2C3.6%2C2.6%2C6.3%2C2.6%0A%09c2.7%2C0%2C4.7-0.9%2C6.1-2.6c1.4-1.7%2C2.1-4.2%2C2.1-7.6c0-3.3-0.7-5.8-2.2-7.5c-1.4-1.7-3.4-2.5-6-2.5c-2.7%2C0-4.7%2C0.9-6.2%2C2.7%0A%09C306.3%2C60.5%2C305.5%2C63%2C305.5%2C66.3z%20M353.9%2C56.6h-10.9v25h-7.4v-25h-5.2v-6h5.2v-4.3c0-3.3%2C1.1-5.9%2C3.2-8c2.1-2.1%2C4.8-3.1%2C8.1-3.1%0A%09c0.9%2C0%2C1.7%2C0%2C2.4%2C0.1c0.7%2C0.1%2C1.3%2C0.2%2C1.8%2C0.4V42c-0.2-0.1-0.7-0.3-1.3-0.5c-0.6-0.2-1.3-0.3-2.1-0.3c-1.5%2C0-2.7%2C0.5-3.5%2C1.4%0A%09s-1.2%2C2.4-1.2%2C4.2v3.7h10.9v-7l7.3-2.2v9.2h7.4v6h-7.4v14.5c0%2C1.9%2C0.3%2C3.3%2C1%2C4c0.7%2C0.8%2C1.8%2C1.2%2C3.3%2C1.2c0.4%2C0%2C0.9-0.1%2C1.5-0.3%0A%09c0.6-0.2%2C1.1-0.4%2C1.6-0.7v6c-0.5%2C0.3-1.2%2C0.5-2.3%2C0.7c-1.1%2C0.2-2.1%2C0.3-3.2%2C0.3c-3.1%2C0-5.4-0.8-6.9-2.5c-1.5-1.6-2.3-4.1-2.3-7.4%0A%09V56.6z%22/%3E%0A%3Cg%3E%0A%09%3Crect%20x%3D%2231%22%20y%3D%2224%22%20class%3D%22st2%22%20width%3D%2234.2%22%20height%3D%2234.2%22/%3E%0A%09%3Crect%20x%3D%2268.8%22%20y%3D%2224%22%20class%3D%22st3%22%20width%3D%2234.2%22%20height%3D%2234.2%22/%3E%0A%09%3Crect%20x%3D%2231%22%20y%3D%2261.8%22%20class%3D%22st4%22%20width%3D%2234.2%22%20height%3D%2234.2%22/%3E%0A%09%3Crect%20x%3D%2268.8%22%20y%3D%2261.8%22%20class%3D%22st5%22%20width%3D%2234.2%22%20height%3D%2234.2%22/%3E%0A%3C/g%3E%0A%3C/svg%3E%0A");
|
||||
}
|
||||
|
||||
.ms-logo-container>div {
|
||||
min-height: 60px;
|
||||
width: 150px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.row {
|
||||
padding: 90px 0px 0 20px;
|
||||
min-width: 480px;
|
||||
max-width: 1366px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.column {
|
||||
float: left;
|
||||
width: 45%;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
.row:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.download-the-emulator {
|
||||
height: 20px;
|
||||
color: #0063B1;
|
||||
font-size: 15px;
|
||||
line-height: 20px;
|
||||
padding-bottom: 70px;
|
||||
}
|
||||
|
||||
.how-to-iframe {
|
||||
max-width: 700px !important;
|
||||
min-width: 650px !important;
|
||||
height: 700px !important;
|
||||
}
|
||||
|
||||
.remove-frame-height {
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1300px) {
|
||||
.ms-logo {
|
||||
padding-top: 30px;
|
||||
}
|
||||
|
||||
.header-text {
|
||||
font-size: 40x;
|
||||
}
|
||||
|
||||
.column {
|
||||
float: none;
|
||||
padding-top: 30px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ms-logo-container {
|
||||
padding-top: 30px;
|
||||
min-width: 480px;
|
||||
max-width: 650px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.row {
|
||||
padding: 20px 0px 0 20px;
|
||||
min-width: 480px;
|
||||
max-width: 650px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1370px) {
|
||||
header {
|
||||
background-color: #55A0E0;
|
||||
background-size: auto 200px;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1230px) {
|
||||
header {
|
||||
background-color: #55A0E0;
|
||||
background-size: auto 200px;
|
||||
}
|
||||
|
||||
.header-text {
|
||||
font-size: 44px;
|
||||
}
|
||||
|
||||
.header-icon {
|
||||
height: 120px;
|
||||
width: 120px;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1000px) {
|
||||
header {
|
||||
background-color: #55A0E0;
|
||||
background-image: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 632px) {
|
||||
.header-text {
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
.row {
|
||||
padding: 10px 0px 0 10px;
|
||||
max-width: 490px !important;
|
||||
min-width: 410px !important;
|
||||
}
|
||||
|
||||
.endpoint {
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
.main-text {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.step-container dl>dd {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.column {
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.header-icon {
|
||||
height: 110px;
|
||||
width: 110px;
|
||||
}
|
||||
|
||||
.how-to-iframe {
|
||||
max-width: 480px !important;
|
||||
min-width: 400px !important;
|
||||
height: 650px !important;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.remove-frame-height {
|
||||
max-height: 10px;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
loadFrame();
|
||||
});
|
||||
var loadFrame = function () {
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.setAttribute("id", "iframe");
|
||||
var offLineHTMLContent = "";
|
||||
var frameElement = document.getElementById("how-to-iframe");
|
||||
if (window.navigator.onLine) {
|
||||
iframe.src = 'https://docs.botframework.com/static/abs/pages/f5.htm';
|
||||
iframe.setAttribute("scrolling", "no");
|
||||
iframe.setAttribute("frameborder", "0");
|
||||
iframe.setAttribute("width", "100%");
|
||||
iframe.setAttribute("height", "100%");
|
||||
var frameDiv = document.getElementById("how-to-iframe");
|
||||
frameDiv.appendChild(iframe);
|
||||
} else {
|
||||
frameElement.classList.add("remove-frame-height");
|
||||
}
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header class="header">
|
||||
<div class="header-inner-container">
|
||||
<div class="header-icon" style="display: inline-block"></div>
|
||||
<div class="header-text" style="display: inline-block">NLP With Dispatch Sample</div>
|
||||
</div>
|
||||
</header>
|
||||
<div class="row">
|
||||
<div class="column" class="main-content-area">
|
||||
<div class="content-title">Your bot is ready!</div>
|
||||
<div class="main-text main-text-p1">You can test your bot in the Bot Framework Emulator<br />
|
||||
by connecting to http://localhost:3978/api/messages.</div>
|
||||
<div class="main-text download-the-emulator"><a class="ctaLink" href="https://aka.ms/bot-framework-F5-download-emulator"
|
||||
target="_blank">Download the Emulator</a></div>
|
||||
<div class="main-text">Visit <a class="ctaLink" href="https://aka.ms/bot-framework-F5-abs-home" target="_blank">Azure
|
||||
Bot Service</a> to register your bot and add it to<br />
|
||||
various channels. The bot's endpoint URL typically looks
|
||||
like this:</div>
|
||||
<div class="endpoint">https://<i>your_bots_hostname</i>/api/messages</div>
|
||||
</div>
|
||||
<div class="column how-to-iframe" id="how-to-iframe"></div>
|
||||
</div>
|
||||
<div class="ms-logo-container">
|
||||
<div class="ms-logo"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
Загрузка…
Ссылка в новой задаче