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:
Eyal 2021-04-26 15:49:19 -07:00 коммит произвёл GitHub
Родитель 2dac7be647
Коммит bc115918ee
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
59 изменённых файлов: 16400 добавлений и 1 удалений

2
Orchestrator/Samples/Composer/OrchestratorDispatch/.gitignore поставляемый Normal file
Просмотреть файл

@ -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

Двоичный файл не отображается.

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 59 KiB

Двоичный файл не отображается.

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

@ -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 .
## Default Models
### 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"