How to access JSON to parrot back user response? - python

I'm trying to make a google home assistant that just parrots back whatever a user says to it. Basically I need to capture what the user is saying, and then feed it back into a response.
I have some puzzle pieces figured out.
One is initializing the API to do queries:
api = ApiAi(os.environ['DEV_ACCESS_TOKEN'], os.environ['CLIENT_ACCESS_TOKEN'])
The other is a fallback intent that is intended to just capture whatever the user says and repeat it back:
#assist.action('fallback', is_fallback=True)
def say_response():
""" Setting the fallback to act as a looper """
speech = "test this" # <-- this should be whatever the user just said
return ask(speech)
Another is the JSON response on the API.AI site looks like this:
{
"id": "XXXX",
"timestamp": "2017-07-20T14:10:06.149Z",
"lang": "en",
"result": {
"source": "agent",
"resolvedQuery": "ok then",
"action": "say_response",
"actionIncomplete": false,
"parameters": {},
"contexts": [],
"metadata": {
"intentId": "a452b371-f583-46c6-8efd-16ad9cde24e4",
"webhookUsed": "true",
"webhookForSlotFillingUsed": "true",
"webhookResponseTime": 112,
"intentName": "fallback"
},
"fulfillment": {
"speech": "test this",
"source": "webhook",
"messages": [
{
"speech": "test this",
"type": 0
}
],
"data": {
"google": {
"expect_user_response": true,
"is_ssml": true
}
}
},
"score": 1
},
"status": {
"code": 200,
"errorType": "success"
},
"sessionId": "XXXX"
}
The module I'm intializing from looks like this: https://github.com/treethought/flask-assistant/blob/master/api_ai/api.py
Full program looks like this:
import os
from flask import Flask, current_app, jsonify
from flask_assistant import Assistant, ask, tell, event, context_manager, request
from flask_assistant import ApiAi
app = Flask(__name__)
assist = Assistant(app, '/')
api = ApiAi(os.environ['DEV_ACCESS_TOKEN'], os.environ['CLIENT_ACCESS_TOKEN'])
# api.post_query(query, None)
#assist.action('fallback', is_fallback=True)
def say_response():
""" Setting the fallback to act as a looper """
speech = "test this" # <-- this should be whatever the user just said
return ask(speech)
#assist.action('help')
def help():
speech = "I just parrot things back!"
## a timeout and event trigger would be nice here?
return ask(speech)
#assist.action('quit')
def quit():
speech = "Leaving program"
return tell(speech)
if __name__ == '__main__':
app.run(debug=False, use_reloader=False)
How do I go about getting the "resolvedQuery" out of the JSON to be fedback as "speech" for the response?
Thanks.

The flask_assistant library does a good job of parsing the request into a dict object.
You can get the resolvedQuery by writing:
speech = request['result']['resolvedQuery']

Just create a new intent (doesn’t matter the name) and a template with sys.any; after that go on your server and use something similar to the following code
userInput = req.get(‘result’).get(‘parameters’).get(‘YOUR_SYS_ANY_PARAMETER_NAME’)
Then send userInput back as the speech response.
Something like this is how you get the initial JSON data:
#app.route(’/google_webhook’, methods=[‘POST’])
def google_webhook():
# Get JSON request
jsonRequest = request.get_json(silent=True, force=True, cache=False)
print("Google Request:")
print(json.dumps(jsonRequest, indent=4))
# Get result
appResult = google_process_request(jsonRequest)
appResult = json.dumps(appResult, indent=4)
print("Google Request finished")
# Make a JSON response
jsonResponse = make_response(appResult)
jsonResponse.headers['Content-Type'] = 'application/json'
return jsonResponse

Related

How to extract tags name and description in FastAPI?

