如何向Google机器学习预测端点发起带认证的REST调用及获取有效访问令牌?
我尝试向Google机器学习预测端点发起一个简单的HTTP REST调用,但一直找不到正确的实现方法。根据有限的文档,我需要使用Java或Python库(或者通过REST认证端点完成加密)获取credentials对象,但文档没有说明这个对象的具体用法。
我目前的代码如下:
import urllib2 from google.oauth2 import service_account # Constants ENDPOINT_URL = 'ml.googleapis.com/v1/projects/{project}/models/{model}:predict?access_token=' SCOPES = ['https://www.googleapis.com/auth/cloud-platform'] SERVICE_ACCOUNT_FILE = 'service.json' credentials = service_account.Credentials.from_service_account_file( SERVICE_ACCOUNT_FILE, scopes=SCOPES) access_token=credentials.token opener = urllib2.build_opener(urllib2.HTTPHandler) request = urllib2.Request(ENDPOINT_URL + access_token) request.get_method = lambda: 'POST' result = opener.open(request).read() print(str(result))
现在遇到的问题是,打印credentials.valid返回False,我推测凭据对象初始化有问题,但代码没有报错,而且对象内的字段看起来都是正确的,操作完全按照文档步骤来。另外,service.json是移动端团队已经成功用来获取access token的有效文件。请问我该如何获取可以调用机器学习服务预测端点的有效access token?
问题分析与解决办法
你踩的坑其实挺常见的——service_account.Credentials对象刚初始化完,并不会自动获取可用的access token,这就是为什么credentials.valid返回False,credentials.token大概率是None或者无效值的原因。下面一步步帮你修复:
1. 先主动刷新凭据拿到有效Token
你需要调用credentials.refresh()方法来触发token的获取,这里要用到google.auth.transport.requests里的Request类:
from google.auth.transport.requests import Request # 初始化凭据之后,加这行刷新操作 credentials.refresh(Request()) # 现在再看credentials.valid应该就是True了,token也能用了 access_token = credentials.token
2. 修正Endpoint URL的格式
你的URL缺了https://前缀,而且把token拼在URL里不是最佳实践(官方更推荐放在请求头里),正确的URL应该是:
# 记得替换{project}和{model}为你的实际项目ID和模型名 ENDPOINT_URL = 'https://ml.googleapis.com/v1/projects/{project}/models/{model}:predict'
3. 正确构造POST请求(带请求体和认证头)
Google ML的预测端点需要你传入JSON格式的预测数据,而且要把access token放在Authorization请求头里。完整的修正代码如下:
import urllib2 import json from google.oauth2 import service_account from google.auth.transport.requests import Request # 替换成你的实际信息 PROJECT_ID = "your-project-id-here" MODEL_ID = "your-model-name-here" ENDPOINT_URL = f'https://ml.googleapis.com/v1/projects/{PROJECT_ID}/models/{MODEL_ID}:predict' SCOPES = ['https://www.googleapis.com/auth/cloud-platform'] SERVICE_ACCOUNT_FILE = 'service.json' # 初始化并刷新凭据 credentials = service_account.Credentials.from_service_account_file( SERVICE_ACCOUNT_FILE, scopes=SCOPES) credentials.refresh(Request()) # 构造预测请求的body,格式要和你的模型输入匹配 predict_payload = { "instances": [ # 示例:如果你的模型接收两个特征,就像这样写 # {"age": 30, "income": 50000} ] } # 构建HTTP请求 opener = urllib2.build_opener(urllib2.HTTPHandler) request = urllib2.Request( ENDPOINT_URL, data=json.dumps(predict_payload).encode('utf-8') ) # 添加认证头和Content-Type头 request.add_header('Authorization', f'Bearer {credentials.token}') request.add_header('Content-Type', 'application/json') # 发送请求并处理结果 try: response = opener.open(request).read() print(json.loads(response)) except urllib2.HTTPError as err: print(f"请求失败: {err.code} - {json.loads(err.read())}")
4. 更省心的方案:用官方AI Platform库
其实Google有现成的库google-cloud-aiplatform,可以完全跳过手动处理token和HTTP请求的步骤,直接调用预测接口,代码更简洁也更可靠:
from google.cloud import aiplatform # 初始化客户端 aiplatform.init(project=PROJECT_ID) # 加载你的模型 model = aiplatform.Model(f"projects/{PROJECT_ID}/models/{MODEL_ID}") # 发起预测 predict_response = model.predict(instances=[ # 这里放你的输入数据,和上面payload里的格式一致 ]) print(predict_response.predictions)
这个库会自动帮你处理认证、token刷新和请求格式,出错概率低很多。
内容的提问来源于stack exchange,提问作者Alex Egli

