├── Workshop
├── README.md
└── Images
│ ├── Dot.png
│ ├── CloneGitHubRepo.png
│ ├── AppServiceSelection.png
│ ├── BotDevelopmentPhases.png
│ ├── PublishingSummaryPage.png
│ ├── VSPublishUserInterface.png
│ ├── BotLifeCycle Horizontal.png
│ ├── PublishingTargetUserInterface.png
│ ├── ConfigurationSettingUserInterface.png
│ └── bot_framework_accelerators_header.png
├── MultiturnQnAMaker
├── README.md
├── Changes to Startup.cs.pdf
├── Dialogs
│ └── Changes to MainDialog.cs.pdf
├── Services
│ ├── Changes to BotServices.cs.pdf
│ └── MultiturnQnAMaker.cs
├── Models
│ ├── MultiturnQnAContext.cs
│ ├── MultiturnQnAResultList.cs
│ ├── MultiturnQnAMetadata.cs
│ ├── MultiturnQnAPrompts.cs
│ ├── MultiturnQnAState.cs
│ └── MultiturnQnAResult.cs
└── Helpers
│ └── CardHelper.cs
├── DialogAccelerator
├── Images
│ ├── DialogDI.png
│ ├── Startup.png
│ ├── BeginDialog.png
│ ├── RawButton.png
│ ├── PlanBBeginDialog.png
│ └── AddSrcControlInVS.png
├── README.md
└── GetLibraryCard.cs
├── SecuredWebChatControl
├── README.md
├── Controllers
│ └── TokenController.cs
└── wwwroot
│ └── default.htm
├── LICENSE
├── README.md
├── .gitattributes
├── RazorWebChatHost
├── README.md
└── Pages
│ ├── Index.cshtml.cs
│ └── Index.cshtml
└── .gitignore
/Workshop/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/managedcoder/BotFrameworkAccelerators/HEAD/Workshop/README.md
--------------------------------------------------------------------------------
/Workshop/Images/Dot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/managedcoder/BotFrameworkAccelerators/HEAD/Workshop/Images/Dot.png
--------------------------------------------------------------------------------
/MultiturnQnAMaker/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/managedcoder/BotFrameworkAccelerators/HEAD/MultiturnQnAMaker/README.md
--------------------------------------------------------------------------------
/Workshop/Images/CloneGitHubRepo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/managedcoder/BotFrameworkAccelerators/HEAD/Workshop/Images/CloneGitHubRepo.png
--------------------------------------------------------------------------------
/DialogAccelerator/Images/DialogDI.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/managedcoder/BotFrameworkAccelerators/HEAD/DialogAccelerator/Images/DialogDI.png
--------------------------------------------------------------------------------
/DialogAccelerator/Images/Startup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/managedcoder/BotFrameworkAccelerators/HEAD/DialogAccelerator/Images/Startup.png
--------------------------------------------------------------------------------
/DialogAccelerator/Images/BeginDialog.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/managedcoder/BotFrameworkAccelerators/HEAD/DialogAccelerator/Images/BeginDialog.png
--------------------------------------------------------------------------------
/DialogAccelerator/Images/RawButton.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/managedcoder/BotFrameworkAccelerators/HEAD/DialogAccelerator/Images/RawButton.png
--------------------------------------------------------------------------------
/Workshop/Images/AppServiceSelection.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/managedcoder/BotFrameworkAccelerators/HEAD/Workshop/Images/AppServiceSelection.png
--------------------------------------------------------------------------------
/Workshop/Images/BotDevelopmentPhases.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/managedcoder/BotFrameworkAccelerators/HEAD/Workshop/Images/BotDevelopmentPhases.png
--------------------------------------------------------------------------------
/Workshop/Images/PublishingSummaryPage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/managedcoder/BotFrameworkAccelerators/HEAD/Workshop/Images/PublishingSummaryPage.png
--------------------------------------------------------------------------------
/Workshop/Images/VSPublishUserInterface.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/managedcoder/BotFrameworkAccelerators/HEAD/Workshop/Images/VSPublishUserInterface.png
--------------------------------------------------------------------------------
/DialogAccelerator/Images/PlanBBeginDialog.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/managedcoder/BotFrameworkAccelerators/HEAD/DialogAccelerator/Images/PlanBBeginDialog.png
--------------------------------------------------------------------------------
/MultiturnQnAMaker/Changes to Startup.cs.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/managedcoder/BotFrameworkAccelerators/HEAD/MultiturnQnAMaker/Changes to Startup.cs.pdf
--------------------------------------------------------------------------------
/Workshop/Images/BotLifeCycle Horizontal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/managedcoder/BotFrameworkAccelerators/HEAD/Workshop/Images/BotLifeCycle Horizontal.png
--------------------------------------------------------------------------------
/DialogAccelerator/Images/AddSrcControlInVS.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/managedcoder/BotFrameworkAccelerators/HEAD/DialogAccelerator/Images/AddSrcControlInVS.png
--------------------------------------------------------------------------------
/Workshop/Images/PublishingTargetUserInterface.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/managedcoder/BotFrameworkAccelerators/HEAD/Workshop/Images/PublishingTargetUserInterface.png
--------------------------------------------------------------------------------
/MultiturnQnAMaker/Dialogs/Changes to MainDialog.cs.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/managedcoder/BotFrameworkAccelerators/HEAD/MultiturnQnAMaker/Dialogs/Changes to MainDialog.cs.pdf
--------------------------------------------------------------------------------
/Workshop/Images/ConfigurationSettingUserInterface.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/managedcoder/BotFrameworkAccelerators/HEAD/Workshop/Images/ConfigurationSettingUserInterface.png
--------------------------------------------------------------------------------
/Workshop/Images/bot_framework_accelerators_header.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/managedcoder/BotFrameworkAccelerators/HEAD/Workshop/Images/bot_framework_accelerators_header.png
--------------------------------------------------------------------------------
/MultiturnQnAMaker/Services/Changes to BotServices.cs.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/managedcoder/BotFrameworkAccelerators/HEAD/MultiturnQnAMaker/Services/Changes to BotServices.cs.pdf
--------------------------------------------------------------------------------
/MultiturnQnAMaker/Models/MultiturnQnAContext.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT License.
3 |
4 | namespace QnA.MultiturnQnAMaker
5 | {
6 | public class MultiturnQnAContext
7 | {
8 | public MultiturnQnAPrompts[] Prompts { get; set; }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/MultiturnQnAMaker/Models/MultiturnQnAResultList.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT License.
3 |
4 | namespace QnA.MultiturnQnAMaker
5 | {
6 | public class MultiturnQnAResultList
7 | {
8 | public MultiturnQnAResult[] Answers { get; set; }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/MultiturnQnAMaker/Models/MultiturnQnAMetadata.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT License.
3 |
4 | namespace QnA.MultiturnQnAMaker
5 | {
6 | public class MultiturnQnAMetadata
7 | {
8 | public string Name { get; set; }
9 |
10 | public string Value { get; set; }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/MultiturnQnAMaker/Models/MultiturnQnAPrompts.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT License.
3 |
4 | namespace QnA.MultiturnQnAMaker
5 | {
6 | public class MultiturnQnAPrompts
7 | {
8 | public int DisplayOrder { get; set; }
9 |
10 | public int QnaId { get; set; }
11 |
12 | public string DisplayText { get; set; }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/MultiturnQnAMaker/Models/MultiturnQnAState.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace QnA.MultiturnQnAMaker
7 | {
8 | ///
9 | /// This is passed as the context in the body of the call to generateanswer API in the QnA service
10 | ///
11 | public class MultiturnQnAState
12 | {
13 | public int PreviousQnaId { get; set; }
14 |
15 | public string PreviousUserQuery { get; set; }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/MultiturnQnAMaker/Models/MultiturnQnAResult.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT License.
3 |
4 | namespace QnA.MultiturnQnAMaker
5 | {
6 | public class MultiturnQnAResult
7 | {
8 | public string[] Questions { get; set; }
9 |
10 | public string Answer { get; set; }
11 |
12 | public double Score { get; set; }
13 |
14 | public int Id { get; set; }
15 |
16 | public string Source { get; set; }
17 |
18 | public MultiturnQnAMetadata[] Metadata { get; }
19 |
20 | public MultiturnQnAContext Context { get; set; }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/SecuredWebChatControl/README.md:
--------------------------------------------------------------------------------
1 | # Secured Web Chat Control
2 | This accelerator shows how to embed a Web Chat control on a web page without exposing the bot secret. You can also use it
3 | to create a quick test page so others can explore or test your bot without having to use bot emulator or browse to the
4 | portal.
5 |
6 | For more information about securely embedding a Web Chat conrol, see the Direct Line documentation
7 | [here](https://docs.microsoft.com/en-us/azure/bot-service/rest-api/bot-framework-rest-direct-line-3-0-authentication?view=azure-bot-service-4.0)
8 |
9 | ## To Use
10 | 1. Copy wwwroot\default.htm to the wwwroot folder and replace the existing default.htm file
11 | 2. Copy Controllers\TokenController.cs to your Controllers folder in your Virtual Assistant and follow the instructions at the top
12 | of that file
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Russ Williams
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Bot Framework Development Accelerators
2 | This repository is home to a set of development accelerators for bots and advanced conversational experiences that are built
3 | on the [Microsoft Bot Framework](https://dev.botframework.com/) and the [Virtual Assistant](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-virtual-assistant-introduction?view=azure-bot-service-4.0).
4 |
5 | This repository is NOT an official Microsoft repository nor is it part of the Micorosoft Bot Framework but you should find
6 | it useful.
7 |
8 | ## [Bot Accelerator Workshop](Workshop)
9 | This workshop is a step-by-step guide for building your first enterprise bot. Its part recipe, part master plan, which you can
10 | use to accelerate your bot journey from conception to production deployment.
11 |
12 | ## [Secure Your Web Chat Control](SecuredWebChatControl)
13 | Shows how to embed a Web Chat control on a web page without exposing the bot secret
14 |
15 | ## [Add Multiturn QnA to a Virtual Assistant](MultiturnQnAMaker)
16 | Shows how to enable QnA Maker follow-on prompts in a bot that was created in Visual Studio
17 | using the Virtual Assistant template.
18 |
19 | ## [Dialog Accelerator](DialogAccelerator)
20 | Dialog template you can use to create moderate to complex conversational bot dialogs
21 |
--------------------------------------------------------------------------------
/MultiturnQnAMaker/Helpers/CardHelper.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT License.
3 |
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using Microsoft.Bot.Schema;
7 | using QnA.MultiturnQnAMaker;
8 |
9 | namespace QnAPrompting.Helpers
10 | {
11 | public class CardHelper
12 | {
13 | ///
14 | /// Get Hero card
15 | ///
16 | /// Title of the card
17 | /// List of suggested prompts
18 | /// Message activity
19 | public static Activity GetHeroCard(string cardTitle, QnAPrompts[] prompts)
20 | {
21 | var chatActivity = Activity.CreateMessageActivity();
22 | var buttons = new List();
23 |
24 | var sortedPrompts = prompts.OrderBy(r => r.DisplayOrder);
25 | foreach (var prompt in sortedPrompts)
26 | {
27 | buttons.Add(
28 | new CardAction()
29 | {
30 | Value = prompt.DisplayText,
31 | Type = ActionTypes.ImBack,
32 | Title = prompt.DisplayText,
33 | });
34 | }
35 |
36 | var plCard = new HeroCard()
37 | {
38 | Title = cardTitle,
39 | Subtitle = string.Empty,
40 | Buttons = buttons
41 | };
42 |
43 | var attachment = plCard.ToAttachment();
44 |
45 | chatActivity.Attachments.Add(attachment);
46 |
47 | return (Activity)chatActivity;
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/RazorWebChatHost/README.md:
--------------------------------------------------------------------------------
1 | # Razor Page Web Chat Host
2 |
3 | This Razor page shows how to securly hosts a Web Chat control and it can be used as a convenient
4 | test page during development that others can use to access your bot. To use this page, do the
5 | following:
6 |
7 | 1) Add the `Pages` folder and its contents to your bot project (could be added to your assistant or skill or both)
8 | 2) Add the following member to the Startup class in startup.cs:
9 | ```c#
10 | public static HttpClient HttpClient = new HttpClient();
11 | ```
12 | 3) Add a using statement to Index.cshtml.cs that resolves the Startup.HttpClient reference
13 | ```
14 | using ;
15 | ```
16 | 4) Add the following to ConfigureServices() method in startup.cs:
17 | ```c#
18 | // Add Razor Pages
19 | services.AddRazorPages();
20 | ```
21 | 5) Replace the UseEndpoints statement in Configure() method in startup.cs:
22 | ```c#
23 | .UseEndpoints(endpoints =>
24 | {
25 | endpoints.MapControllers();
26 | endpoints.MapRazorPages();
27 | });
28 | ```
29 | 6) Add the Direct Line Channel to your bot in the Azure portal and use it's bot secret to set
30 | the BotSecret configuration setting in your appsettings.json file
31 | ```json
32 | "BotSecret": "",
33 | ```
34 | 7) Take a look at the IndexModel() constructor in the code behind to see which other settings
35 | can be configured, if desired
36 | 8) Optional - Delete the `default.htm` file from the `wwwroot` folder since you now have a new home page
37 |
38 | **Note:** Unlike other approaches, this Razor page DOES NOT require a token controller API to be
39 | added to your solution since that functionality is taken care of in the code behind for this page.
40 |
41 | **Note:** Its important to understand that when this page runs in localhost it will be interacting with
42 | the deployed bot, **NOT THE BOT RUNNING IN LOCAL HOST**. So you can't use it for localhost debugging
43 | to hit breakpoints in your code unless you create a separate Bot Channels Registration that points to
44 | an ngrok-exposed localhost.
45 |
46 | If you want to use the this page to drive localhost debugging via a separate Bot Channel Registration,
47 | install ngrok and run this ngrok command
48 | ```
49 | ngrok http 3978 -host-header=localhost:3978
50 | ```
51 | When creating the Bot Channel Registration, you'll have to set the messaging endpoint of the Bot Channel
52 | Registration to the https version of the endpoints exposed by ngrok which should look something like
53 | the following. Remember, the ngrok exposed endpoint only lasts as long as the command window is
54 | running so the next time you run ngrok you'll have to reset/update the messaging endpoint in the Bot
55 | Chanel Registration.
56 |
57 | ```
58 | https://.ngrok.io/api/messages
59 | ```
60 |
61 | Details regarding securing web chat control can be found [here](https://docs.microsoft.com/en-us/azure/bot-service/rest-api/bot-framework-rest-direct-line-3-0-authentication?view=azure-bot-service-4.0)
62 |
63 |
--------------------------------------------------------------------------------
/RazorWebChatHost/Pages/Index.cshtml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Net.Http;
5 | using System.Net.Http.Headers;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using Microsoft.AspNetCore.Mvc;
9 | using Microsoft.AspNetCore.Mvc.RazorPages;
10 | using Microsoft.Extensions.Configuration;
11 | using Newtonsoft.Json;
12 | using SBA_Assistant;
13 |
14 | namespace SecuredWebChat.Razor.Pages
15 | {
16 | public class IndexModel : PageModel
17 | {
18 | const string TokenGenerationUrl = "https://directline.botframework.com/v3/directline/tokens/generate";
19 |
20 | public IndexModel(IConfiguration configuration)
21 | {
22 | BotSecret = configuration["BotSecret"];
23 | HideUploadButton = bool.Parse(configuration["HideUploadButton"]);
24 | BotAvatarInitials = configuration["BotAvatarInitials"];
25 | UserAvatarInitials = configuration["UserAvatarInitials"];
26 |
27 | DLToken = GetTokenAsync().ConfigureAwait(false).GetAwaiter().GetResult().token;
28 | }
29 | public string DLToken { get; set; }
30 |
31 | // Dynamic values (not appsettings values)
32 | public string UserId { get; set; } = $"dl_{Guid.NewGuid()}";
33 | public string UserName { get; set; } = "botUser";
34 |
35 | //Index.cshtml settings
36 | public string BotSecret { get; set; }
37 | public bool HideUploadButton { get; set; }
38 | public string BotAvatarInitials { get; set; }
39 | public string UserAvatarInitials { get; set; }
40 |
41 | public void OnGet()
42 | {
43 |
44 | }
45 |
46 | public async Task GetTokenAsync()
47 | {
48 | using (var request = new HttpRequestMessage(HttpMethod.Post, TokenGenerationUrl))
49 | {
50 | // For more information on exchanging a secret for a token see:
51 | // https://docs.microsoft.com/en-us/azure/bot-service/rest-api/bot-framework-rest-direct-line-3-0-authentication#generate-token
52 | request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", BotSecret);
53 | request.Content = new StringContent(JsonConvert.SerializeObject(new { User = new { Id = UserId } }), Encoding.UTF8, "application/json");
54 |
55 | using (var response = await Startup.HttpClient.SendAsync(request).ConfigureAwait(false))
56 | {
57 | if (response.IsSuccessStatusCode)
58 | {
59 | var body = await response.Content.ReadAsStringAsync();
60 | var dlToken = JsonConvert.DeserializeObject(body);
61 | dlToken.userId = UserId;
62 | return dlToken;
63 | }
64 | else
65 | {
66 | throw new Exception($"Could not swap bot secret for token - Status Code: {response.StatusCode}, Response: {response.ReasonPhrase}");
67 | }
68 | }
69 | }
70 |
71 | return null;
72 | }
73 |
74 | public class DirectLineToken
75 | {
76 | public string userId { get; set; }
77 | public string token { get; set; }
78 | public int expires_in { get; set; }
79 | public string streamUrl { get; set; }
80 | }
81 |
82 | }
83 | }
--------------------------------------------------------------------------------
/MultiturnQnAMaker/Services/MultiturnQnAMaker.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT License.
3 |
4 | using System.Collections;
5 | using System.Collections.Generic;
6 | using System.Net.Http;
7 | using System.Threading;
8 | using System.Threading.Tasks;
9 | using Microsoft.Bot.Builder;
10 | using Microsoft.Bot.Builder.AI.QnA;
11 | using Microsoft.Bot.Builder.Dialogs;
12 | using Microsoft.Bot.Schema;
13 | using Microsoft.Extensions.Configuration;
14 | using Newtonsoft.Json;
15 | using QnAPrompting.Helpers;
16 |
17 | namespace QnA.MultiturnQnAMaker
18 | {
19 | public class MultiturnQnAMaker : QnAMaker
20 | {
21 | public const string FunctionStateName = "functionState";
22 | private readonly HttpClient _httpClient;
23 | private readonly QnAMakerEndpoint _endpoint;
24 | private readonly QnAMakerOptions _options;
25 |
26 | public MultiturnQnAMaker(QnAMakerEndpoint endpoint, HttpClient httpClient, IBotTelemetryClient telemetryClient, bool logPersonalInformation = false) : base(endpoint, null, httpClient, telemetryClient, logPersonalInformation)
27 | {
28 | _httpClient = httpClient;
29 | _endpoint = endpoint;
30 | _options = new QnAMakerOptions { Top = 3 };
31 | }
32 |
33 | public async Task<(MultiturnQnAState newState, IEnumerable output)> GetAnswersAsync(MultiturnQnAState oldState, ITurnContext turnContext, QnAMakerOptions options, Dictionary telemetryProperties, Dictionary telemetryMetrics = null)
34 | {
35 | Activity outputActivity = null;
36 | MultiturnQnAState newState = null;
37 |
38 | var query = turnContext.Activity.Text;
39 | var qnaResult = await QueryQnAServiceAsync(query, oldState);
40 | var qnaAnswer = qnaResult[0].Answer;
41 | var prompts = qnaResult[0].Context?.Prompts;
42 |
43 | if (prompts == null || prompts.Length < 1)
44 | {
45 | outputActivity = MessageFactory.Text(qnaAnswer);
46 | }
47 | else
48 | {
49 | // Set bot state only if prompts are found in QnA result
50 | newState = new MultiturnQnAState
51 | {
52 | PreviousQnaId = qnaResult[0].Id,
53 | PreviousUserQuery = query
54 | };
55 |
56 | outputActivity = CardHelper.GetHeroCard(qnaAnswer, prompts);
57 | }
58 |
59 | return (newState, new Activity[] { outputActivity });
60 | }
61 |
62 | public async Task QueryQnAServiceAsync(string query, MultiturnQnAState oldState)
63 | {
64 | var requestUrl = $"{_endpoint.Host}/knowledgebases/{_endpoint.KnowledgeBaseId}/generateanswer";
65 | var request = new HttpRequestMessage(HttpMethod.Post, requestUrl);
66 | var jsonRequest = JsonConvert.SerializeObject(
67 | new
68 | {
69 | question = query,
70 | top = _options.Top,
71 | context = oldState,
72 | strictFilters = _options.StrictFilters,
73 | metadataBoost = _options.MetadataBoost,
74 | scoreThreshold = _options.ScoreThreshold,
75 | }, Formatting.None);
76 |
77 | request.Headers.Add("Authorization", $"EndpointKey {_endpoint.EndpointKey}");
78 | request.Content = new StringContent(jsonRequest, System.Text.Encoding.UTF8, "application/json");
79 |
80 | var response = await _httpClient.SendAsync(request);
81 | response.EnsureSuccessStatusCode();
82 |
83 | var contentString = await response.Content.ReadAsStringAsync();
84 |
85 | var result = JsonConvert.DeserializeObject(contentString);
86 |
87 | return result.Answers;
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/SecuredWebChatControl/Controllers/TokenController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Net.Http;
5 | using System.Threading.Tasks;
6 | using Microsoft.AspNetCore.Http;
7 | using Microsoft.AspNetCore.Mvc;
8 | using Microsoft.Extensions.Configuration;
9 | using Microsoft.IdentityModel.Protocols;
10 | using Newtonsoft.Json;
11 | using Newtonsoft.Json.Linq;
12 |
13 | /* ----------------------------------------------------------------------------------
14 | * ToDo: Important tasks that must be complete for TokenController will work
15 | * The following tasks must be completed before running this code or it will fail:
16 | * 1) To avoid connection exhaustion issues, this code uses a single static instance
17 | * of an HttpClient that needs to be added as a member of the Startup class:
18 | * `public static HttpClient HttpClient = new HttpClient();`
19 | * 2) Change the fully qualified namespace of the reference to the HttpClient on line 42
20 | * of the TokenController constructor to match the namespace of your Startup class:
21 | * `Client = .Startup.HttpClient;`
22 | * 2) This code expects that to get the DirectLine secret from the appsettings.json file so
23 | * you'll need to add the following setting to the appsettings.json file:
24 | * `"directLineSecret": "",`
25 | * 3) Go to the Azure portal and enable the Direct Line channel and copy the Secret Key
26 | * and paste it in as the value of the directLineSecret setting that you created in
27 | * the previous step.
28 | * ----------------------------------------------------------------------------------
29 | */
30 | namespace SecuredWebChatConrol.Controllers
31 | {
32 | [Route("api/[controller]")]
33 | [ApiController]
34 | public class TokenController : ControllerBase
35 | {
36 | public IConfiguration Configuration { get; set; }
37 | public HttpClient Client { get; set; }
38 |
39 | public TokenController(IConfiguration configuration)
40 | {
41 | // If you are seeing a runtime error that complains about not being able to inject the
42 | // HttpClient, then see the note at the note at the top of this file
43 | Configuration = configuration;
44 | Client = Microsoft.BotBuilderSamples.Startup.HttpClient;
45 | }
46 |
47 | // GET: api/Token
48 | [HttpGet]
49 | [Produces("application/json")]
50 | async public Task Get()
51 | {
52 | string generateTokenUri = "https://directline.botframework.com/v3/directline/tokens/generate";
53 | var directLineSecret = Configuration["directLineSecret"];
54 |
55 | return JsonConvert.SerializeObject(await GetTokenAsync(generateTokenUri, directLineSecret));
56 | }
57 |
58 | // GET: api/Token/5
59 | [HttpGet("{token}", Name = "Get")]
60 | [Produces("application/json")]
61 | async public Task Get(string directLineSecret)
62 | {
63 | return JsonConvert.SerializeObject(await GetTokenAsync("https://directline.botframework.com/v3/directline/tokens/refresh", directLineSecret));
64 | }
65 |
66 | async Task