Chatbot refuses to display x = input() in the frontend but keeps displaying in cmd

def searchByProductDesc():
    product=input('Enter food item name\n')
    csv_file=csv.reader(open('chatbot_codes\GeneralProductPricing.csv','r'))

    for row in csv_file:
        if product==row[2]:
            c=str(print(row))
    return c

def searchByDate():
    product=input('Enter observed date of food prices\n')
    csv_file=csv.reader(open('chatbot_codes\GeneralProductPricing.csv','r'))

    for row in csv_file:
        if product==row[0]:
            c=str(print(row))
    return c

def searchByLocation():
    product=input('Enter the location of the market\n')
    csv_file=csv.reader(open('chatbot_codes\GeneralProductPricing.csv','r'))

    for row in csv_file:
        if product==row[4]:
            c=str(print(row))
    return c

def searchByMarketName():
    product=input('Enter the name of the market\n')
    csv_file=csv.reader(open('chatbot_codes\GeneralProductPricing.csv','r'))

    for row in csv_file:
        if product==row[5]:
            c=str(print(row))
    return c

def get_response(return_list,intents_json,text):

    if len(return_list)==0:
        tag='noanswer'
    else:
        tag=return_list[0]['intent']

    if tag=='prices':

        r = int(input('For food prices: \n Enter 1 to search by product name (eg. Bitterleaf) \n Enter 2 to search by observed date (eg. 03/03/2023) \n Enter 3 to search by market location (eg. Wuse, FCT Abuja) \n Enter 4 to search by market name (eg. Wuse Market) \n You may proceed... '))

        if r==1:
            x = searchByProductDesc()
            return x, 'prices'
        elif r==2:
            x = searchByDate()
            return x, 'prices'
        elif r==3:
            x = searchByLocation()
            return x, 'prices'
        elif r==4:
            x = searchByMarketName()
            return x, 'prices'
        else:
            x = 'Sorry, invalid input!'
            print(x)
            return x, 'prices'

@app.route("/get")
def chatbot():
    userText = request.args.get('msg')
    resp=response(userText)
    return resp

Where, when, and how do you think the user should be able to type, in order to provide data to the input calls? Keeping in mind that the user is not on the same computer that the code is running?

When you write @app.route("/get"), exactly what do you think this means? How will the user communicate with this part of the code?

