I just started using Dialogflow and I'd like to create an Dialog
where I can ask "What time do I have to go to University today"
and depending on what day of the week it will give me a different answer.
I know I can get the date via #sys.date, but is there something similiar
to get the day of the week?
Thanks!
Dialogflow doesn't have a lot of built-in conditional processing. So while you can use #sys.date to turn "today" into the date, you can't then use the date to figure out some other value.
You can, however, use the Fulfillment section to turn a date passed as a parameter into whatever you want using whatever logic is available. For a simple task like this, you can use the built-in Fulfillment Inline Editor. If you enable it, you'll be presented with some sample code, including an illustration how to access the parameters from the request.
Once you have deployed it, you'll also need to turn on Fulfillment for the specific Intent that is doing the processing. (See the second image below.)
(Update: It does have some conditional processing, since it can choose different Intents based on the Contexts that are set and specific utterances. However, there is no Context that is set for the current day of the week. While you can set one yourself, this would be done through Fulfillment, so it is probably just as simple as actually processing the parameter. It might be useful for a more extensive conversation, but not for a short question-answer.)
Related
With v1 of the measurement protocol, you could use these parameters to add custom dimensions or change medium, source or refer for a page view:
https://ssl.google-analytics.com/collect?v=1&tid=UA-xxxxxxxx&cid=[custom-id]&t=pageview&dp=[Url of pageview]&dh=[hostname of pageview]&cm=[new-medium]&cs=[new-source]&dr=[new-referer]&cd1=[custom-dimension-1]&cd2=[custom-dimension-2]
How is it done in measurement protocol v2?
I couldn't find any documentation about the page-view-event in V2 (for example it's just not mentioned here
https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference/events), even the event-builder (https://ga-dev-tools.web.app/ga4/event-builder/) doesn't support a simple page-view.
So, all I got so far is this:
$data = '
{ "client_id": "'.[custom-id].'",
"events": [
{
"name": "page_view",
"params": {
"page_location": "'.[Url of pageview].'"
}
}
]
}
';
So, what are possible parameters for a page-view-event?
Ok, a few things here right away that you should know if you're playing with MP:
Measurement protocol is a poor name. It implies there's more than one protocol for data gathering. There's none. There is just only one protocol for tracking.
MP2 still largely MP1. Google tries to pose GA4 as a new product, but it's just our old good GA UA with a simplified backend and overengineered front-end that tries to deliver the level of quality Site Catalyst/Omniture/Adobe Analytics have been delivering for a decade. MP is largely the same. dr, cm, cs and a lot of other fields are still there. cds aren't there anymore cuz they're replaced with eps and ups, but more about that a bit later.
GA4 uses this big marketing claim that the new analytics is so wonderfully event-based, unlike the old one. When I dug into why they keep claiming it everywhere, I realized that the only difference is that pageviews are now events. Not much difference really. But yes, a pageview is just an event named page_view. We'll talk about it a bit more later.
Custom dimensions are no more. Now they're called event properties and user properties. The same thing really, Google just tries to make it less obvious that there are no more session level custom dimensions. Or product-level CDs. Though the product level is seemingly on their roadmap.
Make sure you're using the correct measurement id. They made it a lot harder to find it in GA4. It's no longer just the property id visible in the property list, unfortunately.
GA's real-time reports don't include all dimensions, especially if those dimensions are involved in advanced metrics/dimensions calculations. Do not use real time reports for inspecting the content of your events. It's not meant for debugging. It's a vanity report. Still helpful to check the volume of events when you're sending a bunch and expect to see them in GA. Google even has a warning here:
Like the DebugView report, the Realtime report performs limited attribution analysis to ensure responsive reporting. We recommend that you refer to the Acquisition reports for the most accurate attribution information.
Finally, what I often do instead of reading the so-still-unfinished-and-not-really-helpful documentation on MP2, is either use a library like this.
Or, since 1 is the case, I would just implement a moniker tracking in my test GTM, then see what and how it sends to where in the Network debugger and simply reimplement it on my side exactly how GTM does it. No magic involved. Here is how my GTM tag would look like:
With a trigger on any click or any page load. After all is done, I publish the lib. Then I would inject this GTM's code in a local site, or in my test site, or however else you want to test it. And trigger the tag that you need to mimic with MP.
I use this wonderful extension to show all events that fire and their details right in my console.
Now this is how the above tag looks on my test site through the extension:
It's pretty useful.
How do I know that page_referrer is used as dr instead of ep in GTM? Here is the list of the fields that will never be seen as ep. But Google doesn't care enough to map them properly to what these fields are called in MP, so you either have to test, or know, or google it elsewhere.
Finally, here is how the network request looks like:
I published the tag to prod (I keep a test site in prod), so you can go and look at it. Or just find a site that uses GA4 and see its network requests. How does google know that this is a pageview? by the event name: en=page_view
Of course, you do the same with medium and source. Judging from the documentation I've linked to above, the medium and source look like campaign_source and campaign_medium in GTM. GTM maps them accordingly to cs and cm fields. And that's how you know these are the correct mp fields. Give GA time to process these and check on them in a few days.
Good, now this is applicable to the enhanced ecommerce hits too, it's just that they have more variables and data structures in them typically.
Finally, if you want to simulate batch events, you can just make a few tags fire in rapid succession and GTM will neatly pack them in one network request if they fit. You can then digest how the packing is done through the same methods as we do here and simulate.
While developing and testing the conversation, IBM Watson Assistant identifies multiple intents and respond to the one with highest confidence level. Sometimes I want it to respond to second intent not the first one because it is more relevant to the current conversation context. For example, if the dialogue contains nodes to handle making transfer or payment, during the transfer scenario the user can say execute which will match both execute transfer and execute payment. So I want Watson to always respond to execute transfer which is the current context even if it identifies execute payment with higher confidence.
So users ask generic questions assuming that the bot is aware about the current context and will reply accordingly.
For example, assume that I'm developing a FAQ bot to answer inquires about 2 programs Loyalty and Saving. For simplicity I'll assume there are 4 intents
(Loyality-Define - which has examples related to what is the loyalty program)
(Loyality-Join - which has examples related to how to join loyalty program)
(Saving-Define - which has examples related to what is the saving program)
(Saving-Join - which has examples related to how to join saving program)
so users can start the conversation by utterance like "tell me about the loyalty program". then they will ask "how to join" (without mentioning the program assuming that the bot is aware). In that case Watson will identify 2 intents (Loyalty-Join, Saving-Join) and Saving-Join intent may have a higher confidence.
so I need to intercept the dialogue (may be be creating a parent node to check the context and based on that will filter-about the wrong intents).
I couldn't find a way to write code in the dialogue to check the context and modify the intents array so I want to ask about the best practice to do that.
You can't edit the intents object, so it makes what you want to do tricky but not impossible.
In your answer node, add a context variable like $topic. You fill this with a term that will denote the topic.
Then if the users question is not answered, you can check for the topic context and add that to a new context variable. This new variable is then picked up by the application layer to re-ask the question.
Example:
User: tell me about the loyalty program
WA-> Found #Loyality-Define
Set $topic to "loyalty"
Return answer.
User: how to join
WA-> No intent found.
$topic is not blank.
Set $reask to "$topic !! how to join"
APP-> $reask is set.
Ask question "loyalty !! how to join"
Clear $reask and $topic
WA-> Found #Loyalty-join
$topic set to "loyalty"
Return answer
Now in the last situation, if even with the loaded question it is not found, clearing the $topic stops it looping.
The other thing to be aware is that if a user changes topic you must either set the topic or clear it. To prevent it picking the old topics.
NOTE: The question was changed so it is technically a different question. Leaving previous answer below
You can use the intents[] object to analyse the returning the results.
So you can check the confidence difference between the first intent and second intent. If they fall inside a certain range, then you can take action.
Example condition:
intents[0] > 0.24 && intents.[1] - intents[0] > 0.05
This checks if two intents are within 5% of each other. The threshold of 0.24 is to ignore the second intent as it will likely fall below 0.2 which normally means the intent should not be actioned on.
You may want to play with this threshold.
Just to explain why you do this. Look at these two charts. The first one it's clear there is only one question asked. The second chart shows that the two intents are close together.
To take actual action, it's best to have a closed folder (condition = false). In that folder you look for matching intents[1]. This will lower the complexity within the dialog.
If you want something more complex, you can do k-means at the application layer. Then pass back the second intent at the application layer to have the dialog logic take action. There is an example here.
Watson Assistant Plus also does this automatically with the Disambiguation feature.
You can train Watson Assistant to respond accordingly. In the tool where you work on the skill click on the User conversations page in the navigation bar. In the message overview you would need to identify those that have been answered incorrectly and then specify the correct intent. Watson Assistant will pick that up, retrain and then hopefully answer correctly.
In addition, you could revisit how you define the intents. Are the examples like the real user messages? Could you provide more variations? What are the conflicts that make Watson Assistant pick the one, but not the other intent?
Added:
If you want Watson Assistant to "know" about the context, you could extract the current intent and store it as topic in a context variable. Then, if the "join" intent is detected, switch to the dialog node based on intent "join" and the specific topic. For that I would recommend to either have only one intent for "join program" or if really needed, put details about the specifics into the intent. Likely there is not much difference and you end up with just one intent.
For various reasons I need to get from the iPhone the current date and time that can't be meddled with by the user. Yes, I've seen how one can check a server (e.g., here), but that's not invulnerable to tampering if you take a moment to reflect.
There are two knee-jerk reactions I'm expecting to hear:
Use the GPS time.
It can't be done.
In answer to another question, I've described my researches into this matter. To summarize them:
The GPS time shifts with the user-defined settings.
The iPhone definitely has an internal tamper-proof time and date, as shown when date-time reverts after Set Automatically in Settings > General > Time & Date is turned back to on even in a fallout shelter.
What I want to know is how to access this tamper-proof time.
Edit
Just to be clear, the server-based solution is not suitable. For one, it could be faked. For another, the app needs to work without a network connection.
Assuming you always have Internet available, you could implement a class or object that connects to a remote Network Time Protocol server.
Here's an open source GitHub project that should get you started, and the related StackOverflow question I found it at.
Is it possible to programmatically create a new version of a CQ5 page that has a start time some time in the future?
As an example, let's say we have a page that displays tax rates. We have a component that allows the author to upload a new rates table (in the form of a css file) and it creates the rates page content. We would like to allow the author to upload rates that will be effective the first of next month.
I know the jcr supports multiple versions of nodes, but its unclear how (or whether) this relates to cq5 page versioning. And, further, whether a new version can be activated in the future.
Given the requirements as you've described them, I would probably accomplish the task in a slightly different way...
Instead of storing my rates table information directly within the page's jcr:content node (or a sub node their of) I'd probably abstract it out to somewhere else in the repository. You could then, if you so desired, create some sort of an admin interface to allow content authors to upload their csv file of new rates, and ingest that into the repository as needed. Alternatively, assuming that data comes from some sort of a database, you could probably just write a job to automatically injest it on some sort of a scheduled basis by using a JDBC connection from CQ. Once the data is in the repository, you could then write the display component to read the data from the repository, instead of it being directly inside the page.
This approach has the advantage of making that data re-useable within CQ to be shown on multiple pages, multiple sites, even many different display formats if need be. In addition, you can design your jcr structure to support whatever requirement you have around updates to the data, including daily, monthly, weekly, yearly etc., obviously this will depend on the specific requirements.
The one downside to this is that since there is a separation b/w the data and the page(s) where it is displayed, you may need to find a way to ensure the cache is properly cleared whenever the data does change.
Update (based on your comment):
The problem I foresee with versioning the page, and granted I've not tried this so maybe it will work, is that there can only ever be one active version at a time. Therefore, once the next months data is uploaded, you need to maintain the old data (active) and the new data (not yet active) at the same time. What happens if you require a separate content change during that window...from a business process perspective that just seems messy to me.
Back to cache clear issues, If you know the affected pages, especially if they are all in one subtree, you could write a custom workflow process that uses the replicator service to clear the cache for the affected pages, then set up a launcher to run the wf on node change for the data.
The other option, and this one is less defined in my head, so some experimentation required, would be to use CQs built in activate later and de-activate later functionality.
Maybe create a specific template for the rates data, with the implicit requirement that only one page using that template is ever active at one time. Your display components could use a query to find the currently active rates data.
I have not personally tried this, but...
I assume that you can use the PageManager service's createRevision method, and then if that returns without throwing an exception, you may call page.getContentResource.adaptTo(Node.class), and from there take the node that is returned and edit the JCR properties for your tax rates component.
See PageManager
You could write a workflow that includes a publish step that is triggered by the arrival of a calendar date. The version of the page with the new tax rates remains in the workflow pipeline in draft form and is only published/activated when the date arrives. (So you'd need some sort of process that wakes up once a day to check the calendar.)
Each time a page is modified cq creates a version of the page.
This modified page's modification time is set in jcr:lastModified property of the page.
Manipulation of this property can be done to save future date and activate page on that date though its not preferred way.
You can store the future date as a property in the page.
Later as suggested by #David you can create a workflow or a scheduled job which activates pages with a future date.
I am currently drafting a concept for a (mostly) HTML-based collaboration suite which I plan to implement using CQRS. This software will contain messages that can be sent to the user (which can either be read or unread, obviously) and other elements which shall be marked "new" if they were created after the last user login.
Hardly something new, but I am not quite sure how that would be correctly implemented using CQRS. As I understand it, Change of any kind should, without exception, only be possible via Commands. But creating commands for every single (new) element that is being accessed seems a bit too much, not to mention the overhead.
I don't know if I need it, but what would be the best way to implement a Last-Accessed Timestamp on elements. Basically the same problem like the above, with the difference that the change happens EVERY time the element is accessed, not only the first time for each user.
CQRS seems to be an awesome concept but it really needs more learning material. Can't wait till a book is released :)
Regards
[Edit] No one? Wouldn't have thought that this is such a complicated issue..
I assume you're using event-sourcing in which case once you allow your query-service/event-handlers to raise appropriate events then this becomes fairly easy to solve.
For your messages/elements; when handling the specific creation events of your elements either add to existing or create additional event-handlers, to store to a messages read-model with a status of new and appropriate information about the element.
As part of you're user login I don't see why you can't raise a user-logged-in event (from the security/query service depending on how your implementing authentication) to say the user has logged in. An event-handler could capture this and write the last-login timestamp to a specific user-last-login read-model.
In addition the user-logged-in event-handler would need to update all the new messages (for that user) to an unread status. Seeing as we're changing the status of the messages as the user logs in do you still need to store the last-login timestamp?
For your last-accessed timestamp, perhaps you could just work this into your query service as queries for your different elements complete. Raise a query-completed event with element id/type information.