Chatbot Preview
Connection Process
To open the chatbot preview, the frontend will start with getting the token of accessing
Watson Assistant API, the id of the Watson Assistant instance, and a new Watson Assistant
workspace. When creating the new workspace, the existing ones will be deleted to avoid
exceeding the workspace number limit. The connection process is handled by the
handlePreview
function in the DialogSearch
component.
const handlePreview = async () => {
try {
…
if(token === ""){
token = (await getBearerToken(wtsnAssistant.iamKey))["access_token"]
assert(token !== undefined, "failed to get token")
setWtsnAssistant({…})
}
const workspaces = await getWorkspaceList(token, wtsnAssistant.instanceId)
const workspaceIds = workspaces["workspaces"].map(ws => ws["workspace_id"])
console.log(workspaceIds)
for(let i = 0; i < workspaceIds.length; i++){
await delWorkspaceById(token, wtsnAssistant.instanceId, workspaceIds[i])
}
const newWS = await newWorkspace(token, wtsnAssistant.instanceId, dialogJson)
const newWSID = newWS["workspace_id"]
console.log(newWSID)
setWtsnAssistant({…})
…
} catch (e) {
…
}
}
The functions for connecting Watson Assistant API are imported from the
watsonAssistantConnection.js
in the CustomizedChatbot
folder. Each of the functions will
call an Azure Function. For example the following is the sendMsgToWatsonAssistant
function
and corresponding Azure Function sendMsgToWtsnAssistant
.
sendMsgToWatsonAssistant
export const sendMsgToWatsonAssistant = async (instanceId, workspaceId, token, message) => {
const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: `{"token":"${token}","msg":"${message}","instanceId":"${instanceId}","workspaceId":"${workspaceId}"}`
};
return await fetch(bingApiConnections.sendMsgToWatsonAssistant, options)
.then(response => response.json())
.catch(err => console.error(err));
}
Azure Function sendMsgToWtsnAssistant
module.exports = async function (context, req) {
const token = req.body.token
const msg = req.body.msg
const instanceId = req.body.instanceId
const workspaceId = req.body.workspaceId
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`
},
body: `{"input":{"text":"${msg}","spelling_suggestions":true,"spelling_auto_correct":true}}`
};
const baseUrl = "https://api.us-south.assistant.watson.cloud.ibm.com"
const version = "2021-11-27"
const res = await fetch(`${baseUrl}/instances/${instanceId}/v1/workspaces/${workspaceId}/message?version=${version}`, options)
.then(response => response.json())
context.res = {
headers: {
'Content-Type': 'application/json'
},
body: {
"text": res["output"]["generic"][0]["text"] || "invaild"
}
};
}
Preview Chatbot (using React Chatbot
Kit)
We use the Node.js library React Chatbot Kit to build the chatbot integrated
into the NHS
Chatbot Generation website for preview. All the preview-chatbot-related files are stored in
the CustomizedChatbot
folder, and CustomizedBotPreview
is the
React component for the preview chatbot.
To start chatting with the preview bot, the handleStartChatSession
function will be
executed first. It starts a session with Watson Assistant using the first workspace.
const handleStartChatSession = async () => {
let accessToken
try {
setIsConnecting(true)
accessToken = (await getBearerToken(wtsnAssistant.iamKey))["access_token"]
assert(accessToken !== undefined && accessToken !== "", "failed to get token")
} catch (e) {
console.error("failed to get a token - " + accessToken)
setIsConnecting(false)
}
let wsId
try {
// connect to the first workspace
wsId = (await getWorkspaceList(accessToken, wtsnAssistant.instanceId))["workspaces"][0]["workspace_id"]
console.log("workspace id:\n" + wsId)
setShowBot(true)
console.log("Watson Assistant session established")
} catch (e) {
console.error("failed to get the workspace id - " + wsId)
} finally {
setIsConnecting(false)
}
…
}
Then the MessageParser
function will start listing the
message input from user, and it
will call different actions according to the message parse result. Here, as long as the
message is not empty, it will call the handleMessage
function from the ActionProvider
.
const MessageParser = ({ children, actions }) => {
const parse = (message) => {
if(message !== ""){
actions.handleMessage(message).catch(err => console.error((err)))
}
};
…
};
The handleMessage
function will send the message from
the user to Watson Assistant and creates an answer message element from Watson Assistant's
response.
const ActionProvider = ({ setState, children }) => {
const handleMessage = async (userMsg) => {
const resp = await sendMsgToWatsonAssistant(wtsnAssistant.instanceId, wtsnAssistant.workspaceId, wtsnAssistant.token, userMsg)
console.log(resp)
const botMessage = createCustomMessage("custom", 'htmlMsg', {
payload: {
message: resp !== undefined ? resp["text"] : "ERROR"
}
})
setState((prev) => ({
...prev,
messages: [...prev.messages, botMessage],
}));
};
…
};