Dialogflow CX: Is it possible to verify the value of an intent param in the condition section of the page? - chatbot

I would like to use Conditions to dispatch the conversation through different Routes depending on the intent entity that appeared in the last user's message:
But it only enables me to use the condition $intent.params.entityX != null; when I try to extract the exact value of that entity like: $intent.params.entityX = "some_value" it does not match. I have also try $intent.params.entityX.original and $intent.params.entityX.resolved. It seems that the intent param values can apparently only be read in the Route response.

If what you're looking for is to evaluate a parameter that may have been filled through entity detection, you may wanna check in session rather than the intent:
$session.params.entityX

Related

What is the best way to validate input parameters?

I'm creating a simple Rest Api with the basic layering Controller-Service-Repository.
I have the following questions:
Where should I check if the correct parameters are given?
How should I validate thiese parameters e.g throw Response error?
You could validate your parameters on the first middleware (or after the authorization middleware). For example, in an express application you could pass your request body into a joi validation scheme.
Depends on your business logic. You can either set default values for parameters not defined by user or throw error. For example, if a user has not given any username or password parameter, then you should throw an error. All errors should be handled by the last middleware and return a relevant status code (401, 402, etc) with an information message if needed.

Is it possible to use one intent to detect all user input to be use to query data from Firestore?

I am trying to connect my chat bot created using Dialogflow to the Google Cloud Firestore. I was thinking if I have to map the intent in the fulfillment one by one that'd be a huge amount of work.
Is it possible to write a fulfillment to detect the user input and maps to the intent then go on to query data from the Firestore?
For example, I would like the agent below to map the user input to the intent I already created then query
function intentHandler(agent) {
const userInput = request.body.queryResult.parameters['Entity_detected'];
}
Dialogflow provides default intent called Fallback Intent. It will be called when there is no matching intent found.
You can take advantage of this and call webhooks on this intent.
Checkout official document
You can indeed map to a different intent using the user input. For this you can use context to map to a different intent after sending a response. I've never tried it with entities, but I imagine it would be implemented something like this.
const userInput = request.body.queryResult.parameters['Your Entity'];
switch (typeof(userInput)) {
case SelectQueryEntity:
// perform select query
conv.ask("I've performed a select query");
conv.context.set("SelectQueryIntent", 1);
break;
case UpdateQueryEntity:
// perform update query
conv.ask("I've performed a update query");
conv.context.set("UpdateQueryIntent", 1);
break;
etc..
};
The context will allow you to navigate the conversation into your desired direction. So if the user inputs anything that matches a SelectQueryEntity, the context will be set to SelectQueryIntent. Any intent which has SelectQueryIntent as an input context will then be allowed to follow up the users next input. Using an intent lifespan of 1 makes this navigation easier to work with.

How to perform slot validation in webhook in Dialogflow?

