I'm trying to process an utterance in the format "Get News from Impeachment Sage" where Impeachment Sage corresponds to an enum of publication names. Bixby is successfully understanding the utterance and trying to call my goal (GetNewsByName) but the trained Value is not arriving at the function. (This is based off the user persistence data example).
The operative portion of the function is thus:
function getNewsByName(altBrainsNames) {
// const name = "Impeachment Sage" //hard coded for testing
const url = properties.get("config", "baseUrl") + "altbrains"
console.log("i got to restdb.js and the url is ", url);
console.log("AltBrainsNames is", altBrainsNames)
const query = {
apikey: properties.get("secret", "apiKey"),
q: "{\"" + "name" + "\":\"" + name + "\"}"
// q: "{}"
}
console.log("query", query)
const options = {
format: "json",
query: query,
cacheTime: 0
}
const response = http.getUrl(url, options)
if (response) {
const content1 = response
// const altBrainsData = response[0][properties.get("config", "altbrainsName")]
// altbrainsData.$id = response[0]["_id"]
console.log('content1', content1);
console.log('identifier', content1)
return content1
} else {
// Doesn't exist
console.log('doesnae exist');
return
}
}
What is happening here where the Value is not reaching the function?
The Action model is:
action (GetNewsByName) {
description ("Get news data from remote Content db by searching on AltBrain name")
type (Calculation)
output (Content)
collect {
input (altBrainsNames) {
type (AltBrainsNames)
min (Required) max (One) //this means js must catch error when multiple names offered
}
}
}
We resolved this offline, just wanted to follow up on the public channel to any fellow Bixby developers seeing this question posted. The function that calls 'getNewsByName' needs to receive the input parameter. Once populated, the action worked successfully.
Related
Is there a way to query the results to show only data that has been published and is not in draft state? I looked in the documentation and didn't quite find it.
This is what I currently have:
export const getAllPages = async (context?) => {
const client = createClient({
space: process.env.CONTENTFUL_SPACE_ID,
accessToken: process.env.CONTENTFUL_ACCESS_TOKEN,
});
const pages = await client.getEntries({
content_type: "page",
include: 10,
"fields.slug[in]": `/${context.join().replace(",", "/")}`,
});
return pages?.items?.map((item) => {
const fields = item.fields;
return {
title: fields["title"],
};
});
};
You can detect that the entries you get are in Published state:
function isPublished(entity) {
return !!entity.sys.publishedVersion &&
entity.sys.version == entity.sys.publishedVersion + 1
}
In your case, I would look for both Published and Changed:
function isPublishedChanged(entity) {
return !!entity.sys.publishedVersion &&
entity.sys.version >= entity.sys.publishedVersion + 1
}
Check the documentation:
https://www.contentful.com/developers/docs/tutorials/general/determine-entry-asset-state/
To get only the published data you will need to use the Content Delivery API token. If you use the Content Preview API Token, you will receive both the published and draft entries.
You can read more about it here: https://www.contentful.com/developers/docs/references/content-delivery-api/
If using the Content Delivery API you need to filter on the sys.revision attribute for each item. A published item should have its revision attribute set to greater than 0.
const publishedItems = data.items.filter(item => item.sys.revision > 0)
I'm using Bot Framework SDK with nodejs to implement a disamibuation flow.
I want that if two intents predicted by Luis are close to each other, ask the user from which of them are the one they want. I have done the validator but, I have a problem with the flow.
It is a waterfall Dialog with 3 steps:
FirstStep: Calls Orchestrator and Luis to get intents and entities. It pass the data with return await step.next({...})
Disamiguation Step: Checks if it is necessary to disambiguate, and, in that case, prompts the options. If not, it pass the data like the first step.
Answer step: If it has a disambiguation flag in the data it receives in step.result, it prompts the answer acordingly with the user response. Elsewhere, it uses the data in step.result that comes from the first step.
The problem is that, when it prompts user to say the intent, I lost the data of the FirstStep since I cannot use step.next({...})
¿How can I maintain both the data from the first step and the user answer in the prompt?
Here are the basic code:
async firstStep(step) {
logger.info(`FinalAnswer Dialog: firstStep`);
let model_dispatch = await this.bot.get_intent_dispatch(step.context);
let result = await this.bot.dispatchToTopIntentAsync(step.context, model_dispatch.model)
// model_dispatch = orchestrator_model
// result = {topIntent: String, entities: Array, disamibiguation: Array}
return await step.next({ model_dispatch: model_dispatch, result: result})
}
async disambiguationStep(step) {
logger.info(`FinalAnswer Dialog: disambiguationStep`);
if (step.result.result.disambiguation) {
logger.info("We need to disambiguate")
let disambiguation_options = step.result.result.disambiguation
const message_text = "What do you need";
const data = [
{
"title": "TEXT",
"value": disambiguation_option[0]
},
{
"title": "TEXT",
"value": disambiguation_option[1]
},
]
let buttons = data.map(function (d) {
return {
type: ActionTypes.PostBack,
title: d.title,
value: d.value
}
});
const msg = MessageFactory.suggestedActions(buttons, message_text);
return await step.prompt(TEXT_PROMPT, { prompt: msg });
return step.next(step.result) //not working
}
else {
logger.info("We dont desambiguate")
return step.next(step.result)
}
}
async answerStep(step) {
logger.info(`FinalAnswer Dialog: answerStep`);
let model_dispatch = step.result.model_dispatch
let result = step.result.result
//Show answer
return await step.endDialog();
}
You can use the step dictionary to store your values. The complex dialogs sample on GitHub is excellent for demonstrating this. https://github.com/microsoft/BotBuilder-Samples/blob/main/samples/javascript_nodejs/43.complex-dialog/dialogs/topLevelDialog.js
You can save data in the context with whatever name you want:
step.values['nameProperty'] = {}
This will be accessible within the entire execution context of the waterfall dialog:
const data = step.values['nameProperty'] // {}
I am building a tool to use for work. Basically I upload a csv to extract details which will act as parameters in an axios get request.
I am using multiple urls in axios.all, and my problem is I cannot match up the reponse data to each object of that specific url. The details are below with code snippets. I hope I've made it clear enough below, but this has to do with mass requesting many urls at once, and receiving response data. The problem lies in matching up that response data to its correct url from which it was called.
Here we go...to start, I am mapping an array of vehicle data I am uploading from an external csv file. 'resultsArray' is my array and it holds the year, make, model, trim, price, a url to locate the original posting, and location of the vehicle.
let vehicle_specs = resultsArray.map(function(d, index) {
let values = {
year: d['Title_name'].split(' ')[0], // Iterate with bracket notation
make: d['Title_name'].split(' ')[1],
model: d['Title_name'].split(' ')[2],
trim: d['Title_name'].split(' ')[3],
price: d['Title_Price'],
cl_url: d['Title_Price_url'],
cl_location: d['Title_Location'],
}
return values;
});
I use the new keyword to create an object of the vehicle.
let Vehicle = function(year, make, model, trim, price, url, cl_url, cl_location) {
this.year = year;
this.make = make;
this.model = model;
this.trim = trim;
this.price = price;
this.url = url;
this.cl_url = cl_url;
this.cl_location = cl_location;
}
I then build the object with a new instance of Vehicle and return each vehicle as I need it to be.
let vehicle_data = vehicle_specs.map(function(s) {
let url = `http://api.marketcheck.com/v2/stats/car?api_key={}&ymm=${s.year}|${s.make}|${s.model}`;
let new_vehicle = new Vehicle(`${s.year}`, `${s.make}`, `${s.model}`, `${s.trim}`, `${s.price}`, `${url}`, `${s.cl_url}`, `${s.cl_location}`);
return new_vehicle;
});
I extract the URL's in the following code snippet and use axios.all to request data from each one.
let urls = vehicle_data.map(function(m) {
return m.url;
})
let options = {
'method': 'GET',
'headers': {
'Host': 'marketcheck-prod.apigee.net'
}
};
axios.all(urls.map(url => {
request(url, options, function (error, response, body) {
if(error) {
console.log(error);
} else {
console.log(response);
}
});
}))
My Problem:
I am using a 3rd Party API (Marcketcheck) - Holds data on vehicles.
The response data comes back (See below as an example. This is data for just 1 url)
{"price_stats":{"geometric_mean":3413,"min":899,"median":3595,"population_standard_deviation":1323,"variance":1750285,"ax":7995,"mean":3655,"trimmed_mean":3572,"standard_deviation":1323,"iqr":1800},"miles_stats":{"geometric_mean":97901,"min":2,"median":125000,"population_standard_deviation":51713,"variance":2147483647,"max":230456,"mean":125182,"trimmed_mean":125879,"standard_deviation":51713,"iqr":74734},"dom_stats":{"geometric_mean":100,"min":1,"median":100,"population_standard_deviation":399,"variance":159152,"max":2513,"mean":247,"trimmed_mean":162,"standard_deviation":399,"iqr":217},"count":101}
I cannot figure out how to match up each response data to the vehicle object of that specific url.
For example, if I request 3 urls from the vehicle object. Let's name them:
Url-1
Url-2
Url-3
I get my response data back as objects:
OBJ-1
OBJ-2
OBJ-3
I have no way as far as I know with my level of knowledge, how to assign each object back to it's specific URL and THEN, match up that OBJ data with it's specific vehicle.
I haven been beating my head against a wall for about 4 days, I cannot figure this out.
Any suggestions are welcome and I really appreciate anybody looking at this post to help out.
Check this out
let requests = urls.map((url) => {
return axios.get(url, {
headers: {
'Host': 'marketcheck-prod.apigee.net'
}
});
});
Promise.all(requests).then((responces) => {
console.log(responces);
}).catch((err) => {
console.log(err)
});
I am wondering if it is possible to fetch a job by requisitionId in Google Cloud Talent Solution. requisitionId has to be unique across jobs so it seems like a natural candidate for looking a job up.
When a job is created the api returns a job name that can be used to look the job up:
You can retrieve the details of a previously inserted job by sending a GET request to the Cloud Talent Solution. The URI should include the previously inserted job name returned by the original create request, as a URL parameter.
I'd like to avoid storing these names if possible. In my view storing them adds unnecessary complexity since I already have a unique requisitionId. To be clear the API does not let you add jobs with a duplicate requisitionId:
Job projects/{my_app_id}/jobs/{google_assigned_id} already exists. Request ID for tracking: ... Related Job requisition ID: ...
So can I look up jobs by requisitionId?
I could parse the error message that's returned to get the job name..but that seems pretty brittle.
It turns out the list method takes requisitionId so for a full, read-create-update cycle we can do:
const listRequest = {
parent: `projects/${projectId}`,
'filter': `companyName="${companyName}" AND requisitionId="${requisitionId}"`
}
const listResult = await jobService.projects.jobs.list(listRequest)
const existingJobs = listResult.data.jobs || [];
let existingJob = null
if (existingJobs && existingJobs.length > 0) {
existingJob = existingJobs[0]
}
let googleJob
if (!existingJob) {
const createRequest = {
'parent': `projects/${projectId}`,
'resource': {
'job': {
companyName,
requisitionId,
title,
description,
applicationInfo: {
emails: ['email#example.com']
}
}
}
}
googleJob = await jobService.projects.jobs.create(createRequest)
.then(result => result)
.catch(resp => {
console.error("ERROR")
console.error(resp)
})
} else {
const patchRequest = {
'name': existingJob.name,
'resource': {
'job': {
companyName,
requisitionId,
title,
description,
applicationInfo: {
emails: ['email#example.com']
}
}
}
}
googleJob = await jobService.projects.jobs.patch(patchRequest)
.then(result => result)
.catch(resp => {
console.error("ERROR")
console.error(resp)
})
}
Docs: https://cloud.google.com/talent-solution/job-search/docs/reference/rest/v3/projects.jobs/list?authuser=0&hl=de
Notes:
The double quotes in the filter parameter are important. It will not accept single quotes and will give a cryptic error message.
The patch request cannot take a parent parameter even though everything else requires a parent parameter...
one can add it as custom attribute:
Map<String, CustomAttribute> attributes = new HashMap<>();
attributes
.put("requisitionId", new CustomAttribute().setStringValue(requisitionId)
.setFilterable(true));
Job job = new Job()
...
.setCustomAttributes(attributes);
Job jobCreated = createJob(job);
String jobName = jobCreated.getName();
and then search for requisitionId with a custom attribute filter:
JobQuery jobQuery = new JobQuery().setCustomAttributeFilter(filter);
this is a little redundant, but JobQuery has no method .setRequisitionId().
here's the documentation.
This is probably very simple ,so sorry...
I'm trying to create an application where i can create users and store informations by Firebase. There is an example here :
http://image.noelshack.com/fichiers/2015/11/1426182307-log.png
But now I want to check if the name already exists if someone wants to create a new user.
How would I go about grabbing individual user information without knowing their id , like simplelogin:54?
I've found this topic Get users by name property using Firebase but it is not the same thing because in my case I don't know the children after "Users"
Cheers,
Like Frank said, you must know something about the user to be able to look her/him up.
However, here is a general answer. I am assuming that by "name" you mean the property "identifiant" that you've created.
Suggestions
Start by looking over the Firebase Query documentation.
Short Answer
To check if a user exists by the identifiant property, you'd orderByChild("identifiant") and query for a specific user with the .equalTo("<identifient_here>").
For example, to check if a user with identifient="aaa",
var usersRef = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/Users");
var identifient = "aaa";
usersRef.orderByChild("identifiant").equalTo(identifient).once("value", function(snapshot) {
console.log("Loaded user by identifient:",identifient,snapshot.val());
});
If instead you want to query by the key (such as simplelogin:53), you could query by using orderByKey() instead of orderByChild()... or just simply setting the ref to the user's key like so:
var userKey = 'simplelogin:53';
var userRef = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/Users" + userKey);
userRef.once("value", function(snapshot) {
console.log("Loaded user",snapshot.val());
});
Long(er) Answer
You can handle this with a user factory (see Angular Providers documentation).
You return a promise in the factory using the $q service.
Here is the Angular API documentation for $q.
Example with UserFactory
Check out this working PLNKR example.
It's tied to one of my public Firebase instances.
I created the same simplelogin:53 user in /Users like you have.
If you search for the identifient = aaa, you'll get the right user.
The controller implementation here is for example purposes, and doesn't really do anything worth while. It's just for reference.
The Data
{
"Users" : {
"simplelogin:53" : {
"identifiant" : "aaa"
}
}
}
UserFactory
.factory('UserFactory', function($q, $firebaseObject, fbUrl){
return function(userId){
var deferred = $q.defer();
if (userId.isNotEmpty()) {
var userRef = new Firebase(fbUrl + '/Users/').orderByChild("identifiant").equalTo(userId);
userRef.once("value",
function(dataSnapshot){
if (dataSnapshot.val()) {
console.log("Loaded user",dataSnapshot.val());
deferred.resolve(dataSnapshot.val());
} else {
console.info("Couldn't find user by id",userId);
deferred.reject("No user found by identifient = '"+userId+"'");
}
},
function(error){
console.error("Error loading user",error);
deferred.reject(error);
}
);
} else {
deferred.reject("No id entered!");
}
return deferred.promise;
}
})
Controller
.controller('HomeController',function($scope, UserFactory) {
$scope.identifient = '';
var showError = function(errorMessage) {
if (errorMessage) {
showUser(false);
$scope.error = errorMessage;
} else {
delete $scope.error;
}
}
var showUser = function (userObject) {
if (userObject) {
showError(false);
$scope.user = userObject;
} else {
delete $scope.user;
}
}
$scope.loadUser = function() {
var userPromise = new UserFactory($scope.identifient);
userPromise.then(function(data){
showUser(data);
}).catch(function(error){
showError(error);
});
}
})
Template
<div ng-controller="HomeController">
<h2>Home Template</h2>
<input ng-model="identifient" placeholder="identifient"/>
<button ng-click="loadUser()">Find User</button>
<hr/>
<div ng-if="user">User: {{user}}</div>
<div ng-if="error">Error: {{error}}</div>
</div>
Hope that helps.