I want to use the name and description present in tags_metadata inside the method. I don't how to do that is there any way I can use those attributes
from fastapi import FastAPI
tags_metadata = [
{
"name": "select name",
"description": "Operations with users. The **login** logic is also here.",
},
{
"name": "items",
"description": "Manage items. So _fancy_ they have their own docs.",
"externalDocs": {
"description": "Items external docs",
"url": "https://fastapi.tiangolo.com/",
},
},
]
app = FastAPI(openapi_tags=tags_metadata)
#app.get("/users/", tags=["users"])
async def get_users():
return [{"name": "Harry"}, {"name": "Ron"}]
#app.get("/items/", tags=["items"])
async def get_items():
return [{"name": "wand"}, {"name": "flying broom"}]
here I want to select the first name attribute from tags_metadata in the get_users() method
output need to be -- > "select name"
https://fastapi.tiangolo.com/tutorial/metadata/?h=+tags#use-your-tags
Yes there is.
from fastapi import FastAPI
app = FastAPI()
#app.get("/dummy", tags=["dummy2"])
async def dummy():
...
#app.post("/dummy2", tags=["dummy2"])
async def dummy2():
...
Let's assume we have these routes. By checking each route from app.router, we can find the paths.
#app.get("/tags", tags=["tags"])
async def tags():
tags = {}
for route in app.router.__dict__["routes"]:
if hasattr(route, "tags"):
tags[route.__dict__["path"]] = route.__dict__["tags"]
return tags
When we hit the /tags endpoint we will see this.
{
"/dummy":[
"dummy2"
],
"/dummy2":[
"dummy2"
],
"/tags":[
"tags"
]
}

Amazon lex error-An error has occurred: Invalid Lambda Response: Received error response from Lambda: Unhandled

I am developing a chatbot using lex.I created one intent called "latestdetails" and one slot "uniquename".I want to validate the slot "uniquename" such that it does not accept alphabets and ask the message "please enter again" when the input is wrong . Below is my code in python.
When testing the lambda function,I get the correct response but when lambda function is connected with lex via initialization and validation code hook,I get the following error at bot :"Amazon lex error-An error has occurred: Invalid Lambda Response: Received error response from Lambda: Unhandled".
I saw related questions in stackoverflow but I am not able to get the required solution.
import os
import time
import json
import logging
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
def get_slots(event):
return event['currentIntent']['slots']
def elicit_slot(intent_name, slots, slot_to_elicit ,message):
response = {
"dialogAction":
{
"type":"ElicitSlot",
"intentName": intent_name,
"slots": slots,
"slotToElicit": slot_to_elicit,
"message": {
"content": message,
"contentType": "PlainText"
}
}
}
return response
def delegate(slots):
response = {
"dialogAction":
{
"type":"Delegate",
"slots": slots
}
}
return response
def close():
response = {
"dialogAction":
{
"fulfillmentState":"Fulfilled",
"type":"Close",
"message":
{
"contentType":"PlainText",
"content": "Hey your ticket has been raised"
}
}
}
return response
def dispatch(event):
intent_name=event['currentIntent']['name']
if intent_name == 'latestdetails':
source = event['invocationSource']
if source == 'DialogCodeHook':
slots= get_slots(event)
uniquename = event["currentIntent"]["slots"]["uniquename"]
if uniquename.isalpha():
return elicit_slot(intent_name,'uniquename','uniquename','please enteragain')
return delegate(slots)
return close('Fulfilled')
elif source == 'FulfillmentCodeHook':
return close()
def lambda_handler(event, context):
return dispatch(event)

Able to get response but not in display

