为什么Clarifai无法使用Clarifai Portal中生成的API密钥或Personal Access令牌来验证模型输出请求?

问题描述

更新

我能够获得原始代码,并且在单独运行时的建议也能正常工作。但是,我需要做的是在Firebase onRequestonCall函数调用它。当这些代码被这些代码包装时,格式错误的标头和授权请求仍然是一个问题。我们以这种方式使用许多其他API,这令人困惑为什么Clarifiai API遇到这些问题。有关在Firebase中使用它的任何建议?

原始

Clarifai的新手,在尝试从食物模型中检索模型输出时遇到一些验证问题。

我尝试了两个不同的键:

  • 从我在门户网站中创建的应用程序生成的API密钥
  • API密钥-我为自己生成的个人访问令牌

在两种情况下,我都遇到Empty or malformed authorization header响应。

{
   "status":{
      "code":11102,"description":"Invalid request","details":"Empty or malformed authorization header. Please provide an API key or session token.","req_id":"xyzreasdfasdfasdfasdfasf"
   },"outputs":[
      
   ]
}

我已经按照以下文章整理了这段代码。它在Node 10环境中运行。

  const { ClarifaiStub } = require('clarifai-nodejs-grpc');
  const grpc = require('@grpc/grpc-js');
  const stub = ClarifaiStub.json();
  const Metadata = new grpc.Metadata();
  Metadata.set("authorization","Key xyzKey");

  return new Promise((resolve,reject) => {
    stub.PostModelOutputs(
      {
        model_id: 'bd367be194cf45149e75f01d59f77ba7',inputs: [{ data: { image: { url: 'https://samples.clarifai.com/metro-north.jpg' } } }],},Metadata,(err,response) => {
        if (err) {
          return reject(`ERROR: ${err}`);
        }

        resolve(JSON.stringify(response));
      }
    );
  });
}

解决方法

通过两种方式向Clarifai API进行身份验证:

  • 带有特定于应用程序的API密钥,这意味着API密钥已附加到应用程序,并且只能在该应用程序内执行操作,
  • 具有特定于用户的个人访问令牌(PAT),这意味着您可以评估/操纵/对用户拥有/有权访问的所有应用程序进行操作(以及自己创建/更新/删除应用程序) 。

使用PAT时,必须在请求数据中指定要定位的应用程序。使用API​​密钥,则不需要。

我已经用有效的API密钥测试了您的示例(使用Node 12,尽管它也应该在10中工作),并且它的工作原理是fina(将其放入异步函数后)。这是一个完整的可运行示例(将YOUR_API_KEY替换为有效的API密钥)。

function predict() {
  const { ClarifaiStub } = require('clarifai-nodejs-grpc');
  const grpc = require('@grpc/grpc-js');
  const stub = ClarifaiStub.json();
  const metadata = new grpc.Metadata();
  metadata.set("authorization","Key YOUR_API_KEY");

  return new Promise((resolve,reject) => {
    stub.PostModelOutputs(
      {   
        model_id: 'bd367be194cf45149e75f01d59f77ba7',inputs: [{ data: { image: { url: 'https://samples.clarifai.com/metro-north.jpg' } } }],},metadata,(err,response) => {
        if (err) {
          return reject(`ERROR: ${err}`);
        }

        resolve(JSON.stringify(response));
      }   
    );  
  }); 
}

async function main() {
    const response = await predict();
    console.log(response);
}

main();

如果要在以上示例中使用PAT,则必须更改两件事。首先,将API密钥替换为PAT:

...
metadata.set("authorization","Key YOUR_PAT");
...

向方法请求对象添加应用程序ID。

...
    stub.PostModelOutputs(
      {
         user_app_id: {
           user_id: "me",// The literal "me" resolves to your user ID.
           app_id: "YOUR_APPLICATION_ID"
         },model_id: 'bd367be194cf45149e75f01d59f77ba7',...
,

确保您已尊重在代码中传递密钥的格式,例如:

const metadata = new grpc.Metadata();
metadata.set("authorization","Key {YOUR_CLARIFAI_API_KEY}");

确保存在“密钥”。

让我知道。

,

编辑:看来Firebase不支持自定义标头。这可能会影响“授权”标头。至少这是我最好的猜测。请参阅以下票证中的评论。

Firebase hosting custom headers not working


以下代码对我有用:

{
  const { ClarifaiStub } = require('clarifai-nodejs-grpc');
  const grpc = require('@grpc/grpc-js');
  const stub = ClarifaiStub.json();
  const metadata = new grpc.Metadata();
  metadata.set("authorization","Key {APP API KEY}");

  return new Promise((resolve,reject) => {
    stub.PostModelOutputs(
      {
        model_id: 'bd367be194cf45149e75f01d59f77ba7',response) => {
        if (err) {
          return reject(`ERROR: ${err}`);
        }
        console.log(JSON.stringify(response));
        resolve(JSON.stringify(response));
      }
    );
  });
}

虽然我不确定您正在运行的实际代码中是否反映了缺失的{,但仍然不确定。在这种情况下,我使用的是APP API密钥(创建应用程序时,“应用程序详细信息”页面上将有一个API密钥。

听起来您可能正在使用个人访问令牌,但可以这样使用:

{  
  const { ClarifaiStub } = require('clarifai-nodejs-grpc');
  const grpc = require('@grpc/grpc-js');
  const stub = ClarifaiStub.json();
  const metadata = new grpc.Metadata();
  metadata.set("authorization","Key {Personal Access Token}"); // Sounds like you've made the personal access token correctly - go into settings,then authentication,then create one.  Make sure it has proper permissions (I believe all by default).

  return new Promise((resolve,reject) => {
    stub.PostModelOutputs(
      {
        user_app_id: {
          user_id: "{USER ID}",// I used my actual ID,I did not put 'me'.  You can find this under your profile.
          app_id: "{APP NAME}" // This is the app ID found in the upper left corner of the app after it is created - not the API Key.  This is generally what you named the app when you created it.
        },response) => {
        if (err) {
          return reject(`ERROR: ${err}`);
        }
        console.log(JSON.stringify(response));
        resolve(JSON.stringify(response));
      }
    );
  });
}

请务必填写:{个人访问令牌},{用户ID}和{APP NAME}。我使用了我的实际用户ID(在配置文件中找到),并且该应用程序名称不是该应用程序的API密钥,而是您在“应用程序详细信息”页面上时在左上角的名称。这个电话对我有用。