forked from microsoft/BotBuilder-Samples
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Program.cs
179 lines (153 loc) · 8.28 KB
/
Program.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
namespace LuisActions.Samples.Console
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Configuration;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Bot.Builder.Luis;
using Microsoft.Bot.Builder.Luis.Models;
using Microsoft.Cognitive.LUIS.ActionBinding;
using Samples;
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Query samples:\n");
Console.WriteLine("- What is the time in Miami?");
Console.WriteLine("- Search for 5 stars hotels in Barcelona");
Console.WriteLine("- Tell me the weather in Buenos Aires");
Console.WriteLine("- Find airport with code PMV");
while (true)
{
Console.Write("\n> Your Query? ");
var query = Console.ReadLine();
if (!string.IsNullOrWhiteSpace(query))
{
RunQuery(query).Wait();
}
}
}
private static async Task<ActionExecutionContext> RunActions(ILuisService luisService, IList<ActionExecutionContext> actions)
{
if (actions == null || actions.Count == 0)
{
Console.WriteLine(">> ERROR: Action chain cannot be null or empty.");
return null;
}
var actionExecutionContext = actions.First();
var intentAction = actions.First().Action;
actions.RemoveAt(0);
if (actions.Count > 0)
{
await RunActions(luisService, actions);
}
var validationResults = default(ICollection<ValidationResult>);
bool isValid = intentAction.IsValid(out validationResults);
while (!isValid)
{
var fieldValidation = validationResults.FirstOrDefault();
if (fieldValidation != null)
{
var paramName = fieldValidation.MemberNames.First();
Console.Write("({0}) {1}: ", paramName, fieldValidation.ErrorMessage);
var input = Console.ReadLine();
var queryResult = await LuisActionResolver.QueryValueFromLuisAsync(luisService, intentAction, paramName, input, CancellationToken.None);
if (!queryResult.Succeed && !string.IsNullOrWhiteSpace(queryResult.NewIntent) && queryResult.NewAction != null)
{
var newActionDefinition = LuisActionResolver.GetActionDefinition(queryResult.NewAction);
var currentActionDefinition = LuisActionResolver.GetActionDefinition(intentAction);
var isContextual = false;
if (LuisActionResolver.IsValidContextualAction(queryResult.NewAction, intentAction, out isContextual))
{
var executionContextChain = new List<ActionExecutionContext> { new ActionExecutionContext(queryResult.NewIntent, queryResult.NewAction) };
var executionContext = await RunActions(luisService, executionContextChain);
if (executionContext.ChangeRootSignaling)
{
if (LuisActionResolver.IsContextualAction(intentAction))
{
return executionContext;
}
else
{
intentAction = executionContext.Action;
}
}
}
else if (isContextual && !LuisActionResolver.IsContextualAction(intentAction))
{
Console.WriteLine($"Cannot execute action '{newActionDefinition.FriendlyName}' in the context of '{currentActionDefinition.FriendlyName}' - continuing with current action");
}
else if (!intentAction.GetType().Equals(queryResult.NewAction.GetType()))
{
var valid = LuisActionResolver.UpdateIfValidContextualAction(queryResult.NewAction, intentAction, out isContextual);
if (!valid && isContextual)
{
Console.WriteLine($"Cannot switch to action '{newActionDefinition.FriendlyName}' from '{currentActionDefinition.FriendlyName}' due to invalid context - continuing with current action");
}
else if (currentActionDefinition.ConfirmOnSwitchingContext)
{
Console.Write($"You are about to discard the current action '{currentActionDefinition.FriendlyName}' and start executing '{newActionDefinition.FriendlyName}'\nContinue? ");
var response = Console.ReadLine();
if (response.ToUpperInvariant().StartsWith("Y"))
{
if (LuisActionResolver.IsContextualAction(intentAction) && !LuisActionResolver.IsContextualAction(queryResult.NewAction))
{
return new ActionExecutionContext(queryResult.NewIntent, queryResult.NewAction) { ChangeRootSignaling = true };
}
intentAction = queryResult.NewAction;
}
}
else
{
intentAction = queryResult.NewAction;
}
}
}
// re-evaluate
isValid = intentAction.IsValid(out validationResults);
}
}
var result = await intentAction.FulfillAsync();
// We just show the ToString() of the result - not care about the result type here
Console.WriteLine(result != null ? result.ToString() : "Cannot resolve your query");
return actionExecutionContext;
}
private static async Task RunQuery(string query)
{
// Process message
var luisService = new LuisService(new LuisModelAttribute(ConfigurationManager.AppSettings["LUIS_ModelId"], ConfigurationManager.AppSettings["LUIS_SubscriptionKey"]));
var luisResult = await luisService.QueryAsync(query, CancellationToken.None);
// Try to resolve intent to action
var intentName = default(string);
var intentEntities = default(IList<EntityRecommendation>);
var intentAction = new LuisActionResolver(typeof(GetTimeInPlaceAction).Assembly)
.ResolveActionFromLuisIntent(luisResult, out intentName, out intentEntities);
if (intentAction != null)
{
var executionContextChain = new List<ActionExecutionContext> { new ActionExecutionContext(intentName, intentAction) };
while (LuisActionResolver.IsContextualAction(intentAction))
{
var luisActionDefinition = default(LuisActionBindingAttribute);
if (!LuisActionResolver.CanStartWithNoContextAction(intentAction, out luisActionDefinition))
{
Console.WriteLine($"Cannot start contextual action '{luisActionDefinition.FriendlyName}' without a valid context.");
return;
}
intentAction = LuisActionResolver.BuildContextForContextualAction(intentAction, out intentName);
if (intentAction != null)
{
executionContextChain.Insert(0, new ActionExecutionContext(intentName, intentAction));
}
}
await RunActions(luisService, executionContextChain);
}
else
{
Console.WriteLine("Could not understand the input.");
}
}
}
}