|
| 1 | +--- |
| 2 | +category: Skills |
| 3 | +subcategory: Handbook |
| 4 | +title: Experimental - Adding Bot Framework Composer dialogs to a Skill |
| 5 | +description: Add dialogs built using Bot Framework Composer to a Skill enabling side by side composition of Waterfall Dialogs and Composer built Adaptive Dialogs. |
| 6 | +order: 1 |
| 7 | +toc: true |
| 8 | +--- |
| 9 | + |
| 10 | +# {{ page.title }} |
| 11 | +{:.no_toc} |
| 12 | +{{ page.description }} |
| 13 | + |
| 14 | +## Introduction |
| 15 | + |
| 16 | +The [Bot Framework Composer](https://aka.ms/bfcomposer) is a visual designer that lets you quickly and easily build sophisticated conversational bots without writing code. Composer is currently in Public Preview and the documentation below covers manual steps to move Dialog management for an existing Skill created using the [Skill Template](https://microsoft.github.io/botframework-solutions/skills/tutorials/create-skill/csharp/1-intro/) to Composer. |
| 17 | + |
| 18 | +For customers that already have existing Bot Framework Virtual Assistant or Custom Skill projects it's important to ensure that Waterfall dialogs and co-exist with Adaptive Dialogs built using Bot Framework Compopser. This documentation covers initial experimental tests to enable you to test hybrid dialog scenarios. |
| 19 | + |
| 20 | +Moving forward there will be an updated Skill Template that will support Bot Framework Composer out of the box without these changes and you can of course use any Composer built dialog as a Skill without using the Skill Template. |
| 21 | + |
| 22 | +> Note that this guidance is experimental and for testing purposes only. |
| 23 | +
|
| 24 | +## Pre-Requisites |
| 25 | + |
| 26 | +- An existing Skill created using the Skill Template, follow [this tutorial](https://microsoft.github.io/botframework-solutions/skills/tutorials/create-skill/csharp/1-intro/) if needed. |
| 27 | +- If you have a Skill created using an older version of the Skill Template, ensure it's updated to the 4.9 Bot Framework SDK as per documentation. |
| 28 | + |
| 29 | +## Build your Composer dialogs |
| 30 | + |
| 31 | +The first step is to create a Composer project and create the appropriate LU, Dialog and LG assets for your scenario. Ensure these work as expected using the `Start Bot` and `Test in Emulator` feature of the Bot Framework Emulator, this will also ensure LUIS resources are published. |
| 32 | + |
| 33 | +## Retrieve the Generated Files |
| 34 | + |
| 35 | +1. Within Composer, and your active project. Click the `Export assets to .zip` option under the Export Menu. This self-contained ZIP file contains all of your declarative assets making up your Composer project. |
| 36 | + |
| 37 | + |
| 38 | + |
| 39 | +2. Unpack this ZIP file into a new sub-folder of your Skill project called `ComposerDialogs` |
| 40 | +3. Copy the `Generated Folder` from your Composer Project into the same `ComposerDialogs` folder. (Temporary) |
| 41 | + |
| 42 | +## Add additional Nuget package references |
| 43 | + |
| 44 | +Add the following additional Nuget packages to your project file |
| 45 | + |
| 46 | +```xml |
| 47 | + <PackageReference Include="Microsoft.Bot.Builder.Dialogs.Adaptive" Version="4.9.1" /> |
| 48 | + <PackageReference Include="Microsoft.Bot.Builder.Dialogs.Declarative" Version="4.9.1" /> |
| 49 | +``` |
| 50 | + |
| 51 | +## Ensure Composer Dialog resources are configured as project content files |
| 52 | + |
| 53 | +1. Edit your `.csproj` file to add the following lines under an `ItemGroup` section |
| 54 | + |
| 55 | +```xml |
| 56 | + <Content Include="**/*.dialog" Exclude="bin/**"> |
| 57 | + <CopyToOutputDirectory>Always</CopyToOutputDirectory> |
| 58 | + </Content> |
| 59 | + <Content Include="**/*.lg" Exclude="bin/**"> |
| 60 | + <CopyToOutputDirectory>Always</CopyToOutputDirectory> |
| 61 | + </Content> |
| 62 | + <Content Include="**/*.lu" Exclude="bin/**"> |
| 63 | + <CopyToOutputDirectory>Always</CopyToOutputDirectory> |
| 64 | + </Content> |
| 65 | +``` |
| 66 | + |
| 67 | +## Update Startup.cs |
| 68 | + |
| 69 | +1. Add the following class variable |
| 70 | + |
| 71 | +```csharp |
| 72 | + private IWebHostEnvironment HostingEnvironment { get; set; } |
| 73 | +``` |
| 74 | + |
| 75 | +2. Add the following to your constructor |
| 76 | + |
| 77 | +```csharp |
| 78 | + this.HostingEnvironment = env; |
| 79 | +``` |
| 80 | + |
| 81 | +3. In the main `ConfigureServices` handler add the following lines to initialise Declarative dialog support and enumerate the Composer built resources. |
| 82 | + |
| 83 | +```csharp |
| 84 | + // Configure Adaptive |
| 85 | + ComponentRegistration.Add(new DialogsComponentRegistration()); |
| 86 | + ComponentRegistration.Add(new AdaptiveComponentRegistration()); |
| 87 | + ComponentRegistration.Add(new DeclarativeComponentRegistration()); |
| 88 | + ComponentRegistration.Add(new LanguageGenerationComponentRegistration()); |
| 89 | + ComponentRegistration.Add(new LuisComponentRegistration()); |
| 90 | + |
| 91 | + // Resource explorer to manage declarative resources for adaptive dialog |
| 92 | + var resourceExplorer = new ResourceExplorer().LoadProject(this.HostingEnvironment.ContentRootPath); |
| 93 | + services.AddSingleton(resourceExplorer); |
| 94 | +``` |
| 95 | + |
| 96 | +4. Ensure any configuration used by the Composer based dialogs is avialable to use through adding this line to the `builder` section of the constructor |
| 97 | + |
| 98 | +```csharp |
| 99 | + .AddJsonFile($"ComposerDialogs\\settings\\appsettings.json", optional:true) |
| 100 | +``` |
| 101 | + |
| 102 | +## Update Adapter |
| 103 | + |
| 104 | +Update the `DefaultAdapter.cs` file under the `Adapters` folder as follows: |
| 105 | + |
| 106 | +1. Add the following additional parameters to the constructor |
| 107 | + |
| 108 | +```csharp |
| 109 | + IStorage storage, |
| 110 | + UserState userState, |
| 111 | + IConfiguration configuration |
| 112 | +``` |
| 113 | + |
| 114 | +2. Then add the following lines to the constructor |
| 115 | + ```csharp |
| 116 | + this.Use(new RegisterClassMiddleware<IConfiguration>(configuration)); |
| 117 | + this.UseStorage(storage); |
| 118 | + this.UseBotState(userState); |
| 119 | + this.UseBotState(conversationState); |
| 120 | + ``` |
| 121 | + |
| 122 | +## Update DefaultActivityHandler |
| 123 | + |
| 124 | +We need to make use of DialogManager to ensure that the Composer based dialogs execute correctly and also send the appropriate EndOfConversation event once dialogs are complete within the Skill. |
| 125 | + |
| 126 | +1. Declare two new local variables |
| 127 | + |
| 128 | +```csharp |
| 129 | + protected readonly DialogManager _dialogManager; |
| 130 | + protected readonly ResourceExplorer _resourceExplorer; |
| 131 | +``` |
| 132 | + |
| 133 | +2. Update the constructor to includes the following lines |
| 134 | + |
| 135 | +```csharp |
| 136 | + _resourceExplorer = serviceProvider.GetService<ResourceExplorer>(); |
| 137 | + _dialogManager = new DialogManager(dialog); |
| 138 | + _dialogManager.UseResourceExplorer(_resourceExplorer); |
| 139 | + _dialogManager.UseLanguageGeneration(); |
| 140 | +``` |
| 141 | + |
| 142 | +3. Update the OnTurnAsync handler to use `_dialogManager` in place of `_dialog` |
| 143 | + |
| 144 | +```csharp |
| 145 | + await _dialogManager.OnTurnAsync(turnContext, cancellationToken: cancellationToken); |
| 146 | +``` |
| 147 | + |
| 148 | +## MainDialog |
| 149 | + |
| 150 | +1. Update the constructor to include the following line |
| 151 | + |
| 152 | +```csharp |
| 153 | + ResourceExplorer resourceExplorer |
| 154 | +``` |
| 155 | + |
| 156 | +2. Then register **each** top-level Composer Dialog you wish to make available |
| 157 | + |
| 158 | +```csharp |
| 159 | + var dialogResource = resourceExplorer.GetResource("todobotwithluissample-0.dialog"); |
| 160 | + var composerDialog = resourceExplorer.LoadType<AdaptiveDialog>(dialogResource); |
| 161 | + |
| 162 | + // Add the dialog |
| 163 | + AddDialog(composerDialog); |
| 164 | +``` |
| 165 | + |
| 166 | +3. Within the appropriate Intent handler within Main Dialog you can now `begin` the Composer based dialog of your choice by adding the following code: |
| 167 | + |
| 168 | +```csharp |
| 169 | + object adaptiveOptions = null; |
| 170 | + return await stepContext.BeginDialogAsync("todobotwithluissample-0.dialog", adaptiveOptions, cancellationToken); |
| 171 | +``` |
| 172 | + |
| 173 | +## LUIS Key |
| 174 | + |
| 175 | +A different LUIS endpoint key is used for your Composer built dialogs but this must be present within the `ComposerDialogs\settings\appSettings.json` file. Add an `endpointKey` entry to the `luis` section of this configuration file, you can find the right key within Composer - Bot Settings. |
| 176 | + |
| 177 | +```json |
| 178 | +"luis": { |
| 179 | + "endpointKey": "YOUR KEY" |
| 180 | + }, |
| 181 | +``` |
| 182 | + |
| 183 | +## Updating Composer artifacts |
| 184 | + |
| 185 | +Using Composer, you can now Open the folder containing your updated Skill and see the Dialogs as before enabling you to easily make changes directly within the updated Skill. |
0 commit comments