Closed mohamed-benali closed 4 years ago
All the documentation we have right now is in the wiki. Indeed there is a lack of documentation for the language, I'll add it when I have some time. Let me know if you want help on a specific use case (with an execution model example), I'll be happy to give a hand to achieve what you want to do. I'll post in this thread when I'll have news regarding the documentation.
Hi Mohamed,
As Gwendal says , and while we improve the documentation, please feel free to get in touch for specific questions.
Follows defines a partial order so that an intent is only matched after another one has been matched before.
Thank you for your response. I have seen the following code in https://github.com/xatkit-bot-platform/xatkit-runtime/wiki/Multi-Platform-Example
intent SpecifyRepository follows OpenIssue {
inputs {
"Repository MyRepo"
"(Repository:repoName=@any)"
}
creates context Repository {
sets parameter repoName from fragment "MyRepo" (entity any)
}
}
intent SpecifyOwner follows SpecifyRepository {
inputs {
"(Repository:repoOwner=@any)"
}
}
I would like to know how the following fragments work
"(Repository:repoOwner=@any)"
and
inputs {
"Repository MyRepo"
"(Repository:repoName=@any)"
}
creates context Repository {
sets parameter repoName from fragment "MyRepo" (entity any)
}
I also would like to know how I should implement conditionals split and join.
An example of what i mean could be a user that uses the chatbot to know what he/she has to do. -The Chatbot asks the price. -The user writes the price. Internally, the chatbot decides, based on the price, the branch that follows. -The chatbot explains the task based on the price. -Then the chatbot "joins" the branches. So no matter the branch chosen, the chatbot will end in the same intent.
Basically i need two things: -How can i define a Intent that 'follows' two Intents. -How can i change the Intent where the Chatbot is(with code).
I think that with 'Context' i can pass the price. But i dont know how i can change the intent/state. I also think that using 'follows' i can do the Split&Join. So if an Intent can has two follows, i can simulate the join branches. Something like:
intent Test5 follows Test1, Test2, Test3{
inputs {
"After that, what i do?"
}
}
More important. The general idea of what i want to achieve is that I want the Chatbot to simulate a BPMN diagram. So the user can ask about the process. Something like: The nodes, would represent the Intents.
As the documentation is not completed, i have to ask. It is possible, right now, to achieve it with Xatkit?
Hi,
First of all, the example you are referring to is outdated (the up-to-date information is now centralized in our main wiki). Specifically, the syntax "(Repository:repoOwner=@any)"
is not supported anymore.
The fragment
intent MyIntent {
inputs {
"Repository MyRepo"
}
creates context Repository {
sets parameter repoName from fragment "MyRepo" (entity any)
}
}
Means that you define an intent with 1 training sentence ("Repository MyRepo"). This intent creates the context Repository, with 1 parameter repoName extracted from the fragment "MyRepo" from your training sentence. The entity specifies the type of information extracted from the fragment, in our case any, but it could be number, date, etc.
In practice this means that your intent will recognize the sentences looking like "Repository Repository.repoName
.
Now, from your bot's execution rules you can access this context parameter, using the following syntax:
on intent MyIntent do
if(context.get("Repository").get("repoName").equals( [...] ) ) {
SlackPlatform.Reply("Branch 1")
} else {
SlackPlatform.Reply("Branch 2")
}
Note that you can use context values in if
condition to do the kind of branching you explain in your other message (in your example this context value would be the price specified by the user). Xatkit embeds xbase as its expression language, so you can benefit out of the box of branching, loops, etc
Here is the full syntax of our running example:
intent MyIntent {
inputs {
"Repository MyRepo"
}
creates context Repository with lifespan 5 {
sets parameter repoName from fragment "MyRepo" (entity any)
}
}
Note the presence of with lifespan 5
, that is not specified in the original example since it's the default value. This means that the context Repository
(and all its parameters) is created and "alive" for 5 interactions. An interaction in Xatkit is a user input received, so, for the next 5 message received the expression context.get("Repository").get("repoName")
will return the value matched by the intent (unless it has been overriden by another intent).
We can now create a new intent that will require this context to be matched:
intent MyIntent2 {
requires context Repository
inputs {
"another input"
}
}
Here the requires context Repository
forces the underlying NLP engine to check if a context Repository
is "alive" for the current session (i.e. if it has been created in the last 5 interactions by another intent). Note that you can require multiple contexts, in this case you need to duplicated the line requires context XXX
for each one.
In our example we are now sure that MyIntent2
follows MyIntent
, because it cannot be matched if the context Repository
is not set. Since this syntax is a bit heavy we have defined some syntactic sugar for simple use cases:
intent MyIntent2 follows MyIntent {
[...]
}
Here the semantic is almost the same as the example before, but some things are happening under the hood:
2
and cannot be changedcreates context
in MyIntent
and requires context
in MyIntent2
to materialize the follows relationship. You don't have to define it, it is automatically created when the bot is deployed, and is typically named something like MyIntent_Follows_MyIntent2. This context does not contain any parameter, and is only used to check precedence.Repository
context we specify in the intent definition).As a summary, the follows construct should be seen as a lightweight version of the creates context/requires context
constructs. It is less powerful, cannot be fully configured, but do the job quite well for simple use cases.
You can create as many context as you want in an intent (with and without parameters):
intent MyIntent {
inputs {
"Repository MyRepo"
}
creates context Repository {
sets parameter repoName from fragment "MyRepo" (entity any)
}
creates context AnotherContext
}
And you can use them to enable specific conversation paths in your bot using the requires context
construct. This should be the key point for your BPMN to bot translation. Yet, note that you cannot specify complex expressions in requires context
construct (it is not possible to specify something like requires context XXX or YYY
, it may be the case in a future release).
For the following example:
intent Test5 follows Test1, Test2, Test3{
inputs {
"After that, what i do?"
}
}
I'd proceed like that:
intent Test1 {
input { ... }
creates context Questionable
creates context ...
}
intent Test2 {
input { ... }
creates context Questionable
creates context ...
}
[...]
intent Test5 {
requires context Questionable
inputs {
"After that, what I do?"
}
}
This way you ensure that the question "After that, what I do?" can be asked after each intent. Of course this may need to be polished, but I hope you get the general idea.
Finally, context parameters are always overwritten: this means that if you set the same context parameter in multiple intents only the last one can be retrieved from the context.get(...)
expression. E.g. if the intent MyIntent
is matched two times, the first one from "Repository ABC", and the second one from "Repository XYZ", the expression context.get("Repository").get("repoName")
will be evaluated as "XYZ".
I hope this gives you a better idea of what can be done with Xatkit and how to manage contexts. I'd add that querying a BPMN process using a Xatkit bot is certainly possible (we have worked internally on this some time ago), but requires some work to carefully define the intents and their order.
Let me know if you have any additional question/remark.
Gwendal
Thank you for your explanations.
I would like to know if there is a way to change the actual Intent using code. So at any moment, i can change the actual intent. So it is posible to change the intent where is the Chatbot without the user's response?
Also i would like to have automatic tests. So can i simulate the user's response via code? Something like:
ChatPlatform.USER.Reply("BLA BLA BLA")
An intent is not a state of the bot, it's an abstraction of what the user says. Think about it as an event more than a state. If you want to test the bot's reaction to a specific intent you'll have to forge one by yourself and send it manually to Xatkit internals:
[Create an EventInstance object]
xatkitCore.getExecutionService().handleEventInstance(eventInstance, session);
You can look at the example from this test case to see how to create an EventInstance object. Note that in this specific case you are also responsible of the XatkitSession
content (and thus the associated context variable), so it's quite a lot of work to make it work.
Another solution is to write your tests at the IntentProvider
level (which seems to be more aligned with what you want to do with automated tests). In this case you can take a look at this class (assuming you are using Slack). It contains some test cases that simulate incoming messages from Slack to check that the recognized intents are correct.
If you are using the ReactPlatform
I don't have an out of the box example to show, a colleague tested his bot using Selenium and seems to be happy with the result.
Thanks Gwendal for this very detailed responses. @mohamed-benali I think the best you could do at this point is to spend some time playing with Xatkit and creating some example bots to see if the above explanations are enough for you to keep going.
Then we can worry about more advanded stuff like the tests.
And I hope you don't forget to star and watch the repo and share Xatkit with your colleagues!!
Thanks you for your responses. I watched the repo :)
I would like to know if there is a way to erase/remove a context before the lifespan ends(for example, when entering into an intent).
I ask because I'm trying to do a query over the following BPMN to know who does a task.
Test
is done by Empleat
Test2
is done by Departament
I created two intents that represents the tasks, Test
and Test2
. And then i created two intents more, that represents WHO does the tasks: SUBJECT_Empleat
, SUBJECT_Departament
.
My idea is that SUBJECT_Empleat
can only be matched if the Intent Test
has been matched. The same for SUBJECT_Departament
and Test2
So when the user asks "Who does this task?", the correspondent intent will be matched.
I got it working, but it has an issue. The problem is that the two contexts are overlapped. Because in both cases, they are triggered by the same question: "Who does this task?". So after matching Test2
, there are two contexts living(one for SUBJECT_Empleat
and another for SUBJECT_Departament
). And here comes the mistake, when the user asks "Who does this task?", the Chatbot says Empleat instead of Departament. And if the question is repeated, then the Chatbot replies correctly (Departament).
Here are two photos of what i explained above:
In summary, i would like to know if there is a way to erase/remove a context before the lifespan ends(for example, when entering into an intent).
I also would like to know if my approach is correct or if in Xatkit already exists a functionality that helps doing it.
As the code is small, I will put it here. It may clarify what i said before. .intent
intent Test {
inputs {
"testing"
}
creates context CONTEXT_Test with lifespan 4
creates context SUBJECT_CONTEXT_Empleat with lifespan 4
}
intent Test2 {
requires context CONTEXT_Test
inputs {
"testing"
}
creates context CONTEXT_Test2 with lifespan 4
creates context SUBJECT_CONTEXT_Departament with lifespan 4
}
intent SUBJECT_Departament {
requires context SUBJECT_CONTEXT_Departament
inputs {
"Who does this task?"
"Who does it?"
"Who performs this task"
}
}
intent SUBJECT_Empleat {
requires context SUBJECT_CONTEXT_Empleat
inputs {
"Who does this task?"
"Who does it?"
"Who performs this task"
}
}
.execution
on intent Test do
ChatPlatform.Reply("Intent: Test")
on intent Test2 do
ChatPlatform.Reply("Intent: Test2")
on intent SUBJECT_Departament do
ChatPlatform.Reply("Departament")
on intent SUBJECT_Empleat do
ChatPlatform.Reply("Empleat")
on intent Default_Fallback_Intent do
ChatPlatform.Reply("Sorry I didn't get it")
Also, I would like to know if i can create a context in execution.
I have another question: Can I, in creates context
, set a parameter with a hardcoded value?
So i have the posibility to not take it from the user input.
Something like:
creates context Repository {
sets parameter repoName "my value"
}
I have another question: There is a way to know which input
has matched the actual Intent
?
No you can't erase a context before the lifespan end, the only option you have is to change the lifespan value in the intent definition. This is by design: the context is immutable and contains intent-related information automatically extracted by the underlying NLP engine (and also from events, but it's not the topic here). More precisely: you cannot create, modify, or delete contexts and context parameters.
The issue in your example is that you define two intents for the same input: SUBJECT_Departament
and SUBJECT_Empleat
have the same training sentences, this will confuse the NLP engine.
A possible solution is to use the descriptive contexts CONTEXT_Test
and CONTEXT_Test2
to filter the reply returned by the bot (see below). In this case these contexts have a lifespan of 2, meaning that they will be alive for the matched input and the next input:
Note that I also removed the contexts used to trigger the different versions of your previous SUBJECT intents, and created a new Askable context, that is set by both intents and can be used to trigger the WhoDoesIt intent. In this case the Askable context is re-created every time an intent is matched.
.intent
intent Test {
inputs {
"testing"
}
creates context Askable with lifespan 2
context CONTEXT_Test with lifespan 2
}
intent Test2 {
requires context CONTEXT_Test
inputs {
"testing"
}
creates context Askable with lifespan 2
creates context CONTEXT_Test2 with lifespan 2
}
intent WhoDoesIt {
requires context Askable
inputs {
"Who does this task?"
"Who does it?"
"Who performs this task"
}
}
.execution
on intent Test do
ChatPlatform.Reply("Intent: Test")
on intent Test2 do
ChatPlatform.Reply("Intent: Test2")
on intent WhoDoesIt do
if(context.containsKey("CONTEXT_Test2")) {
ChatPlatform.Reply("Departament")
else if(context.containsKey("CONTEXT_Test")) {
ChatPlatform.Reply("Empleat")
}
on intent Default_Fallback_Intent do
ChatPlatform.Reply("Sorry I didn't get it")
While this solution should work, I have to admit it's not really handy. If you want to store information manually I'd use the session
(that can contain arbitrary key/value pairs) instead of contexts:
intent Test {
inputs {
"testing"
}
creates context Askable with lifespan 2
creates context CONTEXT_Test with lifespan 4
}
intent Test2 {
requires context CONTEXT_Test
inputs {
"testing"
}
creates context Askable with lifespan 2
creates context CONTEXT_Test2 with lifespan 4
}
intent WhoDoesIt {
requires context Askable
inputs {
"Who does this task?"
"Who does it?"
"Who performs this task"
}
}
.execution
on intent Test do
session.put("whoDoesIt", "Empleat")
ChatPlatform.Reply("Intent: Test")
on intent Test2 do
session.put("whoDoesIt", "Departament")
ChatPlatform.Reply("Intent: Test2")
on intent WhoDoesIt do
ChatPlatform.Reply(session.get("whoDoesIt") as String)
on intent Default_Fallback_Intent do
ChatPlatform.Reply("Sorry I didn't get it")
In this version you store a session value with the key "whoDoesIt", that is set/erased in the execution rules Test and Test2. The rule WhoDoesIt access the value and prints it in the returned message. Note that session values does not have a lifespan, you have to manage them manually.
Also, I would like to know if i can create a context in execution. No you can't, see the beginning of my comment, if you need to create and store information use the
session
instead of thecontext
I have another question: Can I, in creates context, set a parameter with a hardcoded value? No, even if it looks like a possible solution for your issue I don't think it should be the case, again, the
session
can do it for you.I have another question: There is a way to know which input has matched the actual Intent? Yes, you can access the raw input from the
intent
variable (and also the recognition confidence) see below:on intent Test do intent.matchedInput // "testing" intent.recognitionConfidence // [0 .. 1]
Note that the matchedInput value is the raw input from the user, so if you use a ML-based NLP engine such as DialogFlow it may not be exactly a training sentence. The recognitionConfidence is a percentage (always 100% for the RegExp NLP engine, different for DialogFlow), and can be used to trigger specific responses from the bot when the intent confidence is low.
Thank you for your response. You are helping me a lot.
Can i delete/remove a context if i create a context(with the same name) with lifespan 0?
To be fair I don't know, but for sure it's not how it is supposed to work, why do you want to remove a context? You can set the lifespan to 1 (or 2, I don't remember right now if the current interaction is counted in the lifespan or not) to make it visible only for the next intent.
I am interested to know more about your use case, deleting context may make sense in specific scenario.
My objective is to generate automatically a Chatbot using any BPMN. So being able to delete contexts gives me more control.
It could be used in order to do a "reset". For example, if i have a BPMN with multiple subproceses, and in a determined moment the chatbot is in the middle of one. If the user asks for another, i want to be able to "jump" at the begining of the subproces. So i may want to do a "reset" to be sure that there will not be conflicting contexts.
I have a question. There is way to prevent lifespan decreasing when no intent is matched(when default fallback intent is activated).
I ask because i'm having problems with the lifespan of my contexts. I set them to 2, but if the user says, twice, something that does not match any intent, then the context ends. I would like to prevent that, so if there is no input matched then the lifespan does not decrease.
I would also like to know if i can define a fallback intent for a specific intent. So i can have different fallback intents for different intents. Something like a "follow-up" fallback intent. Intent1 --> Fallback1 Intent2 --> Fallback2
I also tried creating a context
with lifespan 0
(to remove it).
I tried it in Dialog Flow console and worked for me. It deletes the context
properly.
But when i try it in Xatkit, doesn't work, it feels like the context
is still alive.
I would like to know why in Xatkit doesn't work. I also would like to know how i can make it work so it has the same behavior as Dialog Flow console(there is any option on Xatkit configuration i can change?).
im basically implementing this:
So what i have is this branch and merge structure. When it ends(after End
is matched), i say "begin", so Begin
is matched.
Here comes the difference. In Xatkit the contexts are not erased after creating a context
with lifespan 0
. However, in Dialog Flow they are.
So i would like to know how i can have the same behavior as Dialog Flow.
I will put here the relevant code of my intent
file. It may clarify what i mean.
(the execution
file is just a fixed response, so i will not put it here)
intent Begin {
inputs {
"begin"
}
creates context CONTEXT_Begin with lifespan 5
creates context CONTEXT_Price with lifespan 0
creates context CONTEXT_Price_Question with lifespan 0
creates context CONTEXT_Test2 with lifespan 0
}
intent Price {
requires context CONTEXT_Begin
inputs {
"next"
}
creates context CONTEXT_Price with lifespan 5
}
intent Price_YES {
requires context CONTEXT_Price
inputs {
"yes"
}
creates context CONTEXT_Price_Question with lifespan 5
}
intent Price_NO {
requires context CONTEXT_Price
inputs {
"no"
}
creates context CONTEXT_Price_Question with lifespan 5
}
intent End {
requires context CONTEXT_Price
requires context CONTEXT_Price_Question
inputs {
"next"
}
creates context CONTEXT_Test2 with lifespan 5
}
I will also leave a capture:
What surprises me is that when Xatkit is started. If i go to DialogFlow console i see the following:
So the intents are well uploaded. And if i execute them(on DialogFlow console) it works properly. But dont work properly on Xatkit.
So i would like to know how if there is any configuration on Xatkit to solve this issue.
I also would like to ask if there is a way to do faster the intent registration on Dialog Flow. So it takes less time.
Where can I find documention about what can be done with Xatkit? Explanations for "follows", "context" and others functionalities. I have seen them in the examples, but I have not seen them in the documentation.
I ask because, now, I need to represent states. I think that this can be achieved by using "follows" and "context", but I am not sure how they work. So there is any documentation that I can read to understand what I can do with Xatkit?