I have a scenario like this
User says: What's the temperature in SF?
bot executes: get_forecast
updates context with: forecast
bot send: {forecast}
Is there a way to use {forecast} and extract entities from it? For example, I can continue the above story as -
User say: convert that in celsius
<extract temperature from {forecast} set entities>
bot execute: convert_to_celsius
updates context with: temperature
bot sends: {temperature}
Any suggestions on how to do this?
The entity value can be stored in context, or on your backend/server.
If you store {forecast} in context, when user request conversion to celsius, you retrieve it from context, convert it and update context with {temperature}.
However, note that 'context' is passed around between user and your backend so I do not recommend putting too many unnecessary values in it, due to more data being transmitted for each call.
For your use case, you could storing {forecast} on your server instead. When user request conversion, simply retrieve it and update context.
Related
I am building a telegram bot where I am attempting to get the user to fill in detail about an event and store them in a dictionary which is itself in a list.
However I want it be link a conversation. I want it to look like:
user: /create
bot-reply: What would you like to call it?
user-reply: Chris' birth day
bot-reply: When is it?
user-reply: 08/11/2021
bot-reply: Event Chris birth day on 08/11/2021 has been saved!
To achieve this I plan to use ForceReply which states in the documentation
This can be extremely useful if you want to create user-friendly step-by-step interfaces without having to sacrifice privacy mode.
The problem is the documentation does not seem to explain how to handle responses.
Currently my code looks like this:
#app.on_message(filters.command('create'))
async def create_countdown(client, message):
global countdowns
countdown = {
'countdown_id': str(uuid4())[:8],
'countdown_owner_id': message.from_user.id,
'countdown_onwner_username': message.from_user.username,
}
try:
await message.reply('What do you want to name the countdown?',
reply_markup=ForceReply()
)
except FloodWait as e:
await asyncio.sleep(e.x)
Looking through the form I have found options like this:
python telegram bot ForceReply callback
which are exactly what I am looking for but they are using different libraries like python-telegram-bot which permit them to use ConversationHandler. It seems to not be part of pyrogram
How to I create user-friendly step-by-step interfaces with pyrogram?
Pyrogram doesn't have a ConversationHandler.
You could use a dict with your users' ID as the key and the state they're in as the value, then you can use that dictionary of states as your reference to know where your User is in the conversation.
Dan: (Pyrogram creator)
A conversation-like feature is not available yet in the lib. One way to do that is saving states into a dictionary using user IDs as keys. Check the dictionary before taking actions so that you know in which step your users are and update it once they successfully go past one action
https://t.me/pyrogramchat/213488
Hi all,
I have question about control flow in Dialogflow. Is it possible to control Dialogflow in fullfillment?
Below are my Dialogflow Process.
I created 'Intent1' -> wait for user input about 'Document Type' such as 'Document No.1' or 'Document No.2', etc ...
I created 'Intent2' -> It is follow-up intent of 'Intent1'. It get user input (Training Phrases) such as 'Document No.1' or 'Document No.2' or etc. This 'Intent2' has created parameters for get 'Document Type' such as 'No.1' or 'No.2' from user input.
I created fulfillment 'Inline' for 'Intent2' too. After user input 'No.1' or 'No.2' or etc. I check the parameter value with my Firebase Realtime Database. And then return result message to user for waiting next user input by using ...
agent.add("...some phrase...");
I want to know, is it possible to control Dialogflow in fullfillment?
Such as, if I check 'No.3' does not in by Database, may I send message
"It is not in database" and force process back to 'Intent1'.
But if 'No.1' is in my Database, may I send message "Please input time
to get it?" to user and wait user input at 'Intent3' (follow-up intent
of 'Intent2').
I try to search guide for solving but not found.
Thank in advance
Using Firebase to retrieve data
When using firebase to retrieve data for your dialogflow agent, try not to have any ' business logic' in your databases. Instead, query the database, get the results in your application code (for this example Inline fulfillment), and have your logic there (i.e. did the results come back null or non-null, depending on if it exists in the database). Now, let's get back to your problem at stake.
Implementing a solution
First, you should have code that looks like this to set up the connection between Dialogflow and Firebase.
const admin = require('firebase-admin');
admin.initializeApp({
credential: admin.credential.applicationDefault(),
databaseURL: 'ws://project_name.firebaseio.com/'
});
If you have issues with respect to using firebase-admin, you will need greater permission and check out this out.
Next, when your user says a Document Type to the agent, you query the database based on what you extracted from the user. This extraction is stored in a variable you named when you created parameters in the console. You can name this variable anything; I am going to call this extracted parameter userType. The inline fulfillment code is as follows:
function getDoc(agent){
// userType is what the user responded to you
const response = agent.parameters.userType;
return admin.database().ref('data').once('value').then((snapshot) => {
const type = snapshot.child(response).val();// response is variable so no quotes
if(type!== null){
agent.add(`You chose Document type ${type}`);
}
else{
// type == null indicating the type doesn't exist in the database
agent.add('You gave an invalid type');
}
});
}
If the Document Type the user said to agent exists in your database, then the variable above I called type will be some value (not null). If it is null, then what the user asked for is not in the database, and you can prompt a message to user as a follow up such as, "Your input is invalid."
In your example, if the user asked for No. 3 then response would refer to No. 3 and the type would be null. indicative of the fact No. 3 is not is your database.
Resources:
Video by Axle Web Technologies about the workflow and syntax of connecting Dialogflow to Firebase (highly recommended)
Accessing parameters from inside a fulfillment, by GCP Quickstart
Get data using Firebase, from the Firebase Documentation
I'm now stuck on the problem of getting user input (what user says) in my index.js. For example, the user says: please tell me if {animals} can live between temperature {x} to {y}. I want to get exact value (in string) for what animals, x and y so that I can check if it is possible in my own server. I am wondering how to do that since the entities need to map to some exact key values if I annotate these three parameters to some entities category.
The methods for ApiAiApp is very limited: https://developers.google.com/actions/reference/nodejs/ApiAiApp
And from my perspective, none of the listed methods work in this case.
Please help!
Generally API.AI entities are for some set of known values, rather than listening for any value and validating in the webhook. First, I'd identify the kinds of entities you expect to validate against. For the temperatures (x and y), I'd use API.AI's system entities. Calling getArgument() for those parameters (as explained in the previous answer) should return the exact number value.
For the animals, I'd use API.AI's developer entities. You can upload them in the Entity console using JSON or CSV. You can enable API.AI's automated expansion to allow the user to speak animals which you don't support, and then getArgument() in webhook the webhook will return the new value recognized by API.AI. You can use this to validate and respond with an appropriate message. For each animal, you can also specify synonymous names and when any of these are spoken, and getArgument() will return the canonical entity value for that animal.
Extra tip, if you expect the user might speak more than one animal, make sure to check the Is List box in the parameter section of the API.AI intent.
If "animals", "x", and "y" are defined as parameters in your Intent in API.AI, then you can use the getArgument() method defined in ApiAiApp.
So the following should work:
function tempCheck( app ){
var animals = app.getArgument('animals');
var x = app.getArgument('x');
var y = app.getArgument('y');
// Check the range and then use something like app.tell() to give a response.
}
I'm sending series of texts to be classified by https://iab.taxonome.org classification API, but since I work in node JS enviroment in a proper, async way, the responses get's out of sync with the requests. I can use recorsive calls, but this might overflow my stack. Any idea how to sync calls with classification responses?
You might use the optional private ID to pass a "cookie" to identify the session.
From https://iab.taxonome.org/api
id optional String Request user defined identifier or empty string.
curl -i https://rest.taxonome.org/v1/taxono?me=this%20is%20a%20text%20to%20be%20classified&token=123e4567-e89b-12d3-a456-426655440000&ver=1&id=MyUserDefinedId
I'm writing a REST api in node js that will execute a sql query and send the results;
in the request I need to send the WHERE conditions; ex:
GET 127.0.0.1:5007/users //gets the list of users
GET 127.0.0.1:5007/users
id = 1 //gets the user with id 1
Right now the conditions are passed from the client to the rest api in the request's headers.
In the API I'm using sequelize, an ORM that needs to receive WHERE conditions in a particular form (an object); ex: having the condition:
(x=1 AND (y=2 OR z=3)) OR (x=3 AND y=1)
this needs to be formatted as a nested object:
-- x=1
-- AND -| -- y=2
| -- OR ----|
| -- z=3
-- OR -|
|
| -- x=3
-- AND -|
-- y=1
so the object would be:
Sequelize.or (
Sequelize.and (
{x=1},
Sequelize.or(
{y=2},
{z=3}
)
),
Sequelize.and (
{x=3},
{y=1}
)
)
Now I'm trying to pass a simple string (like "(x=1 AND (y=2 OR z=3)) OR (x=3 AND y=1)"), but then I will need a function on the server that can convert the string in the needed object (this method in my opinion has the advantage that the developer writing the client, can pass the where conditions in a simple way, like using sql, and this method is also indipendent from the used ORM, with no need to change the client if we need to change the server or use a different ORM);
The function to read and convert the conditions' string into an object is giving me headache (I'm trying to write one without success, so if you have some examples about how to do something like this...)
What I would like to get is a route capable of executing almost any kind of sql query and give the results:
now I have a different route for everything:
127.0.0.1:5007/users //to get all users
127.0.0.1:5007/users/1 //to get a single user
127.0.0.1:5007/lastusers //to get user registered in the last month
and so on for the other tables i need to query (one route for every kind of request I need in the client);
instead I would like to have only one route, something like:
127.0.0.1:5007/request
(when calling this route I will pass the table name and the conditions' string)
Do you think this solution would be a good solution or you generally use other ways to handle this kind of things?
Do you have any idea on how to write a function to convert the conditions' string into the desired object?
Any suggestion would be appreciated ;)
I would strongly advise you not to expose any part of your database model to your clients. Doing so means you can't change anything you expose without the risk of breaking the clients. One suggestion as far as what you've supplied is that you can and should use query parameters to cut down on the number of endpoints you've got.
GET /users //to get all users
GET /users?registeredInPastDays=30 //to get user registered in the last month
GET /users/1 //to get a single user
Obviously "registeredInPastDays" should be renamed to something less clumsy .. it's just an example.
As far as the conditions string, there ought to be plenty of parsers available online. The grammar looks very straightforward.
IMHO the main disadvantage of your solution is that you are creating just another API for quering data. Why create sthm from scratch if it is already created? You should use existing mature query API and focus on your business logic rather then inventing sthm new.
For example, you can take query syntax from Odata. Many people have been developing that standard for a long time. They have already considered different use cases and obstacles for query API.
Resources are located with a URI. You can use or mix three ways to address them:
Hierarchically with a sequence of path segments:
/users/john/posts/4711
Non hierarchically with query parameters:
/users/john/posts?minVotes=10&minViews=1000&tags=java
With matrix parameters which affect only one path segment:
/users;country=ukraine/posts
This is normally sufficient enough but it has limitations like the maximum length. In your case a problem is that you can't easily describe and and or conjunctions with query parameters. But you can use a custom or standard query syntax. For instance if you want to find all cars or vehicles from Ford except the Capri with a price between $10000 and $20000 Google uses the search parameter
q=cars+OR+vehicles+%22ford%22+-capri+%2410000..%2420000
(the %22 is a escaped ", the %24 a escaped $).
If this does not work for your case and you want to pass data outside of the URI the format is just a matter of your taste. Adding a custom header like X-Filter may be a valid approach. I would tend to use a POST. Although you just want to query data this is still RESTful if you treat your request as the creation of a search result resource:
POST /search HTTP/1.1
your query-data
Your server should return the newly created resource in the Location header:
HTTP/1.1 201 Created
Location: /search/3
The result can still be cached and you can bookmark it or send the link. The downside is that you need an additional POST.