So the backend has been connected to the frontend via flask and the Chatbot works in responding to queries all working on a development server. The issue arises when a user asks to know about prices. The x = int(input(…) runs perfectly in the cmd but doesn’t display on the frontend (web app).

Yes, I understood that. Of course it appears in the cmd window, because that’s always on the same computer as the code for the web server. It doesn’t display on the web app because there isn’t anywhere in the web app where it could display. That’s not what a web app is. If you want something to happen in the web app, your program has to communicate with the web app - for example, by sending back some JSON or HTML data which the web app has to be written to understand - for example by using JavaScript to modify the page.

Really grateful for your responses so far…I really appreciate them as this issue has been bugging me for almost 2 weeks now…
So this is the javascript to communicate between the JSON data and the web app…

index.html
msgerForm.addEventListener(“submit”, event => {
event.preventDefault();

  const msgText = msgerInput.value;
	temp=msgText.split(':')
  if((temp[0].toLowerCase()).trim()=='google')
  {search='https://www.google.com/search?q=' + temp[1].trim()
  window.open(search)}
  if (!msgText) return;
  if((temp[0].toLowerCase()).trim()=='set a timer')
  {
  play()}


  appendMessage(PERSON_NAME, PERSON_IMG, "right", msgText);
  msgerInput.value = "";
  botResponse(msgText);
});

function appendMessage(name, img, side, text) {
  //   Simple solution for small apps
  const msgHTML = `
${name}
${formatDate(new Date())}
${text}
`;
  msgerChat.insertAdjacentHTML("beforeend", msgHTML);
  msgerChat.scrollTop += 500;
}

function botResponse(rawText) {

  // Bot Response
  $.get("/get", { msg: rawText }).done(function (data) {
		console.log(rawText);
		console.log(data);
		msgText = data;
		msgText = msgText.split("\n")
		var i;
		for (i = 0; i < msgText.length; i++) {
			appendMessage(BOT_NAME, BOT_IMG, "left", msgText[i]);
		}
	});

}

routes.py

def searchByProductDesc():
product=input(‘Enter food item name\n’)
csv_file=csv.reader(open(‘chatbot_codes\GeneralProductPricing.csv’,‘r’))

for row in csv_file:
    if product==row[2]:
        c=str(print(', '.join(row)))
return c

def get_response(return_list,intents_json,text):

if len(return_list)==0:
    tag='noanswer'
else:
    tag=return_list[0]['intent']
    
if tag=='prices':
    while True:
        try:

            r = int(input('For food prices: \n Enter 1 to search by product name (eg. Bitterleaf) \n Enter 2 to search by observed date (eg. 03/03/2023) \n Enter 3 to search by market location (eg. Wuse, FCT Abuja) \n Enter 4 to search by market name (eg. Wuse Market) \n Enter here: '))

            return r,'prices'

            if r==1:
                x = searchByProductDesc()
                #print(x)
                return str(x), 'prices'
            elif r==2:
                x = searchByDate()
                #print(x)
                return x, 'prices'
            elif r==3:
                x = searchByLocation()
                #print(x)
                return x, 'prices'
            elif r==4:
                x = searchByMarketName()
                #print(x)
                return x, 'prices'

        except ValueError:
            print ("Sorry your input must be a number")
        continue          
list_of_intents= intents_json['intents']
for i in list_of_intents:
    if tag==i['tag'] :
        result= random.choice(i['responses'])
return result,tag

def response(text):
return_list=predict_class(text,model)
response,_=get_response(return_list,intents,text)
return response

@app.route(“/get”,methods=[‘GET’,‘POST’])
def chatbot():
userText = request.args.get(‘msg’)
resp=response(userText)
return resp

So the json file is working but once r = int(input('… ')) is prompted, the responses switch from the frontend to the backend…

Yes. Instead of using the input function - there is not any way that you can make it useful for solving the problem - you should arrange the code so that, the first time response is called, it just directly returns the prompt that you want to show to the user. Then, the user will chat again, in response to that prompt. The server needs to remember what that user was doing, and respond to that message appropriately. This sort of thing requires a lot of design work and planning.

If your server is going to have any kind of back-and-forth communication with users, then you must have some kind of user tracking (whether that’s a login system, tracking the user by IP, or getting the information from the client each time from additional request data, cookies etc.). This is because every user is having a separate conversation. In order for the server to know what comes next in each conversation, it must know who the conversation is with, and it must keep a record (either in global variables, a database, etc.) of the state of each conversation; or else the client needs to remind it somehow (maybe the JavaScript keeps track of the conversation locally and feeds it into the request data somehow). Every time the route handler is called it’s starting fresh, so it needs to be reminded: who are we talking to? What have we said so far? Only then can we write the logic to know what comes next.

Wow… I totally get what you are saying but what suggestions do you have on what could be the simplest way without these because it’s clear the code is working but just not linking up with the frontend?

There is no simple path for this. Making web apps is not simple.

@Qoshawa
Obviously, I’ve no idea what course or tutorial you’re using in order to learn about ‘Flask’, but you may find the Harvard University CS50x 2023 Lectures of value. David Malan does tend to go at a pace that I find a little hard to keep up with, but the video lectures can be paused and re-run, so there’s that.

See what you think: This is CS50, Harvard University’s introduction to the intellectual enterprises of computer science and the art of programming.

Most definitely… Thanks for the responses so far… Really appreciated…

I’ll look at them… Thanks for the advice!

What do you think of this answer??

The issue you’re facing is that the input function is a blocking function that waits for user input from the command line, which is not suitable for use in a web application. Instead of using the input function to get user input, you can modify your code to get user input from the frontend and pass it to the backend via an HTTP request.

Here’s an example of how you can modify your code to achieve this:

// index.html
msgerForm.addEventListener("submit", event => {
  event.preventDefault();

  const msgText = msgerInput.value;
  temp = msgText.split(':')
  if ((temp[0].toLowerCase()).trim() == 'google') {
    search = 'https://www.google.com/search?q=' + temp[1].trim()
    window.open(search)
  }
  if (!msgText) return;
  if ((temp[0].toLowerCase()).trim() == 'set a timer') {
    play()
  }

  appendMessage(PERSON_NAME, PERSON_IMG, "right", msgText);
  msgerInput.value = "";
  botResponse(msgText);
});

function appendMessage(name, img, side, text) {
  //   Simple solution for small apps
  const msgHTML = `
    ${name}
    ${formatDate(new Date())}
    ${text}
  `;
  msgerChat.insertAdjacentHTML("beforeend", msgHTML);
  msgerChat.scrollTop += 500;
}

function botResponse(rawText) {
  // Bot Response
  $.get("/get", { msg: rawText }).done(function (data) {
    console.log(rawText);
    console.log(data);
    msgText = data;
    msgText = msgText.split("\n")
    var i;
    for (i = 0; i < msgText.length; i++) {
      appendMessage(assistant, BOT_IMG, "left", msgText[i]);
    }
  });
}
# routes.py
from flask import request

def searchByProductDesc(product):
    csv_file = csv.reader(open('chatbot_codes\GeneralProductPricing.csv', 'r'))
    for row in csv_file:
        if product == row[2]:
            c = str(print(', '.join(row)))
    return c

def get_response(return_list, intents_json, text):
    if len(return_list) == 0:
        tag = 'noanswer'
    else:
        tag = return_list[0]['intent']

    if tag == 'prices':
        r = request.args.get('r')
        if r == '1':
            product = request.args.get('product')
            x = searchByProductDesc(product)
            return str(x), 'prices'
        elif r == '2':
            x = searchByDate()
            return x, 'prices'
        elif r == '3':
            x = searchByLocation()
            return x, 'prices'
        elif r == '4':
            x = searchByMarketName()
            return x, 'prices'

list_of_intents = intents_json['intents']
for i in list_of_intents:
    if tag == i['tag']:
        result = random.choice(i['responses'])
return result, tag

def response(text):
    return_list = predict_class(text, model)
    response, _ = get_response(return_list, intents, text)
    return response

@app.route("/get", methods=['GET', 'POST'])
def chatbot():
    userText = request.args.get('msg')
    resp = response(userText)
    return resp

In this example, I have modified the get_response function to get the value of r and product from the request arguments instead of using the input function. This allows you to pass these values from the frontend to the backend via an HTTP request.

On the frontend, you can use JavaScript to prompt the user for input and pass the values to the backend via an HTTP request. For example:

function botResponse(rawText) {
  // Bot Response
  var r = prompt("For food prices: \n Enter 1 to search by product name (eg. Bitterleaf) \n Enter 2 to search by observed date (eg. 03/03/2023) \n Enter 3 to search by market location (eg. Wuse, FCT Abuja) \n Enter 4 to search by market name (eg. Wuse Market) \n Enter here: ");
  
  var data = { msg: rawText, r: r };
  
  if (r === "1") {
      var product = prompt("Enter food item name");
      data.product = product;
  }
  
  $.get("/get", data).done(function (data) {
    console.log(rawText);
    console.log(data);
    msgText = data;
    msgText = msgText.split("\n")
    var i;
    for (i = 0; i < msgText.length; i++) {
      appendMessage(assistant, BOT_IMG, "left", msgText[i]);
    }
  });
}

In this example, I have modified the botResponse function to prompt the user for the value of r and product using the prompt function. These values are then passed to the backend via an HTTP request.

I hope this helps! Let me know if you have any further questions

It’s very long.

I think most advice so far has been overly complex. To my mind you’ve
got two primary issues:

  • your functions getting the response to a prompt call input() directly
  • your web URL mapping calls that function

All the stuff about annotating the web page with JavaScript or other
“modify the page directly” stuff take you down a complex path. The
F;laks framework is designed to make hooking up a web app pretty easy.

So my advice would be:

  • break out the response() function to take the prompt as input, and
    return the bot’s answer, and ONLY THAT
  • have a distinct function to call input(), call response(), print() the
    answer
  • this has a parallel to your Flask endpoint, which receives a query,
    calls response, and returns the answer - the web browser prints that
    to the user

So:

 def cli_chat1():
     prompt = input("Prompt me: ")
     answer = response(prompt)
     print(answer)

This is conceptually parallel to your flask function, which went:

 @app.route("/get")
 def chatbot():
     userText = request.args.get('msg')
     resp=response(userText)
     return resp

because userText is the prompt and resp is the answer.

Modify repsonse() to not call input or print, instead expecting to
be given the prompt and return the answer.

What you will need is a very simple web page to present an input form to
the user, because the Flask endpoint function about expects the prompt
text in a form element called msg, sothing looking like this:

 <form method="GET" action="/get">
   Enter a prompt:
   <input name="msg" type="text">
 </form>

When you view such a form in the web browser and submit it, it calls the
/get endpoint on the web server with the prompt text in the msg
parameter, and your Flask endpoint function above receives it and uses
it. What you return from that function is returned as a web page by the
server, and the browser displays it.

So this flow is conceptually just like the input(),response(),print()
function cli_chat1 above, just hooked to different mechanisms for the
input and output.

Better, you can test this without writing the form or using a browser.
When you run a Flask app it should start a web server, usually on a
default address like http://127.0.0.1:8000. It tells you IIRC, so note
down what it says.

From the command like, and assuming the address above, you can submit a
form like this using wget or curl:

 wget -S -O - http://127.0.0.1:8000/get?msg=my+prompt+goes+here

curl will be similar - the options -S and -O are wget specific.
curl looks like this:

 curl -o - http://127.0.0.1:8000/get?msg=my+prompt+goes+here

This will submit just like the form would, and Flask should call your
function, and you should then see some result. Or, of course, some error
:slight_smile:

All the stuff about JavaScript, keeping state between calls so you can
have a conversation, etc? Complex. Do it later. Get the basic mechanism
working first.

Cheers,
Cameron Simpson cs@cskk.id.au

I’ll check this out and get back to you on it… Thanks for your detailed feedback tho…its much appreciated