How to use AllowPartialMatches in Microsoft.Bot.Builder.Dialogs.Choices? - c#

I'm using Microsoft BotFramework with Microsoft.Bot.Builder 4.0 library in C#.
I want to use Dialogs.Choices, and have been able to get simple ChoicePrompt working. However, the above link does not help much in understanding the namespace in depth. Online demos and samples are very basic, so I have to guess & experiment to understand the functionality.
Specifically, I'm looking at AllowPartialMatches, which appears to support some kind of fuzzy/similarity match. I.e. user types something without exact match, and the prompt finds the 'nearest' match. Is my guess correct?
Can someone explain and provide examples? Thanks?

In the waterfall dialog, create the dialog step as:
AddDialog(new ChoicePrompt(UNSPSCPrompt){
RecognizerOptions = new FindChoicesOptions()
{ AllowPartialMatches = true }
});
In the dialog step itself:
var choices = new List<Choice>
{
new Choice()
{
Value = "itm001",
Synonyms = new List<string> {"hotdog", "hot dog"},
Action = new CardAction()
{
Type = ActionTypes.ImBack,
Title = "Buy a hotdog",
Value = "hotdog"
}
},
new Choice()
{
Value = "itm002",
Synonyms = new List<string> {"bulldog", "bull dog"},
Action = new CardAction()
{
Type = ActionTypes.ImBack,
Title = "Buy a bulldog",
Value = "bulldog"
}
},
};
return await stepContext.PromptAsync("myPrompt",
new PromptOptions {
Prompt = MessageFactory.Text("What can I offer you?"),
RetryPrompt = MessageFactory.Text("I dont have that"),
Choices = choices,
Style = ListStyle.HeroCard
}, cancellationToken);
This will make utterance "a hot one" match "hot dog".
However, "hotdogs" will match nothing, i.e. tokens (words) need exact match.
"dog" will match either of the choices, and it seems that only the 'top' score is returned. (Fully implemented?)

Related

Anyone knows how to virtually click keyboard's keys with a UWP app?

I'm creating a sort of program that holds the letter W in games to avoid AFK penaltie
I tried reading the documentation but is a complete mess.
Anyone knows how to do that?
To inject keyboard input, you will need to create a InputInjector class first. It represents the virtual input device for sending the input data. Then you will need to create a InjectedInputKeyboardInfo Class which contains the key input. After that, you could call inputInjector.InjectKeyboardInput method to inject the keyboard input.
Please also note that the APIs in the Windows.UI.Input.Preview.Injection Namespace require the inputInjectionBrokered restricted capability.
Here is the code that you could refer to:
InputInjector inputInjector = InputInjector.TryCreate();
var controlkey = new InjectedInputKeyboardInfo();
controlkey.VirtualKey = (ushort)(VirtualKey.LeftControl);
controlkey.KeyOptions = InjectedInputKeyOptions.None;
var altkey = new InjectedInputKeyboardInfo();
altkey.VirtualKey = (ushort)(VirtualKey.Menu);
altkey.KeyOptions = InjectedInputKeyOptions.None;
var delkey = new InjectedInputKeyboardInfo();
delkey.VirtualKey = (ushort)(VirtualKey.Delete);
delkey.KeyOptions = InjectedInputKeyOptions.None;
inputInjector.InjectKeyboardInput(new[] { controlkey, altkey, delkey });
controlkey.KeyOptions = InjectedInputKeyOptions.KeyUp;
altkey.KeyOptions = InjectedInputKeyOptions.KeyUp;
delkey.KeyOptions = InjectedInputKeyOptions.KeyUp;
inputInjector.InjectKeyboardInput(new[] { controlkey, altkey, delkey });

How to mirror AdaptiveChoiceSetInput behavior on mobile and desktop devices?

