使用BentoML部署模型时遇TypeError: 'RunnerMethod'不可调用问题求助
问题
尝试用BentoML部署机器学习模型,通过estimator_runner = bentoml.keras.get(BENTO_MODEL_TAG).to_runner()将模型封装为runner,但调用estimator_runner.predict(input_data)时返回错误:
"处理该请求时BentoML用户代码出错,请查看服务器日志"
服务器日志显示:
return estimator_runner.predict(input_data) TypeError: 'RunnerMethod' object is not callable 2022-11-23T17:09:47+0100 [INFO] [dev_api_server] 127.0.0.1:60377 (scheme=http,method=POST,path=/predict,type=application/json,length=294) (status=500,type=application/json,length=110) 3.932ms (trace=28b577785679ee4866ff6cbd61589e24,span=722cdd8b6467bfb6,sampled=0)
服务代码
import numpy as np import bentoml from bentoml.io import NumpyNdarray BENTO_MODEL_TAG = "mmrt_model:p2ya6otlggzx4me4" iestimator_runner = bentoml.keras.get(BENTO_MODEL_TAG).to_runner() MMRT_service = bentoml.Service("MMRT_Estimator", runners=[estimator_runner]) @MMRT_service.api(input=NumpyNdarray(), output=float) def predict(input_data: np.ndarray) -> float: return estimator_runner.predict(input_data)
请求代码
import json from sys import argv import numpy as np import requests SERVICE_URL = "http://localhost:3000/predict" def make_request_to_bento_service(service_url: str, input_array: np.ndarray) -> str: serialized_input_data = json.dumps(input_array.tolist()) response = requests.post( service_url, data=serialized_input_data, headers={"Content-Type": "application/json"} ) return response.text def main(): # 从argv读取数据转为np.ndarray input_data = np.array([float(x) for x in argv[1:]]) print(input_data) prediction = make_request_to_bento_service(SERVICE_URL, input_data) print(prediction) if __name__ == "__main__": main()
解决方法
错误原因
BentoML中Runner的方法(如predict)是RunnerMethod对象,不能直接调用,必须通过.run()(同步调用)或.async_run()(异步调用)方法执行预测。同时原代码存在变量名笔误,可能引发额外错误。
修改后的服务代码
import numpy as np import bentoml from bentoml.io import NumpyNdarray BENTO_MODEL_TAG = "mmrt_model:p2ya6otlggzx4me4" # 修正变量名笔误,统一变量命名 estimator_runner = bentoml.keras.get(BENTO_MODEL_TAG).to_runner() MMRT_service = bentoml.Service("MMRT_Estimator", runners=[estimator_runner]) @MMRT_service.api(input=NumpyNdarray(), output=float) def predict(input_data: np.ndarray) -> float: # 使用.run()方法执行同步预测 result = estimator_runner.predict.run(input_data) # 将Keras返回的数组转换为单个float值,匹配服务输出类型 return float(result.flatten()[0])
关键修改点
- 修正变量名笔误:原代码定义
iestimator_runner但后续使用estimator_runner,统一为estimator_runner避免未定义错误。 - 调整调用方式:将
estimator_runner.predict(input_data)改为estimator_runner.predict.run(input_data),符合BentoML Runner的调用规范。 - 结果格式转换:Keras模型预测返回数组,需转为单个float值以匹配服务定义的输出类型。
内容的提问来源于stack exchange,提问作者FLOROID
相关产品推荐
相关产品推荐