I wrote a python code for the dialog flow using the flask and webhook. I am able to get the response but it not displayed in the dialog flow. This code running perfectly.
CODE:
# import os
import json
# import urllib
import datetime
from config import Configuration
from swe_commands import SweCommands
from flask import Flask, request, make_response
# Flask application should start in global layout
app = Flask(__name__)
#app.route('/webhook', methods=['POST'])
def webhook():
req = request.get_json(silent=True, force=True)
print "Request:"
print json.dumps(req, indent=1)
res = make_webhook_result(req)
res = json.dumps(res, indent=1)
print "Response:"
print res
r = make_response(res)
r.headers['Content-Type'] = 'application/json'
return r
def make_webhook_result(req):
# if req.get("queryResult").get("action") != "nakshatra":
# return {}
swe_path = Configuration.swe_path()
date_and_time = str(datetime.datetime.now())[:19]
panchang_dictionary = SweCommands.find_panchang(swe_path, date_and_time)
result = req.get("queryResult")
parameters = result.get("parameters")
angam = parameters.get("nakshatra")
nakshatra = panchang_dictionary[angam]
speech = "Current nakshatra is %s" % nakshatra
source = "Panchangam"
output = {'speech': speech, "displayText": speech, "source": source}
return output
if __name__ == '__main__':
port = 5000
print "Starting app in port %s" % port
app.run(debug=True, port=port, host='127.0.0.1')
REQUEST:
**{
"queryResult": {
"fulfillmentMessages": [
{
"text": {
"text": [
""
]
}
}
],
"allRequiredParamsPresent": true,
"parameters": {
"nakshatra": "nakshatra"
},
"languageCode": "en",
"intentDetectionConfidence": 0.6725314,
"action": "nakshatra",
"intent": {
"displayName": "PanchangFind",
"name": "projects/my-project-1536557558293/agent/intents/6d1d46bf-3787-48cd-9b45-0766d5f2b107"
},
"queryText": "What is nakshatra"
},
"originalDetectIntentRequest": {
"payload": {}
},
"session": "projects/my-project-1536557558293/agent/sessions/08857865-1d08-2eef-5d4f-83b92107f09b",
"responseId": "2137da9d-23a9-4735-aec2-7adb7ae52d85-9cc28bb4"
}**
RESPONSE:
**{
"displayText": "Current nakshatra is Shravana",
"speech": "Current nakshatra is Shravana",
"source": "Panchangam"
}**
But it not get displayed in the dialog flow panel? Whether I have to set any parameters for dialog flow panel to receive the response in a dialog flow. Please let me know.
I got an answer to this. When we use V1 in dialog flow, the response key is displayText. But in V2 the response key is fulfillmentText. When I added the response key in this name it able to detect the output.

How to run dialog in slack app with flask?

