Add Orchestrator dispatch sample (simple with skill, qna, luis) (#6275)
* orchestrator docs pointers * update orchestrator readme * left NLR readme shell to be filled in * bf orchestrator cli usage * fixed TBD * fix merge * added examples * more orchestrator docs * rm white space * CR comments * one more CR item * one more * moved perf table to nlrmodels * added license term to models in docs * reference to license for models * updated api ref * with ptr to composer preview doc * fixed link... * fixed link... * added tech references * re-added ref to composer steps * doc: LU processing in Orchestrator * Orchestrator intro pptx * updates to orchestrator readme * revert to main * OrchestratorDispatch sample * fix condition * fix condition 2
This commit is contained in:
Родитель
2dac7be647
Коммит
bc115918ee
|
@ -0,0 +1,2 @@
|
||||||
|
# prevent appsettings.json get checked in
|
||||||
|
**/appsettings.json
|
|
@ -0,0 +1,27 @@
|
||||||
|
# Welcome to your new bot
|
||||||
|
|
||||||
|
This Bot Project was created using the Empty Bot template, and contains a minimal set of files necessary to have a working bot.
|
||||||
|
|
||||||
|
## Next steps
|
||||||
|
|
||||||
|
### Start building your bot
|
||||||
|
|
||||||
|
Composer can help guide you through getting started building your bot. From your bot settings page (the wrench icon on the left navigation rail), click on the rocket-ship icon on the top right for some quick navigation links.
|
||||||
|
|
||||||
|
Another great resource if you're just getting started is the **[guided tutorial](https://docs.microsoft.com/en-us/composer/tutorial/tutorial-introduction)** in our documentation.
|
||||||
|
|
||||||
|
### Connect with your users
|
||||||
|
|
||||||
|
Your bot comes pre-configured to connect to our Web Chat and DirectLine channels, but there are many more places you can connect your bot to - including Microsoft Teams, Telephony, DirectLine Speech, Slack, Facebook, Outlook and more. Check out all of the places you can connect to on the bot settings page.
|
||||||
|
|
||||||
|
### Publish your bot to Azure from Composer
|
||||||
|
|
||||||
|
Composer can help you provision the Azure resources necessary for your bot, and publish your bot to them. To get started, create a publishing profile from your bot settings page in Composer (the wrench icon on the left navigation rail). Make sure you only provision the optional Azure resources you need!
|
||||||
|
|
||||||
|
### Extend your bot with packages
|
||||||
|
|
||||||
|
From Package Manager in Composer you can find useful packages to help add additional pre-built functionality you can add to your bot - everything from simple dialogs & custom actions for working with specific scenarios to custom adapters for connecting your bot to users on clients like Facebook or Slack.
|
||||||
|
|
||||||
|
### Extend your bot with code
|
||||||
|
|
||||||
|
You can also extend your bot with code - simply open up the folder that was generated for you in the location you chose during the creation process with your favorite IDE (like Visual Studio). You can do things like create custom actions that can be used during dialog flows, create custom middleware to pre-process (or post-process) messages, and more. See [our documentation](https://aka.ms/bf-extend-with-code) for more information.
|
|
@ -0,0 +1,76 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Bot.Builder;
|
||||||
|
using Microsoft.Bot.Builder.Dialogs.Adaptive.Runtime.Settings;
|
||||||
|
using Microsoft.Bot.Builder.Integration.AspNet.Core;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace OrchestratorDispatch.Controllers
|
||||||
|
{
|
||||||
|
// This ASP Controller is created to handle a request. Dependency Injection will provide the Adapter and IBot
|
||||||
|
// implementation at runtime. Multiple different IBot implementations running at different endpoints can be
|
||||||
|
// achieved by specifying a more specific type for the bot constructor argument.
|
||||||
|
[ApiController]
|
||||||
|
public class BotController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly Dictionary<string, IBotFrameworkHttpAdapter> _adapters = new Dictionary<string, IBotFrameworkHttpAdapter>();
|
||||||
|
private readonly IBot _bot;
|
||||||
|
private readonly ILogger<BotController> _logger;
|
||||||
|
|
||||||
|
public BotController(
|
||||||
|
IConfiguration configuration,
|
||||||
|
IEnumerable<IBotFrameworkHttpAdapter> adapters,
|
||||||
|
IBot bot,
|
||||||
|
ILogger<BotController> logger)
|
||||||
|
{
|
||||||
|
_bot = bot ?? throw new ArgumentNullException(nameof(bot));
|
||||||
|
_logger = logger;
|
||||||
|
|
||||||
|
var adapterSettings = configuration.GetSection(AdapterSettings.AdapterSettingsKey).Get<List<AdapterSettings>>() ?? new List<AdapterSettings>();
|
||||||
|
adapterSettings.Add(AdapterSettings.CoreBotAdapterSettings);
|
||||||
|
|
||||||
|
foreach (var adapter in adapters ?? throw new ArgumentNullException(nameof(adapters)))
|
||||||
|
{
|
||||||
|
var settings = adapterSettings.FirstOrDefault(s => s.Enabled && s.Type == adapter.GetType().FullName);
|
||||||
|
|
||||||
|
if (settings != null)
|
||||||
|
{
|
||||||
|
_adapters.Add(settings.Route, adapter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
[HttpGet]
|
||||||
|
[Route("api/{route}")]
|
||||||
|
public async Task PostAsync(string route)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(route))
|
||||||
|
{
|
||||||
|
_logger.LogError($"PostAsync: No route provided.");
|
||||||
|
throw new ArgumentNullException(nameof(route));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_adapters.TryGetValue(route, out IBotFrameworkHttpAdapter adapter))
|
||||||
|
{
|
||||||
|
if (_logger.IsEnabled(LogLevel.Debug))
|
||||||
|
{
|
||||||
|
_logger.LogInformation($"PostAsync: routed '{route}' to {adapter.GetType().Name}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delegate the processing of the HTTP POST to the appropriate adapter.
|
||||||
|
// The adapter will invoke the bot.
|
||||||
|
await adapter.ProcessAsync(Request, Response, _bot).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogError($"PostAsync: No adapter registered and enabled for route {route}.");
|
||||||
|
throw new KeyNotFoundException($"No adapter registered and enabled for route {route}.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Bot.Builder;
|
||||||
|
using Microsoft.Bot.Builder.Integration.AspNet.Core;
|
||||||
|
using Microsoft.Bot.Schema;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace OrchestratorDispatch.Controllers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A controller that handles skill replies to the bot.
|
||||||
|
/// </summary>
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/skills")]
|
||||||
|
public class SkillController : ChannelServiceController
|
||||||
|
{
|
||||||
|
private readonly ILogger<SkillController> _logger;
|
||||||
|
|
||||||
|
public SkillController(ChannelServiceHandlerBase handler, ILogger<SkillController> logger)
|
||||||
|
: base(handler)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task<IActionResult> ReplyToActivityAsync(string conversationId, string activityId, Activity activity)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_logger.IsEnabled(LogLevel.Debug))
|
||||||
|
{
|
||||||
|
_logger.LogDebug($"ReplyToActivityAsync: conversationId={conversationId}, activityId={activityId}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.ReplyToActivityAsync(conversationId, activityId, activity);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, $"ReplyToActivityAsync: {ex}");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task<IActionResult> SendToConversationAsync(string conversationId, Activity activity)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_logger.IsEnabled(LogLevel.Debug))
|
||||||
|
{
|
||||||
|
_logger.LogDebug($"SendToConversationAsync: conversationId={conversationId}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.SendToConversationAsync(conversationId, activity);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, $"SendToConversationAsync: {ex}");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
<packageSources>
|
||||||
|
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
|
||||||
|
<add key="BotBuilder.myget.org" value="https://botbuilder.myget.org/F/botbuilder-v4-dotnet-daily/api/v3/index.json" protocolVersion="3" />
|
||||||
|
</packageSources>
|
||||||
|
</configuration>
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://raw.githubusercontent.com/microsoft/BotFramework-Composer/main/Composer/packages/server/schemas/botproject.schema",
|
||||||
|
"name": "OrchestratorDispatch",
|
||||||
|
"skills": {
|
||||||
|
"theSkill": {
|
||||||
|
"manifest": "https://theskill.azurewebsites.net/manifests/TheSkill-2-1-manifest.json",
|
||||||
|
"remote": true,
|
||||||
|
"endpointName": "Prod"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
|
<AspNetCoreHostingModel>OutOfProcess</AspNetCoreHostingModel>
|
||||||
|
<UserSecretsId>f24230a7-de92-41e1-a10c-5c5f4b350bb4</UserSecretsId>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="**/*.blu;**/*.dialog;**/*.lg;**/*.lu;**/*.onnx;**/*.qna;**/*.txt" Exclude="$(BaseOutputPath)/**;$(BaseIntermediateOutputPath)/**;wwwroot/**">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.8" />
|
||||||
|
<PackageReference Include="Microsoft.Bot.Builder.AI.Orchestrator" Version="4.14.0-daily.preview.20210414.235020.dcacf50" />
|
||||||
|
<PackageReference Include="Microsoft.Bot.Builder.Dialogs.Adaptive.Runtime" Version="4.13.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
|
@ -0,0 +1,277 @@
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.AdaptiveDialog",
|
||||||
|
"$designer": {
|
||||||
|
"name": "OrchestratorDispatch",
|
||||||
|
"description": "",
|
||||||
|
"id": "A79tBe"
|
||||||
|
},
|
||||||
|
"autoEndDialog": true,
|
||||||
|
"defaultResultProperty": "dialog.result",
|
||||||
|
"triggers": [
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.OnConversationUpdateActivity",
|
||||||
|
"$designer": {
|
||||||
|
"id": "376720"
|
||||||
|
},
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.Foreach",
|
||||||
|
"$designer": {
|
||||||
|
"id": "518944",
|
||||||
|
"name": "Loop: for each item"
|
||||||
|
},
|
||||||
|
"itemsProperty": "turn.Activity.membersAdded",
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.IfCondition",
|
||||||
|
"$designer": {
|
||||||
|
"id": "641773",
|
||||||
|
"name": "Branch: if/else"
|
||||||
|
},
|
||||||
|
"condition": "string(dialog.foreach.value.id) != string(turn.Activity.Recipient.id)",
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.SendActivity",
|
||||||
|
"$designer": {
|
||||||
|
"id": "859266",
|
||||||
|
"name": "Send a response"
|
||||||
|
},
|
||||||
|
"activity": "${SendActivity_Welcome()}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.SendActivity",
|
||||||
|
"$designer": {
|
||||||
|
"id": "7MNTfM"
|
||||||
|
},
|
||||||
|
"activity": "${SendActivity_7MNTfM()}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.TextInput",
|
||||||
|
"$designer": {
|
||||||
|
"id": "sL5okG"
|
||||||
|
},
|
||||||
|
"disabled": false,
|
||||||
|
"maxTurnCount": 30,
|
||||||
|
"alwaysPrompt": true,
|
||||||
|
"allowInterruptions": true,
|
||||||
|
"prompt": "${TextInput_Prompt_sL5okG()}",
|
||||||
|
"unrecognizedPrompt": "",
|
||||||
|
"invalidPrompt": "",
|
||||||
|
"property": "dialog.response"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.SendActivity",
|
||||||
|
"$designer": {
|
||||||
|
"id": "Zy3DnL"
|
||||||
|
},
|
||||||
|
"activity": "${SendActivity_Zy3DnL()}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.OnQnAMatch",
|
||||||
|
"$designer": {
|
||||||
|
"id": "TDfQbW"
|
||||||
|
},
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.SendActivity",
|
||||||
|
"$designer": {
|
||||||
|
"id": "VJYzMf"
|
||||||
|
},
|
||||||
|
"activity": "${SendActivity_VJYzMf()}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.IfCondition",
|
||||||
|
"$designer": {
|
||||||
|
"id": "02rejJ"
|
||||||
|
},
|
||||||
|
"condition": "count(turn.recognized.answers[0].context.prompts) > 0",
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.SetProperty",
|
||||||
|
"$designer": {
|
||||||
|
"id": "CybRJX"
|
||||||
|
},
|
||||||
|
"property": "dialog.qnaContext",
|
||||||
|
"value": "=turn.recognized.answers[0].context.prompts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.TextInput",
|
||||||
|
"$designer": {
|
||||||
|
"id": "PcQgSy"
|
||||||
|
},
|
||||||
|
"maxTurnCount": 3,
|
||||||
|
"alwaysPrompt": true,
|
||||||
|
"allowInterruptions": false,
|
||||||
|
"prompt": "${TextInput_Prompt_HGB0yC()}",
|
||||||
|
"property": "turn.qnaMultiTurnResponse"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.SetProperty",
|
||||||
|
"$designer": {
|
||||||
|
"id": "XyTPCZ"
|
||||||
|
},
|
||||||
|
"property": "turn.qnaMatchFromContext",
|
||||||
|
"value": "=where(dialog.qnaContext, item, item.displayText == turn.qnaMultiTurnResponse)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.DeleteProperty",
|
||||||
|
"$designer": {
|
||||||
|
"id": "dLd5CS"
|
||||||
|
},
|
||||||
|
"property": "dialog.qnaContext"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.IfCondition",
|
||||||
|
"$designer": {
|
||||||
|
"id": "dDQVFz"
|
||||||
|
},
|
||||||
|
"condition": "turn.qnaMatchFromContext && count(turn.qnaMatchFromContext) > 0",
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.SetProperty",
|
||||||
|
"$designer": {
|
||||||
|
"id": "gLHgkE"
|
||||||
|
},
|
||||||
|
"property": "turn.qnaIdFromPrompt",
|
||||||
|
"value": "=turn.qnaMatchFromContext[0].qnaId"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.EmitEvent",
|
||||||
|
"$designer": {
|
||||||
|
"id": "8HeqE7"
|
||||||
|
},
|
||||||
|
"eventName": "activityReceived",
|
||||||
|
"eventValue": "=turn.activity"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"elseActions": [
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.SendActivity",
|
||||||
|
"$designer": {
|
||||||
|
"id": "Fmz0Iy"
|
||||||
|
},
|
||||||
|
"activity": "${SendActivity_ESxCuC()}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.OnIntent",
|
||||||
|
"$designer": {
|
||||||
|
"id": "Uu57gW",
|
||||||
|
"name": "PartnersInfo"
|
||||||
|
},
|
||||||
|
"intent": "PartnersInfo",
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.BeginDialog",
|
||||||
|
"$designer": {
|
||||||
|
"id": "TU9sPg"
|
||||||
|
},
|
||||||
|
"activityProcessed": true,
|
||||||
|
"dialog": "PartnersDialog"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"condition": "turn.recognized.score > 0.7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.OnUnknownIntent",
|
||||||
|
"$designer": {
|
||||||
|
"id": "drtUJk"
|
||||||
|
},
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.SendActivity",
|
||||||
|
"$designer": {
|
||||||
|
"id": "xjrS5L"
|
||||||
|
},
|
||||||
|
"activity": "${SendActivity_xjrS5L()}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.OnIntent",
|
||||||
|
"$designer": {
|
||||||
|
"id": "JYVSpD",
|
||||||
|
"name": "None"
|
||||||
|
},
|
||||||
|
"intent": "None",
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.SendActivity",
|
||||||
|
"$designer": {
|
||||||
|
"id": "v8rqlc"
|
||||||
|
},
|
||||||
|
"activity": "${SendActivity_v8rqlc()}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.OnIntent",
|
||||||
|
"$designer": {
|
||||||
|
"id": "ggt6ci",
|
||||||
|
"name": "exit"
|
||||||
|
},
|
||||||
|
"intent": "exit",
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.SendActivity",
|
||||||
|
"$designer": {
|
||||||
|
"id": "bzZc9B"
|
||||||
|
},
|
||||||
|
"activity": "${SendActivity_bzZc9B()}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.EndDialog",
|
||||||
|
"$designer": {
|
||||||
|
"id": "42pVbi"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"condition": "turn.recognized.score > 0.7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.OnIntent",
|
||||||
|
"$designer": {
|
||||||
|
"id": "4SkTnT",
|
||||||
|
"name": "TheSkill"
|
||||||
|
},
|
||||||
|
"intent": "TheSkill",
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.SendActivity",
|
||||||
|
"$designer": {
|
||||||
|
"id": "EZm3u2"
|
||||||
|
},
|
||||||
|
"activity": "${SendActivity_EZm3u2()}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.BeginSkill",
|
||||||
|
"$designer": {
|
||||||
|
"id": "Gss1qy"
|
||||||
|
},
|
||||||
|
"activityProcessed": true,
|
||||||
|
"botId": "=settings.MicrosoftAppId",
|
||||||
|
"skillHostEndpoint": "=settings.skillHostEndpoint",
|
||||||
|
"connectionName": "=settings.connectionName",
|
||||||
|
"allowInterruptions": true,
|
||||||
|
"skillEndpoint": "=settings.skill['theSkill'].endpointUrl",
|
||||||
|
"skillAppId": "=settings.skill['theSkill'].msAppId"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"condition": "turn.recognized.score > 0.7"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"generator": "OrchestratorDispatch.lg",
|
||||||
|
"id": "OrchestratorDispatch",
|
||||||
|
"recognizer": "OrchestratorDispatch.lu.qna"
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
using System;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.Bot.Builder.Dialogs.Adaptive.Runtime.Extensions;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
|
||||||
|
namespace OrchestratorDispatch
|
||||||
|
{
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
CreateHostBuilder(args).Build().Run();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
||||||
|
Host.CreateDefaultBuilder(args)
|
||||||
|
.ConfigureAppConfiguration((hostingContext, builder) =>
|
||||||
|
{
|
||||||
|
var applicationRoot = AppDomain.CurrentDomain.BaseDirectory;
|
||||||
|
var environmentName = hostingContext.HostingEnvironment.EnvironmentName;
|
||||||
|
var settingsDirectory = "settings";
|
||||||
|
|
||||||
|
builder.AddBotRuntimeConfiguration(applicationRoot, settingsDirectory, environmentName);
|
||||||
|
|
||||||
|
builder.AddCommandLine(args);
|
||||||
|
})
|
||||||
|
.ConfigureWebHostDefaults(webBuilder =>
|
||||||
|
{
|
||||||
|
webBuilder.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"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"BotProject": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"applicationUrl": "http://localhost:3978",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
# Dispatch with Orchestrator Sample
|
||||||
|
|
||||||
|
The following bot demonstrates a simple Bot with Orchestrator as top dispatcher to the following:
|
||||||
|
|
||||||
|
* Remote skill
|
||||||
|
* LUIS dialog
|
||||||
|
* QnAMaker KB
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
The bot depends on external services, namely LUIS, QnAMaker, and the remote skill which is already deployed for demonstration purposes.
|
||||||
|
|
||||||
|
### Steps
|
||||||
|
|
||||||
|
1. Start Composer and load this project.
|
||||||
|
2. Configure LUIS and QnAMaker keys.
|
||||||
|
3. Configure Microsoft App Id & password.
|
||||||
|
4. Get the Orchestrator package in package manager.
|
||||||
|
5. Build/run, note your bot port.
|
||||||
|
6. Setup tunneling to localhost using ngrok (or other technology) using the noted port.
|
||||||
|
7. Specify in Skill Configuration the skill callback URL e.g. https://tunnel-id.ngrok.io/api/skills (assuming ngrok).
|
||||||
|
8. Build/run again
|
||||||
|
9. Test your bot
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Demo Patterns
|
||||||
|
|
||||||
|
You may try the following:
|
||||||
|
|
||||||
|
* Type: "The skill" to invoke and interact with the skill.
|
||||||
|
* Type: "tell me about Composer" or "custom actions" to trigger QnA KB response.
|
||||||
|
* Type: "partners info" to invoke the LUIS dialog, then type "healthbot" to trigger LUIS recognition.
|
||||||
|
|
||||||
|
### Diagram
|
||||||
|
|
||||||
|
![](./media/diagram.png)
|
||||||
|
|
||||||
|
## Other Observations
|
||||||
|
|
||||||
|
### Parent/Skill Intent Collisions
|
||||||
|
|
||||||
|
When calling *TheSkill*'s "Aks a question" you will be interacting with the skill's LUIS recognizer via the parent bot. In this case, there can be intent recognition "collision" where if the intent is also detected by the parent, it'll take over the conversation. Thus, since in this case both parent and skill have same triggers, collisions will happen and the conversation will be interrupted by the parent.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
* *skills*: parent to invoke the skill; the skill about skill info
|
||||||
|
* *composer*: info about composer in parent via QnAMaker; in skill via LUIS dialog
|
||||||
|
* *exit*: both parent and skill implement a trigger for exit. Parent will override skill's trigger.
|
||||||
|
* *contact*: will only be recognized by skill. To prevent low score detection at parent, an intent condition of > 0.7 was specified.
|
|
@ -0,0 +1,355 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
|
||||||
|
"contentVersion": "1.0.0.0",
|
||||||
|
"parameters": {
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "[resourceGroup().name]"
|
||||||
|
},
|
||||||
|
"appId": {
|
||||||
|
"type": "string",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Active Directory App ID, set as MicrosoftAppId in the Web App's Application Settings."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"appSecret": {
|
||||||
|
"type": "string",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Active Directory App Password, set as MicrosoftAppPassword in the Web App's Application Settings. Defaults to \"\"."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"useCosmosDb": {
|
||||||
|
"type": "bool",
|
||||||
|
"defaultValue": true
|
||||||
|
},
|
||||||
|
"useAppInsights": {
|
||||||
|
"type": "bool",
|
||||||
|
"defaultValue": true
|
||||||
|
},
|
||||||
|
"shouldCreateAuthoringResource": {
|
||||||
|
"type": "bool",
|
||||||
|
"defaultValue": true
|
||||||
|
},
|
||||||
|
"shouldCreateLuisResource": {
|
||||||
|
"type": "bool",
|
||||||
|
"defaultValue": true
|
||||||
|
},
|
||||||
|
"cosmosDbName": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "[resourceGroup().name]"
|
||||||
|
},
|
||||||
|
"botId": {
|
||||||
|
"type": "string",
|
||||||
|
"metadata": {
|
||||||
|
"description": "The globally unique and immutable bot ID. Also used to configure the displayName of the bot, which is mutable."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"botSku": {
|
||||||
|
"defaultValue": "F0",
|
||||||
|
"type": "string",
|
||||||
|
"metadata": {
|
||||||
|
"description": "The pricing tier of the Bot Service Registration. Acceptable values are F0 and S1."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"luisAuthoringKey": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": ""
|
||||||
|
},
|
||||||
|
"newAppServicePlanName": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "[resourceGroup().name]",
|
||||||
|
"metadata": {
|
||||||
|
"description": "The name of the new App Service Plan."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"newAppServicePlanSku": {
|
||||||
|
"type": "object",
|
||||||
|
"defaultValue": {
|
||||||
|
"name": "S1",
|
||||||
|
"tier": "Standard",
|
||||||
|
"size": "S1",
|
||||||
|
"family": "S",
|
||||||
|
"capacity": 1
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"description": "The SKU of the App Service Plan. Defaults to Standard values."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"appServicePlanLocation": {
|
||||||
|
"type": "string",
|
||||||
|
"metadata": {
|
||||||
|
"description": "The location of the App Service Plan."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"existingAppServicePlan": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Name of the existing App Service Plan used to create the Web App for the bot."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"newWebAppName": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "[resourceGroup().name]",
|
||||||
|
"metadata": {
|
||||||
|
"description": "The globally unique name of the Web App. Defaults to the value passed in for \"botId\"."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"appInsightsName": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "[resourceGroup().name]"
|
||||||
|
},
|
||||||
|
"location": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "[resourceGroup().location]"
|
||||||
|
},
|
||||||
|
"appInsightsLocation": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "[resourceGroup().location]"
|
||||||
|
},
|
||||||
|
"useStorage": {
|
||||||
|
"type": "bool",
|
||||||
|
"defaultValue": true
|
||||||
|
},
|
||||||
|
"storageAccountName": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "[resourceGroup().name]"
|
||||||
|
},
|
||||||
|
"luisServiceName": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "[concat(resourceGroup().name, '-luis')]"
|
||||||
|
},
|
||||||
|
"luisServiceAuthoringSku": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "F0"
|
||||||
|
},
|
||||||
|
"luisServiceRunTimeSku": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "S0"
|
||||||
|
},
|
||||||
|
"luisServiceLocation": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "[resourceGroup().location]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": {
|
||||||
|
"defaultAppServicePlanName": "[if(empty(parameters('existingAppServicePlan')), 'createNewAppServicePlan', parameters('existingAppServicePlan'))]",
|
||||||
|
"useExistingAppServicePlan": "[not(equals(variables('defaultAppServicePlanName'), 'createNewAppServicePlan'))]",
|
||||||
|
"servicePlanName": "[if(variables('useExistingAppServicePlan'), parameters('existingAppServicePlan'), parameters('newAppServicePlanName'))]",
|
||||||
|
"resourcesLocation": "[parameters('appServicePlanLocation')]",
|
||||||
|
"cosmosDbAccountName": "[toLower(take(replace(parameters('cosmosDbName'), '_', ''), 31))]",
|
||||||
|
"webAppName": "[if(empty(parameters('newWebAppName')), parameters('botId'), parameters('newWebAppName'))]",
|
||||||
|
"siteHost": "[concat(variables('webAppName'), '.azurewebsites.net')]",
|
||||||
|
"botEndpoint": "[concat('https://', variables('siteHost'), '/api/messages')]",
|
||||||
|
"storageAccountName": "[toLower(take(replace(replace(parameters('storageAccountName'), '-', ''), '_', ''), 24))]",
|
||||||
|
"LuisAuthoringAccountName": "[concat(parameters('luisServiceName'), '-Authoring')]"
|
||||||
|
},
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"comments": "Create a Web App using an App Service Plan",
|
||||||
|
"type": "Microsoft.Web/sites",
|
||||||
|
"apiVersion": "2015-08-01",
|
||||||
|
"location": "[variables('resourcesLocation')]",
|
||||||
|
"kind": "functionapp",
|
||||||
|
"name": "[variables('webAppName')]",
|
||||||
|
"properties": {
|
||||||
|
"name": "[variables('webAppName')]",
|
||||||
|
"kind": "functionapp",
|
||||||
|
"httpsOnly": true
|
||||||
|
},
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"name": "appsettings",
|
||||||
|
"type": "config",
|
||||||
|
"apiVersion": "2015-08-01",
|
||||||
|
"dependsOn": [
|
||||||
|
"[concat('Microsoft.Web/Sites/', variables('webAppName'))]"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"FUNCTIONS_EXTENSION_VERSION": "~3",
|
||||||
|
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
|
||||||
|
"APPINSIGHTS_INSTRUMENTATIONKEY": "[reference(resourceId('microsoft.insights/components/', parameters('appInsightsName')), '2015-05-01').InstrumentationKey]",
|
||||||
|
"MicrosoftAppId": "[parameters('appId')]",
|
||||||
|
"MicrosoftAppPassword": "[parameters('appSecret')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"comments": "CosmosDB for bot state.",
|
||||||
|
"type": "Microsoft.DocumentDB/databaseAccounts",
|
||||||
|
"kind": "GlobalDocumentDB",
|
||||||
|
"apiVersion": "2015-04-08",
|
||||||
|
"name": "[variables('cosmosDbAccountName')]",
|
||||||
|
"location": "[parameters('location')]",
|
||||||
|
"properties": {
|
||||||
|
"databaseAccountOfferType": "Standard",
|
||||||
|
"locations": [
|
||||||
|
{
|
||||||
|
"locationName": "[parameters('location')]",
|
||||||
|
"failoverPriority": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"condition": "[parameters('useCosmosDb')]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases",
|
||||||
|
"apiVersion": "2020-03-01",
|
||||||
|
"name": "[concat(variables('cosmosDbAccountName'), '/botstate-db')]",
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.DocumentDB/databaseAccounts', variables('cosmosDbAccountName'))]"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"resource": {
|
||||||
|
"id": "botstate-db"
|
||||||
|
},
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"condition": "[parameters('useCosmosDb')]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers",
|
||||||
|
"apiVersion": "2020-03-01",
|
||||||
|
"name": "[concat(variables('cosmosDbAccountName'), '/botstate-db/botstate-container')]",
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', variables('cosmosDbAccountName'), 'botstate-db')]",
|
||||||
|
"[resourceId('Microsoft.DocumentDB/databaseAccounts', variables('cosmosDbAccountName'))]"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"resource": {
|
||||||
|
"id": "botstate-container",
|
||||||
|
"indexingPolicy": {
|
||||||
|
"indexingMode": "consistent",
|
||||||
|
"automatic": true,
|
||||||
|
"includedPaths": [
|
||||||
|
{
|
||||||
|
"path": "/*"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"excludedPaths": [
|
||||||
|
{
|
||||||
|
"path": "/\"_etag\"/?"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"partitionKey": {
|
||||||
|
"paths": [
|
||||||
|
"/id"
|
||||||
|
],
|
||||||
|
"kind": "Hash"
|
||||||
|
},
|
||||||
|
"conflictResolutionPolicy": {
|
||||||
|
"mode": "LastWriterWins",
|
||||||
|
"conflictResolutionPath": "/_ts"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"condition": "[parameters('useCosmosDb')]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"apiVersion": "2017-12-01",
|
||||||
|
"type": "Microsoft.BotService/botServices",
|
||||||
|
"name": "[parameters('botId')]",
|
||||||
|
"location": "global",
|
||||||
|
"kind": "bot",
|
||||||
|
"sku": {
|
||||||
|
"name": "[parameters('botSku')]"
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"name": "[parameters('botId')]",
|
||||||
|
"displayName": "[parameters('botId')]",
|
||||||
|
"endpoint": "[variables('botEndpoint')]",
|
||||||
|
"msaAppId": "[parameters('appId')]",
|
||||||
|
"developerAppInsightsApplicationId": null,
|
||||||
|
"developerAppInsightKey": null,
|
||||||
|
"publishingCredentials": null,
|
||||||
|
"storageResourceId": null
|
||||||
|
},
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.Web/sites/', variables('webAppName'))]"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"comments": "app insights",
|
||||||
|
"type": "Microsoft.Insights/components",
|
||||||
|
"kind": "web",
|
||||||
|
"apiVersion": "2015-05-01",
|
||||||
|
"name": "[parameters('appInsightsName')]",
|
||||||
|
"location": "[parameters('appInsightsLocation')]",
|
||||||
|
"properties": {
|
||||||
|
"Application_Type": "web"
|
||||||
|
},
|
||||||
|
"condition": "[parameters('useAppInsights')]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"comments": "storage account",
|
||||||
|
"type": "Microsoft.Storage/storageAccounts",
|
||||||
|
"kind": "StorageV2",
|
||||||
|
"apiVersion": "2018-07-01",
|
||||||
|
"name": "[variables('storageAccountName')]",
|
||||||
|
"location": "[parameters('location')]",
|
||||||
|
"sku": {
|
||||||
|
"name": "Standard_LRS"
|
||||||
|
},
|
||||||
|
"condition": "[parameters('useStorage')]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"comments": "Cognitive service authoring key for all LUIS apps.",
|
||||||
|
"apiVersion": "2017-04-18",
|
||||||
|
"name": "[variables('LuisAuthoringAccountName')]",
|
||||||
|
"location": "[parameters('luisServiceLocation')]",
|
||||||
|
"type": "Microsoft.CognitiveServices/accounts",
|
||||||
|
"kind": "LUIS.Authoring",
|
||||||
|
"sku": {
|
||||||
|
"name": "[parameters('luisServiceAuthoringSku')]"
|
||||||
|
},
|
||||||
|
"condition": "[parameters('shouldCreateAuthoringResource')]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"comments": "Cognitive service endpoint key for all LUIS apps.",
|
||||||
|
"type": "Microsoft.CognitiveServices/accounts",
|
||||||
|
"kind": "LUIS",
|
||||||
|
"apiVersion": "2017-04-18",
|
||||||
|
"name": "[parameters('luisServiceName')]",
|
||||||
|
"location": "[parameters('luisServiceLocation')]",
|
||||||
|
"sku": {
|
||||||
|
"name": "[parameters('luisServiceRunTimeSku')]"
|
||||||
|
},
|
||||||
|
"condition": "[parameters('shouldCreateLuisResource')]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outputs": {
|
||||||
|
"ApplicationInsights": {
|
||||||
|
"type": "object",
|
||||||
|
"value": {
|
||||||
|
"InstrumentationKey": "[if(parameters('useAppInsights'), reference(resourceId('Microsoft.Insights/components', parameters('appInsightsName'))).InstrumentationKey, '')]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"cosmosDb": {
|
||||||
|
"type": "object",
|
||||||
|
"value": {
|
||||||
|
"cosmosDBEndpoint": "[if(parameters('useCosmosDb'), reference(resourceId('Microsoft.DocumentDB/databaseAccounts', variables('cosmosDbAccountName'))).documentEndpoint, '')]",
|
||||||
|
"authKey": "[if(parameters('useCosmosDb'), listKeys(resourceId('Microsoft.DocumentDB/databaseAccounts', variables('cosmosDbAccountName')), '2015-04-08').primaryMasterKey, '')]",
|
||||||
|
"databaseId": "botstate-db",
|
||||||
|
"containerId": "botstate-container"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"blobStorage": {
|
||||||
|
"type": "object",
|
||||||
|
"value": {
|
||||||
|
"connectionString": "[if(parameters('useStorage'), concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2018-07-01').keys[0].value, ';EndpointSuffix=core.windows.net'), '')]",
|
||||||
|
"container": "transcripts"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"luis": {
|
||||||
|
"type": "object",
|
||||||
|
"value": {
|
||||||
|
"endpointKey": "[if(parameters('shouldCreateLuisResource'), listKeys(resourceId('Microsoft.CognitiveServices/accounts', parameters('luisServiceName')),'2017-04-18').key1, '')]",
|
||||||
|
"authoringKey": "[if(parameters('shouldCreateAuthoringResource'), listKeys(resourceId('Microsoft.CognitiveServices/accounts', variables('LuisAuthoringAccountName')),'2017-04-18').key1, parameters('luisAuthoringKey'))]",
|
||||||
|
"region": "[parameters('luisServiceLocation')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
|
||||||
|
"contentVersion": "1.0.0.0",
|
||||||
|
"parameters": {
|
||||||
|
"groupLocation": {
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"groupName": {
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"appId": {
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"appSecret": {
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"botId": {
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"botSku": {
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"newAppServicePlanName": {
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"newAppServicePlanSku": {
|
||||||
|
"value": {
|
||||||
|
"name": "S1",
|
||||||
|
"tier": "Standard",
|
||||||
|
"size": "S1",
|
||||||
|
"family": "S",
|
||||||
|
"capacity": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"newAppServicePlanLocation": {
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"newWebAppName": {
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
|
||||||
|
"contentVersion": "1.0.0.0",
|
||||||
|
"parameters": {
|
||||||
|
"appId": {
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"appSecret": {
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"botId": {
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"botSku": {
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"newAppServicePlanName": {
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"newAppServicePlanSku": {
|
||||||
|
"value": {
|
||||||
|
"name": "S1",
|
||||||
|
"tier": "Standard",
|
||||||
|
"size": "S1",
|
||||||
|
"family": "S",
|
||||||
|
"capacity": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"appServicePlanLocation": {
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"existingAppServicePlan": {
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"newWebAppName": {
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,217 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
|
||||||
|
"contentVersion": "1.0.0.0",
|
||||||
|
"parameters": {
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "[resourceGroup().name]"
|
||||||
|
},
|
||||||
|
"newAppServicePlanName": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "[resourceGroup().name]",
|
||||||
|
"metadata": {
|
||||||
|
"description": "The name of the new App Service Plan."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"newAppServicePlanSku": {
|
||||||
|
"type": "object",
|
||||||
|
"defaultValue": {
|
||||||
|
"name": "S1",
|
||||||
|
"tier": "Standard",
|
||||||
|
"size": "S1",
|
||||||
|
"family": "S",
|
||||||
|
"capacity": 1
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"description": "The SKU of the App Service Plan. Defaults to Standard values."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"appServicePlanLocation": {
|
||||||
|
"type": "string",
|
||||||
|
"metadata": {
|
||||||
|
"description": "The location of the App Service Plan."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"existingAppServicePlan": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Name of the existing App Service Plan used to create the Web App for the bot."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"appInsightsName": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "[resourceGroup().name]"
|
||||||
|
},
|
||||||
|
"appInsightsLocation": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "[resourceGroup().location]"
|
||||||
|
},
|
||||||
|
"qnaMakerServiceName": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "[concat(parameters('name'), '-qna')]"
|
||||||
|
},
|
||||||
|
"qnaMakerServiceSku": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "S0"
|
||||||
|
},
|
||||||
|
"qnaMakerServiceLocation": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "westus"
|
||||||
|
},
|
||||||
|
"qnaMakerSearchName": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "[concat(parameters('name'), '-search')]"
|
||||||
|
},
|
||||||
|
"qnaMakerSearchSku": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "standard"
|
||||||
|
},
|
||||||
|
"qnaMakerSearchLocation": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "[resourceGroup().location]"
|
||||||
|
},
|
||||||
|
"qnaMakerWebAppName": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "[concat(parameters('name'), '-qnahost')]"
|
||||||
|
},
|
||||||
|
"qnaMakerWebAppLocation": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "[resourceGroup().location]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": {
|
||||||
|
"defaultAppServicePlanName": "[if(empty(parameters('existingAppServicePlan')), 'createNewAppServicePlan', parameters('existingAppServicePlan'))]",
|
||||||
|
"useExistingAppServicePlan": "[not(equals(variables('defaultAppServicePlanName'), 'createNewAppServicePlan'))]",
|
||||||
|
"servicePlanName": "[if(variables('useExistingAppServicePlan'), parameters('existingAppServicePlan'), parameters('newAppServicePlanName'))]",
|
||||||
|
"resourcesLocation": "[parameters('appServicePlanLocation')]",
|
||||||
|
"qnaMakerSearchName": "[toLower(replace(parameters('qnaMakerSearchName'), '_', ''))]",
|
||||||
|
"qnaMakerWebAppName": "[replace(parameters('qnaMakerWebAppName'), '_', '')]"
|
||||||
|
},
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"apiVersion": "2018-02-01",
|
||||||
|
"name": "1d41002f-62a1-49f3-bd43-2f3f32a19cbb",
|
||||||
|
"type": "Microsoft.Resources/deployments",
|
||||||
|
"properties": {
|
||||||
|
"mode": "Incremental",
|
||||||
|
"template": {
|
||||||
|
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
|
||||||
|
"contentVersion": "1.0.0.0",
|
||||||
|
"resources": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"comments": "Create a new App Service Plan if no existing App Service Plan name was passed in.",
|
||||||
|
"type": "Microsoft.Web/serverfarms",
|
||||||
|
"condition": "[not(variables('useExistingAppServicePlan'))]",
|
||||||
|
"name": "[variables('servicePlanName')]",
|
||||||
|
"apiVersion": "2018-02-01",
|
||||||
|
"location": "[variables('resourcesLocation')]",
|
||||||
|
"sku": "[parameters('newAppServicePlanSku')]",
|
||||||
|
"properties": {
|
||||||
|
"name": "[variables('servicePlanName')]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"comments": "app insights",
|
||||||
|
"type": "Microsoft.Insights/components",
|
||||||
|
"kind": "web",
|
||||||
|
"apiVersion": "2015-05-01",
|
||||||
|
"name": "[parameters('appInsightsName')]",
|
||||||
|
"location": "[parameters('appInsightsLocation')]",
|
||||||
|
"properties": {
|
||||||
|
"Application_Type": "web"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"comments": "Cognitive service key for all QnA Maker knowledgebases.",
|
||||||
|
"type": "Microsoft.CognitiveServices/accounts",
|
||||||
|
"kind": "QnAMaker",
|
||||||
|
"apiVersion": "2017-04-18",
|
||||||
|
"name": "[parameters('qnaMakerServiceName')]",
|
||||||
|
"location": "[parameters('qnaMakerServiceLocation')]",
|
||||||
|
"sku": {
|
||||||
|
"name": "[parameters('qnaMakerServiceSku')]"
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"apiProperties": {
|
||||||
|
"qnaRuntimeEndpoint": "[concat('https://',reference(resourceId('Microsoft.Web/sites', variables('qnaMakerWebAppName'))).hostNames[0])]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.Web/Sites', variables('qnaMakerWebAppName'))]",
|
||||||
|
"[resourceId('Microsoft.Search/searchServices/', variables('qnaMakerSearchName'))]",
|
||||||
|
"[resourceId('microsoft.insights/components/', parameters('appInsightsName'))]"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"comments": "Search service for QnA Maker service.",
|
||||||
|
"type": "Microsoft.Search/searchServices",
|
||||||
|
"apiVersion": "2015-08-19",
|
||||||
|
"name": "[variables('qnaMakerSearchName')]",
|
||||||
|
"location": "[parameters('qnaMakerSearchLocation')]",
|
||||||
|
"sku": {
|
||||||
|
"name": "[parameters('qnaMakerSearchSku')]"
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"replicaCount": 1,
|
||||||
|
"partitionCount": 1,
|
||||||
|
"hostingMode": "default"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"comments": "Web app for QnA Maker service.",
|
||||||
|
"type": "Microsoft.Web/sites",
|
||||||
|
"apiVersion": "2016-08-01",
|
||||||
|
"name": "[variables('qnaMakerWebAppName')]",
|
||||||
|
"location": "[parameters('qnaMakerWebAppLocation')]",
|
||||||
|
"properties": {
|
||||||
|
"enabled": true,
|
||||||
|
"name": "[variables('qnaMakerWebAppName')]",
|
||||||
|
"hostingEnvironment": "",
|
||||||
|
"serverFarmId": "[concat('/subscriptions/', Subscription().SubscriptionId,'/resourcegroups/', resourceGroup().name, '/providers/Microsoft.Web/serverfarms/', variables('servicePlanName'))]",
|
||||||
|
"siteConfig": {
|
||||||
|
"cors": {
|
||||||
|
"allowedOrigins": ["*"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dependsOn": ["[resourceId('Microsoft.Web/serverfarms/', variables('servicePlanName'))]"],
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"apiVersion": "2016-08-01",
|
||||||
|
"name": "appsettings",
|
||||||
|
"type": "config",
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.Web/Sites', variables('qnaMakerWebAppName'))]",
|
||||||
|
"[resourceId('Microsoft.Insights/components', parameters('appInsightsName'))]",
|
||||||
|
"[resourceId('Microsoft.Search/searchServices/', variables('qnaMakerSearchName'))]"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"AzureSearchName": "[variables('qnaMakerSearchName')]",
|
||||||
|
"AzureSearchAdminKey": "[listAdminKeys(resourceId('Microsoft.Search/searchServices/', variables('qnaMakerSearchName')), '2015-08-19').primaryKey]",
|
||||||
|
"UserAppInsightsKey": "[reference(resourceId('Microsoft.Insights/components/', parameters('appInsightsName')), '2015-05-01').InstrumentationKey]",
|
||||||
|
"UserAppInsightsName": "[parameters('appInsightsName')]",
|
||||||
|
"UserAppInsightsAppId": "[reference(resourceId('Microsoft.Insights/components/', parameters('appInsightsName')), '2015-05-01').AppId]",
|
||||||
|
"PrimaryEndpointKey": "[concat(variables('qnaMakerWebAppName'), '-PrimaryEndpointKey')]",
|
||||||
|
"SecondaryEndpointKey": "[concat(variables('qnaMakerWebAppName'), '-SecondaryEndpointKey')]",
|
||||||
|
"DefaultAnswer": "No good match found in KB.",
|
||||||
|
"EnableMultipleTestIndex": "true",
|
||||||
|
"QNAMAKER_EXTENSION_VERSION": "latest"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outputs": {
|
||||||
|
"qna": {
|
||||||
|
"type": "object",
|
||||||
|
"value": {
|
||||||
|
"endpoint": "[concat('https://', reference(resourceId('Microsoft.Web/sites', variables('qnaMakerWebAppName'))).hostNames[0])]",
|
||||||
|
"subscriptionKey": "[listKeys(resourceId('Microsoft.CognitiveServices/accounts', parameters('qnaMakerServiceName')),'2017-04-18').key1]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,183 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
|
||||||
|
"contentVersion": "1.0.0.0",
|
||||||
|
"parameters": {
|
||||||
|
"groupLocation": {
|
||||||
|
"type": "string",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Specifies the location of the Resource Group."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"groupName": {
|
||||||
|
"type": "string",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Specifies the name of the Resource Group."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"appId": {
|
||||||
|
"type": "string",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Active Directory App ID, set as MicrosoftAppId in the Web App's Application Settings."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"appSecret": {
|
||||||
|
"type": "string",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Active Directory App Password, set as MicrosoftAppPassword in the Web App's Application Settings."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"botId": {
|
||||||
|
"type": "string",
|
||||||
|
"metadata": {
|
||||||
|
"description": "The globally unique and immutable bot ID. Also used to configure the displayName of the bot, which is mutable."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"botSku": {
|
||||||
|
"type": "string",
|
||||||
|
"metadata": {
|
||||||
|
"description": "The pricing tier of the Bot Service Registration. Acceptable values are F0 and S1."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"newAppServicePlanName": {
|
||||||
|
"type": "string",
|
||||||
|
"metadata": {
|
||||||
|
"description": "The name of the App Service Plan."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"newAppServicePlanSku": {
|
||||||
|
"type": "object",
|
||||||
|
"defaultValue": {
|
||||||
|
"name": "S1",
|
||||||
|
"tier": "Standard",
|
||||||
|
"size": "S1",
|
||||||
|
"family": "S",
|
||||||
|
"capacity": 1
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"description": "The SKU of the App Service Plan. Defaults to Standard values."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"newAppServicePlanLocation": {
|
||||||
|
"type": "string",
|
||||||
|
"metadata": {
|
||||||
|
"description": "The location of the App Service Plan. Defaults to \"westus\"."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"newWebAppName": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "",
|
||||||
|
"metadata": {
|
||||||
|
"description": "The globally unique name of the Web App. Defaults to the value passed in for \"botId\"."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": {
|
||||||
|
"appServicePlanName": "[parameters('newAppServicePlanName')]",
|
||||||
|
"resourcesLocation": "[parameters('newAppServicePlanLocation')]",
|
||||||
|
"webAppName": "[if(empty(parameters('newWebAppName')), parameters('botId'), parameters('newWebAppName'))]",
|
||||||
|
"siteHost": "[concat(variables('webAppName'), '.azurewebsites.net')]",
|
||||||
|
"botEndpoint": "[concat('https://', variables('siteHost'), '/api/messages')]"
|
||||||
|
},
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"name": "[parameters('groupName')]",
|
||||||
|
"type": "Microsoft.Resources/resourceGroups",
|
||||||
|
"apiVersion": "2018-05-01",
|
||||||
|
"location": "[parameters('groupLocation')]",
|
||||||
|
"properties": {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Microsoft.Resources/deployments",
|
||||||
|
"apiVersion": "2018-05-01",
|
||||||
|
"name": "storageDeployment",
|
||||||
|
"resourceGroup": "[parameters('groupName')]",
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.Resources/resourceGroups/', parameters('groupName'))]"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"mode": "Incremental",
|
||||||
|
"template": {
|
||||||
|
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
|
||||||
|
"contentVersion": "1.0.0.0",
|
||||||
|
"parameters": {},
|
||||||
|
"variables": {},
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"comments": "Create a new App Service Plan",
|
||||||
|
"type": "Microsoft.Web/serverfarms",
|
||||||
|
"name": "[variables('appServicePlanName')]",
|
||||||
|
"apiVersion": "2018-02-01",
|
||||||
|
"location": "[variables('resourcesLocation')]",
|
||||||
|
"sku": "[parameters('newAppServicePlanSku')]",
|
||||||
|
"properties": {
|
||||||
|
"name": "[variables('appServicePlanName')]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"comments": "Create a Web App using the new App Service Plan",
|
||||||
|
"type": "Microsoft.Web/sites",
|
||||||
|
"apiVersion": "2015-08-01",
|
||||||
|
"location": "[variables('resourcesLocation')]",
|
||||||
|
"kind": "app",
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.Web/serverfarms/', variables('appServicePlanName'))]"
|
||||||
|
],
|
||||||
|
"name": "[variables('webAppName')]",
|
||||||
|
"properties": {
|
||||||
|
"name": "[variables('webAppName')]",
|
||||||
|
"serverFarmId": "[variables('appServicePlanName')]",
|
||||||
|
"siteConfig": {
|
||||||
|
"appSettings": [
|
||||||
|
{
|
||||||
|
"name": "WEBSITE_NODE_DEFAULT_VERSION",
|
||||||
|
"value": "10.14.1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "MicrosoftAppId",
|
||||||
|
"value": "[parameters('appId')]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "MicrosoftAppPassword",
|
||||||
|
"value": "[parameters('appSecret')]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"cors": {
|
||||||
|
"allowedOrigins": [
|
||||||
|
"https://botservice.hosting.portal.azure.net",
|
||||||
|
"https://hosting.onecloud.azure-test.net/"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"apiVersion": "2017-12-01",
|
||||||
|
"type": "Microsoft.BotService/botServices",
|
||||||
|
"name": "[parameters('botId')]",
|
||||||
|
"location": "global",
|
||||||
|
"kind": "bot",
|
||||||
|
"sku": {
|
||||||
|
"name": "[parameters('botSku')]"
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"name": "[parameters('botId')]",
|
||||||
|
"displayName": "[parameters('botId')]",
|
||||||
|
"endpoint": "[variables('botEndpoint')]",
|
||||||
|
"msaAppId": "[parameters('appId')]",
|
||||||
|
"developerAppInsightsApplicationId": null,
|
||||||
|
"developerAppInsightKey": null,
|
||||||
|
"publishingCredentials": null,
|
||||||
|
"storageResourceId": null
|
||||||
|
},
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.Web/sites/', variables('webAppName'))]"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outputs": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,391 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
|
||||||
|
"contentVersion": "1.0.0.0",
|
||||||
|
"parameters": {
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "[resourceGroup().name]"
|
||||||
|
},
|
||||||
|
"appId": {
|
||||||
|
"type": "string",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Active Directory App ID, set as MicrosoftAppId in the Web App's Application Settings."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"appSecret": {
|
||||||
|
"type": "string",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Active Directory App Password, set as MicrosoftAppPassword in the Web App's Application Settings. Defaults to \"\"."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"useCosmosDb": {
|
||||||
|
"type": "bool",
|
||||||
|
"defaultValue": true
|
||||||
|
},
|
||||||
|
"useAppInsights": {
|
||||||
|
"type": "bool",
|
||||||
|
"defaultValue": true
|
||||||
|
},
|
||||||
|
"shouldCreateAuthoringResource": {
|
||||||
|
"type": "bool",
|
||||||
|
"defaultValue": true
|
||||||
|
},
|
||||||
|
"shouldCreateLuisResource": {
|
||||||
|
"type": "bool",
|
||||||
|
"defaultValue": true
|
||||||
|
},
|
||||||
|
"cosmosDbName": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "[resourceGroup().name]"
|
||||||
|
},
|
||||||
|
"botId": {
|
||||||
|
"type": "string",
|
||||||
|
"metadata": {
|
||||||
|
"description": "The globally unique and immutable bot ID. Also used to configure the displayName of the bot, which is mutable."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"botSku": {
|
||||||
|
"defaultValue": "F0",
|
||||||
|
"type": "string",
|
||||||
|
"metadata": {
|
||||||
|
"description": "The pricing tier of the Bot Service Registration. Acceptable values are F0 and S1."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"luisAuthoringKey": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": ""
|
||||||
|
},
|
||||||
|
"newAppServicePlanName": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "[resourceGroup().name]",
|
||||||
|
"metadata": {
|
||||||
|
"description": "The name of the new App Service Plan."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"newAppServicePlanSku": {
|
||||||
|
"type": "object",
|
||||||
|
"defaultValue": {
|
||||||
|
"name": "S1",
|
||||||
|
"tier": "Standard",
|
||||||
|
"size": "S1",
|
||||||
|
"family": "S",
|
||||||
|
"capacity": 1
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"description": "The SKU of the App Service Plan. Defaults to Standard values."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"appServicePlanLocation": {
|
||||||
|
"type": "string",
|
||||||
|
"metadata": {
|
||||||
|
"description": "The location of the App Service Plan."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"existingAppServicePlan": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Name of the existing App Service Plan used to create the Web App for the bot."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"newWebAppName": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "[resourceGroup().name]",
|
||||||
|
"metadata": {
|
||||||
|
"description": "The globally unique name of the Web App. Defaults to the value passed in for \"botId\"."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"appInsightsName": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "[resourceGroup().name]"
|
||||||
|
},
|
||||||
|
"location": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "[resourceGroup().location]"
|
||||||
|
},
|
||||||
|
"appInsightsLocation": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "[resourceGroup().location]"
|
||||||
|
},
|
||||||
|
"useStorage": {
|
||||||
|
"type": "bool",
|
||||||
|
"defaultValue": true
|
||||||
|
},
|
||||||
|
"storageAccountName": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "[resourceGroup().name]"
|
||||||
|
},
|
||||||
|
"luisServiceName": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "[concat(resourceGroup().name, '-luis')]"
|
||||||
|
},
|
||||||
|
"luisServiceAuthoringSku": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "F0"
|
||||||
|
},
|
||||||
|
"luisServiceRunTimeSku": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "S0"
|
||||||
|
},
|
||||||
|
"luisServiceLocation": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "[resourceGroup().location]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": {
|
||||||
|
"defaultAppServicePlanName": "[if(empty(parameters('existingAppServicePlan')), 'createNewAppServicePlan', parameters('existingAppServicePlan'))]",
|
||||||
|
"useExistingAppServicePlan": "[not(equals(variables('defaultAppServicePlanName'), 'createNewAppServicePlan'))]",
|
||||||
|
"servicePlanName": "[if(variables('useExistingAppServicePlan'), parameters('existingAppServicePlan'), parameters('newAppServicePlanName'))]",
|
||||||
|
"resourcesLocation": "[parameters('appServicePlanLocation')]",
|
||||||
|
"cosmosDbAccountName": "[toLower(take(replace(parameters('cosmosDbName'), '_', ''), 31))]",
|
||||||
|
"webAppName": "[if(empty(parameters('newWebAppName')), parameters('botId'), parameters('newWebAppName'))]",
|
||||||
|
"siteHost": "[concat(variables('webAppName'), '.azurewebsites.net')]",
|
||||||
|
"botEndpoint": "[concat('https://', variables('siteHost'), '/api/messages')]",
|
||||||
|
"storageAccountName": "[toLower(take(replace(replace(parameters('storageAccountName'), '-', ''), '_', ''), 24))]",
|
||||||
|
"LuisAuthoringAccountName": "[concat(parameters('luisServiceName'), '-Authoring')]"
|
||||||
|
},
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"apiVersion": "2018-02-01",
|
||||||
|
"name": "1d41002f-62a1-49f3-bd43-2f3f32a19cbb",
|
||||||
|
"type": "Microsoft.Resources/deployments",
|
||||||
|
"properties": {
|
||||||
|
"mode": "Incremental",
|
||||||
|
"template": {
|
||||||
|
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
|
||||||
|
"contentVersion": "1.0.0.0",
|
||||||
|
"resources": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"comments": "Create a new App Service Plan if no existing App Service Plan name was passed in.",
|
||||||
|
"type": "Microsoft.Web/serverfarms",
|
||||||
|
"condition": "[not(variables('useExistingAppServicePlan'))]",
|
||||||
|
"name": "[variables('servicePlanName')]",
|
||||||
|
"apiVersion": "2018-02-01",
|
||||||
|
"location": "[variables('resourcesLocation')]",
|
||||||
|
"sku": "[parameters('newAppServicePlanSku')]",
|
||||||
|
"properties": {
|
||||||
|
"name": "[variables('servicePlanName')]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"comments": "Create a Web App using an App Service Plan",
|
||||||
|
"type": "Microsoft.Web/sites",
|
||||||
|
"apiVersion": "2015-08-01",
|
||||||
|
"location": "[variables('resourcesLocation')]",
|
||||||
|
"kind": "app",
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.Web/serverfarms/', variables('servicePlanName'))]"
|
||||||
|
],
|
||||||
|
"name": "[variables('webAppName')]",
|
||||||
|
"properties": {
|
||||||
|
"name": "[variables('webAppName')]",
|
||||||
|
"serverFarmId": "[variables('servicePlanName')]",
|
||||||
|
"siteConfig": {
|
||||||
|
"webSocketsEnabled": true,
|
||||||
|
"appSettings": [
|
||||||
|
{
|
||||||
|
"name": "WEBSITE_NODE_DEFAULT_VERSION",
|
||||||
|
"value": "10.14.1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "MicrosoftAppId",
|
||||||
|
"value": "[parameters('appId')]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "MicrosoftAppPassword",
|
||||||
|
"value": "[parameters('appSecret')]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"cors": {
|
||||||
|
"allowedOrigins": [
|
||||||
|
"https://botservice.hosting.portal.azure.net",
|
||||||
|
"https://hosting.onecloud.azure-test.net/"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"comments": "CosmosDB for bot state.",
|
||||||
|
"type": "Microsoft.DocumentDB/databaseAccounts",
|
||||||
|
"kind": "GlobalDocumentDB",
|
||||||
|
"apiVersion": "2015-04-08",
|
||||||
|
"name": "[variables('cosmosDbAccountName')]",
|
||||||
|
"location": "[parameters('location')]",
|
||||||
|
"properties": {
|
||||||
|
"databaseAccountOfferType": "Standard",
|
||||||
|
"locations": [
|
||||||
|
{
|
||||||
|
"locationName": "[parameters('location')]",
|
||||||
|
"failoverPriority": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"condition": "[parameters('useCosmosDb')]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases",
|
||||||
|
"apiVersion": "2020-03-01",
|
||||||
|
"name": "[concat(variables('cosmosDbAccountName'), '/botstate-db')]",
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.DocumentDB/databaseAccounts', variables('cosmosDbAccountName'))]"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"resource": {
|
||||||
|
"id": "botstate-db"
|
||||||
|
},
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"condition": "[parameters('useCosmosDb')]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers",
|
||||||
|
"apiVersion": "2020-03-01",
|
||||||
|
"name": "[concat(variables('cosmosDbAccountName'), '/botstate-db/botstate-container')]",
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', variables('cosmosDbAccountName'), 'botstate-db')]",
|
||||||
|
"[resourceId('Microsoft.DocumentDB/databaseAccounts', variables('cosmosDbAccountName'))]"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"resource": {
|
||||||
|
"id": "botstate-container",
|
||||||
|
"indexingPolicy": {
|
||||||
|
"indexingMode": "consistent",
|
||||||
|
"automatic": true,
|
||||||
|
"includedPaths": [
|
||||||
|
{
|
||||||
|
"path": "/*"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"excludedPaths": [
|
||||||
|
{
|
||||||
|
"path": "/\"_etag\"/?"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"partitionKey": {
|
||||||
|
"paths": [
|
||||||
|
"/id"
|
||||||
|
],
|
||||||
|
"kind": "Hash"
|
||||||
|
},
|
||||||
|
"conflictResolutionPolicy": {
|
||||||
|
"mode": "LastWriterWins",
|
||||||
|
"conflictResolutionPath": "/_ts"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"condition": "[parameters('useCosmosDb')]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"apiVersion": "2018-07-12",
|
||||||
|
"type": "Microsoft.BotService/botServices",
|
||||||
|
"name": "[parameters('botId')]",
|
||||||
|
"location": "global",
|
||||||
|
"kind": "azurebot",
|
||||||
|
"sku": {
|
||||||
|
"name": "[parameters('botSku')]"
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"name": "[parameters('botId')]",
|
||||||
|
"displayName": "[parameters('botId')]",
|
||||||
|
"endpoint": "[variables('botEndpoint')]",
|
||||||
|
"msaAppId": "[parameters('appId')]",
|
||||||
|
"openWithHint": "bfcomposer://",
|
||||||
|
"developerAppInsightsApplicationId": null,
|
||||||
|
"developerAppInsightKey": null,
|
||||||
|
"publishingCredentials": null,
|
||||||
|
"storageResourceId": null
|
||||||
|
},
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.Web/sites/', variables('webAppName'))]"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"comments": "app insights",
|
||||||
|
"type": "Microsoft.Insights/components",
|
||||||
|
"kind": "web",
|
||||||
|
"apiVersion": "2015-05-01",
|
||||||
|
"name": "[parameters('appInsightsName')]",
|
||||||
|
"location": "[parameters('appInsightsLocation')]",
|
||||||
|
"properties": {
|
||||||
|
"Application_Type": "web"
|
||||||
|
},
|
||||||
|
"condition": "[parameters('useAppInsights')]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"comments": "storage account",
|
||||||
|
"type": "Microsoft.Storage/storageAccounts",
|
||||||
|
"kind": "StorageV2",
|
||||||
|
"apiVersion": "2018-07-01",
|
||||||
|
"name": "[variables('storageAccountName')]",
|
||||||
|
"location": "[parameters('location')]",
|
||||||
|
"sku": {
|
||||||
|
"name": "Standard_LRS"
|
||||||
|
},
|
||||||
|
"condition": "[parameters('useStorage')]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"comments": "Cognitive service authoring key for all LUIS apps.",
|
||||||
|
"apiVersion": "2017-04-18",
|
||||||
|
"name": "[variables('LuisAuthoringAccountName')]",
|
||||||
|
"location": "[parameters('luisServiceLocation')]",
|
||||||
|
"type": "Microsoft.CognitiveServices/accounts",
|
||||||
|
"kind": "LUIS.Authoring",
|
||||||
|
"sku": {
|
||||||
|
"name": "[parameters('luisServiceAuthoringSku')]"
|
||||||
|
},
|
||||||
|
"condition": "[parameters('shouldCreateAuthoringResource')]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"comments": "Cognitive service endpoint key for all LUIS apps.",
|
||||||
|
"type": "Microsoft.CognitiveServices/accounts",
|
||||||
|
"kind": "LUIS",
|
||||||
|
"apiVersion": "2017-04-18",
|
||||||
|
"name": "[parameters('luisServiceName')]",
|
||||||
|
"location": "[parameters('luisServiceLocation')]",
|
||||||
|
"sku": {
|
||||||
|
"name": "[parameters('luisServiceRunTimeSku')]"
|
||||||
|
},
|
||||||
|
"condition": "[parameters('shouldCreateLuisResource')]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outputs": {
|
||||||
|
"ApplicationInsights": {
|
||||||
|
"type": "object",
|
||||||
|
"value": {
|
||||||
|
"InstrumentationKey": "[if(parameters('useAppInsights'), reference(resourceId('Microsoft.Insights/components', parameters('appInsightsName'))).InstrumentationKey, '')]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"cosmosDb": {
|
||||||
|
"type": "object",
|
||||||
|
"value": {
|
||||||
|
"cosmosDBEndpoint": "[if(parameters('useCosmosDb'), reference(resourceId('Microsoft.DocumentDB/databaseAccounts', variables('cosmosDbAccountName'))).documentEndpoint, '')]",
|
||||||
|
"authKey": "[if(parameters('useCosmosDb'), listKeys(resourceId('Microsoft.DocumentDB/databaseAccounts', variables('cosmosDbAccountName')), '2015-04-08').primaryMasterKey, '')]",
|
||||||
|
"databaseId": "botstate-db",
|
||||||
|
"containerId": "botstate-container"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"blobStorage": {
|
||||||
|
"type": "object",
|
||||||
|
"value": {
|
||||||
|
"connectionString": "[if(parameters('useStorage'), concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2018-07-01').keys[0].value, ';EndpointSuffix=core.windows.net'), '')]",
|
||||||
|
"container": "transcripts"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"luis": {
|
||||||
|
"type": "object",
|
||||||
|
"value": {
|
||||||
|
"endpointKey": "[if(parameters('shouldCreateLuisResource'), listKeys(resourceId('Microsoft.CognitiveServices/accounts', parameters('luisServiceName')),'2017-04-18').key1, '')]",
|
||||||
|
"authoringKey": "[if(parameters('shouldCreateAuthoringResource'), listKeys(resourceId('Microsoft.CognitiveServices/accounts', variables('LuisAuthoringAccountName')),'2017-04-18').key1, parameters('luisAuthoringKey'))]",
|
||||||
|
"region": "[parameters('luisServiceLocation')]",
|
||||||
|
"endpoint": "[if(parameters('shouldCreateLuisResource'), reference(resourceId('Microsoft.CognitiveServices/accounts', parameters('luisServiceName'))).endpoint, '')]",
|
||||||
|
"authoringEndpoint": "[if(parameters('shouldCreateAuthoringResource'), reference(resourceId('Microsoft.CognitiveServices/accounts', variables('LuisAuthoringAccountName'))).endpoint, '')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,193 @@
|
||||||
|
# Manually provision resources and publish a bot to Azure (_Preview_)
|
||||||
|
|
||||||
|
This article covers script-based instructions to manually provision resources and publish a bot built using Composer to _Azure Web App (Preview)_ and _Azure Functions (Preview)_.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- A subscription to [Microsoft Azure](https://azure.microsoft.com/free/).
|
||||||
|
- [A basic bot built using Composer](https://aka.ms/composer-create-first-bot).
|
||||||
|
- Latest version of the [Azure CLI](https://docs.microsoft.com/cli/azure/install-azure-cli).
|
||||||
|
- [Node.js](https://nodejs.org/). Use version 12.13.0 or later.
|
||||||
|
- PowerShell version 6.0 and later.
|
||||||
|
|
||||||
|
## Provision Azure resources
|
||||||
|
|
||||||
|
This section covers steps to provision required Azure resources using JavaScript scripts. If you already have your Azure resources provisioned, skip to the [publish a bot to Azure](#publish-a-bot-to-azure) section.
|
||||||
|
|
||||||
|
Follow these instructions to manually provision Azure resources:
|
||||||
|
|
||||||
|
1. Open a new Command Prompt and navigate to the **scripts** folder of your bot's project folder. For example:
|
||||||
|
|
||||||
|
```cmd
|
||||||
|
cd C:\Users\UserName\Documents\Composer\BotName\scripts
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Run the following command to install the dependencies:
|
||||||
|
|
||||||
|
```cmd
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Run the following command to provision new Azure resources.
|
||||||
|
|
||||||
|
- **_Azure Web App (Preview)_**:
|
||||||
|
|
||||||
|
```cmd
|
||||||
|
node provisionComposer.js --subscriptionId=<YOUR AZURE SUBSCRIPTION ID> --name=<NAME OF YOUR RESOURCE GROUP> --appPassword=<APP PASSWORD> --environment=<NAME FOR ENVIRONMENT DEFAULT to dev>
|
||||||
|
```
|
||||||
|
|
||||||
|
- **_Azure Functions (Preview)_**:
|
||||||
|
|
||||||
|
```cmd
|
||||||
|
node provisionComposer.js --subscriptionId=<YOUR AZURE SUBSCRIPTION ID> --name=<NAME OF YOUR RESOURCE GROUP> --appPassword=<APP PASSWORD> --environment=<NAME FOR ENVIRONMENT DEFAULT to dev> --customArmTemplate=DeploymentTemplates/function-template-with-preexisting-rg.json
|
||||||
|
```
|
||||||
|
|
||||||
|
| Property | Description |
|
||||||
|
| --------------------------- | --------------------------------------------------------------------------------------- |
|
||||||
|
| Your Azure Subscription ID | Find it in your Azure resource in the **Subscription ID** field. |
|
||||||
|
| Name of your resource group | The name you give to the resource group you are creating. |
|
||||||
|
| App password | At least 16 characters with at least one number, one letter, and one special character. |
|
||||||
|
| Name for environment | The name you give to the publish environment. |
|
||||||
|
|
||||||
|
Once completed, the provision scripts will create the following resources in the Azure portal:
|
||||||
|
|
||||||
|
| Resource | Required/Optional |
|
||||||
|
| --------------------------------------------- | ----------------- |
|
||||||
|
| App Service plan | Required |
|
||||||
|
| App Service | Required |
|
||||||
|
| Application Registration | Required |
|
||||||
|
| Azure Cosmos DB | Optional |
|
||||||
|
| Application Insights | Optional |
|
||||||
|
| Azure Blob Storage | Optional |
|
||||||
|
| LUIS authoring resource (Cognitive Services) | Optional |
|
||||||
|
| LUIS prediction resource (Cognitive Services) | Optional |
|
||||||
|
| QnA Maker resources (Cognitive Services) | Optional |
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> Read the [parameters list](#provision-scripts-parameters-list) to customize the provision scripts and create the Azure resources you want.
|
||||||
|
|
||||||
|
1. You will be asked to login to the Azure portal in your browser.
|
||||||
|
|
||||||
|
> ![publish az login](./media/publish-az-login.png)
|
||||||
|
|
||||||
|
2. If you see the error message "InsufficientQuota", add a param '--createLuisAuthoringResource false' and run the script again.
|
||||||
|
|
||||||
|
- **_Azure Web App_**:
|
||||||
|
|
||||||
|
```cmd
|
||||||
|
node provisionComposer.js --subscriptionId=<YOUR AZURE SUBSCRIPTION ID> --name=<NAME OF YOUR RESOURCE GROUP>--appPassword=<APP PASSWORD> --environment=<NAME FOR ENVIRONMENT DEFAULT to dev> --createLuisAuthoringResource false
|
||||||
|
```
|
||||||
|
|
||||||
|
- **_Azure Functions_**:
|
||||||
|
|
||||||
|
```cmd
|
||||||
|
node provisionComposer.js --subscriptionId=<YOUR AZURE SUBSCRIPTION ID> --name=<NAME OF YOUR RESOURCE GROUP> --appPassword=<APP PASSWORD> --environment=<NAME FOR ENVIRONMENT DEFAULT to dev> --createLuisAuthoringResource false --customArmTemplate=DeploymentTemplates/function-template-with-preexisting-rg.json
|
||||||
|
```
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> If you use `--createLuisAuthoringResource false` in this step, you should manually add the LUIS authoring key to the publish configuration in the [deploy bot to new Azure resources](#deploy-bot-to-new-azure-resources) section. The default region is `westus`. To provision to other regions, you should add `--location region`.
|
||||||
|
|
||||||
|
4. As the Azure resources are being provisioned, which takes a few minutes, you will see the following:
|
||||||
|
|
||||||
|
> ![Create Azure resource command line](./media/create-azure-resource-command-line.png)
|
||||||
|
|
||||||
|
Once completed, you will see the generated JSON appears in the command line like the following. The JSON output is the publishing profile, which will be used in step **3** of the [Publish a bot to Azure](#publish-a-bot-to-azure) section.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"accessToken": "<SOME VALUE>",
|
||||||
|
"name": "<NAME OF YOUR RESOURCE GROUP>",
|
||||||
|
"environment": "<ENVIRONMENT>",
|
||||||
|
"hostname": "<NAME OF THE HOST>",
|
||||||
|
"luisResource": "<NAME OF YOUR LUIS RESOURCE>",
|
||||||
|
"settings": {
|
||||||
|
"applicationInsights": {
|
||||||
|
"InstrumentationKey": "<SOME VALUE>"
|
||||||
|
},
|
||||||
|
"cosmosDb": {
|
||||||
|
"cosmosDBEndpoint": "<SOME VALUE>",
|
||||||
|
"authKey": "<SOME VALUE>",
|
||||||
|
"databaseId": "botstate-db",
|
||||||
|
"collectionId": "botstate-collection",
|
||||||
|
"containerId": "botstate-container"
|
||||||
|
},
|
||||||
|
"blobStorage": {
|
||||||
|
"connectionString": "<SOME VALUE>",
|
||||||
|
"container": "transcripts"
|
||||||
|
},
|
||||||
|
"luis": {
|
||||||
|
"endpointKey": "<SOME VALUE>",
|
||||||
|
"authoringKey": "<SOME VALUE>",
|
||||||
|
"region": "westus"
|
||||||
|
},
|
||||||
|
"qna": {
|
||||||
|
"endpoint": "<SOME VALUE>",
|
||||||
|
"subscriptionKey": "<SOME VALUE>"
|
||||||
|
},
|
||||||
|
"MicrosoftAppId": "<SOME VALUE>",
|
||||||
|
"MicrosoftAppPassword": "<SOME VALUE>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Publish a bot to Azure
|
||||||
|
|
||||||
|
This section covers instructions to publish a bot to Azure using PowerShell scripts. Make sure you already have required Azure resources provisioned before publishing a bot, if not, follow these instructions from the [provision Azure resources](#provision-azure-resources) section.
|
||||||
|
|
||||||
|
Follow these steps to manually publish a bot to Azure:
|
||||||
|
|
||||||
|
1. Install the required dependencies.
|
||||||
|
|
||||||
|
bf command
|
||||||
|
|
||||||
|
```cmd
|
||||||
|
npm i -g @microsoft/botframework-cli@next
|
||||||
|
```
|
||||||
|
|
||||||
|
bf plugins
|
||||||
|
|
||||||
|
```cmd
|
||||||
|
bf plugins:install @microsoft/bf-sampler-cli@beta
|
||||||
|
```
|
||||||
|
|
||||||
|
2. [Eject your bot's C# runtime](https://aka.ms/composer-customize-action#export-runtime).
|
||||||
|
|
||||||
|
3. Save your publishing profile in `json` format (the JSON output from step **4** of the [provision Azure resources](#provision-azure-resources) section and execute the following command:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
.\Scripts\deploy.ps1 -publishProfilePath <path to your publishing profile>
|
||||||
|
```
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Make sure you [set the correct subscription](https://docs.microsoft.com/cli/azure/account?view=azure-cli-latest#az_account_set) when running the scripts to publish your bot. Use the Azure CLI command `az account set --subscription` to set subscription if needed. The publishing process will take a couple of minutes to finish.
|
||||||
|
|
||||||
|
## Refresh your Azure Token
|
||||||
|
|
||||||
|
Follow these steps to get a new token if you encounter an error about your access token being expired:
|
||||||
|
|
||||||
|
- Open a terminal window.
|
||||||
|
- Run `az account get-access-token`.
|
||||||
|
- This will result in a JSON object containing the new `accessToken`, printed to the console.
|
||||||
|
- Copy the value of the accessToken from the terminal and into the publish `accessToken` field in the profile in Composer.
|
||||||
|
|
||||||
|
## Additional information
|
||||||
|
|
||||||
|
### Provision scripts parameters list
|
||||||
|
|
||||||
|
You don't need to create a complete list of the Azure resources as covered in **step 3** of the [provision Azure resources](#provision-azure-resources) section. The following is a table of the parameters you can use to customize the provision scripts so that you only provision the resources needed.
|
||||||
|
|
||||||
|
| Parameter | Required/Optional | Default value | Description |
|
||||||
|
| --------------------------- | ----------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||||
|
| subscriptionId | Required | N/A | Your Azure subscription ID. |
|
||||||
|
| name | Required | N/A | The name of your resource group |
|
||||||
|
| appPassword | Required | N/A | The password to create the resource. It must be at least 16 characters long, contain at least 1 upper or lower case alphabetical character, and contain at least 1 special character |
|
||||||
|
| environment | Optional | dev | N/A |
|
||||||
|
| location | Optional | `westus` | Your Azure resource group region |
|
||||||
|
| tenantId | Optional | default tenantId | ID of your tenant if required. |
|
||||||
|
| customArmTemplate | Optional | `/DeploymentTemplates/template-with-preexisting-rg.json` | For Azure Functions or your own template for a custom deployment. |
|
||||||
|
| createLuisResource | Optional | `true` | The LUIS prediction resource to create. Region is default to `westus` and cannot be changed. |
|
||||||
|
| createLuisAuthoringResource | Optional | true | The LUIS authoring resource to create. Region is default to `westus` and cannot be changed. |
|
||||||
|
| createQnAResource | Optional | `true` | The QnA resource to create. |
|
||||||
|
| createCosmosDb | Optional | `true` | The CosmosDb resource to create. |
|
||||||
|
| createStorage | Optional | `true` | The BlobStorage resource to create. |
|
||||||
|
| createAppInsights | Optional | `true` | The AppInsights resource to create. |
|
|
@ -0,0 +1,241 @@
|
||||||
|
Param(
|
||||||
|
[string] $name,
|
||||||
|
[string] $environment,
|
||||||
|
[string] $luisAuthoringKey,
|
||||||
|
[string] $luisAuthoringRegion,
|
||||||
|
[string] $language,
|
||||||
|
[string] $projFolder = $(Get-Location),
|
||||||
|
[string] $botPath,
|
||||||
|
[string] $logFile = $(Join-Path $PSScriptRoot .. "deploy_log.txt")
|
||||||
|
)
|
||||||
|
|
||||||
|
if ($PSVersionTable.PSVersion.Major -lt 6) {
|
||||||
|
Write-Host "! Powershell 6 is required, current version is $($PSVersionTable.PSVersion.Major), please refer following documents for help."
|
||||||
|
Write-Host "For Windows - https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell-core-on-windows?view=powershell-6"
|
||||||
|
Write-Host "For Mac - https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell-core-on-macos?view=powershell-6"
|
||||||
|
Break
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((dotnet --version) -lt 3) {
|
||||||
|
Write-Host "! dotnet core 3.0 is required, please refer following documents for help."
|
||||||
|
Write-Host "https://dotnet.microsoft.com/download/dotnet-core/3.0"
|
||||||
|
Break
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get mandatory parameters
|
||||||
|
if (-not $name) {
|
||||||
|
$name = Read-Host "? Bot Web App Name"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not $environment) {
|
||||||
|
$environment = Read-Host "? Environment Name (single word, all lowercase)"
|
||||||
|
$environment = $environment.ToLower().Split(" ") | Select-Object -First 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not $language) {
|
||||||
|
$language = "en-us"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Reset log file
|
||||||
|
if (Test-Path $logFile) {
|
||||||
|
Clear-Content $logFile -Force | Out-Null
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
New-Item -Path $logFile | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check for existing deployment files
|
||||||
|
if (-not (Test-Path (Join-Path $projFolder '.deployment'))) {
|
||||||
|
# Add needed deployment files for az
|
||||||
|
az bot prepare-deploy --lang Csharp --code-dir $projFolder --proj-file-path Microsoft.Bot.Runtime.WebHost.csproj --output json | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
# Delete src zip, if it exists
|
||||||
|
$zipPath = $(Join-Path $projFolder 'code.zip')
|
||||||
|
if (Test-Path $zipPath) {
|
||||||
|
Remove-Item $zipPath -Force | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
# Perform dotnet publish step ahead of zipping up
|
||||||
|
$publishFolder = $(Join-Path $projFolder 'bin\Release\netcoreapp3.1')
|
||||||
|
dotnet publish -c release -o $publishFolder -v q > $logFile
|
||||||
|
|
||||||
|
# Copy bot files to running folder
|
||||||
|
$remoteBotPath = $(Join-Path $publishFolder "ComposerDialogs")
|
||||||
|
Remove-Item $remoteBotPath -Recurse -ErrorAction Ignore
|
||||||
|
|
||||||
|
if (-not $botPath) {
|
||||||
|
# If don't provide bot path, then try to copy all dialogs except the runtime folder in parent folder to the publishing folder (bin\Realse\ Folder)
|
||||||
|
$botPath = '../../..'
|
||||||
|
}
|
||||||
|
|
||||||
|
$botPath = $(Join-Path $botPath '*')
|
||||||
|
Write-Host "Publishing dialogs from external bot project: $($botPath)"
|
||||||
|
Copy-Item -Path (Get-Item -Path $botPath -Exclude ('runtime', 'generated')).FullName -Destination $remoteBotPath -Recurse -Force -Container
|
||||||
|
|
||||||
|
# Try to get luis config from appsettings
|
||||||
|
$settingsPath = $(Join-Path $remoteBotPath settings appsettings.json)
|
||||||
|
$settings = Get-Content $settingsPath | ConvertFrom-Json
|
||||||
|
$luisSettings = $settings.luis
|
||||||
|
|
||||||
|
if (-not $luisAuthoringKey) {
|
||||||
|
$luisAuthoringKey = $luisSettings.authoringKey
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not $luisAuthoringRegion) {
|
||||||
|
$luisAuthoringRegion = $luisSettings.region
|
||||||
|
}
|
||||||
|
|
||||||
|
# set feature configuration
|
||||||
|
$featureConfig = @{ }
|
||||||
|
if ($settings.feature) {
|
||||||
|
$featureConfig = $settings.feature
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
# Enable all features to true by default
|
||||||
|
$featureConfig["UseTelementryLoggerMiddleware"] = $true
|
||||||
|
$featureConfig["UseTranscriptLoggerMiddleware"] = $true
|
||||||
|
$featureConfig["UseShowTypingMiddleware"] = $true
|
||||||
|
$featureConfig["UseInspectionMiddleware"] = $true
|
||||||
|
$featureConfig["UseCosmosDb"] = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add Luis Config to appsettings
|
||||||
|
if ($luisAuthoringKey -and $luisAuthoringRegion) {
|
||||||
|
Set-Location -Path $remoteBotPath
|
||||||
|
|
||||||
|
$models = Get-ChildItem $remoteBotPath -Recurse -Filter "*.lu" | Resolve-Path -Relative
|
||||||
|
|
||||||
|
# Generate Luconfig.json file
|
||||||
|
$luconfigjson = @{
|
||||||
|
"name" = $name;
|
||||||
|
"defaultLanguage" = $language;
|
||||||
|
"models" = $models
|
||||||
|
}
|
||||||
|
|
||||||
|
$luString = $models | Out-String
|
||||||
|
Write-Host $luString
|
||||||
|
|
||||||
|
$luconfigjson | ConvertTo-Json -Depth 100 | Out-File $(Join-Path $remoteBotPath luconfig.json)
|
||||||
|
|
||||||
|
# create generated folder if not
|
||||||
|
if (!(Test-Path generated)) {
|
||||||
|
$null = New-Item -ItemType Directory -Force -Path generated
|
||||||
|
}
|
||||||
|
|
||||||
|
# ensure bot cli is installed
|
||||||
|
if (Get-Command bf -errorAction SilentlyContinue) {}
|
||||||
|
else {
|
||||||
|
Write-Host "bf luis:build does not exist. Start installation..."
|
||||||
|
npm i -g @microsoft/botframework-cli
|
||||||
|
Write-Host "successfully"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Execute bf luis:build command
|
||||||
|
bf luis:build --luConfig $(Join-Path $remoteBotPath luconfig.json) --botName $name --authoringKey $luisAuthoringKey --dialog crosstrained --out ./generated --suffix $environment -f --region $luisAuthoringRegion
|
||||||
|
|
||||||
|
if ($?) {
|
||||||
|
Write-Host "lubuild succeeded"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Host "lubuild failed, please verify your luis models."
|
||||||
|
Break
|
||||||
|
}
|
||||||
|
|
||||||
|
Set-Location -Path $projFolder
|
||||||
|
|
||||||
|
$settings = New-Object PSObject
|
||||||
|
|
||||||
|
$luisConfigFiles = Get-ChildItem -Path $publishFolder -Include "luis.settings*" -Recurse -Force
|
||||||
|
|
||||||
|
$luisAppIds = @{ }
|
||||||
|
|
||||||
|
foreach ($luisConfigFile in $luisConfigFiles) {
|
||||||
|
$luisSetting = Get-Content $luisConfigFile.FullName | ConvertFrom-Json
|
||||||
|
$luis = $luisSetting.luis
|
||||||
|
$luis.PSObject.Properties | Foreach-Object { $luisAppIds[$_.Name] = $_.Value }
|
||||||
|
}
|
||||||
|
|
||||||
|
$luisEndpoint = "https://$luisAuthoringRegion.api.cognitive.microsoft.com"
|
||||||
|
|
||||||
|
$luisConfig = @{ }
|
||||||
|
|
||||||
|
$luisConfig["endpoint"] = $luisEndpoint
|
||||||
|
|
||||||
|
foreach ($key in $luisAppIds.Keys) { $luisConfig[$key] = $luisAppIds[$key] }
|
||||||
|
|
||||||
|
$settings | Add-Member -Type NoteProperty -Force -Name 'luis' -Value $luisConfig
|
||||||
|
|
||||||
|
$tokenResponse = (az account get-access-token) | ConvertFrom-Json
|
||||||
|
$token = $tokenResponse.accessToken
|
||||||
|
|
||||||
|
if (-not $token) {
|
||||||
|
Write-Host "! Could not get valid Azure access token"
|
||||||
|
Break
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Getting Luis accounts..."
|
||||||
|
$luisAccountEndpoint = "$luisEndpoint/luis/api/v2.0/azureaccounts"
|
||||||
|
$luisAccount = $null
|
||||||
|
try {
|
||||||
|
$luisAccounts = Invoke-WebRequest -Method GET -Uri $luisAccountEndpoint -Headers @{"Authorization" = "Bearer $token"; "Ocp-Apim-Subscription-Key" = $luisAuthoringKey } | ConvertFrom-Json
|
||||||
|
|
||||||
|
foreach ($account in $luisAccounts) {
|
||||||
|
if ($account.AccountName -eq "$name-$environment-luis") {
|
||||||
|
$luisAccount = $account
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-Host "Return invalid status code while gettings luis accounts: $($_.Exception.Response.StatusCode.Value__), error message: $($_.Exception.Response)"
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
$luisAccountBody = $luisAccount | ConvertTo-Json
|
||||||
|
|
||||||
|
# Assign each luis id in luisAppIds with the endpoint key
|
||||||
|
foreach ($k in $luisAppIds.Keys) {
|
||||||
|
$luisAppId = $luisAppIds.Item($k)
|
||||||
|
Write-Host "Assigning to Luis app id: $luisAppId"
|
||||||
|
$luisAssignEndpoint = "$luisEndpoint/luis/api/v2.0/apps/$luisAppId/azureaccounts"
|
||||||
|
try {
|
||||||
|
$response = Invoke-WebRequest -Method POST -ContentType application/json -Body $luisAccountBody -Uri $luisAssignEndpoint -Headers @{"Authorization" = "Bearer $token"; "Ocp-Apim-Subscription-Key" = $luisAuthoringKey } | ConvertFrom-Json
|
||||||
|
Write-Host $response
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-Host "Return invalid status code while assigning key to luis apps: $($_.Exception.Response.StatusCode.Value__), error message: $($_.Exception.Response)"
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$settings | Add-Member -Type NoteProperty -Force -Name 'feature' -Value $featureConfig
|
||||||
|
$settings | ConvertTo-Json -depth 100 | Out-File $settingsPath
|
||||||
|
|
||||||
|
$resourceGroup = "$name-$environment"
|
||||||
|
|
||||||
|
if ($?) {
|
||||||
|
# Compress source code
|
||||||
|
Get-ChildItem -Path "$($publishFolder)" | Compress-Archive -DestinationPath "$($zipPath)" -Force | Out-Null
|
||||||
|
|
||||||
|
# Publish zip to Azure
|
||||||
|
Write-Host "> Publishing to Azure ..." -ForegroundColor Green
|
||||||
|
$deployment = (az webapp deployment source config-zip `
|
||||||
|
--resource-group $resourceGroup `
|
||||||
|
--name "$name-$environment" `
|
||||||
|
--src $zipPath `
|
||||||
|
--output json) 2>> $logFile
|
||||||
|
|
||||||
|
if ($deployment) {
|
||||||
|
Write-Host "Publish Success"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Host "! Deploy failed. Review the log for more information." -ForegroundColor DarkRed
|
||||||
|
Write-Host "! Log: $($logFile)" -ForegroundColor DarkRed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Host "! Could not deploy automatically to Azure. Review the log for more information." -ForegroundColor DarkRed
|
||||||
|
Write-Host "! Log: $($logFile)" -ForegroundColor DarkRed
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
{
|
||||||
|
"name": "azure_provision",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "provision to azure cloud",
|
||||||
|
"main": "provisionComposer.js",
|
||||||
|
"license": "MIT",
|
||||||
|
"scripts": {
|
||||||
|
"start": "node provisionComposer.js"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@azure/arm-appinsights": "^2.1.0",
|
||||||
|
"@azure/arm-botservice": "^1.0.0",
|
||||||
|
"@azure/arm-resources": "^2.1.0",
|
||||||
|
"@azure/graph": "^5.0.1",
|
||||||
|
"@azure/ms-rest-nodeauth": "^3.0.3",
|
||||||
|
"@types/fs-extra": "^8.1.0",
|
||||||
|
"chalk": "^4.0.0",
|
||||||
|
"fs-extra": "^8.1.0",
|
||||||
|
"minimist": "^1.2.5",
|
||||||
|
"ora": "^4.0.4",
|
||||||
|
"request-promise": "^4.2.5"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,818 @@
|
||||||
|
// Copyright (c) Microsoft Corporation.
|
||||||
|
// Licensed under the MIT License.
|
||||||
|
const chalk = require('chalk');
|
||||||
|
const fs = require('fs-extra');
|
||||||
|
const msRestNodeAuth = require('@azure/ms-rest-nodeauth');
|
||||||
|
const argv = require('minimist')(process.argv.slice(2));
|
||||||
|
const path = require('path');
|
||||||
|
const rp = require('request-promise');
|
||||||
|
const { promisify } = require('util');
|
||||||
|
const { GraphRbacManagementClient } = require('@azure/graph');
|
||||||
|
const { ApplicationInsightsManagementClient } = require('@azure/arm-appinsights');
|
||||||
|
const { AzureBotService } = require('@azure/arm-botservice');
|
||||||
|
const { ResourceManagementClient } = require('@azure/arm-resources');
|
||||||
|
const readFile = promisify(fs.readFile);
|
||||||
|
const ora = require('ora');
|
||||||
|
|
||||||
|
const logger = (msg) => {
|
||||||
|
if (msg.status === BotProjectDeployLoggerType.PROVISION_ERROR) {
|
||||||
|
console.log(chalk.red(msg.message));
|
||||||
|
} else if (msg.status === BotProjectDeployLoggerType.PROVISION_ERROR_DETAILS) {
|
||||||
|
console.log(chalk.white(msg.message));
|
||||||
|
} else {
|
||||||
|
console.log(chalk.green(msg.message));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const usage = () => {
|
||||||
|
const options = [
|
||||||
|
['subscriptionId', 'Azure Subscription Id'],
|
||||||
|
['name', 'Project Name'],
|
||||||
|
['appPassword', '16 character password'],
|
||||||
|
['environment', 'Environment name (Defaults to dev)'],
|
||||||
|
['location', 'Azure Region (Defaults to westus)'],
|
||||||
|
['resourceGroup', 'Name of your resource group (Defaults to name-environment)'],
|
||||||
|
['appId', 'Microsoft App ID (Will create if absent)'],
|
||||||
|
['tenantId', 'ID of your tenant if required (will choose first in list by default)'],
|
||||||
|
['createLuisResource', 'Create a LUIS resource? Default true'],
|
||||||
|
['createLuisAuthoringResource', 'Create a LUIS authoring resource? Default true'],
|
||||||
|
['createCosmosDb', 'Create a CosmosDB? Default true'],
|
||||||
|
['createStorage', 'Create a storage account? Default true'],
|
||||||
|
['createAppInsights', 'Create an AppInsights resource? Default true'],
|
||||||
|
['createQnAResource', 'Create a QnA resource? Default true'],
|
||||||
|
[
|
||||||
|
'customArmTemplate',
|
||||||
|
'Path to runtime ARM template. By default it will use an Azure WebApp template. Pass `DeploymentTemplates/function-template-with-preexisting-rg.json` for Azure Functions or your own template for a custom deployment.',
|
||||||
|
],
|
||||||
|
['qnaTemplate', 'Path to qna template. By default it will use `DeploymentTemplates/qna-template.json`'],
|
||||||
|
];
|
||||||
|
|
||||||
|
const instructions = [
|
||||||
|
``,
|
||||||
|
chalk.bold('Provision Azure resources for use with Bot Framework Composer bots'),
|
||||||
|
`* This script will create a new resource group and the necessary Azure resources needed to operate a Bot Framework bot in the cloud.`,
|
||||||
|
`* Use this to create a publishing profile used in Composer's "Publish" toolbar.`,
|
||||||
|
``,
|
||||||
|
chalk.bold(`Basic Usage:`),
|
||||||
|
chalk.greenBright(`node provisionComposer --subscriptionId=`) +
|
||||||
|
chalk.yellow('<Azure Subscription Id>') +
|
||||||
|
chalk.greenBright(' --name=') +
|
||||||
|
chalk.yellow('<Name for your environment>') +
|
||||||
|
chalk.greenBright(' --appPassword=') +
|
||||||
|
chalk.yellow('<16 character password>'),
|
||||||
|
``,
|
||||||
|
chalk.bold(`All options:`),
|
||||||
|
...options.map((option) => {
|
||||||
|
return chalk.greenBright('--' + option[0]) + '\t' + chalk.yellow(option[1]);
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
|
||||||
|
console.log(instructions.join('\n'));
|
||||||
|
};
|
||||||
|
|
||||||
|
// check for required parameters
|
||||||
|
if (Object.keys(argv).length === 0) {
|
||||||
|
return usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!argv.name || !argv.subscriptionId || !argv.appPassword) {
|
||||||
|
return usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get required fields from the arguments
|
||||||
|
const subId = argv.subscriptionId;
|
||||||
|
const name = argv.name.toString();
|
||||||
|
const appPassword = argv.appPassword;
|
||||||
|
|
||||||
|
// Get optional fields from the arguments
|
||||||
|
const environment = argv.environment || 'dev';
|
||||||
|
const location = argv.location || 'westus';
|
||||||
|
const appId = argv.appId; // MicrosoftAppId - generated if left blank
|
||||||
|
|
||||||
|
// Get option flags
|
||||||
|
const createLuisResource = argv.createLuisResource == 'false' ? false : true;
|
||||||
|
const createLuisAuthoringResource = argv.createLuisAuthoringResource == 'false' ? false : true;
|
||||||
|
const createCosmosDb = argv.createCosmosDb == 'false' ? false : true;
|
||||||
|
const createStorage = argv.createStorage == 'false' ? false : true;
|
||||||
|
const createAppInsights = argv.createAppInsights == 'false' ? false : true;
|
||||||
|
const createQnAResource = argv.createQnAResource == 'false' ? false : true;
|
||||||
|
var tenantId = argv.tenantId ? argv.tenantId : '';
|
||||||
|
|
||||||
|
const templatePath =
|
||||||
|
argv.customArmTemplate || path.join(__dirname, 'DeploymentTemplates', 'template-with-preexisting-rg.json');
|
||||||
|
const qnaTemplatePath = argv.qnaTemplate || path.join(__dirname, 'DeploymentTemplates', 'qna-template.json');
|
||||||
|
const resourceGroup = argv.resourceGroup || `${name}-${environment}`;
|
||||||
|
|
||||||
|
const BotProjectDeployLoggerType = {
|
||||||
|
// Logger Type for Provision
|
||||||
|
PROVISION_INFO: 'PROVISION_INFO',
|
||||||
|
PROVISION_ERROR: 'PROVISION_ERROR',
|
||||||
|
PROVISION_WARNING: 'PROVISION_WARNING',
|
||||||
|
PROVISION_SUCCESS: 'PROVISION_SUCCESS',
|
||||||
|
PROVISION_ERROR_DETAILS: 'PROVISION_ERROR_DETAILS',
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a Bot Framework registration
|
||||||
|
* @param {} graphClient
|
||||||
|
* @param {*} displayName
|
||||||
|
* @param {*} appPassword
|
||||||
|
*/
|
||||||
|
const createApp = async (graphClient, displayName, appPassword) => {
|
||||||
|
try {
|
||||||
|
const createRes = await graphClient.applications.create({
|
||||||
|
displayName: displayName,
|
||||||
|
passwordCredentials: [
|
||||||
|
{
|
||||||
|
value: appPassword,
|
||||||
|
startDate: new Date(),
|
||||||
|
endDate: new Date(new Date().setFullYear(new Date().getFullYear() + 2)),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
availableToOtherTenants: true,
|
||||||
|
replyUrls: ['https://token.botframework.com/.auth/web/redirect'],
|
||||||
|
});
|
||||||
|
return createRes;
|
||||||
|
} catch (err) {
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_ERROR,
|
||||||
|
message: err.body.message,
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an Azure resources group
|
||||||
|
* @param {} client
|
||||||
|
* @param {*} location
|
||||||
|
* @param {*} resourceGroupName
|
||||||
|
*/
|
||||||
|
const createResourceGroup = async (client, location, resourceGroupName) => {
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_INFO,
|
||||||
|
message: `> Creating resource group ...`,
|
||||||
|
});
|
||||||
|
const param = {
|
||||||
|
location: location,
|
||||||
|
};
|
||||||
|
|
||||||
|
return await client.resourceGroups.createOrUpdate(resourceGroupName, param);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format parameters
|
||||||
|
* @param {} scope
|
||||||
|
*/
|
||||||
|
const pack = (scope) => {
|
||||||
|
return {
|
||||||
|
value: scope,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const unpackObject = (output) => {
|
||||||
|
const unpacked = {};
|
||||||
|
for (const key in output) {
|
||||||
|
const objValue = output[key];
|
||||||
|
if (objValue.value) {
|
||||||
|
unpacked[key] = objValue.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return unpacked;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For more information about this api, please refer to this doc: https://docs.microsoft.com/en-us/rest/api/resources/Tenants/List
|
||||||
|
* @param {*} accessToken
|
||||||
|
*/
|
||||||
|
const getTenantId = async (accessToken) => {
|
||||||
|
if (!accessToken) {
|
||||||
|
throw new Error(
|
||||||
|
'Error: Missing access token. Please provide a non-expired Azure access token. Tokens can be obtained by running az account get-access-token'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!subId) {
|
||||||
|
throw new Error(`Error: Missing subscription Id. Please provide a valid Azure subscription id.`);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const tenantUrl = `https://management.azure.com/subscriptions/${subId}?api-version=2020-01-01`;
|
||||||
|
const options = {
|
||||||
|
headers: { Authorization: `Bearer ${accessToken}` },
|
||||||
|
};
|
||||||
|
const response = await rp.get(tenantUrl, options);
|
||||||
|
const jsonRes = JSON.parse(response);
|
||||||
|
if (jsonRes.tenantId === undefined) {
|
||||||
|
throw new Error(`No tenants found in the account.`);
|
||||||
|
}
|
||||||
|
return jsonRes.tenantId;
|
||||||
|
} catch (err) {
|
||||||
|
throw new Error(`Get Tenant Id Failed, details: ${getErrorMesssage(err)}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {*} appId the appId of application registration
|
||||||
|
* @param {*} appPwd the app password of application registration
|
||||||
|
* @param {*} location the locaiton of all resources
|
||||||
|
* @param {*} name the name of resource group
|
||||||
|
* @param {*} shouldCreateAuthoringResource
|
||||||
|
* @param {*} shouldCreateLuisResource
|
||||||
|
* @param {*} useAppInsights
|
||||||
|
* @param {*} useCosmosDb
|
||||||
|
* @param {*} useStorage
|
||||||
|
*/
|
||||||
|
const getDeploymentTemplateParam = (
|
||||||
|
appId,
|
||||||
|
appPwd,
|
||||||
|
location,
|
||||||
|
name,
|
||||||
|
shouldCreateAuthoringResource,
|
||||||
|
shouldCreateLuisResource,
|
||||||
|
useAppInsights,
|
||||||
|
useCosmosDb,
|
||||||
|
useStorage
|
||||||
|
) => {
|
||||||
|
return {
|
||||||
|
appId: pack(appId),
|
||||||
|
appSecret: pack(appPwd),
|
||||||
|
appServicePlanLocation: pack(location),
|
||||||
|
botId: pack(name),
|
||||||
|
shouldCreateAuthoringResource: pack(shouldCreateAuthoringResource),
|
||||||
|
shouldCreateLuisResource: pack(shouldCreateLuisResource),
|
||||||
|
useAppInsights: pack(useAppInsights),
|
||||||
|
useCosmosDb: pack(useCosmosDb),
|
||||||
|
useStorage: pack(useStorage),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get QnA template param
|
||||||
|
*/
|
||||||
|
const getQnaTemplateParam = (location, name) => {
|
||||||
|
return {
|
||||||
|
appServicePlanLocation: pack(location),
|
||||||
|
name: pack(name),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate the qna template and the qna template param
|
||||||
|
*/
|
||||||
|
const validateQnADeployment = async (client, resourceGroupName, deployName, templateParam) => {
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_INFO,
|
||||||
|
message: '> Validating QnA deployment ...',
|
||||||
|
});
|
||||||
|
|
||||||
|
const templateFile = await readFile(qnaTemplatePath, { encoding: 'utf-8' });
|
||||||
|
const deployParam = {
|
||||||
|
properties: {
|
||||||
|
template: JSON.parse(templateFile),
|
||||||
|
parameters: templateParam,
|
||||||
|
mode: 'Incremental',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return await client.deployments.validate(resourceGroupName, deployName, deployParam);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a QnA resource deployment
|
||||||
|
* @param {*} client
|
||||||
|
* @param {*} resourceGroupName
|
||||||
|
* @param {*} deployName
|
||||||
|
* @param {*} templateParam
|
||||||
|
*/
|
||||||
|
const createQnADeployment = async (client, resourceGroupName, deployName, templateParam) => {
|
||||||
|
const templateFile = await readFile(qnaTemplatePath, { encoding: 'utf-8' });
|
||||||
|
const deployParam = {
|
||||||
|
properties: {
|
||||||
|
template: JSON.parse(templateFile),
|
||||||
|
parameters: templateParam,
|
||||||
|
mode: 'Incremental',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return await client.deployments.createOrUpdate(resourceGroupName, deployName, deployParam);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate the deployment using the Azure API
|
||||||
|
*/
|
||||||
|
const validateDeployment = async (client, resourceGroupName, deployName, templateParam) => {
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_INFO,
|
||||||
|
message: '> Validating Azure deployment ...',
|
||||||
|
});
|
||||||
|
|
||||||
|
const templateFile = await readFile(templatePath, { encoding: 'utf-8' });
|
||||||
|
const deployParam = {
|
||||||
|
properties: {
|
||||||
|
template: JSON.parse(templateFile),
|
||||||
|
parameters: templateParam,
|
||||||
|
mode: 'Incremental',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return await client.deployments.validate(resourceGroupName, deployName, deployParam);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Using an ARM template, provision a bunch of resources
|
||||||
|
*/
|
||||||
|
const createDeployment = async (client, resourceGroupName, deployName, templateParam) => {
|
||||||
|
const templateFile = await readFile(templatePath, { encoding: 'utf-8' });
|
||||||
|
const deployParam = {
|
||||||
|
properties: {
|
||||||
|
template: JSON.parse(templateFile),
|
||||||
|
parameters: templateParam,
|
||||||
|
mode: 'Incremental',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return await client.deployments.createOrUpdate(resourceGroupName, deployName, deployParam);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format the results into the expected shape
|
||||||
|
*/
|
||||||
|
const updateDeploymentJsonFile = async (client, resourceGroupName, deployName, appId, appPwd) => {
|
||||||
|
const outputs = await client.deployments.get(resourceGroupName, deployName);
|
||||||
|
if (outputs && outputs.properties && outputs.properties.outputs) {
|
||||||
|
const outputResult = outputs.properties.outputs;
|
||||||
|
const applicationResult = {
|
||||||
|
MicrosoftAppId: appId,
|
||||||
|
MicrosoftAppPassword: appPwd,
|
||||||
|
};
|
||||||
|
const outputObj = unpackObject(outputResult);
|
||||||
|
|
||||||
|
if (!createAppInsights) {
|
||||||
|
delete outputObj.applicationInsights;
|
||||||
|
}
|
||||||
|
if (!createCosmosDb) {
|
||||||
|
delete outputObj.cosmosDb;
|
||||||
|
}
|
||||||
|
if (!createLuisAuthoringResource && !createLuisResource) {
|
||||||
|
delete outputObj.luis;
|
||||||
|
}
|
||||||
|
if (!createStorage) {
|
||||||
|
delete outputObj.blobStorage;
|
||||||
|
}
|
||||||
|
const result = {};
|
||||||
|
Object.assign(result, outputObj, applicationResult);
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const provisionFailed = (msg) => {
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_ERROR,
|
||||||
|
message: chalk.bold('** Provision failed **'),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const getErrorMesssage = (err) => {
|
||||||
|
if (err.body) {
|
||||||
|
if (err.body.error) {
|
||||||
|
if (err.body.error.details) {
|
||||||
|
const details = err.body.error.details;
|
||||||
|
let errMsg = '';
|
||||||
|
for (let detail of details) {
|
||||||
|
errMsg += detail.message;
|
||||||
|
}
|
||||||
|
return errMsg;
|
||||||
|
} else {
|
||||||
|
return err.body.error.message;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return JSON.stringify(err.body, null, 2);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return JSON.stringify(err, null, 2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provision a set of Azure resources for use with a bot
|
||||||
|
*/
|
||||||
|
const create = async (
|
||||||
|
creds,
|
||||||
|
subId,
|
||||||
|
name,
|
||||||
|
location,
|
||||||
|
environment,
|
||||||
|
appId,
|
||||||
|
appPassword,
|
||||||
|
createLuisResource = true,
|
||||||
|
createLuisAuthoringResource = true,
|
||||||
|
createQnAResource = true,
|
||||||
|
createCosmosDb = true,
|
||||||
|
createStorage = true,
|
||||||
|
createAppInsights = true
|
||||||
|
) => {
|
||||||
|
// App insights is a dependency of QnA
|
||||||
|
if (createQnAResource) {
|
||||||
|
createAppInsights = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const resourceGroupName = resourceGroup;
|
||||||
|
|
||||||
|
// If tenantId is empty string, get tenanId from API
|
||||||
|
if (!tenantId) {
|
||||||
|
const token = await creds.getToken();
|
||||||
|
const accessToken = token.accessToken;
|
||||||
|
// the returned access token will almost surely have a tenantId.
|
||||||
|
// use this as the default if one isn't specified.
|
||||||
|
if (token.tenantId) {
|
||||||
|
tenantId = token.tenantId;
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_INFO,
|
||||||
|
message: `> Using Tenant ID: ${tenantId}`,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
tenantId = await getTenantId(accessToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const graphCreds = new msRestNodeAuth.DeviceTokenCredentials(
|
||||||
|
creds.clientId,
|
||||||
|
tenantId,
|
||||||
|
creds.username,
|
||||||
|
'graph',
|
||||||
|
creds.environment,
|
||||||
|
creds.tokenCache
|
||||||
|
);
|
||||||
|
const graphClient = new GraphRbacManagementClient(graphCreds, tenantId, {
|
||||||
|
baseUri: 'https://graph.windows.net',
|
||||||
|
});
|
||||||
|
|
||||||
|
// If the appId is not specified, create one
|
||||||
|
if (!appId) {
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_INFO,
|
||||||
|
message: '> Creating App Registration ...',
|
||||||
|
});
|
||||||
|
|
||||||
|
// create the app registration
|
||||||
|
const appCreated = await createApp(graphClient, name, appPassword);
|
||||||
|
if (appCreated === false) {
|
||||||
|
return provisionFailed();
|
||||||
|
}
|
||||||
|
|
||||||
|
// use the newly created app
|
||||||
|
appId = appCreated.appId;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_INFO,
|
||||||
|
message: `> Create App Id Success! ID: ${appId}`,
|
||||||
|
});
|
||||||
|
|
||||||
|
// timestamp will be used as deployment name
|
||||||
|
const timeStamp = new Date().getTime().toString();
|
||||||
|
const client = new ResourceManagementClient(creds, subId);
|
||||||
|
|
||||||
|
// Create a resource group to contain the new resources
|
||||||
|
try {
|
||||||
|
const rpres = await createResourceGroup(client, location, resourceGroupName);
|
||||||
|
} catch (err) {
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_ERROR,
|
||||||
|
message: getErrorMesssage(err),
|
||||||
|
});
|
||||||
|
return provisionFailed();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Caste the parameters into the right format
|
||||||
|
const deploymentTemplateParam = getDeploymentTemplateParam(
|
||||||
|
appId,
|
||||||
|
appPassword,
|
||||||
|
location,
|
||||||
|
name,
|
||||||
|
createLuisAuthoringResource,
|
||||||
|
createLuisResource,
|
||||||
|
createAppInsights,
|
||||||
|
createCosmosDb,
|
||||||
|
createStorage
|
||||||
|
);
|
||||||
|
|
||||||
|
// Validate the deployment using the Azure API
|
||||||
|
const validation = await validateDeployment(client, resourceGroupName, timeStamp, deploymentTemplateParam);
|
||||||
|
|
||||||
|
// Handle validation errors
|
||||||
|
if (validation.error) {
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_ERROR,
|
||||||
|
message: `! Error: ${validation.error.message}`,
|
||||||
|
});
|
||||||
|
if (validation.error.details) {
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_ERROR_DETAILS,
|
||||||
|
message: JSON.stringify(validation.error.details, null, 2),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_ERROR,
|
||||||
|
message: `+ To delete this resource group, run 'az group delete -g ${resourceGroupName} --no-wait'`,
|
||||||
|
});
|
||||||
|
return provisionFailed();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the entire stack of resources inside the new resource group
|
||||||
|
// this is controlled by an ARM template identified in templatePath
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_INFO,
|
||||||
|
message: `> Deploying Azure services (this could take a while)...`,
|
||||||
|
});
|
||||||
|
const spinner = ora().start();
|
||||||
|
try {
|
||||||
|
const deployment = await createDeployment(client, resourceGroupName, timeStamp, deploymentTemplateParam);
|
||||||
|
// Handle errors
|
||||||
|
if (deployment._response.status != 200) {
|
||||||
|
spinner.fail();
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_ERROR,
|
||||||
|
message: `! Template is not valid with provided parameters. Review the log for more information.`,
|
||||||
|
});
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_ERROR,
|
||||||
|
message: `! Error: ${validation.error}`,
|
||||||
|
});
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_ERROR,
|
||||||
|
message: `+ To delete this resource group, run 'az group delete -g ${resourceGroupName} --no-wait'`,
|
||||||
|
});
|
||||||
|
return provisionFailed();
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
spinner.fail();
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_ERROR,
|
||||||
|
message: getErrorMesssage(err),
|
||||||
|
});
|
||||||
|
return provisionFailed();
|
||||||
|
}
|
||||||
|
|
||||||
|
var qnaResult = null;
|
||||||
|
|
||||||
|
// Create qna resources, the reason why seperate the qna resources from others: https://github.com/Azure/azure-sdk-for-js/issues/10186
|
||||||
|
if (createQnAResource) {
|
||||||
|
const qnaDeployName = new Date().getTime().toString();
|
||||||
|
const qnaDeploymentTemplateParam = getQnaTemplateParam(location, name);
|
||||||
|
const qnaValidation = await validateQnADeployment(
|
||||||
|
client,
|
||||||
|
resourceGroupName,
|
||||||
|
qnaDeployName,
|
||||||
|
qnaDeploymentTemplateParam
|
||||||
|
);
|
||||||
|
if (qnaValidation.error) {
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_ERROR,
|
||||||
|
message: `! Error: ${qnaValidation.error.message}`,
|
||||||
|
});
|
||||||
|
if (qnaValidation.error.details) {
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_ERROR_DETAILS,
|
||||||
|
message: JSON.stringify(qnaValidation.error.details, null, 2),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_ERROR,
|
||||||
|
message: `+ To delete this resource group, run 'az group delete -g ${resourceGroupName} --no-wait'`,
|
||||||
|
});
|
||||||
|
return provisionFailed();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create qna deloyment
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_INFO,
|
||||||
|
message: `> Deploying QnA Resources (this could take a while)...`,
|
||||||
|
});
|
||||||
|
const spinner = ora().start();
|
||||||
|
try {
|
||||||
|
const qnaDeployment = await createQnADeployment(
|
||||||
|
client,
|
||||||
|
resourceGroupName,
|
||||||
|
qnaDeployName,
|
||||||
|
qnaDeploymentTemplateParam
|
||||||
|
);
|
||||||
|
// Handle errors
|
||||||
|
if (qnaDeployment._response.status != 200) {
|
||||||
|
spinner.fail();
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_ERROR,
|
||||||
|
message: `! QnA Template is not valid with provided parameters. Review the log for more information.`,
|
||||||
|
});
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_ERROR,
|
||||||
|
message: `! Error: ${qnaValidation.error}`,
|
||||||
|
});
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_ERROR,
|
||||||
|
message: `+ To delete this resource group, run 'az group delete -g ${resourceGroupName} --no-wait'`,
|
||||||
|
});
|
||||||
|
return provisionFailed();
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
spinner.fail();
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_ERROR,
|
||||||
|
message: getErrorMesssage(err),
|
||||||
|
});
|
||||||
|
return provisionFailed();
|
||||||
|
}
|
||||||
|
|
||||||
|
const qnaDeploymentOutput = await client.deployments.get(resourceGroupName, qnaDeployName);
|
||||||
|
if (qnaDeploymentOutput && qnaDeploymentOutput.properties && qnaDeploymentOutput.properties.outputs) {
|
||||||
|
const qnaOutputResult = qnaDeploymentOutput.properties.outputs;
|
||||||
|
qnaResult = unpackObject(qnaOutputResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If application insights created, update the application insights settings in azure bot service
|
||||||
|
if (createAppInsights) {
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_INFO,
|
||||||
|
message: `> Linking Application Insights settings to Bot Service ...`,
|
||||||
|
});
|
||||||
|
|
||||||
|
const appinsightsClient = new ApplicationInsightsManagementClient(creds, subId);
|
||||||
|
const appComponents = await appinsightsClient.components.get(resourceGroupName, resourceGroupName);
|
||||||
|
const appinsightsId = appComponents.appId;
|
||||||
|
const appinsightsInstrumentationKey = appComponents.instrumentationKey;
|
||||||
|
const apiKeyOptions = {
|
||||||
|
name: `${resourceGroupName}-provision-${timeStamp}`,
|
||||||
|
linkedReadProperties: [
|
||||||
|
`/subscriptions/${subId}/resourceGroups/${resourceGroupName}/providers/microsoft.insights/components/${resourceGroupName}/api`,
|
||||||
|
`/subscriptions/${subId}/resourceGroups/${resourceGroupName}/providers/microsoft.insights/components/${resourceGroupName}/agentconfig`,
|
||||||
|
],
|
||||||
|
linkedWriteProperties: [
|
||||||
|
`/subscriptions/${subId}/resourceGroups/${resourceGroupName}/providers/microsoft.insights/components/${resourceGroupName}/annotations`,
|
||||||
|
],
|
||||||
|
};
|
||||||
|
const appinsightsApiKeyResponse = await appinsightsClient.aPIKeys.create(
|
||||||
|
resourceGroupName,
|
||||||
|
resourceGroupName,
|
||||||
|
apiKeyOptions
|
||||||
|
);
|
||||||
|
const appinsightsApiKey = appinsightsApiKeyResponse.apiKey;
|
||||||
|
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_INFO,
|
||||||
|
message: `> AppInsights AppId: ${appinsightsId} ...`,
|
||||||
|
});
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_INFO,
|
||||||
|
message: `> AppInsights InstrumentationKey: ${appinsightsInstrumentationKey} ...`,
|
||||||
|
});
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_INFO,
|
||||||
|
message: `> AppInsights ApiKey: ${appinsightsApiKey} ...`,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (appinsightsId && appinsightsInstrumentationKey && appinsightsApiKey) {
|
||||||
|
const botServiceClient = new AzureBotService(creds, subId);
|
||||||
|
const botCreated = await botServiceClient.bots.get(resourceGroupName, name);
|
||||||
|
if (botCreated.properties) {
|
||||||
|
botCreated.properties.developerAppInsightKey = appinsightsInstrumentationKey;
|
||||||
|
botCreated.properties.developerAppInsightsApiKey = appinsightsApiKey;
|
||||||
|
botCreated.properties.developerAppInsightsApplicationId = appinsightsId;
|
||||||
|
const botUpdateResult = await botServiceClient.bots.update(resourceGroupName, name, botCreated);
|
||||||
|
|
||||||
|
if (botUpdateResult._response.status != 200) {
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_ERROR,
|
||||||
|
message: `! Something went wrong while trying to link Application Insights settings to Bot Service Result: ${JSON.stringify(
|
||||||
|
botUpdateResult
|
||||||
|
)}`,
|
||||||
|
});
|
||||||
|
throw new Error(`Linking Application Insights Failed.`);
|
||||||
|
}
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_INFO,
|
||||||
|
message: `> Linking Application Insights settings to Bot Service Success!`,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_WARNING,
|
||||||
|
message: `! The Bot doesn't have a keys properties to update.`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
spinner.succeed('Success!');
|
||||||
|
|
||||||
|
// Validate that everything was successfully created.
|
||||||
|
// Then, update the settings file with information about the new resources
|
||||||
|
const updateResult = await updateDeploymentJsonFile(client, resourceGroupName, timeStamp, appId, appPassword);
|
||||||
|
|
||||||
|
// Handle errors
|
||||||
|
if (!updateResult) {
|
||||||
|
const operations = await client.deploymentOperations.list(resourceGroupName, timeStamp);
|
||||||
|
if (operations) {
|
||||||
|
const failedOperations = operations.filter(
|
||||||
|
(value) => value && value.properties && value.properties.statusMessage.error !== null
|
||||||
|
);
|
||||||
|
if (failedOperations) {
|
||||||
|
failedOperations.forEach((operation) => {
|
||||||
|
switch (
|
||||||
|
operation &&
|
||||||
|
operation.properties &&
|
||||||
|
operation.properties.statusMessage.error.code &&
|
||||||
|
operation.properties.targetResource
|
||||||
|
) {
|
||||||
|
case 'MissingRegistrationForLocation':
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_ERROR,
|
||||||
|
message: `! Deployment failed for resource of type ${operation.properties.targetResource.resourceType}. This resource is not avaliable in the location provided.`,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_ERROR,
|
||||||
|
message: `! Deployment failed for resource of type ${operation.properties.targetResource.resourceType}.`,
|
||||||
|
});
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_ERROR,
|
||||||
|
message: `! Code: ${operation.properties.statusMessage.error.code}.`,
|
||||||
|
});
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_ERROR,
|
||||||
|
message: `! Message: ${operation.properties.statusMessage.error.message}.`,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger({
|
||||||
|
status: BotProjectDeployLoggerType.PROVISION_ERROR,
|
||||||
|
message: `! Deployment failed. Please refer to the log file for more information.`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge qna outputs with other resources' outputs
|
||||||
|
if (createQnAResource) {
|
||||||
|
if (qnaResult) {
|
||||||
|
Object.assign(updateResult, qnaResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return updateResult;
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log(chalk.bold('Login to Azure:'));
|
||||||
|
msRestNodeAuth
|
||||||
|
.interactiveLogin({ domain: tenantId })
|
||||||
|
.then(async (creds) => {
|
||||||
|
const createResult = await create(
|
||||||
|
creds,
|
||||||
|
subId,
|
||||||
|
name,
|
||||||
|
location,
|
||||||
|
environment,
|
||||||
|
appId,
|
||||||
|
appPassword,
|
||||||
|
createLuisResource,
|
||||||
|
createLuisAuthoringResource,
|
||||||
|
createQnAResource,
|
||||||
|
createCosmosDb,
|
||||||
|
createStorage,
|
||||||
|
createAppInsights
|
||||||
|
);
|
||||||
|
|
||||||
|
if (createResult) {
|
||||||
|
console.log('');
|
||||||
|
console.log(
|
||||||
|
chalk.bold(
|
||||||
|
`Your Azure hosting environment has been created! Copy paste the following configuration into a new profile in Composer's Publishing tab.`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
console.log('');
|
||||||
|
|
||||||
|
const token = await creds.getToken();
|
||||||
|
const profile = {
|
||||||
|
accessToken: token.accessToken,
|
||||||
|
name: name,
|
||||||
|
environment: environment,
|
||||||
|
hostname: `${name}-${environment}`,
|
||||||
|
luisResource: `${name}-${environment}-luis`,
|
||||||
|
settings: createResult,
|
||||||
|
runtimeIdentifier: 'win-x64',
|
||||||
|
resourceGroup: resourceGroup,
|
||||||
|
botName: name,
|
||||||
|
region: location,
|
||||||
|
subscriptionId: subId,
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log(chalk.white(JSON.stringify(profile, null, 2)));
|
||||||
|
|
||||||
|
console.log('');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(err);
|
||||||
|
});
|
|
@ -0,0 +1,56 @@
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.StaticFiles;
|
||||||
|
using Microsoft.Bot.Builder.Dialogs.Adaptive.Runtime.Extensions;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
|
||||||
|
namespace OrchestratorDispatch
|
||||||
|
{
|
||||||
|
public class Startup
|
||||||
|
{
|
||||||
|
public Startup(IConfiguration configuration)
|
||||||
|
{
|
||||||
|
Configuration = configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IConfiguration Configuration { get; }
|
||||||
|
|
||||||
|
// This method gets called by the runtime. Use this method to add services to the container.
|
||||||
|
public void ConfigureServices(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddControllers().AddNewtonsoftJson();
|
||||||
|
services.AddBotRuntime(Configuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
|
||||||
|
// Set up custom content types - associating file extension to MIME type.
|
||||||
|
var provider = new FileExtensionContentTypeProvider();
|
||||||
|
provider.Mappings[".lu"] = "application/vnd.microsoft.lu";
|
||||||
|
provider.Mappings[".qna"] = "application/vnd.microsoft.qna";
|
||||||
|
|
||||||
|
// Expose static files in manifests folder for skill scenarios.
|
||||||
|
app.UseStaticFiles(new StaticFileOptions
|
||||||
|
{
|
||||||
|
ContentTypeProvider = provider
|
||||||
|
});
|
||||||
|
app.UseWebSockets();
|
||||||
|
app.UseRouting();
|
||||||
|
app.UseAuthorization();
|
||||||
|
app.UseEndpoints(endpoints =>
|
||||||
|
{
|
||||||
|
endpoints.MapControllers();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,244 @@
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.AdaptiveDialog",
|
||||||
|
"$designer": {
|
||||||
|
"id": "wVxMxC",
|
||||||
|
"name": "PartnersDialog",
|
||||||
|
"description": ""
|
||||||
|
},
|
||||||
|
"autoEndDialog": true,
|
||||||
|
"defaultResultProperty": "dialog.result",
|
||||||
|
"triggers": [
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.OnBeginDialog",
|
||||||
|
"$designer": {
|
||||||
|
"name": "BeginDialog",
|
||||||
|
"description": "",
|
||||||
|
"id": "1BtyxI"
|
||||||
|
},
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.SendActivity",
|
||||||
|
"$designer": {
|
||||||
|
"id": "hUgNsF"
|
||||||
|
},
|
||||||
|
"activity": "${SendActivity_hUgNsF()}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.TextInput",
|
||||||
|
"$designer": {
|
||||||
|
"id": "KpFrxh"
|
||||||
|
},
|
||||||
|
"disabled": false,
|
||||||
|
"maxTurnCount": 3,
|
||||||
|
"alwaysPrompt": true,
|
||||||
|
"allowInterruptions": true,
|
||||||
|
"unrecognizedPrompt": "",
|
||||||
|
"invalidPrompt": "",
|
||||||
|
"prompt": "${TextInput_Prompt_KpFrxh()}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.RepeatDialog",
|
||||||
|
"$designer": {
|
||||||
|
"id": "p11WI1"
|
||||||
|
},
|
||||||
|
"activityProcessed": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.OnIntent",
|
||||||
|
"$designer": {
|
||||||
|
"id": "mJDyaJ",
|
||||||
|
"name": "General"
|
||||||
|
},
|
||||||
|
"intent": "General",
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.SendActivity",
|
||||||
|
"$designer": {
|
||||||
|
"id": "KLQrcx"
|
||||||
|
},
|
||||||
|
"activity": "${SendActivity_KLQrcx()}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.ChoiceInput",
|
||||||
|
"$designer": {
|
||||||
|
"id": "GYWo8v"
|
||||||
|
},
|
||||||
|
"defaultLocale": "en-us",
|
||||||
|
"disabled": false,
|
||||||
|
"maxTurnCount": 3,
|
||||||
|
"alwaysPrompt": true,
|
||||||
|
"allowInterruptions": false,
|
||||||
|
"prompt": "${ChoiceInput_Prompt_GYWo8v()}",
|
||||||
|
"unrecognizedPrompt": "",
|
||||||
|
"invalidPrompt": "",
|
||||||
|
"choiceOptions": {
|
||||||
|
"includeNumbers": true,
|
||||||
|
"inlineOrMore": ", or ",
|
||||||
|
"inlineOr": " or "
|
||||||
|
},
|
||||||
|
"property": "dialog.partnerchoice",
|
||||||
|
"choices": [
|
||||||
|
"Power Virtual Agents",
|
||||||
|
"HealthBot"
|
||||||
|
],
|
||||||
|
"recognizerOptions": {
|
||||||
|
"recognizeOrdinals": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.SwitchCondition",
|
||||||
|
"$designer": {
|
||||||
|
"id": "9ypVLZ"
|
||||||
|
},
|
||||||
|
"condition": "dialog.partnerchoice",
|
||||||
|
"cases": [
|
||||||
|
{
|
||||||
|
"value": "Power Virtual Agents",
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.SendActivity",
|
||||||
|
"$designer": {
|
||||||
|
"id": "wJ1PQA"
|
||||||
|
},
|
||||||
|
"activity": "${SendActivity_wJ1PQA()}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "HealthBot",
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.SendActivity",
|
||||||
|
"$designer": {
|
||||||
|
"id": "AlVsyO"
|
||||||
|
},
|
||||||
|
"activity": "${SendActivity_AlVsyO()}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "No Thanks",
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.SendActivity",
|
||||||
|
"$designer": {
|
||||||
|
"id": "8ovgUu"
|
||||||
|
},
|
||||||
|
"activity": "${SendActivity_8ovgUu()}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": [
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.SendActivity",
|
||||||
|
"$designer": {
|
||||||
|
"id": "TK2gtL"
|
||||||
|
},
|
||||||
|
"activity": "${SendActivity_TK2gtL()}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.OnUnknownIntent",
|
||||||
|
"$designer": {
|
||||||
|
"id": "0p0e7t"
|
||||||
|
},
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.SendActivity",
|
||||||
|
"$designer": {
|
||||||
|
"id": "ZV3rta"
|
||||||
|
},
|
||||||
|
"activity": "${SendActivity_ZV3rta()}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.OnIntent",
|
||||||
|
"$designer": {
|
||||||
|
"id": "Xq7yE9",
|
||||||
|
"name": "exit"
|
||||||
|
},
|
||||||
|
"intent": "exit",
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.SendActivity",
|
||||||
|
"$designer": {
|
||||||
|
"id": "lzlH8N"
|
||||||
|
},
|
||||||
|
"activity": "${SendActivity_lzlH8N()}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.EndDialog",
|
||||||
|
"$designer": {
|
||||||
|
"id": "l99ma4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.OnIntent",
|
||||||
|
"$designer": {
|
||||||
|
"id": "o66cYm",
|
||||||
|
"name": "Healthbot"
|
||||||
|
},
|
||||||
|
"intent": "Healthbot",
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.SendActivity",
|
||||||
|
"$designer": {
|
||||||
|
"id": "mroxNS"
|
||||||
|
},
|
||||||
|
"activity": "${SendActivity_mroxNS()}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.SendActivity",
|
||||||
|
"$designer": {
|
||||||
|
"id": "0wl8Dt"
|
||||||
|
},
|
||||||
|
"activity": "${SendActivity_0wl8Dt()}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.OnIntent",
|
||||||
|
"$designer": {
|
||||||
|
"id": "kJsfR9",
|
||||||
|
"name": "PVA"
|
||||||
|
},
|
||||||
|
"intent": "PVA",
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.SendActivity",
|
||||||
|
"$designer": {
|
||||||
|
"id": "6ZhSsX"
|
||||||
|
},
|
||||||
|
"activity": "${SendActivity_6ZhSsX()}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.SendActivity",
|
||||||
|
"$designer": {
|
||||||
|
"id": "TOU1P5"
|
||||||
|
},
|
||||||
|
"activity": "${SendActivity_TOU1P5()}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.OnIntent",
|
||||||
|
"$designer": {
|
||||||
|
"id": "BP2yIj",
|
||||||
|
"name": "None"
|
||||||
|
},
|
||||||
|
"intent": "None"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"generator": "PartnersDialog.lg",
|
||||||
|
"recognizer": "PartnersDialog.lu.qna",
|
||||||
|
"id": "PartnersDialog"
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
[import](common.lg)
|
||||||
|
|
||||||
|
# SendActivity_hUgNsF()
|
||||||
|
[Activity
|
||||||
|
Text = **Partners Information (_LUIS recognizer_)**
|
||||||
|
]
|
||||||
|
|
||||||
|
# TextInput_Prompt_KpFrxh()
|
||||||
|
[Activity
|
||||||
|
Text = Ask me about Bot Framework partner teams within Microsoft now (_exit_ when done) >>
|
||||||
|
]
|
||||||
|
|
||||||
|
# SendActivity_KLQrcx()
|
||||||
|
[Activity
|
||||||
|
Text = Bot Framework is the foundation for the following teams:\r- Power Virtual Agents\r- HealthBot
|
||||||
|
]
|
||||||
|
|
||||||
|
# ChoiceInput_Prompt_GYWo8v()
|
||||||
|
[Activity
|
||||||
|
Text = What do you want to know more about?
|
||||||
|
]
|
||||||
|
|
||||||
|
# SendActivity_wJ1PQA()
|
||||||
|
[Activity
|
||||||
|
Text = To learn more aobut PVA see the following: https://powervirtualagents.microsoft.com/en-us/
|
||||||
|
]
|
||||||
|
|
||||||
|
# SendActivity_AlVsyO()
|
||||||
|
[Activity
|
||||||
|
Text = To learn more about HealthBot see the following: https://www.microsoft.com/en-us/research/project/health-bot/
|
||||||
|
]
|
||||||
|
|
||||||
|
# SendActivity_8ovgUu()
|
||||||
|
[Activity
|
||||||
|
Text = Got you. You can always do a Bing search for more :)
|
||||||
|
]
|
||||||
|
|
||||||
|
# SendActivity_ZV3rta()
|
||||||
|
[Activity
|
||||||
|
Text = I didn't understand. Please rephrase.
|
||||||
|
]
|
||||||
|
|
||||||
|
# SendActivity_lzlH8N()
|
||||||
|
[Activity
|
||||||
|
Text = Alright. See you later.
|
||||||
|
]
|
||||||
|
|
||||||
|
# SendActivity_6ZhSsX()
|
||||||
|
[Activity
|
||||||
|
Text = **Power Virtual Agents**
|
||||||
|
]
|
||||||
|
|
||||||
|
# SendActivity_TOU1P5()
|
||||||
|
[Activity
|
||||||
|
Text = To learn more aobut PVA see the following: https://powervirtualagents.microsoft.com/en-us/
|
||||||
|
]
|
||||||
|
|
||||||
|
# SendActivity_mroxNS()
|
||||||
|
[Activity
|
||||||
|
Text = **Azure Health Bot**
|
||||||
|
]
|
||||||
|
|
||||||
|
# SendActivity_0wl8Dt()
|
||||||
|
[Activity
|
||||||
|
Text = To learn more about HealthBot see the following: https://www.microsoft.com/en-us/research/project/health-bot/
|
||||||
|
]
|
||||||
|
|
||||||
|
# SendActivity_TK2gtL()
|
||||||
|
[Activity
|
||||||
|
Text = Warning: unexpected response.
|
||||||
|
]
|
|
@ -0,0 +1,54 @@
|
||||||
|
|
||||||
|
# General
|
||||||
|
- who are your partners?
|
||||||
|
- partners info
|
||||||
|
- what groups use bot framework at Microsoft?
|
||||||
|
- tell me about your partners
|
||||||
|
- sister teams at microsoft
|
||||||
|
# TheSkill
|
||||||
|
- Tell me about skils
|
||||||
|
- what are skills
|
||||||
|
- skills documentation
|
||||||
|
- The skill
|
||||||
|
- Connect to a skill
|
||||||
|
- consume a skill
|
||||||
|
|
||||||
|
# exit
|
||||||
|
- done
|
||||||
|
- quit
|
||||||
|
- bye
|
||||||
|
- exit
|
||||||
|
|
||||||
|
# Healthbot
|
||||||
|
- Azure Healthbot
|
||||||
|
- healthbot
|
||||||
|
- health bot
|
||||||
|
|
||||||
|
# PVA
|
||||||
|
- Power Virtual Agents
|
||||||
|
- PVA
|
||||||
|
- virtual agent
|
||||||
|
|
||||||
|
# None
|
||||||
|
- add some example phrases to trigger this intent:
|
||||||
|
- please tell me the weather
|
||||||
|
- what is the weather like in {city=Seattle}
|
||||||
|
- Error occurred building the bot
|
||||||
|
- entity definitions
|
||||||
|
- asdf sasdf
|
||||||
|
- qnamaker:build --in CognitiveModels --subscriptionKey
|
||||||
|
|
||||||
|
# TheSkill
|
||||||
|
> AboutSkills
|
||||||
|
- Tell me about skills
|
||||||
|
- what is a skill?
|
||||||
|
- what are expert bots?
|
||||||
|
- how do i create a skill?
|
||||||
|
- call a skill
|
||||||
|
- skill authentication
|
||||||
|
|
||||||
|
> Contact
|
||||||
|
- Contact
|
||||||
|
- Share my info
|
||||||
|
- get in touch with you
|
||||||
|
- Email phone and name
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.LuisRecognizer",
|
||||||
|
"id": "LUIS_PartnersDialog",
|
||||||
|
"applicationId": "=settings.luis.PartnersDialog_en_us_lu.appId",
|
||||||
|
"version": "=settings.luis.PartnersDialog_en_us_lu.version",
|
||||||
|
"endpoint": "=settings.luis.endpoint",
|
||||||
|
"endpointKey": "=settings.luis.endpointKey"
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.MultiLanguageRecognizer",
|
||||||
|
"id": "LUIS_PartnersDialog",
|
||||||
|
"recognizers": {
|
||||||
|
"en-us": "PartnersDialog.en-us.lu",
|
||||||
|
"": "PartnersDialog.en-us.lu"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.CrossTrainedRecognizerSet",
|
||||||
|
"recognizers": [
|
||||||
|
"PartnersDialog.lu"
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
base_model_version,runtime_version pretrained.20200924.microsoft.dte.00.06.en.onnx,1.0.0
|
||||||
|
PartnersInfo who are your partners? 957B792E186275CD8B857BA877256DD728368BBF2B643245ED2525AE3416591F3C630CA5D467565AC8DC8920672EAF612D58E8E2D7D4D8F85B05819C90AB188695253A4363FD550BA2E4FA36AE87CC8D2B5282ABC9B14C6DC666124DFAAA3CE9
|
||||||
|
PartnersInfo partners info 85FB1D2E132BF18D82257B627D25EFCF283EDBAB2AE432004D158FAEA5563D5B3E536C85CC25BD48C05C09206AA6A761071CF8E8CF977EFCE2AF809CD8E91A86B5242242426DBD1AA2409AB63F87CC860B488EA4C1B05C2DD6655C2DE2A6FEEC
|
||||||
|
PartnersInfo what groups use bot framework at Microsoft? D7B339369B6D30C383015B82FB26767D49BF8BED6B6513546F06A52BB471596B385188B7C549464AECBE49E1282A8E63359CD4C08CB54CB04B6B4EF4B8EF16C70539BA520257339822CA93B26DC20D8E7F5FA3E219BC7C14C73003ED67E25DE9
|
||||||
|
PartnersInfo tell me about your partners C5FB3B2D190A750D9A817B6E79A44D4D3A2DC89F1A643A45CD1703AE3E16451B3FE30C808C67D948C2DF0D2463AEA760613CE8EAFEE55AF05B6D019D93AB9A8E95353B4163653C28A2E0AAB6ACC7CC8C3B4A8AB8C1B55C7106750AED73A27EED
|
||||||
|
PartnersInfo sister teams at microsoft 5FFB3B2C1B6B71CF02A17BEA6E872E757DBF8FA64B653270DF27252FF453192B3FC78021C76D005AC19C49816AAAE771039E61C0E6F4DBF0CB8D229CA5AB1F9EA525BA5A626C9B0A32C2B6B4AF02CC8E7B098AA0A1B45E24E64548256A82FCED
|
||||||
|
None add some example phrases to trigger this intent: D116F9A5A51472FB21A7EF9319E0F739FC5F8838B807B2619F36736AB8106D3C302D1DE389C79939DBC67D7528EB8FB220C585B0870D6A48197D8F585C971C8A1724C21001463AF4F9EF03D2A55085D6FE6B9BFAF49C7A430732A3CE6361763E
|
||||||
|
None please tell me the weather CFC359AED30BE1F18501736E5F2CBD7D083CC6C96AE0F0858D03858FBE9705075F6F10BF9CA1685BC41EE935222EA16A43FD6562C7B614E9592384BAABAF0B8E073BB3E929631C2FE2619B352FD3998B5B598290E975FD55167100BD62E2DE4D
|
||||||
|
None what is the weather like in Seattle C54159A4D38E71D9BF817F6E553DFD7E3C3CCFF9EEB4F285AC66A7258A9105031F6DD01FD4A3485AC46DE9B02FAA8769679DE44885B6158873338ABA9BBD11C7873FB36921437D1FA2C19B3627C2998B535F83F2E475DD6D1E73119D3BA25F4D
|
||||||
|
None Error occurred building the bot 5B521B9CC12C24D31B617382797EAA573F1E8F6E18E7B3614A5647EAF6530F2D3C56F939CDED086DC9B36B71C942AC0881E03045851D4E6849AF86D029BA23EEE5A8B262054F014CE28C9226B4C39D3E71CB0701A1347C16C16BD4EC622A57BE
|
||||||
|
None entity definitions 470359EEA02E64E1C92143AE7B6CAFDFCDBD8BFFABD5F2A54D3787AFA4760D393D658DFECDC50C58D0346E6C2BEEA56185D876C0C41E5B647B2FDE9298AB1A821509A3600039B53EB27ED3B3E7938EB63336BE90D5B15C0EC160868D636AFF69
|
||||||
|
None asdf sasdf 5165186EB32E24C989217335192F2BD76832CF8E6844F621DD43E5EAB43705233D7CCCBDDCA9C428C9D06DB02EEAE76905FC72CCC4BF4E6043EB8E9480BF1B8EB5A9B34C07473B3DA2FC11B2AD868FBED1238A93B5717C0FC16319AC6362DE79
|
||||||
|
exit exit 5D4AFC65C5AC60E7713777827D2A2A3469BA86ADE8D7C3515C12618AF4974C677F3DF011D5E3246999E13C66ED77A520066921D2F0DE5C4DF919AEBBAC8F23CBD764EF40275391986649F8B40DCE072B78BBC6A92024CA64C047056D72EA9E69
|
||||||
|
exit quit 7C6BCA4DCBAD6067713733AC092A2E077DBAA1BDC853D3511CD2318ED4A44C677F399015DDE124B198852862A576A6290EFB01C250965D7CB9198EB9A68F2BFBF568DB044F04B1CC667EE8940CCC030F70AB43AD2134EA24424744EDE2C29E69
|
||||||
|
exit done 7D4179E5C726C2EB3273B6AB6B12EE3568ACE206A845D221AD332182E6D54C45392118398DED4D7DC1AD78270FE3227100CD60C2DC1F696153BB9E9BCE8F1FCBA50CAB4965CB11DCE368C2B00DDB9E0E79FB03A02528EB76036755DF7AA2DE69
|
||||||
|
exit bye 5D6AA925D72F459F361B6BA30F162E3438AAC2164BD51A318D1723ABBCD714293C691891CCE96D7980ADCA072EFBA7706E4D22C3FCCE69D151A9A6B3A78F3FC6670CEA4D414211E9A7EA9AB82C53848F3FFF02A0A0B47E65C27F41FD72EADF6D
|
||||||
|
TheSkill Tell me about skills 579319A5934A61859BB1FB051BA60D6C2CACC3CC2A453211CD57870F3E12142B3CE198959745CE48DADF4F352BEFA7E141FCC4E8CC3418B1792B043BD38F1B8E972CBBE0414135A8A3E1B3BEA15585CE3A5F88F08535FC79067280BD72A2FF6D
|
||||||
|
TheSkill what is a skill? D51359B6836A61C7ABB17B891F270F7F3C3CCBED3A4533B1CD57A70FF712152B38618895D7C15E4FD8DFCD242F6BAF6125D884EA4C3428B1D13B861BD38D198F872CBB60410377BCA3E53B362D45D5CE1A5F00F805BD7C798662803D7222DC6D
|
||||||
|
TheSkill what are expert bots? D7F359FE992A31D58F317B12D7776B56293DC3ED6AE53340E9572547B423112B3AC1DC3796611E4CC8FC4D61202AA7610356E5C0C4B5D598F9B32898718B1B878521BB40417173B8A3EE5BB60C468C0C765B82B905B75C2D86655B197AA2DC6D
|
||||||
|
TheSkill how do i create a skill? D71358868F4A8197A329FB933FF4EF7D7C3E83E02C0552318D17330BF652312938450BF985CD9E4CDADF5D69254BAC6105DCA428C4382BF1436B8F7DF3C509CF85ACBA32414B3398FFE433B229679DDF3E4F0AB4153C7E32EF32EBDCE2A6DC4D
|
||||||
|
TheSkill call a skill DF9219BE8D7870D3AB21F3CB27E5AF372E34CBF83C6411318D173B0FDC721F6F384489B99FC98E0ED89FD521674EAEE1157D6CE848B56AF1E3690EDA808939CE9723BA44412FB388A2DD13346940ACDD3F5B080885357C36E632C85EF226544D
|
||||||
|
TheSkill skill authentication 561058E7856801E90A09FB912FF42A556DB4CB2C224D31216D77B18FE45615613D63CBF18EC5CECCDA9E7D3E892BA7C189DCC0EACC3D6C7173BB92B8F1AF1B8F4108A67543D3F7BDA0EED3F8AB56CCDC37720298C1B57E7BC73AC83F63E7D65D
|
||||||
|
DeferToRecognizer_QnA_OrchestratorDispatch What are custom actions? 931279E2830471E3E6337AAB7362EEFD6CBD0BACF245B280FC3E25EBF4544D21386BBC9E85C584CCDDCC59F42FE2A8E1234591E6D413E8485153EA94DBF93F87152DF652416B3B1EA1ED72B2A84AD5C676310ACB55F4FC474762058F7E6A5659
|
||||||
|
DeferToRecognizer_QnA_OrchestratorDispatch how to create custom action in composer D303F8488704D3DB32253A8B95A0FE517C7D0F30A425BA213E56216BF15D5D3D3A4D95B18DC78C68DDE65CFD69EB8900360DA102C7316648D15DAEF4BBDD1F8711A6C03001686B9C71EC32B02F42BDC276272A75D4B4F91665322BCE07635358
|
||||||
|
DeferToRecognizer_QnA_OrchestratorDispatch how to extend composer D1237D25072CB68B3921238D3DA77F117A3E8F748C013B22EF7621AAF15F49FFBEA910A585674D69DAA01B2769A78A451464E24267BD66581B5DAEECEFD5138284A69308027F23387CE6B2D36702D90E1CEB0A24B5AA5E1EC52A8A6DCBA7FE6C
|
||||||
|
DeferToRecognizer_QnA_OrchestratorDispatch What is Composer? D5137924832E71CD07217B093F261F5D7C37CFBEAB65B0298C7605063613517F386984959C654C4ADCB61D672BEA8761251DA0EADEB45BF1517B9EDCB2A91FEE9525B308514371B8A3E6BA972D869D9C735F22BB69B1F83D456482ED72A37F69
|
||||||
|
DeferToRecognizer_QnA_OrchestratorDispatch tell me about composer C5337D2D934E71CD06A15B0F3D261D4D7C2DCD9EBB64B8298D770112361E513F3CC194C49CE5CF58DCBE1F272BEA8761653CE0E2DEE45BD1516F16DD93AB9FAE9725B308114171A8B3E2AABF29839C8C734F8AB0A9B5FC7C067482ED72A37F69
|
||||||
|
DeferToRecognizer_QnA_OrchestratorDispatch bot framework composer 55377946932F31CB0625FB027F263A517936CFFC6945D965CF563562F57F1973385D04F18C6D4E48DCBE9E6F2A6BA763848C4004C4B44EF8C96316D4E2A917EB8728B400115F638CA2EE92B46D921D8E7DBF0BB129BBFC10C730CAED63E35769
|
||||||
|
DeferToRecognizer_QnA_OrchestratorDispatch composer documentation F51378E4B32EC3C920A1DB1D31662E5D6C3EC99CAA45B8219D36018E7716D4573AE580C59CD78C6ADD3E5D376BCB830184ECE0E24F9372D311299EDC58AD9F8E91AE2B80510B33B8B2E4929A6D939C9EB1EF3A740DB1FC369522A0ED62ABF769
|
||||||
|
DeferToRecognizer_QnA_OrchestratorDispatch What are packages? 8F3619F7202A71C5A6036B027F2F5D7F3CAD83096BC5D2E18C0305AEF617456B3863A8379461CC5B80B40B2726DEA67B040DE0E6CEB459F1537BAA90AACB1B8E85353F0001E371BCBAF832B229D6D50F5F7FAAA004E55F2D066500AD76E25D69
|
||||||
|
DeferToRecognizer_QnA_OrchestratorDispatch tell me about packages 4596397D932E31EDB6816B027F2E1D4F1CADC3896A60B0B18D0385AEF616052B3EE380919465CC58C4BE093522FEA6E2049D60E6CEF45AE0516F2E908B8B1B8E87363D0009E931BEB2F032B628D6C58FFB5F8BF0A5657F2D066540AD76AA5D6D
|
||||||
|
DeferToRecognizer_QnA_OrchestratorDispatch what are components? 851159B6A12AE5EDBF61FB29352EEDDF2CB50B79BAC490C1AC4387BFF432052F3CE188BEC4654C58D4BC99252FEF863917D4E0E2CF555970511B4898B3EF1F86872CA7E4186131BCBAEDFAB22FD6910F527FAAB000FC641D166280A97E63CF69
|
||||||
|
DeferToRecognizer_QnA_OrchestratorDispatch components info C5997D3621AAE4E1AB21D3B91D2FEDCF2CBF9B68BA44D2C1BD6387AF643425673C638296C5654C58D4BC49342FAF870197D4F0ECCF135F70711BCA98D9EF1F8695B8A3E0287B393CB07CFAB2369699231169AEB40174453D136284A97AC3D769
|
||||||
|
DeferToRecognizer_QnA_OrchestratorDispatch packages documentation C59629F5AB2EE1E9B6815A0A7B6EEE5F2C3D9A982AC5B0A1AC16858EF716246B7A65A09794458C7A85361D356ACFA6A984ECE0E2CE937AB1113B8A9048891B8691B42F10018B33BEB2F092B278D7D5A67B7FBFE41D65DF372721A4AD72E89D6D
|
||||||
|
DeferToRecognizer_QnA_OrchestratorDispatch how to create packages DF173B4C832ED1B3E6836B833F367E7D3CBF87406C25D2E19F02073BF353752D3A6598F9816D8C58C9A61F6521DFA4B3848C220AC6246AF0436FAE90AB891F9E0588BE1208EC7594BAF412B52953953B7F0F0BF194347F1663314BAF20E0DD4A
|
|
@ -0,0 +1,75 @@
|
||||||
|
|
||||||
|
> LUIS application information
|
||||||
|
> !# @app.versionId = 0.1
|
||||||
|
> !# @app.culture = en-us
|
||||||
|
> !# @app.luis_schema_version = 3.2.0
|
||||||
|
|
||||||
|
|
||||||
|
> # Intent definitions
|
||||||
|
|
||||||
|
# PartnersInfo
|
||||||
|
- who are your partners?
|
||||||
|
- partners info
|
||||||
|
- what groups use bot framework at Microsoft?
|
||||||
|
- tell me about your partners
|
||||||
|
- sister teams at microsoft
|
||||||
|
|
||||||
|
|
||||||
|
# None
|
||||||
|
- add some example phrases to trigger this intent:
|
||||||
|
- please tell me the weather
|
||||||
|
- what is the weather like in {@city=Seattle}
|
||||||
|
- Error occurred building the bot
|
||||||
|
- entity definitions
|
||||||
|
- asdf sasdf
|
||||||
|
|
||||||
|
|
||||||
|
# exit
|
||||||
|
- exit
|
||||||
|
- quit
|
||||||
|
- done
|
||||||
|
- bye
|
||||||
|
|
||||||
|
|
||||||
|
# TheSkill
|
||||||
|
- Tell me about skills
|
||||||
|
- what is a skill?
|
||||||
|
- what are expert bots?
|
||||||
|
- how do i create a skill?
|
||||||
|
- call a skill
|
||||||
|
- skill authentication
|
||||||
|
|
||||||
|
|
||||||
|
> # Entity definitions
|
||||||
|
|
||||||
|
@ ml city
|
||||||
|
|
||||||
|
|
||||||
|
> # PREBUILT Entity definitions
|
||||||
|
|
||||||
|
|
||||||
|
> # Phrase list definitions
|
||||||
|
|
||||||
|
|
||||||
|
> # List entities
|
||||||
|
|
||||||
|
> # RegEx entities
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
> Source: cross training. Please do not edit these directly!
|
||||||
|
# DeferToRecognizer_QnA_OrchestratorDispatch
|
||||||
|
- What are custom actions?
|
||||||
|
- how to create custom action in composer
|
||||||
|
- how to extend composer
|
||||||
|
- What is Composer?
|
||||||
|
- tell me about composer
|
||||||
|
- bot framework composer
|
||||||
|
- composer documentation
|
||||||
|
- What are packages?
|
||||||
|
- tell me about packages
|
||||||
|
- what are components?
|
||||||
|
- components info
|
||||||
|
- packages documentation
|
||||||
|
- how to create packages
|
|
@ -0,0 +1,69 @@
|
||||||
|
# ? What are custom actions?
|
||||||
|
- how to create custom action in composer
|
||||||
|
- how to extend composer
|
||||||
|
|
||||||
|
**Filters:**
|
||||||
|
- dialogName=OrchestratorDispatch
|
||||||
|
|
||||||
|
```
|
||||||
|
You can extend the set of available actions within Composer canvas while building bots.
|
||||||
|
See more here: https://docs.microsoft.com/en-us/composer/how-to-add-custom-action?tabs=csharp
|
||||||
|
```
|
||||||
|
|
||||||
|
# ? What is Composer?
|
||||||
|
- tell me about composer
|
||||||
|
- bot framework composer
|
||||||
|
- composer documentation
|
||||||
|
|
||||||
|
**Filters:**
|
||||||
|
- dialogName=OrchestratorDispatch
|
||||||
|
|
||||||
|
```
|
||||||
|
Composer is a GUI bot building tool for Microsoft Bot Framework. See more here: https://docs.microsoft.com/en-us/composer/introduction
|
||||||
|
```
|
||||||
|
|
||||||
|
# ? What are packages?
|
||||||
|
- tell me about packages
|
||||||
|
- what are components?
|
||||||
|
- components info
|
||||||
|
- packages documentation
|
||||||
|
- how to create packages
|
||||||
|
|
||||||
|
**Filters:**
|
||||||
|
- dialogName=OrchestratorDispatch
|
||||||
|
|
||||||
|
```
|
||||||
|
Reusable components for building Bot Framework Bots in Composer. See more here: https://github.com/microsoft/botframework-components/tree/main/docs
|
||||||
|
```
|
||||||
|
|
||||||
|
> Source: cross training. Please do not edit these directly!
|
||||||
|
> !# @qna.pair.source = crosstrained
|
||||||
|
|
||||||
|
# ? who are your partners?
|
||||||
|
- partners info
|
||||||
|
- what groups use bot framework at Microsoft?
|
||||||
|
- tell me about your partners
|
||||||
|
- sister teams at microsoft
|
||||||
|
- add some example phrases to trigger this intent:
|
||||||
|
- please tell me the weather
|
||||||
|
- what is the weather like in Seattle
|
||||||
|
- Error occurred building the bot
|
||||||
|
- entity definitions
|
||||||
|
- asdf sasdf
|
||||||
|
- exit
|
||||||
|
- quit
|
||||||
|
- done
|
||||||
|
- bye
|
||||||
|
- Tell me about skills
|
||||||
|
- what is a skill?
|
||||||
|
- what are expert bots?
|
||||||
|
- how do i create a skill?
|
||||||
|
- call a skill
|
||||||
|
- skill authentication
|
||||||
|
|
||||||
|
**Filters:**
|
||||||
|
- dialogName=OrchestratorDispatch
|
||||||
|
|
||||||
|
```
|
||||||
|
intent=DeferToRecognizer_LUIS_OrchestratorDispatch
|
||||||
|
```
|
|
@ -0,0 +1,98 @@
|
||||||
|
|
||||||
|
> LUIS application information
|
||||||
|
> !# @app.versionId = 0.1
|
||||||
|
> !# @app.culture = en-us
|
||||||
|
> !# @app.luis_schema_version = 3.2.0
|
||||||
|
|
||||||
|
|
||||||
|
> # Intent definitions
|
||||||
|
|
||||||
|
# General
|
||||||
|
- who are your partners?
|
||||||
|
- partners info
|
||||||
|
- what groups use bot framework at Microsoft?
|
||||||
|
- tell me about your partners
|
||||||
|
- sister teams at microsoft
|
||||||
|
|
||||||
|
|
||||||
|
# TheSkill
|
||||||
|
- Tell me about skils
|
||||||
|
- what are skills
|
||||||
|
- skills documentation
|
||||||
|
- The skill
|
||||||
|
- Connect to a skill
|
||||||
|
- consume a skill
|
||||||
|
- Tell me about skills
|
||||||
|
- what is a skill?
|
||||||
|
- what are expert bots?
|
||||||
|
- how do i create a skill?
|
||||||
|
- call a skill
|
||||||
|
- skill authentication
|
||||||
|
- Contact
|
||||||
|
- Share my info
|
||||||
|
- get in touch with you
|
||||||
|
- Email phone and name
|
||||||
|
|
||||||
|
|
||||||
|
# exit
|
||||||
|
- done
|
||||||
|
- quit
|
||||||
|
- bye
|
||||||
|
- exit
|
||||||
|
|
||||||
|
|
||||||
|
# Healthbot
|
||||||
|
- Azure Healthbot
|
||||||
|
- healthbot
|
||||||
|
- health bot
|
||||||
|
|
||||||
|
|
||||||
|
# PVA
|
||||||
|
- Power Virtual Agents
|
||||||
|
- PVA
|
||||||
|
- virtual agent
|
||||||
|
|
||||||
|
|
||||||
|
# None
|
||||||
|
- add some example phrases to trigger this intent:
|
||||||
|
- please tell me the weather
|
||||||
|
- what is the weather like in {@city=Seattle}
|
||||||
|
- Error occurred building the bot
|
||||||
|
- entity definitions
|
||||||
|
- asdf sasdf
|
||||||
|
- qnamaker:build --in CognitiveModels --subscriptionKey
|
||||||
|
|
||||||
|
|
||||||
|
> # Entity definitions
|
||||||
|
|
||||||
|
@ ml city
|
||||||
|
|
||||||
|
|
||||||
|
> # PREBUILT Entity definitions
|
||||||
|
|
||||||
|
|
||||||
|
> # Phrase list definitions
|
||||||
|
|
||||||
|
|
||||||
|
> # List entities
|
||||||
|
|
||||||
|
> # RegEx entities
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
> Source: cross training. Please do not edit these directly!
|
||||||
|
# _Interruption
|
||||||
|
- What are custom actions?
|
||||||
|
- how to create custom action in composer
|
||||||
|
- how to extend composer
|
||||||
|
- What is Composer?
|
||||||
|
- tell me about composer
|
||||||
|
- bot framework composer
|
||||||
|
- composer documentation
|
||||||
|
- What are packages?
|
||||||
|
- tell me about packages
|
||||||
|
- what are components?
|
||||||
|
- components info
|
||||||
|
- packages documentation
|
||||||
|
- how to create packages
|
|
@ -0,0 +1,62 @@
|
||||||
|
|
||||||
|
> Source: cross training. Please do not edit these directly!
|
||||||
|
> !# @qna.pair.source = crosstrained
|
||||||
|
|
||||||
|
# ? who are your partners?
|
||||||
|
- partners info
|
||||||
|
- what groups use bot framework at Microsoft?
|
||||||
|
- tell me about your partners
|
||||||
|
- sister teams at microsoft
|
||||||
|
- Tell me about skils
|
||||||
|
- what are skills
|
||||||
|
- skills documentation
|
||||||
|
- The skill
|
||||||
|
- Connect to a skill
|
||||||
|
- consume a skill
|
||||||
|
- Tell me about skills
|
||||||
|
- what is a skill?
|
||||||
|
- what are expert bots?
|
||||||
|
- how do i create a skill?
|
||||||
|
- call a skill
|
||||||
|
- skill authentication
|
||||||
|
- Contact
|
||||||
|
- Share my info
|
||||||
|
- get in touch with you
|
||||||
|
- Email phone and name
|
||||||
|
- done
|
||||||
|
- quit
|
||||||
|
- bye
|
||||||
|
- exit
|
||||||
|
- Azure Healthbot
|
||||||
|
- healthbot
|
||||||
|
- health bot
|
||||||
|
- Power Virtual Agents
|
||||||
|
- PVA
|
||||||
|
- virtual agent
|
||||||
|
- add some example phrases to trigger this intent:
|
||||||
|
- please tell me the weather
|
||||||
|
- what is the weather like in Seattle
|
||||||
|
- Error occurred building the bot
|
||||||
|
- entity definitions
|
||||||
|
- asdf sasdf
|
||||||
|
- qnamaker:build --in CognitiveModels --subscriptionKey
|
||||||
|
- What are custom actions?
|
||||||
|
- how to create custom action in composer
|
||||||
|
- how to extend composer
|
||||||
|
- What is Composer?
|
||||||
|
- tell me about composer
|
||||||
|
- bot framework composer
|
||||||
|
- composer documentation
|
||||||
|
- What are packages?
|
||||||
|
- tell me about packages
|
||||||
|
- what are components?
|
||||||
|
- components info
|
||||||
|
- packages documentation
|
||||||
|
- how to create packages
|
||||||
|
|
||||||
|
**Filters:**
|
||||||
|
- dialogName=PartnersDialog
|
||||||
|
|
||||||
|
```
|
||||||
|
intent=DeferToRecognizer_LUIS_PartnersDialog
|
||||||
|
```
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"luis": {
|
||||||
|
"PartnersDialog_en_us_lu": {
|
||||||
|
"appId": "07b46ce0-3bc8-4595-9eb5-ab8e038befde"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"orchestrator": {
|
||||||
|
"models": {
|
||||||
|
"en": "C:/Users/eyals/AppData/Roaming/BotFrameworkComposer/models/pretrained.20200924.microsoft.dte.00.06.en"
|
||||||
|
},
|
||||||
|
"snapshots": {
|
||||||
|
"OrchestratorDispatch_en_us": "c:/workspace/botroot/sdk/Orchestrator/Samples/Composer/OrchestratorDispatch/generated/OrchestratorDispatch.en-us.blu"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"qna": {
|
||||||
|
"OrchestratorDispatch_en_us_qna": "7dc61c7a-69e5-4436-bcad-59909bccee01",
|
||||||
|
"hostname": "https://orchestratorqnasvc.azurewebsites.net/qnamaker",
|
||||||
|
"PartnersDialog_en_us_qna": "7dc61c7a-69e5-4436-bcad-59909bccee01"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
[import](ComposerKB.source.qna)
|
|
@ -0,0 +1,23 @@
|
||||||
|
# ? What are custom actions?
|
||||||
|
- how to create custom action in composer
|
||||||
|
- how to extend composer
|
||||||
|
```
|
||||||
|
You can extend the set of available actions within Composer canvas while building bots.
|
||||||
|
See more here: https://docs.microsoft.com/en-us/composer/how-to-add-custom-action?tabs=csharp
|
||||||
|
```
|
||||||
|
# ? What is Composer?
|
||||||
|
- tell me about composer
|
||||||
|
- bot framework composer
|
||||||
|
- composer documentation
|
||||||
|
```
|
||||||
|
Composer is a GUI bot building tool for Microsoft Bot Framework. See more here: https://docs.microsoft.com/en-us/composer/introduction
|
||||||
|
```
|
||||||
|
# ? What are packages?
|
||||||
|
- tell me about packages
|
||||||
|
- what are components?
|
||||||
|
- components info
|
||||||
|
- packages documentation
|
||||||
|
- how to create packages
|
||||||
|
```
|
||||||
|
Reusable components for building Bot Framework Bots in Composer. See more here: https://github.com/microsoft/botframework-components/tree/main/docs
|
||||||
|
```
|
|
@ -0,0 +1,51 @@
|
||||||
|
[import](common.lg)
|
||||||
|
|
||||||
|
# SendActivity_Welcome
|
||||||
|
- ${WelcomeUser()}
|
||||||
|
|
||||||
|
# SendActivity_7MNTfM()
|
||||||
|
- Ask a question about (_Orchestrator recognizer_)\r- Composer, components, or custom actions --> Dispatch to QnA\r- Ask about Bot Framework partners --> Dispatch to LUIS\r- Ask about skills --> Dispatch to a skill
|
||||||
|
|
||||||
|
# TextInput_Prompt_sL5okG()
|
||||||
|
[Activity
|
||||||
|
Text = How can I help you?
|
||||||
|
]
|
||||||
|
|
||||||
|
# SendActivity_Zy3DnL()
|
||||||
|
[Activity
|
||||||
|
Text = Thank you. Goodbye.
|
||||||
|
]
|
||||||
|
|
||||||
|
# TextInput_Prompt_HGB0yC()
|
||||||
|
[Activity
|
||||||
|
Text = ${expandText(@answer)}
|
||||||
|
SuggestedActions = ${foreach(turn.recognized.answers[0].context.prompts, x, x.displayText)}
|
||||||
|
]
|
||||||
|
|
||||||
|
# SendActivity_ESxCuC()
|
||||||
|
- ${expandText(@answer)}
|
||||||
|
|
||||||
|
# SendActivity_xjrS5L()
|
||||||
|
[Activity
|
||||||
|
Text = Unknown intent. Please rephrase. (_parent trigger_)
|
||||||
|
]
|
||||||
|
|
||||||
|
# SendActivity_bzZc9B()
|
||||||
|
[Activity
|
||||||
|
Text = Good chatting. Goodbye. (_parent trigger_)
|
||||||
|
]
|
||||||
|
|
||||||
|
# SendActivity_VJYzMf()
|
||||||
|
[Activity
|
||||||
|
Text = **QnA Intent**
|
||||||
|
]
|
||||||
|
|
||||||
|
# SendActivity_EZm3u2()
|
||||||
|
[Activity
|
||||||
|
Text = Calling The Skill...
|
||||||
|
]
|
||||||
|
|
||||||
|
# SendActivity_v8rqlc()
|
||||||
|
[Activity
|
||||||
|
Text = Please rephrase. (_parent None trigger_)
|
||||||
|
]
|
|
@ -0,0 +1,2 @@
|
||||||
|
# WelcomeUser
|
||||||
|
- **Simple Orchestrator Dispatch Sample**
|
|
@ -0,0 +1,30 @@
|
||||||
|
|
||||||
|
# PartnersInfo
|
||||||
|
- who are your partners?
|
||||||
|
- partners info
|
||||||
|
- what groups use bot framework at Microsoft?
|
||||||
|
- tell me about your partners
|
||||||
|
- sister teams at microsoft
|
||||||
|
|
||||||
|
# None
|
||||||
|
- add some example phrases to trigger this intent:
|
||||||
|
- please tell me the weather
|
||||||
|
- what is the weather like in {city=Seattle}
|
||||||
|
- Error occurred building the bot
|
||||||
|
- entity definitions
|
||||||
|
- asdf sasdf
|
||||||
|
|
||||||
|
# exit
|
||||||
|
- exit
|
||||||
|
- quit
|
||||||
|
- done
|
||||||
|
- bye
|
||||||
|
|
||||||
|
# TheSkill
|
||||||
|
> AboutSkills
|
||||||
|
- Tell me about skills
|
||||||
|
- what is a skill?
|
||||||
|
- what are expert bots?
|
||||||
|
- how do i create a skill?
|
||||||
|
- call a skill
|
||||||
|
- skill authentication
|
Двоичные данные
Orchestrator/Samples/Composer/OrchestratorDispatch/media/create-azure-resource-command-line.png
Normal file
Двоичные данные
Orchestrator/Samples/Composer/OrchestratorDispatch/media/create-azure-resource-command-line.png
Normal file
Двоичный файл не отображается.
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 59 KiB |
Двоичные данные
Orchestrator/Samples/Composer/OrchestratorDispatch/media/publish-az-login.png
Normal file
Двоичные данные
Orchestrator/Samples/Composer/OrchestratorDispatch/media/publish-az-login.png
Normal file
Двоичный файл не отображается.
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.OrchestratorRecognizer",
|
||||||
|
"modelFolder": "=settings.orchestrator.models.en",
|
||||||
|
"snapshotFile": "=settings.orchestrator.snapshots.OrchestratorDispatch_en_us",
|
||||||
|
"detectAmbiguousIntents": true,
|
||||||
|
"disambiguationScoreThreshold": 0.05
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.QnAMakerRecognizer",
|
||||||
|
"id": "QnA_OrchestratorDispatch",
|
||||||
|
"knowledgeBaseId": "=settings.qna.OrchestratorDispatch_en_us_qna",
|
||||||
|
"hostname": "=settings.qna.hostname",
|
||||||
|
"endpointKey": "=settings.qna.endpointKey"
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.MultiLanguageRecognizer",
|
||||||
|
"id": "LUIS_OrchestratorDispatch",
|
||||||
|
"recognizers": {
|
||||||
|
"en-us": "OrchestratorDispatch.en-us.lu",
|
||||||
|
"": "OrchestratorDispatch.en-us.lu"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.CrossTrainedRecognizerSet",
|
||||||
|
"recognizers": [
|
||||||
|
"OrchestratorDispatch.lu",
|
||||||
|
"OrchestratorDispatch.qna"
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"$kind": "Microsoft.MultiLanguageRecognizer",
|
||||||
|
"id": "QnA_OrchestratorDispatch",
|
||||||
|
"recognizers": {
|
||||||
|
"en-us": "OrchestratorDispatch.en-us.qna",
|
||||||
|
"": "OrchestratorDispatch.en-us.qna"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,98 @@
|
||||||
|
# How to update the schema file
|
||||||
|
|
||||||
|
Once the bot has been setup with Composer and we wish to make changes to the schema, the first step in this process is to eject the runtime through the `Runtime Config` in Composer. The ejected runtime folder will broadly have the following structure
|
||||||
|
|
||||||
|
```
|
||||||
|
bot
|
||||||
|
/bot.dialog
|
||||||
|
/language-generation
|
||||||
|
/language-understanding
|
||||||
|
/dialogs
|
||||||
|
/customized-dialogs
|
||||||
|
/schemas
|
||||||
|
sdk.schema
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Prequisites
|
||||||
|
|
||||||
|
Botframework CLI > 4.10
|
||||||
|
|
||||||
|
```
|
||||||
|
npm i -g @microsoft/botframework-cli
|
||||||
|
```
|
||||||
|
|
||||||
|
> NOTE: Previous versions of botframework-cli required you to install @microsoft/bf-plugin. You will need to uninstall for 4.10 and above.
|
||||||
|
>
|
||||||
|
> ```
|
||||||
|
> bf plugins:uninstall @microsoft/bf-dialog
|
||||||
|
> ```
|
||||||
|
|
||||||
|
- Navigate to to the `schemas (bot/schemas)` folder. This folder contains a Powershell script and a bash script. Run either of these scripts `./update-schema.ps1` or `sh ./update-schema.sh`.
|
||||||
|
|
||||||
|
The above steps should have generated a new sdk.schema file inside `schemas` folder for Composer to use. Reload the bot and you should be able to include your new custom action!
|
||||||
|
|
||||||
|
## Customizing Composer using the UI Schema
|
||||||
|
|
||||||
|
Composer's UI can be customized using the UI Schema. You can either customize one of your custom actions or override Composer defaults.
|
||||||
|
|
||||||
|
There are 2 ways to do this.
|
||||||
|
|
||||||
|
1. **Component UI Schema File**
|
||||||
|
|
||||||
|
To customize a specific component, simply create a `.uischema` file inside of the `/schemas` directory with the same name as the component, These files will be merged into a single `.uischema` file when running the `update-schema` script.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```json
|
||||||
|
// Microsoft.SendActivity.uischema
|
||||||
|
{
|
||||||
|
"$schema": "https://schemas.botframework.com/schemas/ui/v1.0/ui.schema",
|
||||||
|
"form": {
|
||||||
|
"label": "A custom label"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **UI Schema Override File**
|
||||||
|
|
||||||
|
This approach allows you to co-locate all of your UI customizations into a single file. This will not be merged into the `sdk.uischema`, instead it will be loaded by Composer and applied as overrides.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"$schema": "https://schemas.botframework.com/schemas/ui/v1.0/ui.schema",
|
||||||
|
"Microsoft.SendActivity": {
|
||||||
|
"form": {
|
||||||
|
"label": "A custom label"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### UI Customization Options
|
||||||
|
|
||||||
|
##### Form
|
||||||
|
|
||||||
|
| **Property** | **Description** | **Type** | **Default** |
|
||||||
|
| ------------ | -------------------------------------------------------------------------------------- | ------------------- | -------------------- |
|
||||||
|
| description | Text used in tooltips. | `string` | `schema.description` |
|
||||||
|
| helpLink | URI to component or property documentation. Used in tooltips. | `string` | |
|
||||||
|
| hidden | An array of property names to hide in the UI. | `string[]` | |
|
||||||
|
| label | Label override. Can either be a string or false to hide the label. | `string` \| `false` | `schema.title` |
|
||||||
|
| order | Set the order of fields. Use "\_" for all other fields. ex. ["foo", "_", "bar"] | `string[]` | `[*]` |
|
||||||
|
| placeholder | Placeholder override. | `string` | `schema.examples` |
|
||||||
|
| properties | A map of component property names to UI options with customizations for each property. | `object` | |
|
||||||
|
| subtitle | Subtitle rendered in form title. | `string` | `schema.$kind` |
|
||||||
|
| widget | Override default field widget. See list of widgets below. | `enum` | |
|
||||||
|
|
||||||
|
###### Widgets
|
||||||
|
|
||||||
|
- checkbox
|
||||||
|
- date
|
||||||
|
- datetime
|
||||||
|
- input
|
||||||
|
- number
|
||||||
|
- radio
|
||||||
|
- select
|
||||||
|
- textarea
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,27 @@
|
||||||
|
$SCHEMA_FILE="sdk.schema"
|
||||||
|
$UISCHEMA_FILE="sdk.uischema"
|
||||||
|
$BACKUP_SCHEMA_FILE="sdk-backup.schema"
|
||||||
|
$BACKUP_UISCHEMA_FILE="sdk-backup.uischema"
|
||||||
|
|
||||||
|
Write-Host "Running schema merge."
|
||||||
|
|
||||||
|
if (Test-Path $SCHEMA_FILE -PathType leaf) { Move-Item -Force -Path $SCHEMA_FILE -Destination $BACKUP_SCHEMA_FILE }
|
||||||
|
if (Test-Path $UISCHEMA_FILE -PathType leaf) { Move-Item -Force -Path $UISCHEMA_FILE -Destination $BACKUP_UISCHEMA_FILE }
|
||||||
|
|
||||||
|
bf dialog:merge "*.schema" "!**/sdk-backup.schema" "*.uischema" "!**/sdk-backup.uischema" "!**/sdk.override.uischema" "../*.csproj" "../package.json" -o $SCHEMA_FILE
|
||||||
|
|
||||||
|
if (Test-Path $SCHEMA_FILE -PathType leaf)
|
||||||
|
{
|
||||||
|
if (Test-Path $BACKUP_SCHEMA_FILE -PathType leaf) { Remove-Item -Force -Path $BACKUP_SCHEMA_FILE }
|
||||||
|
if (Test-Path $BACKUP_UISCHEMA_FILE -PathType leaf) { Remove-Item -Force -Path $BACKUP_UISCHEMA_FILE }
|
||||||
|
|
||||||
|
Write-Host "Schema merged succesfully."
|
||||||
|
if (Test-Path $SCHEMA_FILE -PathType leaf) { Write-Host " Schema: $SCHEMA_FILE" }
|
||||||
|
if (Test-Path $UISCHEMA_FILE -PathType leaf) { Write-Host " UI Schema: $UISCHEMA_FILE" }
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Write-Host "Schema merge failed. Restoring previous versions."
|
||||||
|
if (Test-Path $BACKUP_SCHEMA_FILE -PathType leaf) { Move-Item -Force -Path $BACKUP_SCHEMA_FILE -Destination $SCHEMA_FILE }
|
||||||
|
if (Test-Path $BACKUP_UISCHEMA_FILE -PathType leaf) { Move-Item -Force -Path $BACKUP_UISCHEMA_FILE -Destination $UISCHEMA_FILE }
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
SCHEMA_FILE=sdk.schema
|
||||||
|
UISCHEMA_FILE=sdk.uischema
|
||||||
|
BACKUP_SCHEMA_FILE=sdk-backup.schema
|
||||||
|
BACKUP_UISCHEMA_FILE=sdk-backup.uischema
|
||||||
|
|
||||||
|
while [ $# -gt 0 ]; do
|
||||||
|
if [[ $1 == *"-"* ]]; then
|
||||||
|
param="${1/-/}"
|
||||||
|
declare $param="$2"
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Running schema merge."
|
||||||
|
[ -f "$SCHEMA_FILE" ] && mv "./$SCHEMA_FILE" "./$BACKUP_SCHEMA_FILE"
|
||||||
|
[ -f "$UISCHEMA_FILE" ] && mv "./$UISCHEMA_FILE" "./$BACKUP_UISCHEMA_FILE"
|
||||||
|
|
||||||
|
bf dialog:merge "*.schema" "!**/sdk-backup.schema" "*.uischema" "!**/sdk-backup.uischema" "!**/sdk.override.uischema" "../*.csproj" "../package.json" -o $SCHEMA_FILE
|
||||||
|
|
||||||
|
if [ -f "$SCHEMA_FILE" ]; then
|
||||||
|
rm -rf "./$BACKUP_SCHEMA_FILE"
|
||||||
|
rm -rf "./$BACKUP_UISCHEMA_FILE"
|
||||||
|
echo "Schema merged succesfully."
|
||||||
|
[ -f "$SCHEMA_FILE" ] && echo " Schema: $SCHEMA_FILE"
|
||||||
|
[ -f "$UISCHEMA_FILE" ] && echo " UI Schema: $UISCHEMA_FILE"
|
||||||
|
else
|
||||||
|
echo "Schema merge failed. Restoring previous versions."
|
||||||
|
[ -f "$BACKUP_SCHEMA_FILE" ] && mv "./$BACKUP_SCHEMA_FILE" "./$SCHEMA_FILE"
|
||||||
|
[ -f "$BACKUP_UISCHEMA_FILE" ] && mv "./$BACKUP_UISCHEMA_FILE" "./$UISCHEMA_FILE"
|
||||||
|
fi
|
|
@ -0,0 +1,23 @@
|
||||||
|
{
|
||||||
|
"OrchestratorDispatch.en-us": {
|
||||||
|
"rootDialog": true,
|
||||||
|
"triggers": {
|
||||||
|
"PartnersInfo": [
|
||||||
|
"PartnersDialog.en-us"
|
||||||
|
],
|
||||||
|
"None": "",
|
||||||
|
"exit": "",
|
||||||
|
"TheSkill": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"PartnersDialog.en-us": {
|
||||||
|
"rootDialog": false,
|
||||||
|
"triggers": {
|
||||||
|
"General": "",
|
||||||
|
"exit": "",
|
||||||
|
"Healthbot": "",
|
||||||
|
"PVA": "",
|
||||||
|
"None": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,364 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>OrchestratorDispatch</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">OrchestratorDispatch</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>
|
|
@ -7,6 +7,8 @@ The following prebuilt language models are now available in [versions repository
|
||||||
|
|
||||||
See the [References](#references) section for technical descriptions of the AI technology behind the models.
|
See the [References](#references) section for technical descriptions of the AI technology behind the models.
|
||||||
|
|
||||||
|
See the [References](#references) section for technical descriptions of the AI technology behind the models .
|
||||||
|
|
||||||
## Default Models
|
## Default Models
|
||||||
|
|
||||||
### pretrained.20200924.microsoft.dte.00.06.en.onnx
|
### pretrained.20200924.microsoft.dte.00.06.en.onnx
|
||||||
|
@ -146,4 +148,3 @@ The models are released under the following [License Terms][6].
|
||||||
[11]: https://www.microsoft.com/en-us/research/blog/microsoft-turing-universal-language-representation-model-t-ulrv2-tops-xtreme-leaderboard/ "Turing Universal Language Representation model"
|
[11]: https://www.microsoft.com/en-us/research/blog/microsoft-turing-universal-language-representation-model-t-ulrv2-tops-xtreme-leaderboard/ "Turing Universal Language Representation model"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче