我计划使用服务帐户获得AI预测结果,并将云功能部署到Firebase项目。当试图获得预测结果时>
https://ml.googleapis.com/v1/projects/projectid/models/category:predict?
使用accesstoken JWT,结果是
{ StatusCodeError: 403 - {"error":{"code":403,"message":"Access to model denied.","status":"PERMISSION_DENIED"}}
已确认我正在使用的服务帐户已添加到ML项目中。
任何想法如何使用服务帐户在Firebase函数中获得ML结果?或其他方法?
这里是代码(我仍然是NodeJS的新手)
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const admin = require('firebase-admin'); const request = require("request"); const requestProm = require("request-promise"); const functions = require('firebase-functions'); const { GoogleAuth } = require('google-auth-library'); admin.initializeApp(); var reportFld, reportNarTr, reportTitTr; var input, input2, input3; var result, predictedHaz, predictedSig, predictedRep, setDoc var getAccessTokenId getAccessTokenId = async function main() { const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/cloud-platform' }); const client = await auth.getClient(); const projectId = await auth.getProjectId(); const accessTokenId = await auth.getAccessToken(); return accessTokenId } exports.newReport = functions.firestore .document('/users/{usersId}') .onCreate((change, context) => { const db = admin.firestore(); const interDoc = db.collection('users').doc(context.params.usersId); interDoc.get().then(doc => { if (!doc.exists) { console.log('No such document!'); } else { var getPrediction getPrediction = async function main2() { reportFld = doc.data(); reportNarTr = JSON.stringify(reportFld.narrative); reportTitTr = JSON.stringify(reportFld.title); reportNumTr = context.params.usersId; input = { instances: [ [reportNumTr, reportTitTr, reportNarTr] ] }; var accessToken = await getAccessTokenId(); var endpointhazCat = 'https://ml.googleapis.com/v1/projects/projectid/models/hazcat:predict?access_token=' + accessToken; var endpointsigCat = 'https://ml.googleapis.com/v1/projects/projectid/models/sig:predict?access_token=' + accessToken; var endpointrepCat = 'https://ml.googleapis.com/v1/projects/projectid/models/type:predict?access_token=' + accessToken; var options1 = { method: 'POST', uri: endpointhazCat, body: input, json: true // Automatically stringifies the body to JSON }; var options2 = { method: 'POST', uri: endpointsigCat, body: input, json: true // Automatically stringifies the body to JSON }; var options3 = { method: 'POST', uri: endpointrepCat, body: input, json: true // Automatically stringifies the body to JSON }; requestProm.post(options1) .then(function (response) { result = response['predictions']; switch (parseInt(result)) { case 0: predictedHaz = 'A'; break; case 1: predictedHaz = 'B'; break; case 2: predictedHaz = 'C'; break; case 3: predictedHaz = 'D'; break; case 4: predictedHaz = 'E'; break; case 5: predictedHaz = 'F'; break; case 6: predictedHaz = 'G'; break; default: predictedHaz = 'error'; } const predictedHazData = { HazardCategory: predictedHaz, }; setDoc = db.collection('users').doc(context.params.usersId).update(predictedHazData); console.log(response); return true }) .catch(function (err) { console.log('Failed', err) }); requestProm.post(options2) .then(function (response) { result = response['predictions']; if (parseInt(result) > -4) { predictedSig = 'Sig'; } else predictedSig = 'Insig' const predictedSigData = { SignifanceCategory: predictedSig, }; setDoc = db.collection('users').doc(context.params.usersId).update(predictedSigData); console.log(response); return true }) .catch(function (err) { console.log('Failed', err) }); requestProm.post(options3) .then(function (response) { result = response['predictions']; if (parseInt(result) === 1) { predictedRep = 'Inc'; } else predictedRep = 'Haz' const predictedRepData = { ReportCategory: predictedRep, }; setDoc = db.collection('users').doc(context.params.usersId).update(predictedRepData); console.log(response); return true }) .catch(function (err) { console.log('Failed', err) }); return true } getPrediction().catch(console.error); } return null }) .catch(err => { console.log('Error getting document', err); }); return true; });
添加了一些详细信息:
这些是服务帐户权限:
ml.jobs.cancel ml.jobs.create ml.jobs.get ml.jobs.getIamPolicy ml.jobs.list ml.jobs.update ml.locations.get ml.locations.list ml.models.create ml.models.delete ml.models.get ml.models.getIamPolicy ml.models.list ml.models.predict ml.models.update ml.operations.cancel ml.operations.get ml.operations.list ml.projects.getConfig ml.studies.create ml.studies.delete ml.studies.get ml.studies.getIamPolicy ml.studies.list ml.trials.create ml.trials.delete ml.trials.get ml.trials.list ml.trials.update ml.versions.create ml.versions.delete ml.versions.get ml.versions.list ml.versions.predict ml.versions.update resourcemanager.projects.get
我尝试在调试控制台上使用其他节点库'googleapis':
google.auth.getApplicationDefault((err, authClient, projectId) => { if (err) { console.log('Authentication failed because of ', err); res.status(401).send('Authentication failed'); } else { // create the full model name which includes the project ID const modelName = 'projects/ml-project-id/models/hazcat'; const mlRequestJson = { 'auth': authClient, 'name': modelName, 'resource': { instances: [['RepNum', 'RepTit', 'RepNar']] } } ml.projects.predict(mlRequestJson, (err, result) => { if (err) { console.log(err); } else { console.log(result.data.predictions[0]); } }); } });
结果是:
3
并部署到firebase:
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const admin = require('firebase-admin'); const request = require("request"); const requestProm = require("request-promise"); const functions = require('firebase-functions'); const { GoogleAuth } = require('google-auth-library'); const { google } = require('googleapis'); const ml = google.ml('v1'); admin.initializeApp(); var reportFld, reportNarTr, reportTitTr, reportNumTr, reportTitStr, reportNarStr; var input, input2, input3; var result, predictedHaz, predictedSig, predictedRep, setDoc exports.predictReport = functions.firestore .document('/users/{usersId}') .onCreate((change, context) => { const db = admin.firestore(); const interDoc = db.collection('users').doc(context.params.usersId); interDoc.get().then(doc => { if (!doc.exists) { console.log('No such document!'); } else { reportFld = doc.data(); reportNarTr = JSON.stringify(reportFld.narrative); reportTitTr = JSON.stringify(reportFld.title); reportNumTr = context.params.usersId; input = { instances: [ [reportNumTr, reportTitTr, reportNarTr] ] }; var result1, result2, result3 google.auth.getApplicationDefault((err, authClient, projectId) => { if (err) { console.log('Authentication failed because of ', err); res.status(401).send('Authentication failed'); } else { const modelName = 'projects/ml-project-id/models/hazcat'; const modelName2 = 'projects/ml-project-id/models/sig'; const modelName3 = 'projects/ml-project-id/models/type'; const mlRequestJson1 = { 'auth': authClient, 'name': modelName, 'resource': input } const mlRequestJson2 = { 'auth': authClient, 'name': modelName2, 'resource': input } const mlRequestJson3 = { 'auth': authClient, 'name': modelName3, 'resource': input } var result1, result2, result3 ml.projects.predict(mlRequestJson1, (err, result) => { if (err) { console.log(err); } else { console.log(result.data.predictions[0]); result1 = result.data.predictions[0]; switch (parseInt(result1)) { case 0: predictedHaz = 'A'; break; case 1: predictedHaz = 'B'; break; case 2: predictedHaz = 'C'; break; case 3: predictedHaz = 'D'; break; case 4: predictedHaz = 'E'; break; case 5: predictedHaz = 'F'; break; case 6: predictedHaz = 'G'; break; default: predictedHaz = 'error'; } const predictedHazData = { HazardCategory: predictedHaz, }; setDoc = db.collection('users').doc(context.params.usersId).update(predictedHazData); } }); // endof predict1 ml.projects.predict(mlRequestJson2, (err, result) => { if (err) { console.log(err); } else { console.log(result.data.predictions[0]); result2 = result.data.predictions[0]; if (parseInt(result2) > -4) { predictedSig = 'Sig'; } else predictedSig = 'Insig' const predictedSigData = { SignifanceCategory: predictedSig, }; setDoc = db.collection('users').doc(context.params.usersId).update(predictedSigData); } });// endof predict2 ml.projects.predict(mlRequestJson3, (err, result) => { if (err) { console.log(err); } else { console.log(result.data.predictions[0]); result3 = result.data.predictions[0]; if (parseInt(result3) === 1) { predictedRep = 'Inc'; } else predictedRep = 'Haz' const predictedRepData = { ReportCategory: predictedRep, }; setDoc = db.collection('users').doc(context.params.usersId).update(predictedRepData); } });// endof predict3 }//endof else getappdefault });//endof getappdefault } return true })//endof getdocument .catch(err => { console.log('Error getting document', err); }); return true; });//endof onCreate
结果是
我已经使用了指向服务帐户json文件的密钥文件。Authentication failed because of Error: Could not load the default credentials. Browse to https://cloud.google.com/docs/authentication/getting-started for more information. at AuthPlus.getApplicationDefaultAsync (/srv/node_modules/googleapis-common/node_modules/google-auth-library/build/src/auth/googleauth.js:156:23) at <anonymous> at process._tickDomainCallback (internal/process/next_tick.js:229:7)
添加了详细信息(更新2)
getAccessTokenId = async function main() { const auth = new GoogleAuth({ keyFile: 'projectid.json', scopes: 'https://www.googleapis.com/auth/cloud-platform' }); const client = await auth.getClient(); const projectId = await auth.getProjectId(); const accessTokenId = await auth.getAccessToken(); return accessTokenId }
像这样获得访问令牌
ya29.c.xxxx
并且该权限被拒绝
我正在使用我的个人凭据在云功能内部输入ML模型作品Failed { StatusCodeError: 403 - {"error":{"code":403,"message":"Access to model denied.","status":"PERMISSION_DENIED"}}
添加了详细信息(更新3)
getAccessTokenId = async function main() { const auth = new GoogleAuth({ keyFile: 'application_default_credentials.json', scopes: 'https://www.googleapis.com/auth/cloud-platform' }); const client = await auth.getClient(); const projectId = await auth.getProjectId(); const accessTokenId = await auth.getAccessToken(); return accessTokenId }
获取结果
{ predictions: [ 3 ] }
我还在服务帐户上添加了服务帐户令牌创建者角色,但仍无法使用服务帐户访问ML模型。>
iam.serviceAccountKeys.create iam.serviceAccountKeys.delete iam.serviceAccountKeys.get iam.serviceAccountKeys.list
但很好奇为什么没有这些
iam.serviceAccounts.getAccessToken iam.serviceAccounts.signBlob iam.serviceAccounts.signJwt iam.serviceAccounts.implicitDelegation iam.serviceAccounts.getOpenIdToken
我计划使用服务帐户获得AI预测结果,并将云功能部署到Firebase项目。尝试获取预测结果时https://ml.googleapis.com/v1/projects / ...
现在正在工作。如here所述,我在模型级别将新的服务帐户设置为ML引擎模型用户。我还重置了以前的服务帐户,并且运行良好。谢谢@NibrassH和@DanielOcando。