I am in the middle of creating todo app integreted with Slack. I need to use dialog.open property of slack.
I managed to go through slack api tutorial however can not finally understand how dialogs work in integration with external systems. I created code which runs after slash command in slack. It should open dialog and show it to user, however it doesn't. I printed some parts of code to see what happens inside - looks like whole code works and server returns 200.
#app.route('/helpdesk', methods=['POST'])
def helpdesk():
print(request.form)
api_url = 'https://slack.com/api/dialog.open'
user_id = request.form['user_id']
trigger_id = request.form['trigger_id']
dialog = {
"token": "J1llSAeQAxNyw8yc37xuEsad",
"trigger_id": trigger_id,
"dialog": {
"callback_id": "ryde-46e2b0",
"title": "Request a Ride",
"submit_label": "Request",
"notify_on_cancel": True,
"state": "Limo",
"elements": [
{
"type": "text",
"label": "Pickup Location",
"name": "loc_origin"
},
{
"type": "text",
"label": "Dropoff Location",
"name": "loc_destination"
}
]
}
}
print(dialog)
requests.post(api_url, data=dialog)
return make_response()
I expect to see dialog window after writing slash command in slack.
What I see in prints:
ImmutableMultiDict([('token', 'J1llSAeQAxNyw8yc37xuEsad'), ('team_id', 'TKWQ5QP7Y'), ('team_domain', 'team-learningslack'), ('channel_id', 'CKH7RSZPC'), ('channel_name', 'slackflask'), ('user_id', 'UKN9KU7JM'), ('user_name', 'konrad.marzec1991'), ('command', '/musi'), ('text', ''), ('response_url', 'https://hooks.slack.com/commands/TKWQ5QP7Y/664885241506/ABjpMYmTWrnXpSBoGMpaJtOV'), ('trigger_id', '669947662833.676821839270.6c4bddd1418d3d4f2c8626f7c9accdf7')])
{'token': 'J1llSAeQAxNyw8yc37xuEsad', 'trigger_id': '669947662833.676821839270.6c4bddd1418d3d4f2c8626f7c9accdf7', 'dialog': {'callback_id': 'ryde-46e2b0', 'title': 'Request a Ride', 'submit_label': 'Request', 'notify_on_cancel': True, 'state': 'Limo', 'elements': [{'type': 'text', 'label': 'Pickup Location', 'name': 'loc_origin'}, {'type': 'text', 'label': 'Dropoff Location', 'name': 'loc_destination'}]}}
127.0.0.1 - - [26/Jun/2019 00:15:35] "POST /helpdesk HTTP/1.1" 200 -
You had 2 issues in your code:
you need to use an access token, not a verification token in the call
to dialog.open
you need to send the dialog definition as JSON, not as as form array
I made these additional changes
- Added code for using a slack token defined as environment variable
- Use the get() method to access form parameters in from the request
- Added code to show the API response from dialog.open
Here is a corrected version of your code:
import os
import requests
from flask import Flask, json, request
app = Flask(__name__) #create the Flask app
#app.route('/helpdesk', methods=['POST'])
def helpdesk():
api_url = 'https://slack.com/api/dialog.open'
trigger_id = request.form.get('trigger_id')
dialog = {
"callback_id": "ryde-46e2b0",
"title": "Request a Ride",
"submit_label": "Request",
"notify_on_cancel": True,
"state": "Limo",
"elements": [
{
"type": "text",
"label": "Pickup Location",
"name": "loc_origin"
},
{
"type": "text",
"label": "Dropoff Location",
"name": "loc_destination"
}
]
}
api_data = {
"token": os.environ['SLACK_TOKEN'],
"trigger_id": trigger_id,
"dialog": json.dumps(dialog)
}
res = requests.post(api_url, data=api_data)
print(res.content)
return make_response()
if __name__ == '__main__':
app.run(debug=True, port=8000) #run app in debug mode on port 8000

How to send data and custom headers using urllib2

Hi I am using urrlib2 to send some data and custom headers to a link. Am getting 500 internal server error. I have contacted the service, and they are saying the data(json data) is correct but there is some error in my python code. What am I doing wrong ?
Following is the code.
import urllib2,urllib
import json
PREPAYMENT_URL = "https://services.gharpay.in/rest/GharpayService/"
PREPAYMENT_USERNAME = "somename"
PREPAYMENT_PASSWORD = "somepass"
data = {
"customerDetails":{
"address": "ads",
"contactNo": "9663924147",
"email": "a#c.com",
"firstName": "akash",
"lastName": "deshpande",
"prefix": "Mr."
},
"orderDetails" : {
"pincode": "411036",
"clientOrderID": "21234",
"deliveryDate": "13-10-2013",
"orderAmount": "123",
"clientComments": "please be carefull",
"paymentMode": "Cash",
"productDetails": {
"productID": "21334",
"productQuantity": "1",
"unitCost": "123",
"productDescription": "tshirt"
},
"templateID": ""
},
}
def create(request):
function = 'createOrder'
url = PREPAYMENT_URL
url = url+ function
headers= {'username':PREPAYMENT_USERNAME,'password':PREPAYMENT_PASSWORD,'Content-type':'application/json'}
data1 = urllib.urlencode(data)
req = urllib2.Request(url,data1,headers)
try:
contents = urllib2.urlopen(req).read()
except urllib2.HTTPError as e:
error_message = e.read()
print error_message # this error message is being printed. It is showing 500 error.
Your code is perfect except for one teensy-weensy detail:
The header should be Content-Type, not Content-type.
Maybe try changing this header and let me know if it works!

Categories

Resources