RasaHQ / rasa

💬 Open source machine learning framework to automate text- and voice-based conversations: NLU, dialogue management, connect to Slack, Facebook, and more - Create chatbots and voice assistants
https://rasa.com/docs/rasa/
Apache License 2.0
18.71k stars 4.61k forks source link

Getting empty array in response when calling from web application #3381

Closed sushilr007 closed 5 years ago

sushilr007 commented 5 years ago
**Rasa version**:0.13.7 **Python version**: 3.6.5 **Operating system** (windows 10): **Issue**: I am trying to call database from the web application but I am getting an empty array. but when I am trying to call from terminal I am getting proper response. **Content of configuration file (config.yml)**: ```yml language: "en" pipeline: spacy_sklearn ``` **Content of domain file (domain.yml)** (if used & relevant): ```yaml intents: - greet - goodbye - thanks - deny - joke - name - PF_UAN_Number entities: - name slots: name: type: text actions: - utter_name - utter_thanks - utter_greet - utter_goodbye - action_db templates: utter_name: - text: "Hey there! Tell me your name." utter_greet: - text: "Nice to you meet you {name}. How can I help?" utter_goodbye: - text: "Talk to you later!" utter_thanks: - text: "My pleasure." ``` **action.py** ```# -*- coding: utf-8 -*- from __future__ import absolute_import from __future__ import division from __future__ import print_function from __future__ import unicode_literals import logging import requests import json import pymysql from rasa_core_sdk import Action logger = logging.getLogger(__name__) class ActionDb(Action): def name(self): # define the name of the action which can then be included in training stories return "action_db" def run(self, dispatcher, tracker, domain): # what your action should do db = pymysql.connect("abc.com","test","12345","DB1") cursor = db.cursor() str1=tracker.latest_message['intent'].get('name') query = "SELECT COL_2 FROM DB1.TABLE_2 WHERE COL_1 = '" + str1 + "'" cursor.execute(query) data = cursor.fetchone() joke = data[0] dispatcher.utter_message(joke) return [] ``` **endpoint.yml** ```action_endpoint: url: "http://localhost:5055/webhook" ``` **server.py** ```import logging from rasa_core.agent import Agent from rasa_core.interpreter import RasaNLUInterpreter from rasa_core.channels.channel import CollectingOutputChannel from rasa_core.channels.channel import UserMessage from rasa_core.channels.channel import InputChannel from flask import json from klein import Klein logger = logging.getLogger(__name__) def request_parameters(request): if request.method.decode('utf-8', 'strict') == 'GET': return { key.decode('utf-8', 'strict'): value[0].decode('utf-8', 'strict') for key, value in request.args.items()} else: content = request.content.read() try: return json.loads(content.decode('utf-8', 'strict')) except ValueError as e: logger.error("Failed to decode json during respond request. " "Error: {}. Request content: " "'{}'".format(e, content)) raise class Server: app = Klein() def __init__(self, model_directory, interpreter): self.model_directory = model_directory self.interpreter = interpreter self.agent = self._create_agent(model_directory, interpreter) @staticmethod def _create_agent(model_directory, interpreter): """Creates a Rasa Agent which runs when the server is started""" try: return Agent.load(model_directory, interpreter) except Exception as e: logger.warn("Failed to load any agent model. Running " "Rasa Core server with out loaded model now. {}" "".format(e)) return None @app.route("/status", methods=['GET']) def status(self, request): """Check if the server is running and responds with the status.""" request.setHeader('Access-Control-Allow-Origin', '*') return json.dumps({'status': 'OK'}) @app.route('/conversations/default/respond', methods=['GET', 'POST']) def parse(self, request): request.setHeader('Content-Type', 'application/json') request.setHeader('Access-Control-Allow-Origin', '*') request_params = request_parameters(request) if 'query' in request_params: message = request_params.pop('query') elif 'q' in request_params: message = request_params.pop('q') else: request.setResponseCode(400) return json.dumps({"error": "Invalid parse parameter specified"}) try: response = self.agent.handle_message(message) request.setResponseCode(200) return json.dumps(response) except Exception as e: request.setResponseCode(500) logger.error("Caught an exception during " "parse: {}".format(e), exc_info=1) return json.dumps({"error": "{}".format(e)}) @app.route('/conversations/default/respond', methods=['GET', 'POST']) def respond(self, request): request.setHeader('Content-Type', 'application/json') request.setHeader('Access-Control-Allow-Origin', '*') request_params = request_parameters(request) if 'query' in request_params: message = request_params.pop('query') elif 'q' in request_params: message = request_params.pop('q') else: request.setResponseCode(400) return json.dumps({"error": "Invalid parse parameter specified"}) try: out = CollectingOutputChannel() response = self.agent.handle_message(message, output_channel=out) request.setResponseCode(200) return json.dumps(response) except Exception as e: request.setResponseCode(500) logger.error("Caught an exception during " "parse: {}".format(e), exc_info=1) return json.dumps({"error": "{}".format(e)}) if __name__ == "__main__": server = Server("models/current/dialogue/", RasaNLUInterpreter("models/current/nlu")) print("SERVER",server) server.app.run("0.0.0.0", 5005) ``` **script.js** : required for HTML ```let status = document.getElementById('status'); let chatbox = document.getElementById('main-box'); let id = Math.floor(Math.random() * 1000 + 1); let ul = document.getElementById('conversation'); let chat = document.getElementById("chat-container"); let input = document.getElementById("chat-input"); let fab = document.getElementById('fab'); let fab_close = document.getElementById('fab-close'); const url = 'http://localhost:5005'; input.addEventListener("keyup", function (event) { event.preventDefault(); if (event.keyCode === 13) { document.getElementById("btn").click(); } }); window.onload = function () { fetch(`${url}/status`, { method: 'GET' }) .then(function (response) { status.innerHTML = " Online"; }) .catch(function (response) { status.innerHTML = " Offline"; }) } function openchat() { chatbox.style.display = "block" fab.style.display = "none"; fab_close.style.display = "block"; } function closechat() { chatbox.style.display = "none"; fab_close.style.display = "none"; fab.style.display = "block"; } function start(msg) { createSender(msg); document.getElementById('typing').style.display = "inline"; respond(msg); } function speak(msg) { var speech = new SpeechSynthesisUtterance(msg); speech.voice = speechSynthesis.getVoices()[5]; window.speechSynthesis.speak(speech); } function createSender(msg) { let li = document.createElement('li'); li.appendChild(document.createTextNode(msg)); li.className = "sender" ul.appendChild(li); document.getElementById('chat-input').value = ""; chat.scrollTop = chat.scrollHeight; } function createResponder(msg) { let li = document.createElement('li'); li.innerHTML = msg; if (voice() == true) speak(li.innerText); li.className = 'responder'; ul.appendChild(li) chat.scrollTop = chat.scrollHeight; } function send() { let message = document.getElementById('chat-input').value; if (message != '') { createSender(message); document.getElementById('typing').style.display = "inline"; respond(message); } } function respond(msg) { data = { query: msg } fetch(`${url}/conversations/default/respond`, { method: 'POST', body: JSON.stringify(data) }) .then(function (response) { document.getElementById('typing').style.display = "none"; console.log(response); return response.json(); }) .then(function (responses) { console.log(responses); if (responses) { for (let response of responses) { createResponder(response.text); } } else { createResponder("Sorry, I'm having trouble understanding you, try asking me in an other way") } }) .catch(function (err) { document.getElementById('typing').style.display = "none"; createResponder("I'm having some technical issues. Try again later :)"); }); } function voice() { let speaker = document.getElementById('voice').checked; if (speaker == true) return true; else return false; } function listen() { let mic = document.getElementById('mic'); mic.style.color = 'red'; mic.className = 'animated pulse infinite'; let hear = new webkitSpeechRecognition(); hear.continuous = false; hear.lang = 'en-IN'; hear.start(); hear.onresult = function (e) { mic.style.color = 'black'; mic.className = ''; userVoiceText = e.results[0][0].transcript; hear.stop(); createSender(userVoiceText); respond(userVoiceText); } } ```
akelad commented 5 years ago

