Skip to content
This repository has been archived by the owner on Jun 30, 2022. It is now read-only.

[4.4 VA Template] Add skill invocation code #1031

Merged
merged 2 commits into from
Mar 28, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,11 @@ public class InvokeSkillTests : SkillTestBase
public void InitSkills()
{
_skillDefinition = new SkillDefinition();
_skillDefinition.Id = "pointOfInterestSkill";
_skillDefinition.Name = "pointOfInterestSkill";
_skillDefinition.Endpoint = "https://djremotepoiskill.azurewebsites.net/api/skill";

// Add the SkillDialog to the available dialogs passing the initialized FakeSkill
Dialogs.Add(new SkillDialog(_skillDefinition, null, null, null, null, false));
Dialogs.Add(new SkillDialog(_skillDefinition, null));
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
<PackageReference Include="Microsoft.Bot.Builder" Version="4.3.1" />
<PackageReference Include="Microsoft.Bot.Builder.Dialogs" Version="4.3.1" />
<PackageReference Include="Microsoft.Bot.Builder.Integration.AspNet.Core" Version="4.3.1" />
<PackageReference Include="Microsoft.Bot.Builder.Solutions" Version="4.4.0-preview-9" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,14 @@

namespace Microsoft.Bot.Builder.Skills
{
public class SkillDefinition : ConnectedService
public class SkillDefinition
{
public SkillDefinition()
: base("skill")
{
}
public string Name { get; set; }

[JsonProperty("dispatchIntent")]
public string DispatchIntent { get; set; }

[JsonProperty("assembly")]
public string Endpoint { get; set; }

[JsonProperty("supportedProviders")]
public string[] SupportedProviders { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Builder.Solutions.Proactive;
using Microsoft.Bot.Builder.Solutions.TaskExtensions;
using Microsoft.Bot.Configuration;
using Microsoft.Bot.Schema;

namespace Microsoft.Bot.Builder.Skills
Expand All @@ -14,12 +11,8 @@ public class SkillDialog : ComponentDialog
{
private static readonly HttpClient _httpClient = new HttpClient();
private SkillDefinition _skillDefinition;

private ProactiveState _proactiveState;
private IBotTelemetryClient _telemetryClient;
private IBackgroundTaskQueue _backgroundTaskQueue;
private bool _useCachedTokens;


/// <summary>
///
/// </summary>
Expand All @@ -29,14 +22,11 @@ public class SkillDialog : ComponentDialog
/// <param name="telemetryClient"></param>
/// <param name="backgroundTaskQueue"></param>
/// <param name="useCachedTokens"></param>
public SkillDialog(SkillDefinition skillDefinition, ProactiveState proactiveState, EndpointService endpointService, IBotTelemetryClient telemetryClient, IBackgroundTaskQueue backgroundTaskQueue, bool useCachedTokens = true)
: base(skillDefinition.Id)
public SkillDialog(SkillDefinition skillDefinition, IBotTelemetryClient telemetryClient)
: base(skillDefinition.Name)
{
_skillDefinition = skillDefinition;
_proactiveState = proactiveState;
_skillDefinition = skillDefinition;
_telemetryClient = telemetryClient;
_backgroundTaskQueue = backgroundTaskQueue;
_useCachedTokens = useCachedTokens;
}

/// <summary>
Expand Down Expand Up @@ -93,7 +83,7 @@ private async Task<DialogTurnResult> ForwardToSkill(DialogContext innerDc, Activ
// TODO - Revist the synchronous approach currently in place below.

try
{
{
var skillResponses = new List<Activity>();
var filteredSkillResponses = new List<Activity>();

Expand All @@ -109,7 +99,7 @@ private async Task<DialogTurnResult> ForwardToSkill(DialogContext innerDc, Activ
skillResponses = await response.Content.ReadAsAsync<List<Activity>>();

var endOfConversation = false;
foreach (Activity skillResponse in skillResponses)
foreach (var skillResponse in skillResponses)
{
// Signal that the SkilLDialog should be unwound once these responses are processed.
if (skillResponse.Type == ActivityTypes.EndOfConversation)
Expand All @@ -126,7 +116,7 @@ private async Task<DialogTurnResult> ForwardToSkill(DialogContext innerDc, Activ
filteredSkillResponses.Add(skillResponse);
}
}

// Send the filtered activities back (for example, token requests, EndOfConversation, etc. are removed)
if (filteredSkillResponses.Count > 0)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,19 @@ public virtual void Initialize()
TelemetryClient = new NullBotTelemetryClient();
BotServices = new BotServices()
{
DispatchRecognizer = DispatchTestUtil.CreateRecognizer(),
LuisServices = new Dictionary<string, ITelemetryLuisRecognizer>
CognitiveModelSets = new Dictionary<string, Configuration.CognitiveModelSet>
{
{ "general", GeneralTestUtil.CreateRecognizer() }
},
QnAServices = new Dictionary<string, ITelemetryQnAMaker>
{
{ "faq", FaqTestUtil.CreateRecognizer() },
{ "chitchat", ChitchatTestUtil.CreateRecognizer() }
}
{"en", new Configuration.CognitiveModelSet
{
DispatchService = DispatchTestUtil.CreateRecognizer(),
LuisServices = new Dictionary<string, IRecognizer>
{
{ "general", GeneralTestUtil.CreateRecognizer() }
},
QnAServices = null
}
}
}
};

builder.RegisterInstance(new BotStateSet(UserState, ConversationState));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,14 @@ public BotServices(BotSettings settings)

CognitiveModelSets.Add(language, set);
}
}

public CosmosDbStorageOptions CosmosDbOptions { get; }
SkillDefinitions = settings.Skills;
}

public Dictionary<string, string> AuthenticationConnections { get; set; } = new Dictionary<string, string>();

public Dictionary<string, CognitiveModelSet> CognitiveModelSets { get; set; } = new Dictionary<string, CognitiveModelSet>();

public List<SkillDefinition> SkillDefinitions { get; set; } = new List<SkillDefinition>();

// public Dictionary<string, SkillEvent> SkillEvents { get; set; } = new Dictionary<string, SkillEvent>();
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.AI.QnA;
using Microsoft.Bot.Builder.Solutions.Telemetry;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace VirtualAssistantTemplate.Configuration
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Dialogs;
using System.Globalization;
using Microsoft.Bot.Builder.Skills;

namespace VirtualAssistantTemplate.Dialogs.Main
{
Expand All @@ -32,6 +33,11 @@ public MainDialog(BotServices services, ConversationState conversationState, Use

AddDialog(new OnboardingDialog(_services, _userState.CreateProperty<OnboardingState>(nameof(OnboardingState)), telemetryClient));
AddDialog(new EscalateDialog(_services));

foreach (var skill in services.SkillDefinitions)
{
AddDialog(new SkillDialog(skill, telemetryClient));
}
}

protected override async Task OnStartAsync(DialogContext dc, CancellationToken cancellationToken = default(CancellationToken))
Expand All @@ -50,7 +56,12 @@ public MainDialog(BotServices services, ConversationState conversationState, Use
var dispatchResult = await cognitiveModels.DispatchService.RecognizeAsync<Dispatch>(dc.Context, CancellationToken.None);
var intent = dispatchResult.TopIntent().intent;

if (intent == Dispatch.Intent.l_general)
if (_services.SkillDefinitions.Any(s => s.DispatchIntent == intent.ToString()))
{
var skill = _services.SkillDefinitions.Where(s => s.DispatchIntent == intent.ToString()).First();
await dc.BeginDialogAsync(skill.Name);
}
else if (intent == Dispatch.Intent.l_general)
{
// If dispatch result is general luis model
cognitiveModels.LuisServices.TryGetValue("general", out var luisService);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ public class Dispatch : IRecognizerConvert
public string AlteredText;
public enum Intent
{
l_calendar,
l_email,
l_todo,
l_pointofinterest,
l_settings,
l_general,
q_chitchat,
q_faq,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// <auto-generated>
// Code generated by LUISGen
// Tool github: https://github.com/microsoft/botbuilder-tools
// Changes may cause incorrect behavior and will be lost if the code is
// regenerated.
// </auto-generated>
using Newtonsoft.Json;
using System.Collections.Generic;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.AI.Luis;
namespace Luis
{
public class General : IRecognizerConvert
{
public string Text;
public string AlteredText;
public enum Intent
{
Cancel,
Confirm,
Escalate,
FinishTask,
GoBack,
Help,
Logout,
None,
ReadAloud,
Reject,
Repeat,
SelectAny,
SelectItem,
SelectNone,
ShowNext,
ShowPrevious,
StartOver,
Stop
};
public Dictionary<Intent, IntentScore> Intents;

public class _Entities
{
// Simple entities
public string[] DirectionalReference;

// Built-in entities
public double[] number;
public double[] ordinal;

// Instance
public class _Instance
{
public InstanceData[] DirectionalReference;
public InstanceData[] number;
public InstanceData[] ordinal;
}
[JsonProperty("$instance")]
public _Instance _instance;
}
public virtual _Entities Entities { get; set; }

[JsonExtensionData(ReadData = true, WriteData = true)]
public IDictionary<string, object> Properties { get; set; }

public void Convert(dynamic result)
{
var app = JsonConvert.DeserializeObject<General>(JsonConvert.SerializeObject(result));
Text = app.Text;
AlteredText = app.AlteredText;
Intents = app.Intents;
Entities = app.Entities;
Properties = app.Properties;
}

public virtual (Intent intent, double score) TopIntent()
{
Intent maxIntent = Intent.None;
var max = 0.0;
foreach (var entry in Intents)
{
if (entry.Value.Score > max)
{
maxIntent = entry.Key;
max = entry.Value.Score.Value;
}
}
return (maxIntent, max);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -84,17 +84,13 @@ public void ConfigureServices(IServiceCollection services)
{
options.CredentialProvider = new SimpleCredentialProvider(settings.MicrosoftAppId, settings.MicrosoftAppPassword);

// Telemetry Middleware (logs activity messages in Application Insights)
var sp = services.BuildServiceProvider();
var telemetryClient = sp.GetService<IBotTelemetryClient>();

var appInsightsLogger = new TelemetryLoggerMiddleware(telemetryClient, logPersonalInformation: true);
var appInsightsLogger = new TelemetryLoggerMiddleware(botTelemetryClient, logPersonalInformation: true);
options.Middleware.Add(appInsightsLogger);

// Catches any errors that occur during a conversation turn and logs them to AppInsights.
options.OnTurnError = async (context, exception) =>
{
telemetryClient.TrackException(exception);
botTelemetryClient.TrackException(exception);
await context.SendActivityAsync(new Activity(type: ActivityTypes.Trace, text: $"{exception.Message}" ));
await context.SendActivityAsync(new Activity(type: ActivityTypes.Trace, text: $"{exception.StackTrace}"));
await context.SendActivityAsync(MainStrings.ERROR);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,55 @@
{

"Skills": [
{
"Name": "CalendarSkill",
"DispatchIntent": "l_calendar",
"Endpoint": "",
"SupportedProviders": [
"Azure Active Directory v2",
"Google"
]
},
{
"Name": "EmailSkill",
"DispatchIntent": "l_email",
"Endpoint": "",
"SupportedProviders": [
"Azure Active Directory v2",
"Google"
]
},
{
"Name": "ToDoSkill",
"DispatchIntent": "l_todo",
"Endpoint": "",
"SupportedProviders": [
"Azure Active Directory v2",
"Todoist"
]
},
{
"Name": "PointOfInterestSkill",
"DispatchIntent": "l_pointofinterest",
"Endpoint": "",
"SupportedProviders": []
},
{
"Name": "AutomotiveSkill",
"DispatchIntent": "l_settings",
"Endpoint": "",
"SupportedProviders": []
},
{
"Name": "NewsSkill",
"DispatchIntent": "l_news",
"Endpoint": "",
"SupportedProviders": []
},
{
"Name": "RestaurantSkill",
"DispatchIntent": "l_restaurant",
"Endpoint": "",
"SupportedProviders": []
}
]
}