Working on a bot for teams using the Bot Framework SDK, I noticed that the AdaptiveChoiceSetInput (dropdowns) in cards don't behave the same way on mobile and desktop devices.
On desktop Teams, if a dropdown does not have a value, it defaults to a placeholder Select. This automatic defaulting also allows for validation to force a choice to be selected from the dropdown.
On mobile Teams, if a dropdown does not have a value, it instead defaults to the first choice. This is obviously incorrect as it makes it appear like a choice is selected in the dropdown, when it's really null.
A solution I tried was to manually add a default choice with value of null so that it would automatically set itself on mobile if the value was null. This caused an issue where the card did not appear on a mobile device.
Another solution was to add a value, like 0. Although it's likely possible to make things work this way, it lead to some complicated code I never finished because on desktop I had to account for the placeholder and the manually added default choice, and figure out how to prevent the form to be submitted with the manually added default choice.
How can I make the AdaptiveChoiceSetInput behave the same way on mobile version of Teams as in the desktop version?
Here's the relevant code:
private async Task<Attachment> GetEditableOrder(OrderModel order)
{
List<AdaptiveChoice> orderAdaptiveChoices = _context.GetOrderAdaptiveChoices(order.id);
var card = new AdaptiveCard(new AdaptiveSchemaVersion(1, 0));
card.Body.Add(new AdaptiveColumnSet
{
Columns = new List<AdaptiveColumn>
{
new AdaptiveColumn
{
Items = new List<AdaptiveElement>
{
new AdaptiveTextBlock
{
Text = "**Order**"
}
}
},
new AdaptiveColumn
{
Items = new List<AdaptiveElement>
{
new AdaptiveChoiceSetInput
{
Id = "orderId",
Choices = orderAdaptiveChoices,
Value = order.Id.ToString(),
Style = AdaptiveChoiceInputStyle.Compact,
Placeholder = "Select",
IsRequired = true,
ErrorMessage = "Selection required."
}
}
}
}
});
card.Actions.Add(new AdaptiveSubmitAction
{
Type = AdaptiveSubmitAction.TypeName,
Title = "Submit",
Data = new JObject {
{ "submitLocation", "editOrder" }
},
});
Attachment attachment = new Attachment()
{
ContentType = "application/vnd.microsoft.card.adaptive",
Content = card
};
return attachment;
}
I solved my issue by manually adding an additional default choice titled "Select" with the value of an empty string. The values null and 0 did not work due to the issues I mentioned in my question. But an empty string seems to behave the same way as the placeholder in desktop version of Teams.
So, to make the dropdown in the cards behave the same way on desktop and mobile version of Teams, simply prepend a default AdaptiveChoice to your list with the value of an empty string:
orderAdaptiveChoices.Insert(0, new AdaptiveChoice { Value = "", Title = "Select" });
Whenever it is selected on either device, it will function the same way as the placeholder that is available only on desktop Teams.

Allow users to multiselect option in BotFramework

I would like my Bot make surveys. The problem is that in some questions, the user could select more than 1 answer.
How could I implement this scenario? Is there an official sample on how to do it with version 3 of the SDK?
Thank you!
The problem is that in some questions, the user could select more than 1 answer.
To enable user to select more than 1 answer to question(s), you can use AdaptiveChoiceSetInput to achieve the requirement. The following code snippet is for your reference.
card.Body.Add(new AdaptiveTextBlock()
{
Text = "Q1:xxxxxxxx?",
Size = AdaptiveTextSize.Default,
Weight = AdaptiveTextWeight.Bolder
});
card.Body.Add(new AdaptiveChoiceSetInput()
{
Id = "choiceset1",
Choices = new List<AdaptiveChoice>()
{
new AdaptiveChoice(){
Title="answer1",
Value="answer1"
},
new AdaptiveChoice(){
Title="answer2",
Value="answer2"
},
new AdaptiveChoice(){
Title="answer3",
Value="answer3"
}
},
Style = AdaptiveChoiceInputStyle.Expanded,
IsMultiSelect = true
});
Test result:

Azure ML Experiment Batch Webservice Call Fails with Invalid Output Extension