Thanks for raising this issue, @paulaWesselmann will get back to you about it soon.

sushilr007 commented 5 years ago

Hello, @akelad If anything went wrong I am waiting for a response from @paulaWesselmann. Thank you.

paulaWesselmann commented 5 years ago

Hey @sushilr007, Sorry I couldn't get to this quicker. I can't seem to get what's going on from the first look and going through the files you posted. Can you describe what exactly you are trying to do and where it fails? Are those your custom endpoints? Did you try using one of the rasa channels?

sushilr007 commented 5 years ago

@paulaWesselmann I have trained a few questions that will give me the output from the database. I am calling API localhost:5005/conversations/default/respond from postman. from this, I am getting a response - [ ]. Example Question - Can I know my PF & UAN Number? Bot (Answers) - your PF number is 123 (This what I am expecting)

Yes in endpoints.yml contains my custom endpoint. I hadn't tried to use rasa channels.

paulaWesselmann commented 5 years ago

Hey @sushilr007, thank you for getting back to me!

I recommend to use one of the rasa channels to connect your bot to a web application, to make your live a bit simpler. For this you can have a look in the docs and an example of a web application similar to yours, which uses their own endpoints similar to yours.

I don't believe this will return the bot response:

out = CollectingOutputChannel()
response = self.agent.handle_message(message, output_channel=out)

The channel you choose collects messages, but doesn't send them anywhere.

I hope this helps! I'll close this issue for now, as I don't see an issue with the rasa code. Please comment any updates and let us know if there is something we have to have a further look at. Happy bot building!

abd-Mohsen commented 1 month ago

hey, did you solve the problem by any chance? i am facing the same thing.. android emulator, Postman and web browser are fine but my phone is recieving empty array from Django server the problimatic client is flutter app on my phone (the app is fine on emulator)