Teneo Query Language helps you to examine what went on during a session by allowing you to query the contents of variables at all levels, be they global variables, flow variabes, or at the session level. Each session log contains a complete record of where and how each of the solution variables is set.
Here we want to walk you through different variable queries you can perform using TQL. If you've already published your solution and wish to query your own variables, you can skip the steps to set up the solution and generate session logs.
Let's take the Longberry Baristas solution and add some variables to document when the Safetynet becomes active during a conversation. We want a flow variable and a global variable. In the case of our global variable, we want to query it at the transaction level as well as at the session level. You can read more about querying variables at the session level here. After following the steps below, you'll be able to try this and other queries yourself.
Define a global variable to count Safetynet hits. Call it
safetyNetCounter, and set the initial value to 0.
Edit the solution's Safetynet (It's the flow "Safetynet" in the folder "Safetynet") and add this On Top script:
Define a flow variable
safetyNetActive and initialize it to
In the solution's global scripts section add an End dialog script:
safetyNetCounter = safetyNetCounter.
Publish the solution; you can find a more detailed explanation of this step here.
Now that the solution is published, we'll need to generate some sessions by chatting with the bot. If you already have session logs, you can skip this step. Since we're counting Safetynet hits, try to create a number of different variations of Safetynet occurrences:
- the Safetynet does not occur
- only one input runs into the Safetynet
- several inputs run into the Safetynet
In our section on generating session logs we show you the necessary steps in more detail.
Each time the Safetynet flow becomes active, the Boolean flow variable safetyNetActive is created and initialized to true. This query employs a constraint based on that variable to show all transactions in which the user input ran into the Safetynet:
1la t.id, t.e1.userInput userInput: 2 t.e2.fv:b:safetyNetActive == true userInput 3
There are a few things to note in the query:
- Since safetyNetActive is a flow variable, it has the prefix fv:b, meaning a flow variable of type Boolean.
- We use a transaction and event prefix to access the variable: t.e or some variation like t1.e2, etc.
- The user input and the setting of the flow variable occur in different events, so we refer to e1 and e2. The input is associated with the request event, whereas the variable is set later, after the Safetynet flow is triggered.
We defined a global variable above called safetyNetCounter. In this section we'll walk through various queries you can use to find out how the Safetynet was used in your bot's session.
First of all, let's try a query that duplicates the result we saw above using the Safetynet flow variable to locate Safetynet transactions. We want to see the transaction ID and the user input when the Safetynet triggered:
1la t.id, t.e1.userInput userInput: 2 t.e2.sv:n:safetyNetCounter > 0 userInput 3
Here are some important details about the query:
- To reference this variable, we use the prefix sv:n, meaning a session variable of type integer. We also look for the variable within a transaction and event.
- We need an additional constraint specifying that the counter has to be greater than zero. This is because the variable is logged each time it changes, including the first time it is created and initialized. The occurrence of the variable (initialized to 0) is not associated with a Safetynet event, meaning we do not want to view those transactions.
- It is important to differentiate which events in the transaction we are looking for. The user input and the Safetynet variable are found in separate events, not the same one.
Our variable counts the number of times the Safetynet became active, meaning we can try some queries to zoom in on particular sessions based on the frequency of Safetynet activity. Here you have to think carefully because there are some subtle nuances to writing the necessary constraints.
Let's say we want to find all the sessions in which the Safetynet was not active at all. If we use this query, we will get some unexpected results, namely that it finds all sessions, including those in which the Safetynet was active:
1la s.id: t.e2.sv:n:safetyNetCounter == 0 2
This is because we are looking at snapshots of the counter in individual transactions. Every session starts out with the counter at 0, meaning there is always a transaction that meets that constraint. This is why the query finds every session. The query does not consider what happens later to the counter. It may increase, or may not. We can, however, formulate the constraint in such a way as to find sessions in which Safetynet usage exceeds a certain threshold.
This query shows us queries in which the Safetynet was active at least once:
1la s.id: t.e2.sv:n:safetyNetCounter > 0 2
This query finds sessions in which the Safetynet was triggered 3 or more times:
1la s.id: t.e2.sv:n:safetyNetCounter >= 3 2
What if we want to find sessions in which the Safetynet was active exactly n times? This is where we reach the limit of what we can query at the transaction level. In the next section, we'll show you how you can query variables at the session level.
If you recall the code we added at the End dialog, we assigned the counter variable to itself. We did this is so that the variable is logged at the session level as a session property. Variables that change during the End dialog script are not associated with a particular transaction, but with the session. Now we can easily write queries to show, for example, sessions in which the Safetynet was never triggered, or triggered a certain number of times.
1la s.id: s.sv:n:safetyNetCounter == 0 2
Note that we use the same prefix sv:n, but this time we associate the variable with the session, not a transaction or event.
To find sessions in which the Safetynet triggered exactly 3 times:
1la s.id: s.sv:n:safetyNetCounter == 3 2
But we can also query for sessions that exceeded or did not exceed a particular threshold; for example, here we want sessions in which the Safetynet triggered less than three times:
1la s.id: s.sv:n:safetyNetCounter < 3 2
And this finds sessions in which the Safetynet triggered more than three times:
1la s.id: s.sv:n:safetyNetCounter > 3 2
We don't have to worry about any unintended side effects of the query, because at the session level we are dealing with one precise value.
You may simply want to generate a report of Safetynet behavior for all your sessions. Here you could try:
1la s.id, s.sv:n:safetyNetCounter 2
This is a distribution query that gives us a feeling of overall Safetynet occurrences:
1d s.sv:n:safetyNetCounter 2
Safetynet activity is an important performance indicator in bots. Over time, as more content is added to the bot, and improvements are made to existing knowledge, we would expect the Safetynet to trigger less frequently. Using queries like this, we can find out if that is the case.