I have an Azure webjob that is calling a ML training experiment via HttpRequests, leveraging the code generated in the ML webportal:
var request = new BatchExecutionRequest()
{
Inputs = new Dictionary<string, AzureBlobDataReference>() {
{
"input1",
new AzureBlobDataReference()
{
ConnectionString = _connectionString,
RelativeLocation = $"{_containerName}/{experimentId}/{tenantId}/{trainingDataFileName}"
}
},
},
Outputs = new Dictionary<string, AzureBlobDataReference>() {
{
"output1",
new AzureBlobDataReference()
{
ConnectionString = "azureStorageConnectionString",
RelativeLocation = $"{_containerName}/{experimentId}/{tenantId}/Model_2018421.ilearner"
}
},
},
GlobalParameters = new Dictionary<string, string>()
{
}
};
However, the request fails with the following message:
The blob reference:
experiments/experimentId/TenantId/Model_2018421.ilearner
has an invalid or missing file extension. Supported file extensions
for this output type are: \\".csv, .tsv, .arff\\"
I'm pretty confused about this, since it's written right the documentation all over the place that if I'm expecting a trained model to use ".ilearner" as the file extension for the model.
I've seen this question asking about the same error leveraging the DataFactory, and also this question on datascience.stackexchange. Neither one had any clues, answers, or other follow up.
Any insight on what I'm missing would be greatly appreciated!
For anyone looking for your "Don't Overthink It" moment of the day:
I needed to provide TWO output blob file references:
var request = new BatchExecutionRequest()
{
Inputs = new Dictionary<string, AzureBlobDataReference>() {
{
"input1",
new AzureBlobDataReference()
{
ConnectionString = _connectionString,
RelativeLocation = $"{_containerName}/{experimentId}/{tenantId}/{trainingDataFileName}.csv"
}
},
},
Outputs = new Dictionary<string, AzureBlobDataReference>() {
{
"output1",
new AzureBlobDataReference()
{
ConnectionString = _connectionString,
RelativeLocation = $"{_containerName}/{experimentId}/{tenantId}/{outputFileNameCsv}.csv"
}
},
{
"output2",
new AzureBlobDataReference()
{
ConnectionString = _connectionString,
RelativeLocation = $"{_containerName}/{experimentId}/{tenantId}/{outputFileNameIlearner}.ilearner"
}
},
},
GlobalParameters = new Dictionary<string, string>()
{
}
};
There's an old saying in American English about not making assumptions, and I assumed the second output was an optional parameter used in batch operations. Since I'm not actually looking for more than one result from each call, I thought I was safe to remove the second output parameter.
TL/DR: Keep all the parameters the webservice portal's "Consume" tab generates, and make sure the first one is a .csv file reference.

EasyPost API - print_custom_1 option won't print on label

This has been driving me batty for over an hour. I'm new to EasyPost and I'm trying to put some custom text on my label (in my particular case, it is which SKU to put in the package), but it just never seemed to work. I'm using the official nuget package from easypost but am guessing it is platform independent.
Shipment shipment = new Shipment() {
to_address = toAddress,
from_address = fromAddress,
parcel = parcel
};
shipment.Create();
var lowestRate = shipment.LowestRate(includeServices: new List<string>() { "First" }, includeCarriers: new List<string>() { "USPS" });
shipment.Buy(lowestRate);
shipment.options.Add("print_custom_1", "this is some sample text");
shipment.options.Add("print_custom_2", "abc");
shipment.options.Add("print_custom_3", "xyz");
shipment.GenerateLabel("pdf");
Well, that was annoying. It makes sense when you step back from it. The issue is that the options need to be set PRIOR to creating the shipment. In my head, it was a print only concern (and it is), but there are other options can and do effect shipping costs, which means that the option needs to be set when creating the shipment. Even setting the options after you create but before you "buy" doesn't work.
See working code below:
Shipment shipment = new Shipment() {
to_address = toAddress,
from_address = fromAddress,
parcel = parcel
};
//DO THIS BEFORE CREATING!
shipment.options = new Dictionary<string, object>();
shipment.options.Add("print_custom_1", "this is some sample text");
shipment.options.Add("print_custom_2", "abc");
shipment.options.Add("print_custom_3", "xyz");
shipment.Create();
var lowestRate = shipment.LowestRate(includeServices: new List<string>() { "First" }, includeCarriers: new List<string>() { "USPS" });
shipment.Buy(lowestRate);
shipment.GenerateLabel("pdf");

Categories