Tutorial
Embed charts or tables into watsonx Assistant
Enhance your user's chatbot experience by adding charts or tablesToday, many organizations are focusing on providing better experiences for their customers through online services. And, they're using artificial intelligence (AI) to do it by using AI to automate some of the manual tasks. One of these automations is chatbots. IBM watsonx Assistant is a Software as a Service (SaaS) virtual assistant platform that is powered by IBM Watson Natural Language Processing (NLP). Watsonx Assistant allows businesses to build and deploy chatbots and virtual assistants. With watsonx Assistant, you can design and train your virtual assistant to handle common customer inquiries, provide information, and help automate customer service and employee self-service tasks.
Sometimes, to create a better experience, you need to enhance your chatbot with charts or tables. Although this function is not directly provided by watsonx Assistant, there is a way to add the charts or tables. In this tutorial, follow the steps to learn how to add these enhancements.
Prerequisites
To follow this tutorial, you need:
- A watsonx Assistant instance.
- A web application (using HTML or JavaScript)
- A web server (using Node.js)
Estimated time
It should take you approximately 1.5 hours to complete this tutorial.
Steps
Step 1. Register a custom response listener in the web app
First, you must register a listener that is triggered when a particular event is sent from the assistant. In this example, this event is triggered whenever the user asks a question.
Take a look at the following code for the JavaScript file of a webpage.
var g_wa_instance;
window.watsonAssistantChatOptions = {
integrationID: "" // your assistant integrationId,
region: "" // your assistant region,
serviceInstanceID: "" // your assistant serviceInstanceID,
showRestartButton: true,
onLoad: function (instance) {
g_wa_instance = instance;
instance.on({
type: "customResponse",
handler: (event, instance) => {
if (
event.data.message.user_defined &&
event.data.message.user_defined.user_defined_type === "embed-multimedia"
) {
embedChartOrTableHandler(event);
}
},
});
instance.render();
};
Step 2. Implement a handler to call an API
Implement a handler that calls a /getAnswer API to fetch the chart or table in the form of HTML. The response is embedded in the assistant window.
async function embedChartOrTableHandler(e) {
const { element, message } = e.data;
const query = message.user_defined.user_query;
const SERVER = ""; // backend server URL
fetch(SERVER + "/getAnswer", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ question: query }),
}).then(
async (res) => {
const response = await res.json();
if (response.data) {
const { data } = response;
element.innerHTML = data;
messageChatbot("step successful", true);
return;
}
messageChatbot("Some error occured.", true);
},
(err) => {
messageChatbot("Unable to get answer based on your query.", true);
}
);
}
Step 3. Endpoint implementation to generate a chart or table
Create a /getAnswer POST endpoint, and add your custom logic. To prepare a chart, get the data in the form of an array of labels and values. To prepare a table, get the data in the form of an array of headers and rows (array of arrays).
To generate a chart or table, the following code shows the individual functions in a Node.js server endpoint.
// endpoint to return chart or table
app.post("/getAnswer", async (req, res) => {
try {
// used as a return values
let type = "";
let data = "";
if (<send-chart-as-output>) {
const labels = ["a", "b"]; // lables to show in chart
const values = [15, 34]; // values on which chart will be prepared
const chartString = await generateChart(labels, values);
const imgTag = `<img class="WACImage__Image WACImage__Image--loaded" src="${chartString}" alt="" style="display: block;"/>`;
type = "img";
data = imgTag;
}
else if (<send-table-as-output>) {
const headers = ["h1", "h2"]; // table headers
const rows = [["hello", "world"], ["hi", "there"]]; // rows to show in the table
const table = generateTable(headers, rows);
type = "table";
data = table;
}
else {
type = "text";
data = "<text-output>"
}
res.json({
type: type !== "" ? type : "text",
data: data !== "" ? data : "No results found",
});
return;
} catch (err) {
res.send({
type: "text",
data: "Unable to get answer, please retry with another query."
});
}
});
Function to generate a chart
The generateChart function takes labels and values and returns a data string of the chart.
// We will use npm package "chartjs-node-canvas" to generate charts.
const { ChartJSNodeCanvas } = require("chartjs-node-canvas");
async function generateChart(labels, values) {
// setting properties for chart
const width = 450;
const height = 300;
const chartJSNodeCanvas = new ChartJSNodeCanvas({
width,
height,
});
const cfg = {
type: "line", // chart type like bar, line, etc.
data: {
datasets: [
{
data: values,
},
],
labels: labels,
},
};
return await chartJSNodeCanvas.renderToDataURL(cfg);
}
Function to generate a table
The generateTable function takes headers and rows and returns an HTML string of the table.
function generateTable(headers, rows) {
let table = "<table><tr>";
headers.map((header) => {
table += `<td style='border: 1px solid black; padding: 5px'><strong>${header}</strong></td>`;
});
table += "</tr>";
rows.map((row) => {
table += "<tr>";
row.map((item) => {
table += `<td style='border: 1px solid black; padding: 5px'>${item}</td>`;
});
table += "</tr>";
});
table += "</table>";
return table;
}
Step 4. Create a step inside an action in watsonx Assistant
Create an action in watsonx Assistant with a step to trigger a custom event named
embed-multimedia. This event is listened to in Step 1.Go to your watsonx Assistant action step, switch to a JSON editor, enter the following JSON code, and save the changes.
{ "generic": [ { "values": [ { "text_expression": { "concat": [ { "scalar": "Getting answer..." } ] } } ], "response_type": "text", "selection_policy": "sequential" }, { "user_defined": { "user_query": "<? input.text ?>", "user_defined_type": "embed-multimedia" }, "response_type": "user_defined", "repeat_on_reprompt": false } ] }Set the customer response type to Free text to enable a conditional flow based on the response.
Run the application, and see the results in your watsonx Assistant webchat window.
Conclusion
In this tutorial, you explored an example use case demo to embed charts or tables in watsonx Assistant that was built using this feature on the dsce.ibm.com platform. For more complex use cases about watsonx Assistant, see the watsonx Assistant demo site.
You can also try out watsonx Assistant to see how it can speed communications with customers and boost productivity.