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.
Related
im running a Redis server. and im gettig the folowwing error.
ERROR: Exception in ASGI application
what have i done wrong?
This is my code:
``
from fastapi import FastAPI
from models import Parks
import requests
import uvicorn
import json
import redis2
SERVER_URL = 'localhost'
SERVER_PORT = 8000
REDIS_SERVER = 'localhost'
REDIS_PORT = 6379
app = FastAPI()
#app.post("/api/v1/ru")
async def get_data(rub_post: Parks):
token = "**************"
url = "https://********************************/users/?filter=" + rub_post.car_number
headers = {"Content-Type": "application/json; charset=utf-8", "X-Access-Token": token}
response = requests.get(url, headers=headers)
j = response.json()
if not j['users']['count'] == 0:
note: str = j['users']['list'][0]['places'][0]['notes']
else:
return {"Answer": "car not found"}
if rub_post.parked_id in note:
return {"Answer": "found car"}
if "P" in note:
redis_cli = redis2.Redis(host=REDIS_SERVER, port=REDIS_PORT, db=0)
dict_f = {"carId": rub_post.car_number, "parkingTicketId": rub_post.parked_id,
"laneId": "cded89ec403083a31", "transactionId": "Invalid Parking",
"currency": "", "price": "", "userPn": "", "userEmail": "", "userName": "",
"companyName": "", "paymentMethod": [{"type": "", "amount": "", "id": ""}]
}
redis_cli.lpush('terminalToLprIsCarAuthorized', json.dumps(dict_f))
return {"Answer": "invalid car"}
if __name__ == '__main__':
uvicorn.run(app, host=SERVER_URL, port=SERVER_PORT)
``
still new to this and i cant find whats wrong. thanks for the helpers
I'm use the fastapi_log library( https://pypi.org/project/fastapi-log/ ) ( https://github.com/12345k/fastapi-log ) in my FastAPI project.
It works great to log request and responses(return statements), but it does not log HTTPExceptions(which I used in some parts of the program instead of return statements).
How can I edit the source code for log_request.py ( https://github.com/12345k/fastapi-log/blob/main/fastapi_log/log_request.py ) to be able to log responses from HTTPExceptions as well ?
The log_request.py source code :
import re
import time
from starlette.requests import Request
from typing import Callable
from fastapi import HTTPException, Request, Response
import time
import os
import uuid
import json
from user_agents import parse
from urllib.parse import parse_qs
from datetime import datetime
from fastapi.routing import APIRoute
import sqlite3
path = os.path.abspath(os.path.dirname(__file__))
path = path.replace("__init__.py","")
conn = sqlite3.connect(path+'/database/test.db')
conn.execute('''CREATE TABLE IF NOT EXISTS REQUEST
(ENDPOINT TEXT NOT NULL,
TYPE INT NOT NULL,
BODY CHAR(50),
UUID REAL,
TIME TEXT NOT NULL);''')
class LoggingRoute(APIRoute):
def get_route_handler(self) -> Callable:
original_route_handler = super().get_route_handler()
async def custom_route_handler(request: Request) -> Response:
try:
uuid_str = str(uuid.uuid4())
header = dict(request.headers)
if "uuid" in header.keys():
uuid_str = header["uuid"]
user_agent = parse(request.headers["user-agent"])
browser=user_agent.browser.version
if len(browser) >=2:
browser_major,browser_minor = browser[0],browser[1]
else:
browser_major,browser_minor =0,0
user_os=user_agent.os.version
if len(user_os) >=2:
os_major,os_minor = user_os[0],user_os[1]
else:
os_major,os_minor =0,0
# Request json
body = await request.body()
if len(body)!=0:
body=json.loads(body)
else:
body=""
request_json = {
"type":"request",
"uuid":uuid_str,
"env": os.environ.get("ENV"),
"region": os.environ.get("REGION"),
"name": os.environ.get("NAME"),
"method": request.method,
"useragent":
{
"family": user_agent.browser.family,
"major": browser_major,
"minor": browser_minor,
"patch": user_agent.browser.version_string,
"device": {
"family": user_agent.device.family,
"brand": user_agent.device.brand,
"model": user_agent.device.model,
"major": "0",
"minor": "0",
"patch": "0"
},
"os": {
"family": user_agent.os.family,
"major": os_major,
"minor": os_minor,
"patch": user_agent.os.version_string
},
},
"url": request.url.path,
"query": parse_qs(str(request.query_params)),
"body":body,
"length": request.get("content-length"),
'ts': f'{datetime.now():%Y-%m-%d %H:%M:%S%z}'
}
print(json.dumps(request_json,indent=4))
start_time = time.time()
response = await original_route_handler(request)
process_time = (time.time() - start_time) * 1000
formatted_process_time = '{0:.2f}'.format(process_time)
metrics_json = {
"type": "metrics",
"uuid": uuid_str,
"env": os.environ.get("ENV"),
"region": os.environ.get("REGION"),
"name": os.environ.get("NAME"),
"method": request.method,
"status_code": response.status_code,
"url": request.url.path,
"query": parse_qs(str(request.query_params)),
"length": response.headers["content-length"],
"latency": formatted_process_time,
"ts": f'{datetime.now():%Y-%m-%d %H:%M:%S%z}'
}
print(json.dumps(metrics_json,indent=4))
try:
if len(request_json) !=0:
url = str(request_json["url"]).replace("/","")
method=request_json["method"]
body=str(request_json["body"])
uuid_str=request_json["uuid"]
time_value = request_json["ts"]
# print(body)
conn.execute(f"INSERT INTO REQUEST VALUES (?,?,?,?,?)",( url , method, body, uuid_str,time_value ))
# VALUES ({request_json["url"].replace("/","")}, {request_json["method"]},"str(request_json[body])", {request_json["uuid"]} )""");
conn.commit()
except Exception as exc:
print(exc)
pass
return response
except Exception as exc:
body = await request.body()
detail = {"errors": str(exc), "body": body.decode("utf-8")}
print(detail)
raise HTTPException(status_code=422, detail=detail)
return custom_route_handler
So, I have an endpoint that works more or less like this:
from flask import Flask, request, jsonify
from flask_cors import CORS
import json
from werkzeug.utils import secure_filename
import os
from mylib import do_stuff
path = os.getcwd()
UPLOAD_FOLDER = os.path.join(path, 'data')
# #load flask
app = Flask(__name__)
CORS(app)
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['JSON_AS_ASCII'] = False
print(UPLOAD_FOLDER,flush=True)
#app.route('/upload', methods=['POST'])
def upload():
if request.method == 'POST':
file = request.files['file']
if file:
try:
# Receives a file and saves on the server
filename = secure_filename(file.filename)
file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
print("saving_here {}".format(file_path))
file.save(file_path)
# The result here is a dict of dicts of dicts
# It consists of a dictionary of DataFrames().to_dict()
result = do_stuff(file_path)
response = app.response_class(
response=json.dumps(result ),
status=200,
mimetype='application/json'
)
return response
except Exception as e:
print(e,flush=True)
return "error"
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port= <PORT>)
The main issue here is that on the front-end sometimes I receive an answer with the "message" key inside data and sometimes I receive one without it(Which is what I expect). The incorrect response:
"response": {
"data": {
"message": "{\"0\": {\"0\": {\"Item\": \"Desinfetante 5L Max Talco Azul\", \"Qtd\": 2, \"UM\": \"GL\", \"Qtd_UM\": \"5L\", \"Qtd_Ttl\": \"10L\"}, \"1\": {\"Item\": \"Caf\\u00e9 A V\\u00e1cuo Tradicional 500G\", \"Qtd\": 10, \"UM\": \"PC\", \"Qtd_UM\": \"500g\", \"Qtd_Ttl\": NaN}}}"
},
"headers": {
"content-type": [
"application/json"
],
"content-length": [
"227"
],
"access-control-allow-origin": [
"*"
],
"server": [
"Werkzeug/1.0.1 Python/3.8.6"
],
"date": [
"Fri, 11 Dec 2020 13:16:32 GMT"
]
},
"status": 200,
"statusText": "OK"
}
}
The expected response (only the data entry):
"response": {
"data": {
"0": {
"0": {
"Pedido": 997,
"Qtd": 5,
"Item": "Água Sanitária 1 Litro",
"Fornecedor": "YYYY"
},
"1": {
"Pedido": 997,
"Qtd": 2,
"Item": "Limpa Vidros Audax Facilita 500ml",
"Fornecedor": "XXXX"
}}}
When I make a post directly from python as in:
import requests
files = {'file': open('<path_to_file>','rb')}
r = requests.post(url="<url>/upload", files = files)
r.json()
Out[12]:
{'0': {'0': {'Item': 'Desinfetante 5L Max Talco Azul',
'Qtd': 2,
'UM': 'GL',
'Qtd_UM': '5L',
'Qtd_Ttl': '10L'},
'1': {'Item': 'Café A Vácuo Tradicional 500G',
'Qtd': 10,
'UM': 'PC',
'Qtd_UM': '500g',
'Qtd_Ttl': nan}}}
r.text
Out[16]: '{"0": {"0": {"Item": "Desinfetante 5L Max Talco Azul", "Qtd": 2, "UM": "GL", "Qtd_UM": "5L", "Qtd_Ttl": "10L"}, "1": {"Item": "Caf\\u00e9 A V\\u00e1cuo Tradicional 500G", "Qtd": 10, "UM": "PC", "Qtd_UM": "500g", "Qtd_Ttl": NaN}}}'
I get the expected json response every time and cannot recreate the issue I have with react, even with the same files and headers.
Things tried:
return json.dumps(result)
return jsonify(resutl)
return response
I found that your response data has \"Qtd_Ttl\": NaN (in the unexpected response you are getting) which is invalid format as a string and that is not parsable to JSON.
So if your data has a valid value for the key "Qtd_Ttl", then you will get the expected result, and if the value is invalid, you will get the response with message key.
This is the reason you are getting a weird format in your frontend.
I think you are using Axios on the frontend.
If you are using Axios, I found that this happens when the JSON response from the server is invalid, use a JSON validator like https://jsonlint.com/ to make sure that your JSON is correctly formatted.
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
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