API Integration

I have created the static script that is expected output for our customer. In attached script, I need to do following:

  1. When I get the input from the user for following section, I need to make the API call, so where should I call make-request function?

  1. When I get the response from make-request call in the above section, I have to show user another section as below based on the list of wines I got in the response.

In below attachment, I have used Wine 1 and Wine 2 as static text but it should be the output of the above make-request call.

Please help as soon as possible

Thanks,
Nick

Hi Nick,

Thank you for posting your question here.

Currently we do support making requests and generating single-choice questions on the fly. However, it is only achievable through editing our chat script at this moment. The screenshots you posted are from our config-doc. From the config-doc, we generates script, this is where we are going to make changes. (You can find some brief introduction of different files in IDE here: https://docs.juji.io/juji-ide/#code-editor) In general, we want to edit the latest web-* or facebook-* script depends on which channel you are using. And it is a good practice to save and download the script (or download the script and edit locally then do upload) so you will always have a copy, in case the script get overwritten. Editing the script file is a little bit involved, because our script are very powerful and flexible. Some coding experience may be handy.

Base on what I understand, what you want to accomplish takes two steps, 1) getting the data from API call and 2) generate a question dynamically.

Getting the data

You probably see something like this for your T1 topic in the script

(deftopic
handle-ask-how-are-you-doing_1
[?q]
{:default-rules
({:include-after
[(juji.topics.interviewing.v4/handle-how-are-you-doing-default
?q)]}
[]
["Thanks. We are looking into our system… "
(<-| topic_1_triggered-by “trigger-1”)
(record-answer ?q (input-text))]),
:include-after
[(juji.topics.interviewing.v4/handle-how-are-you-doing-main ?q)
(juji.topics.interviewing.v4/handle-interview-fallback ?q)],
:include-before [],
:pre-action [],
:post-action []})

Now you want to update the default-rules, more specifically replace the following part

[]
["Thanks. We are looking into our system… "
(<-| topic_1_triggered-by “trigger-1”)
(record-answer ?q (input-text))]

