I want to pass some values to frontend in form of context variables in IBM Watson through my Node app. How can I achieve it?
I tried to add the value I want to add to current context variable object and sent that back. Still no help. Is there any way I can do it?
Edit:
Right now, I am adding the required value as a new key-value pair to the context object from Node app as follows.
...
let user_name = "MJ"
context.user_name = user_name
response.send({
output: output,
context: JSON.stringfy(context)
})
...
And in Watson Console, in one of the dialogue nodes I have used like,
Hey $user_name, How are you?
But the output I am getting is,
Hey , How are you?
I can see user_name value in the context object, but I can't use it in the way I mentioned above. Is there any other way to do so?
Any help is appreciated. Thanks in advance!
I was having the same problem. My solution was changing the code when you call the IBM server and request .json:
...
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
text,
context: {username : variable},
...
The username I set in Watson Assistant as well as a context, the variable I used a function to get the name though Query (Because in my application, I am calling the chatbot though an IFrame.), but you can use any variable set on javascript.
You can add any value to the Context object, which can be accessed in your Node.JS app and if you send that value to the front-end, then it should be accessible in the UI as well.
Below I've mentioned a sample welcome response from Conversation service. You can access the Context object from the response of Conversation service and add a new key-value pair to that object. In the response, you'll see that I'm accessing a context variable username that has the value MJ, which has been added dynamically to the context.
`
{
"intents": [],
"entities": [],
"input": {
"text": ""
},
"output": {
"text": ["Hello MJ! How can I help you today?"],
"nodes_visited": ["Conversation Start"],
"log_messages": []
},
"context": {
"username": "MJ",
"conversation_id": "5835fa3b-6a1c-4ec5-92f9-22844684670e",
"system": {
"dialog_stack": [{
"dialog_node": "Conversation Start"
}],
"dialog_turn_counter": 1,
"dialog_request_counter": 1,
"_node_output_map": {
"Conversation Start": [0]
}
}
}
`
Now to update the context, fetch the response and add a new key-value pair
`
var convResponse = <responseObj from Conversation call>;
var context = convResponse.context;
//add new value to context
context["new_key"] = "new value";
`
Now the next call that you make to Conversation, use this updated context instead of the context you received from the previous call. You can send back the response from Conversation to the front-end as well which can then be shown to the user.
var payload = {
assistantId: assistantId,
sessionId: req.body.session_id,
context: {
skills: {
"main skill": {
user_defined: {
username: 'John Doe'
}
}
}
},
input: {
message_type: 'text',
text: "blah",
},
};
works for me. Seen here: https://medium.com/#pranavbhatia_26901/watson-assistant-v2-context-sharing-3ca18626ed0d
Related
I'm trying to figure out what i'm doing wrong here... I've been out of coding for awhile and trying to jump back in for an external application utilizing QuickBase's RESTful API. I'm simply trying to get data from QuickBase to be used outside in an external app to create charts/graphs.
I'm not able to use GET as it gives me only the field names and no data, if I use POST, then I get the values of these fields as well. I'm able to get all the data rendered in the console, but am struggling to get each field rendered to be used in the app.
let headers = {
'QB-Realm-Hostname': 'XXXXXXXXXXXXX.quickbase.com',
'User-Agent': 'FileService_Integration_V2.1',
'Authorization': 'QB-USER-TOKEN XXXXXX_XXXXX_XXXXXXXXXXXXXXXX',
'Content-Type': 'application/json'
}
let body = {"from":"bpz99ram7","select":[3,6,80,81,82,83,86,84,88,89,90,91,92,93,94,95,96,97,98,99,101,103,104,105,106,107,109,111,113,115,120,123,224,225,226,227,228,229,230,231,477,479,480,481],"sortBy":[{"fieldId":6,"order":"ASC"}],"groupBy":[{"fieldId":40,"grouping":"equal-values"}],"options":{"skip":0,"top":0,"compareWithAppLocalTime":false}}
fetch('https://api.quickbase.com/v1/records/query',
{
method: 'POST',
headers: headers,
body: JSON.stringify(body)
})
.then(res => {
if (res.ok) {
return res.json().then(res => console.log(res));
}
return res.json().then(resBody => Promise.reject({status: res.status, ...resBody}));
})
.catch(err => console.log(err))
Hoping to get some help getting the data rendered to be used in React, as well as any tips from anyone who's used QuickBase's new API calls in their realm! And I apologize if it's an easy question/issue, haven't been in React for a couple years... and I'm feeling it!
Thanks!
A successful response from Quickbase for this call has a property data which is an array of the records returned. Each element of this array is an object where the FID for each field returned is a key for nested object - or objects for some field types - with the field's value. Here's a very contrived example:
{
"data": [
{
"1": {
"value": "2020-10-24T23:22:39Z"
},
"2": {
"value": "2020-10-24T23:22:39Z"
},
"3": {
"value": 2643415
}
}
],
"fields": [
{
"id": 1,
"label": "Date Created",
"type": "timestamp"
},
{
"id": 2,
"label": "Date Modified",
"type": "timestamp"
},
{
"id": 3,
"label": "Record ID#",
"type": "recordid"
}
]
}
If you put the data array of the response directly into state with const [quickbaseData, setQuickbaseData] = useState(res.data); for example, you need to keep the structure of the response in mind when accessing that data. If I want to get the value of FID 3 from the first record in the response I would need to use quickbaseData[0]["3"].value. For most field types value will be a string or integer but for some field types it will be an object. You can see the way values are returned for each field type in Field type details.
Depending on your needs you might consider processing the Quickbase response into a new, simpler array/object to use in your application. This is especially helpful if the value being returned needs additional processing such as converting into a Date() object. This would also allow you to make your application API agnostic since other than initially processing the response from Quickbase the rest of your application doesn't have to have any knowledge of how Quickbase returns queried data.
On the Quickbase side of things, there isn't the equivalent of 'SELECT *' so to get data for all fields of a table where you don't know the schema (or it changes frequently) you can run a GET on the Fields endpoint: https://developer.quickbase.com/operation/getFields an then use the field IDs in the response to make the POST call to /records/query
The Community Connector feature is very new, and I have searched, there isn't much information. We are building a Community Connector to enable Data Studio to pull API data from Google My Business Insights.
the getconfig() function is described here: https://developers.google.com/datastudio/connector/reference#getconfig
We can display our configuration options to the user, that was easy, but the API reference is unclear what the next step is: how to pass the user input to the next step. Pardon me if I am not using the proper terms here.
var config = {
configParams: [
{
"type": "SELECT_SINGLE",
"name": "SELECT_SINGLE",
"displayName": "Select a Location",
"helpText": "Pick One!",
"options": [
{
"label": locationName,
"value": name
},
{
"label": "altLocationName",
"value": "altName"
}
]
},
]
};
return config;
}
The preceding code displays properly to the user and the user can make a selection from the pull-down in Data Studio when making an initial data connection. But to repeat the question another way: how do we access the selection that the user chose?
The getData(), getSchema(), and getConfig() functions are all called with a parameter (which is called "request" in the documentation). The parameter is an object containing various info at each stage.
At the getConfig() stage, it includes a property called languageCode, in my case set to 'en-GB'.
The getSchema() stage is provided a property called configParams, which is essentially the result of all the settings in getConfig() after the user has set them.
Finally, getData() gets the most info, including whether this request is for extracting sample data for google to run heuristics on, and most importantly: again the configParams.
Here's what a sample request object might look like:
{ //------ Present in:
languageCode: en-GB, //////-Only getConfig()
configParams: { //////-getSchema() + getData()
SELECT_SINGLE: altName ////-+
}, //
scriptParams: { //////-Only getData()
sampleExtraction: true ////-|
lastRefresh: 'new Date()' ////-+
}, //
fields: [ //////-Only getData()
{ name: FooAwesomeness }, ////-|
{ name: BarMagicality }, ////-|
{ name: BazPizzazz } ////-+
] //
dimensionsFilters: [ //////-Only getData()
[{ // |
fieldName: "string", ////-|
values: ["string", ...], ////-|
type: DimensionsFilterType, ////-|
operator: Operator ////-+
}] //
] //
} //------
Do note
that the name field in your code, currently set to SELECT_SINGLE, would be better suited to be called location because that it how you'll access it later on.
In this way you would
access:
request.configParams.location
rather than
request.configParams.SELECT_SINGLE
:)
Also note
that the format for specifying a configuration screen has been updated. Your configuration would now be able to be done as follows:
function getConfig(request) {
var cc = DataStudioApp.createCommunityConnector();
var config = cc.getConfig();
config
.newSelectSingle()
.setId('location') // You can call this "location"
.setName('Select a Location')
.setHelpText('Pick One!')
.addOption(config.newOptionBuilder()
.setLabel('Location Name')
.setValue('value'))
.addOption(config.newOptionBuilder()
.setLabel('Alternate Location Name')
.setValue('altValue'))
config.setDateRangeRequired(true);
config.setIsSteppedConfig(false);
return config.build();
}
See: Connector API Reference
See: Build a Connector Guide
The user selections will be passed to getSchema() and getData() requests under configParams object.
Using your example, let's assume the user selects altLocationName in the configuration screen. In your getSchema() and getData() functions, request.configParams.SELECT_SINGLE should return altName.
I am trying to use the VideoApp.Launch directive within my custom skill. Therefore I set the skill information global field for video app to true and added those required intents for video player.
Afterwards I'm started to test it with an example from this page
Before I added the Video directive alexa was simple returning the output content. But after adding this directory I'm getting the error: The target device does not support the specified directive. I couldn't find any documentation which addresses this issue. Is there a device setting which I missed?
Update: I tried it for the Display.RenderTemplate as well with the same outcome. Error: The target device does not support the specified directive. I set the required global fields to true for audio, render template and video.
What I checked so far is: msg.context.System.device.supportedInterfaces
"supportedInterfaces": {
"AudioPlayer": {}
}
I am using the echo. Why are here no other Interfaces available? How can I make them available?
My Code and Error Message are below.
/**
*
* main() will be invoked when you Run This Action
*
* #param Cloud Functions actions accept a single parameter, which must be a JSON object.
*
* #return The output of this action, which must be a JSON object.
*
*/
var main = function(msg) {
var response = {
version: "1.0",
response: {
outputSpeech: {
type: "PlainText",
text: "" + 'JSON.stringify(msg.request.intent)' //'.slots.questionContent.value'
},
"directives": [
{
"type": "VideoApp.Launch",
"videoItem":
{
"source": "https://www.example.com/video/sample-video-1.mp4",
"metadata": {
"title": "Title for Sample Video",
"subtitle": "Secondary Title for Sample Video"
}
}
}
],
"reprompt": null
}, "sessionAttributes": null
};
return {
statusCode: 200,
headers: { "Content-Type": "application/json" },
body: new Buffer(JSON.stringify(response)).toString("base64")
};
};
Error Message in Alexa History:
The problem is your device "Amazon Echo" does not have a display for the video. The "Amazon Echo Show" supports the following:
"supportedInterfaces": {
"Display": {},
"AudioPlayer": {},
"VideoApp": {}
}
More information here: https://developer.amazon.com/docs/custom-skills/best-practices-for-echo-show-skills.html#parse-supported-interfaces
Second, you should not have "sessionAttributes": null in the request. It is also written in the documentation.
Note: The shouldEndSession parameter must not be included in the
response, even if the value is set to null.
https://developer.amazon.com/de/docs/custom-skills/videoapp-interface-reference.html
I'm using Apollo with the Scaphold.io service and for writing blobs to that service I need to be able to add additional options to the request body.
The full Scaphold example can be found here: https://scaphold.io/docs/#uploading-files
But it does something like this:
form.append("variables", JSON.stringify({
"input": {
"name": "Mark Zuck Profile Picture",
"userId": "VXNlcjoxMA==",
"blobFieldName": "myBlobField"
}
}));
// The file's key matches the value of the field `blobFieldName` in the variables
form.append("myBlobField", fs.createReadStream('./mark-zuckerberg.jpg'));
fetch("https://us-west-2.api.scaphold.io/graphql/scaphold-graphql", {
method: 'POST',
body: form
}).then(function(res) {
return res.text();
}).then(function(body) {
console.log(body);
});
Where it adds a blobField to the request body.
Based on this, I need to pass into the variables a blobFieldName property, and then add to the request body the value passed to that property with the blob. However, using Apollo I can't add to the request body. I tried the following, but it's absent from the request body when I check in the network inspector:
export const withCreateCoverPhoto = graphql(CreateCoverPhoto, {
props: ({mutate}) => ({
createCoverPhoto: (name, file) => mutate({
variables: {
input: {
blobFieldName: name,
},
},
[name]: file
}),
}),
});
Please advise.
Thanks for the question. Currently the best way to upload files is by [appending it to FormData and sending it up to the server using fetch] (https://medium.com/#danielbuechele/file-uploads-with-graphql-and-apollo-5502bbf3941e). Basically, you won't be able to have caching here for the file itself, but this is the best way to handle uploading files on Scaphold using a multipart request.
I am currently trying to figure out how to setup my Backand app and its REST API. This question is related to question: Backand deep querying. However, I was hoping that I could get some best practice code examples on how to perform server side code to perform a loop and create a JSON responds with the following criteria:
I want to be able to make a REST request to Backand and get one data object back that has manipulated/merged two data objects from my database.
I have an object called "media" and another named "users". Obviously, users contain user information and media contains information on a picture that the user has uploaded. The two objects are related by the userId and by collection set in Backand. I want to make a GET request that responds with a JSON object with all pictures and a nested user object on each picture object that contains the related user information. I know that I get back "relatedObjects", and I could then make some manipulation on the client side, but I am hoping that there is another easier way to do this from the Backand administration system either on server side code or as a query.
So, my question is, what's the best way to produce a REST call that responds a database object with nested related data object through Backand?
Here's the object models (shorten for clarity):
User object model as set up in Backand
{
"name": "users",
"fields": {
"media": {
"collection": "media",
"via": "user"
},
"email": {
"type": "string"
},
"firstName": {
"type": "string"
},
"lastName": {
"type": "string"
}
} }
Media object model as set up in Backand
{
"name": "media",
"fields": {
"description": {
"type": "string"
},
"thumbnail": {
"type": "string"
},
"fullImage": {
"type": "string"
},
"user": {
"object": "users"
}
}}
Final JSON response that I am looking for:
{
description: 'Blah',
thumbnail: 'someImageUrl.jpg',
fullImage: 'someImageUrl.jpg',
user: {
firstName: 'John'
lastName: 'Smith'
email: 'john#smith.com'
}
}
Just in case anybody else comes across this, I chose to do it with server-side javascript code, since my backend, SQL and NoSQL query skills are very weak. I'm guessing a noSQL query would probably be better in terms of performance. And I would still like to see how it could be done in noSQL. Anyway my server-side javascript code in a Backand action does the job. Here it is:
/* globals
$http - Service for AJAX calls
CONSTS - CONSTS.apiUrl for Backands API URL
Config - Global Configuration
socket - Send realtime database communication
files - file handler, performs upload and delete of files
request - the current http request
*/
'use strict';
function backandCallback(userInput, dbRow, parameters, userProfile) {
var response = [];
var request =
$http({
method: "GET",
url: CONSTS.apiUrl + "/1/objects/media",
headers: {"Authorization": userProfile.token},
params: {
exclude: 'metadata',
deep: true
}
});
var object = request.data;
var related = request.relatedObjects.users;
for (media in object) {
if (object.hasOwnProperty(media)) {
for (user in related) {
if (object[media].user == related[user].id) {
response.push({
id: object[media].id,
thumbnailUrl: object[media].thumbnail,
description: object[media].description,
fullName: related[user].firstName + ' ' + related[user].lastName,
email: related[user].email
});
}
}
}
}
return response;
}