Dialogflow: How to store multiple parameters in a list parameter from different user sentences? - dialogflow-es

Basically I want to achieve this:
1.user: I want apple.
bot: You want apple right?
2.user: I also want banana.
bot: You want apple and banana right?
Here apple and banana are all parameters of the same fruit entity. In my webook backend I want to receive [apple, banana] when the user entered 2nd sentence, so the bot needs to remember all the fruit (parameters) users gave during the conversation.
I was playing around with dialogflow context. I know it could pass parameters between different intents. But at here I'm using the same intent buyFruit, so the output context only has the new fruit parameters user entered in a new sentence:
1.user: I want apple. -> outputContext.parameters = [apple]
2.user: I also want banana. -> outputContext.parameters = [banana]
I couldn't find a way to get the fruit parameters user said in previous sentences. In another word, I want outputContext.parameters = [apple, banana] in the second webhook request. Does anyone know how to achieve this?

You edited the question and did not respond to my answer. I feel you may not really know what question you are asking.
Use context, create your own, store the data in your python application. Its pretty simple.
Please, respectfully take the time to either comment on the direct result, further ask a more concise question or mark as answered.

I found the solution to this. I will assume you understand how to use fulfillment, and adding webhooks. If not, feel free to visit here or shoot a question.
For this, there are 3 necessary parts. Dialogflow, your fulfillment code ( I used flask and python), and communication between the two. Enable Webhook, fill in the appropriate local machine url (for this I used NGROK).
I created a cart and a function for creating and maintaining said cart. Below is the code:
from flask import Flask, request
app = Flask(__name__)
##Create the cart
cart = []
#create a route for the webhook
#app.route('/webhook', methods=['GET', 'POST'])
def webhook():
req = request.get_json(silent=True, force=True)
fulfillmentText = ''
query_result = req.get('queryResult')
if query_result.get('action') == 'order.wings':
food_data = query_result['parameters']
##create temp dictionary so we always extract correct order data
temp_dictionary = []
for item in food_data:
temp_dictionary.append(item)
##add items to cart
new_item = []
for item in temp_dictionary:
new_item.append(food_data[item])
cart.append(new_item)
print(cart)
fulfillmentText = "Added Wings to Cart"
return {
"fulfillmentText": fulfillmentText,
"source": "webhookdata"
}
#run the app
if __name__ == '__main__':
app.run()

Related

How to handle replies in with Pyrogram when using ForceReply?

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

Implementing an observer class in python

I am creating a bidding system where students can log in to a system and make a request for a tutor and sign a contract via a TKinter UI. I have managed to do this successfully. But now I am required to do the following,
"when a student or a tutor logs in into the system, the system should notify the user if there is a contract that is going to expire within a month."
I am having trouble trying to implement this feature as I feel this needs an observer and I for the life of me can't wrap my head around the Observer design pattern. I have no problem creating the methods to call for the contracts and determine which contract expires but I can't seem to figure out how to like display it using an observer. Can I get some guidance on this?
For reference, this is the method that would get all the contracts that are expiring within a month.
def expiring_contracts(self,username):
user_contracts = self.all_contracts_by_user(username)
expiring_contracts = []
for i in user_contracts:
time_string = i["expiryDate"]
time_datetime = datetime.strptime(time_string,'%Y-%m-%dT%H:%M:%S.%f')
one_month = datetime.now() + dateutil.relativedelta.relativedelta(months=1)
if time_datetime < one_month:
expiring_contracts.append(i)
return expiring_contracts
the self.all_contracts_by_user is another method within this class that gets all the contracts by this user. I must implement a design pattern for this.

Let Alexa ask the user a follow up question (NodeJS)

Background
I have an Intent that fetches some Data from an API. This data contains an array and I am iterating over the first 10 entries of said array and read the results back to the user. However the Array is almost always bigger than 10 entries. I am using Lambda for my backend and NodeJS as my language.
Note that I am just starting out on Alexa and this is my first skill.
What I want to archive is the following
When the user triggers the intent and the first 10 entries have been read to the user Alexa should ask "Do you want to hear the next 10 entries?" or something similar. The user should be able to reply with either yes or no. Then it should read the next entries aka. access the array again.
I am struggling with the Alexa implementation of this dialog.
What I have tried so far: I've stumbled across this post here, however I couldn't get it to work and I didn't find any other examples.
Any help or further pointers are appreciated.
That tutorial gets the concept right, but glosses over a few things.
1: Add the yes and no intents to your model. They're "built in" intents, but you have to add them to the model (and rebuild it).
2: Add your new intent handlers to the list in the .addRequestHandlers(...) function call near the bottom of the base skill template. This is often forgotten and is not mentioned in the tutorial.
3: Use const sessionAttributes = handlerInput.attributesManager.getSessionAttributes(); to get your stored session attributes object and assign it to a variable. Make changes to that object's properties, then save it with handlerInput.attributesManager.setSessionAttributes(sessionAttributes);
You can add any valid property name and the values can be a string, number, boolean, or object literal.
So assume your launch handler greets the customer and immediately reads the first 10 items, then asks if they'd like to hear 10 more. You might store sessionAttributes.num_heard = 10.
Both the YesIntent and LaunchIntent handlers should simply pass a num_heard value to a function that retrieves the next 10 items and feeds it back as a string for Alexa to speak.
You just increment sessionAttributes.num_heard by 10 each time that yes intent runs and then save it with handlerInput.attributesManager.setSessionAttributes(sessionAttributes).
What you need to do is something called "Paging".
Let's imagine that you have a stock of data. each page contains 10 entries.
page 1: 1-10, page 2: 11-20, page 3: 21-30 and so on.
When you fetching your data from DB you can set your limitations, In SQL it's implemented with LIMIT ,. But how you get those values based on the page index?
Well, a simple calculation can help you:
let page = 1 //Your identifier or page index. Managed by your client frontend.
let chunk = 10
let _start = page * chunk - (chunk - 1)
let _end = start + (chunk - 1)
Hope this helped you :)

Can i put Many Pictures links in dialogflow and send only one Randomly

I am new to dialogflow. I learned some things the previous month, but I am still searching for how to put a lot of pictures in intent and sending only one to the user, not all of them, and randomly, such as text responses as a kind of entertainment inside the Agent ...
Note :
I linked the client to Facebook Messenger and I want to send the photo there
Can i do this?
Assuming you're using Dialogflow-fulfillment library to respond to webhook requests this should do the trick.
You can store whatever type of response that you want to send in an array...
For example, I'll choose an array of plain text responses
const responses = [
"I didn't get that. Can you say it again?",
'I missed what you said. What was that?',
'Sorry, could you say that again?',
'Sorry, can you say that again?',
'Can you say that again?',
"Sorry, I didn't get that. Can you rephrase?",
'Sorry, what was that?',
'One more time?',
'What was that?',
'Say that one more time?',
"I didn't get that. Can you repeat?",
'I missed that, say that again?'
]
Given the array you can generate a random number between 0 (most programming languages index from 0) and the length of the array.
const index = Math.floor((Math.random() * responses.length) + 1)
In the above case, index is assigned to any number between 0 and 11. You can then pass this index into the array to randomly choose 1 value.
agent.add(responses[index])
You can take this concept and apply it to any response type you want.
Hope this does the trick for you!

Getting arguments/parameters values from api.ai

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.
}

Resources