How to perform slot validation in an intent using backend code (webhook).
I have seen how to perform slot filling using the webhooks but I want to know how to validate the slot data and re-prompt the user if validation fails.
Example:
User: I want to know the your services in London.
Bot: We do not provide service in London, please enter some other city name.
In short: If validation fails, reset the dialog contexts, trigger your intent again, and optionally use default values to keep other parameters that were actually valid (so you don't need to re-prompt the user for those again).
You don't need to declare an incoming context on that intent to achieve this. Note that you can use contexts in intents, even though they are not declared as incoming/outgoing contexts on that intent.
In this example, I'm requesting 2 parameters from the user (car make and model). Of course, Enable webhook call for slot filling needs to be set in your intent.
Steps:
On Dialogflow, in the intent, declare an Event. This can be used to trigger this intent from your fulfillment code:
In your parameters, declare a Default Value for each parameter you want to be able to keep after resetting the intent:
Set the Default Value to a parameter in a helper context. If this helper context does exist, the default value will be set, otherwise, it'll be kept empty. This will allow you to reset the intent and keep other parameters you already had. In this example, I'm using the context show-car-details-data, and setting the default value of parameter model to _model in that incoming context:
In your slot-filling fulfillment method, you can validate your parameter and re-prompt the user by reseting the intent. To do that, you need to 1) clear the current dialog contexts, 2) call setFollowupEvent to trigger your intent again, and 3) optionally set up some helper context you can use to assign default values (so you don't need to re-prompt user for those that were valid).
I'm using Dialogflow Fulfillment Node.js Library:
// clear dialog contexts:
agent.contexts.forEach( e => {
if ( e.name.endsWith('_id_dialog_context') ) agent.context.delete(e.name);
});
// workaround bug: https://github.com/dialogflow/dialogflow-fulfillment-nodejs/issues/160
agent.add('');
// set follow up event: this triggers your intent again
agent.setFollowupEvent('show-car-details');
// optionally set helper context to set default values and avoid re-prompt of already valid values
// in this example, keep make since it was a valid parameter
// clear model because it was invalid. User will be prompted again on model, but not on make
agent.context.set('show-car-details-data', 1, { '_make': make, '_model': '' });
Steps
Enable webhook for slot filing in Dialog flow with Entity set as "Required".
Get entity from arguments.
Programmatically check if it is not null and as per your requirement.
If it is correct, proceed further.
Else, RESET THE CONTEXT and ask the question as per the wrong slot input. Programmatically, set the output context same as input so that user can again respond back slot/entity. If the correct context is not present, the slot will not get captured. When a slot is captured as per set Entity, the context for that slot captured is finished and to recapture it you need to increase the lifespan or create it again.

Linkedin API oAuth 2.0 REST Query parameters

I'm running into a problem with adding a query to the callback URL. I'm getting an invalid URI scheme error attempting to authorize the following string:
https://www.linkedin.com/uas/oauth2/authorization?response_type=code&client_id=75df1ocpxohk88&scope=rw_groups%20w_messages%20r_basicprofile%20r_contactinfo%20r_network&state=7a6c697d357e4921aeb1ba3793d7af5a&redirect_uri=http://marktest.clubexpress.com/basic_modules/club_admin/website/auth_callback.aspx?type=linkedin
I've read some conflicting information in forum posts here. Some say that it's possible to add query strings to callbacks, and others say that it results in error.
If I remove ?type=linkedin, I can authorize just fine and receive the token. It would make my life so much easier if I could use a query string on the callback url, as I need to do some additional processing in the callback.
In short, can I append a query string to the end of the callback url?
For fun, I tried encoding the callback url in the request (obviously this is a no-no according to their documentation):
https://www.linkedin.com/uas/oauth2/authorization?response_type=code&client_id=75df1ocpxohk88&scope=rw_groups%20w_messages%20r_basicprofile%20r_contactinfo%20r_network&state=5cabef71d89149d48df523558bd12121&redirect_uri=http%3a%2f%2fmarktest.clubexpress.com%2fbasic_modules%2fclub_admin%2fwebsite%2fauth_callback.aspx%3ftype%3dlinkedin
This also resulted in an error but was worth a shot.
The documetation here: https://developer.linkedin.com/forum/oauth-20-redirect-url-faq-invalid-redirecturi-error indicates that you CAN use query parameters. And in the first request, it appears that I'm doing it correctly. Post #25 on this page - https://developer.linkedin.com/forum/error-while-getting-access-token indicates that you have to remove the query parameters to make it work
Anyone have experience with successfully passing additional query paramaters in the callback url for the linkedin API using oAuth2.0? If so, what am I doing wrong?
I couldn't wait around for the Linkedin rep's to respond. After much experimentation, I can only surmise that the use of additional query parameters in the callback is not allowed (thanks for making my application more complicated). As it's been suggested in post #25 from the question, I've tucked away the things I need in the "state=" parameter of the request so that it's returned to my callback.
In my situation, I'm processing multiple API's from my callback and requests from multiple users, so I need to know the type and user number. As a solution, I'm attaching a random string to a prefix, so that I can extract the query parameter in my callback and process it. Each state= will therefore be unique as well as giving me a unique key to cache/get object from cache..
so state="Linkedin-5hnx5322d3-543"
so, on my callback page (for you c# folks)
_stateString=Request["state"];
_receivedUserId = _stateString.Split('-')[2];
_receivedCacheKeyPrefix = _stateString.Split('-')[0];
if(_receivedCacheKeyPrefix == "Linkedin") {
getUserDomain(_receivedUserId);
oLinkedIn.AccessTOkenGet(Request["code"],_userDomain);
if (oLinkedin.Token.Length > 0) {
_linkedinToken = oLinkedin.Token;
//now cache token using the entire _statestring and user id (removed for brevity)
}
You not allowed to do that.
Refer to the doc: https://developer.linkedin.com/docs/oauth2
Please note that:
We strongly recommend using HTTPS whenever possible
URLs must be absolute (e.g. "https://example.com/auth/callback", not "/auth/callback")
URL arguments are ignored (i.e. https://example.com/?id=1 is the same as https://example.com/)
URLs cannot include #'s (i.e. "https://example.com/auth/callback#linkedin" is invalid)

Tastypie build_filters access tp request.user

Is there any way to access the user that initiated the request in build_filters override in tastypie.
I want to use the logged in user to give context to one of the filters for example filter contains the word Home and i want to use this as a lookup to the requesting users locations to find their home address.
If build filters took the request as an argument this would be easy as i could simply call
request.user.get_profile().userlocation_set.get(name_iexact=filters['location'])
Is there anyway to force the user into the list of filters or alternatively enrich get parameters before they are passed to build_filters.
There still isn't a great method for this. I'm currently overriding obj_get_list like so, so that I can manually pass the bundle object to build_filters:
def obj_get_list(self, bundle, **kwargs):
filters = {}
if hasattr(bundle.request, 'GET'):
filters = bundle.request.GET.copy()
filters.update(kwargs)
applicable_filters = self.build_filters(filters=filters, bundle=bundle)
try:
objects = self.apply_filters(bundle.request, applicable_filters)
return self.authorized_read_list(objects, bundle)
except ValueError:
raise BadRequest("Invalid resource lookup data provided (mismatched type).")
There is currently an open pull request for this change:
https://github.com/toastdriven/django-tastypie/pull/901
I haven't found a way to do that. I generally 'cheat' by adding the code into apply_authorization_limits where the session is available.