with another rule that captures user input, make a request and stores what you need in a variable. (Please refer to this page: https://docs.juji.io/concept/, for more details about topic and rules) The rule maybe something like the following

[+]
["Thanks. We are looking into our system… "
(record-answer ?q (input-text))
(<-| request-results (make-request “your-api-address” {:query-1 (input-text))]

You can refer to https://docs.juji.io/function/ for different functions used here (<-| is also a function). And now, the data is stored in the variable request-results

Generate a dynamic single choice question

We do this by using make-single-choice-question and the data we have from the API call. You probably have some topic similar to the one below in your script.

(deftopic
collect-basic-info-from-gui_4
[?q]
{:pre-condition [(and (= (>- topic_1_triggered-by) “trigger-1”))],
:pre-action [],
:post-action []}
[]
[(ask-question-gui ?q)]
(juji.topics.interviewing.v4/handle-gui-completion ?q))

What you need to change is to clear out the :pre-condition and update the rule. After the change, it would be something like this:

(deftopic
collect-basic-info-from-gui_4
[]
{:pre-condition [],
:pre-action [],
:post-action []}
[]
[(ask-question-gui (-<- dynamic-choice (make-single-choice-question “Is it one of the wine you are looking for ?” (format-my-data (>- request-results)))))]
(juji.topics.interviewing.v4/handle-gui-completion (>- dynamic-choice)))

Since what you get from the api call may not be the right format for the single-choice-question, you may need to format your data a bit. Here I created one of my own clojure function (refer to https://docs.juji.io/udf/#clojure-udf for more detail about user defined functions) format-my-data for the job.

(defn map-indexed-fn
[ind datom]
[datom ind])

(defn format-my-data
[request-data]
(vec (map-indexed map-indexed-fn (vals (get-in (json/parse-string request-data) [“data” 0])))))

If your data is in json and you would like to use json/parse-string, please make sure you include the namespace for the json package the the beginning of the script (e.g., abcd-1234567.eng00.lal.preview).

You can download an example script with fake data: http://s000.tinyupload.com/index.php?file_id=00334504524239285737
You can upload this script and try the behavior buy using the Preview function in the IDE.

Hopefully this is helpful.

Best,
Wenxi

@nickmodi

I noticed a couple of problems in your chatbot.
(1) The printout you show is from the config file not the chatbot script which you should use to do deeper customization

(2) The topic you used for asking for wine name is an incorrect one. It says “ask-how-are-you-doing” and I don’t think that’s what you want. You need to find the correct topic, something like “ask-for-entity-name”. Check this to find the correct Juji built-in topic:
https://docs.juji.io/design/#customizing-chatbot-actions

(3) Once you have the right topic, you can use the GUI to customize your chatbot actions, e.g., adding a make-request to make an API call by passing the wine name to the API to retrieve the wines. Once the wines retried, you can then write your HTML code to display them in a way you wish.

I go through your script but I am getting error while compiling the script Like Non-nullable field was null.

Also I am getting below error if I am saving the data without compiling the script

I got it the solution and I am looking in to it. Thanks for the help.

One more suggestion from you .
After replying the response data, how can I handle into the bot?

One last question, how should I send the selection of the wine from single selection to my API via server? where should I put make-request function and in which variable, I will get the result?

I have a couple of questions . Please help me out.

  1. Where can I find the perfect topics inside the doc?
  2. How can I write my own custom HTML code to customise chat UI?

Ok, so recall you have something like the following for asking the single-choice question

(deftopic
collect-basic-info-from-gui_4
[]
{:pre-condition [],
:pre-action [],
:post-action []}
[]
[(ask-question-gui (-<- dynamic-choice (make-single-choice-question “Is it one of the wine you are looking for ?” (format-my-data (>- request-results)))))]
(juji.topics.interviewing.v4/handle-gui-completion (>- dynamic-choice)))

So say you want to response right away with some other information retrieved from your API after the user selected their wine in the single choice question. In order to do that, you will need to customize your handling topic for the single choice input (i.e., juji.topics.interviewing.v4/handle-gui-completion; handling topic is a followup topic after asking the questions, you can refer to https://docs.juji.io/concept/#followup-topic for more details). So for example you can create your own handling topic something like the following

(deftopic
handle-collect-basic-info-from-gui_4
[?q]
{:default-rules
({:include-after
[(juji.topics.interviewing.v4/handle-gui-completion-default
?q)]}),
:include-after
[(juji.topics.interviewing.v4/handle-gui-completion-main ?q)
(juji.topics.interviewing.v4/handle-gui-fallback ?q)],
:include-before [],
:pre-action [],
:post-action []}
[(-<- choice (user-move-received?))]
[(<- answer-text (get-in (>- choice) [:move 0 :text]))
(make-request “my-api” {:wine-selected (>- answer-text)})])

Here, user-move-received? retrieves user’s selection data, and we use the get-in clojure function to retrieve the text from the data and stores it in an variable. Then you make a request with the data. Similar to previous example, you can add your functions to manipulate the data before or after sending the request.
In order to use this handling topic, you need to substitute the name collect-basic-info-from-gui_4 into the main topic like the following

(deftopic
collect-basic-info-from-gui_4
[]
{:pre-condition [],
:pre-action [],
:post-action []}
[]
[(ask-question-gui (-<- dynamic-choice (make-single-choice-question “Is it one of the wine you are looking for ?” (format-my-data (>- request-results)))))]
(handle-collect-basic-info-from-gui_4 (>- dynamic-choice)))


  1. https://docs.juji.io/topics/ lists our built-in topics that either handles user input or asks questions.
  2. HTML only works if you intend to deploy to website (https://docs.juji.io/release/#deploy-to-website). If you edit on the design page, you can just insert your html code in your customized replies, question or messages in the GUI. If you are editing the script directly, you can put the html code in your rule trigger as a string. For example,

[some match pattern]
["<ol> <li>first point</li> <li>second point</li> <li>third point</li> </ol>"]

Is there any way to show to audio player and play audio as answer?

First thanks for the help to get answer value and api call. appreciate it.
Here i have one more issue which one i am facing right now.
When I provide any wine name to get first api response with space than it returns me a very weird array.

Code to get input text

(deftopic
handle-ask-how-are-you-doing_1
[?q]
{:default-rules
({:include-after
[(juji.topics.interviewing.v4/handle-user-response-default
?q)]}
[(?x [+])]
["Thanks. We are looking into our system… "
(record-answer ?q (input-text))
(<-| request-results (make-request “http://7fcc6559.ngrok.io/Api/get-wine.php” {:name ?x}))]),
:include-after
[(juji.topics.interviewing.v4/handle-user-response-main ?q)
(juji.topics.interviewing.v4/handle-interview-fallback ?q)],
:include-before [],
:pre-action [],
:post-action []})

OutPut

Right now, you will have to provide your own text-to-speech and speech recognition solution, but we do plan to add these in the future, particularly if the demand is high.

The input is tokenized into an array of tokens. So yes, you will need to join them back into text if you want to display them, (apply str ["abc" "efg"]) will get you “abcefg”. There’s also a (answer-text <question-name>) system function to get you the user’s answer text.

Hi Nick, for free text question, you can use (input-text) to get the entire input the user put in. So you can do something like the following instead:

[+]
["Thanks. We are looking into our system… "
(record-answer ?q (input-text))
(<-| request-results (make-request “http://7fcc6559.ngrok.io/Api/get-wine.php” {:name (input-text)}))]

You will not need the ?x anymore to capture if you just want the entire input. ?x is a capture pattern, you can use it to capture selected part of the user input (refer to: https://docs.juji.io/reference/#captured-content). Just adding to @hyang’s response, if you want to join the captured words in the capture with a space, you can do something like the following:

[I like to (?x [+])]
[“You like to” (clojure.string/join " " ?x)]
;; input: “I like to play basketball”
;; responese: “You like to play basketball”

["Thanks. We are looking into our system… "
(record-answer ?q (input-text))
(<-| request-results (make-request “http://8ce2867b.ngrok.io/Api/get-wine.php” {:name (input-text)}))]),

-- This is not working.

(answer-text )

-- Where can I get question-name?

I just need the audio file player. I will have audio file hosted on our server and I just need a way in chatbot so that when user press the play button it should play the file.

Audio tag of HTML is supported by most modern broswers, e.g.

<audio controls> <source src="https://www.computerhope.com/jargon/m/example.mp3" /></audio>

Hi Nick, sorry for the confusion. You are right, that’s not working. I forget we don’t support evaluation inside a clojure map. So instead of {:name (input-text)} you will need to do (into {} [[:name (input-text)]]), so it would be the following:

[+]
["Thanks. We are looking into our system… "
(record-answer ?q (input-text))
(<-| request-results (make-request “http://7fcc6559.ngrok.io/Api/get-wine.php” (into {} [[:name (input-text)]])))]

And if you want to add more parameters into the map, you may do (into {} [[:parm1 "val1"] [:parm2 "val2"]])

It worked! :slight_smile: Thank you.