我的旅程:在Google Cloud上构建无服务器的transformers管道
我的旅程:构建无服务器的transformers管道在Google Cloud上
社区成员Maxence Dominici的客座博客文章
本文将讨论我在Google Cloud上部署transformers
情感分析流水线的经历。我们将从transformers
的简要介绍开始,然后转向实现的技术部分。最后,我们将总结这个实现并回顾我们所取得的成就。
目标
我想创建一个微服务,自动检测在Discord上留下的客户评论是积极的还是消极的。这将使我能够相应地处理评论并改善客户体验。例如,如果评论是消极的,我可以创建一个功能,与客户联系,为服务质量差表示歉意,并告知客户,我们的支持团队将尽快与他/她联系,协助解决问题。由于我不打算每月超过2000个请求,因此对时间和可扩展性没有施加任何性能约束。
Transformers库
当我下载了.h5文件时,一开始我有点困惑。我以为它与tensorflow.keras.models.load_model
兼容,但事实并非如此。经过几分钟的研究,我发现该文件是一个权重检查点,而不是Keras模型。之后,我尝试了Hugging Face提供的API,并对他们提供的流水线功能进行了更多了解。由于API和流水线的结果都很好,我决定可以通过流水线在自己的服务器上提供模型。
下面是Transformers GitHub页面上的官方示例。
from transformers import pipeline
# 为情感分析分配一个流水线
classifier = pipeline('sentiment-analysis')
classifier('We are very happy to include pipeline into the transformers repository.')
[{'label': 'POSITIVE', 'score': 0.9978193640708923}]
将Transformers部署到Google Cloud
我选择使用GCP,因为它是我个人组织中使用的云环境。
第1步 – 研究
我已经知道可以使用flask
等API服务来提供transformers
模型。我在Google Cloud AI文档中搜索到了一个名为AI-Platform Prediction的用于托管TensorFlow模型的服务。我还在那里找到了App Engine和Cloud Run,但我对App Engine的内存使用情况有所担忧,并且对Docker不太熟悉。
第2步 – 在AI-Platform Prediction上进行测试
由于该模型不是“纯TensorFlow”保存的模型,而是一个检查点,因此我无法将其转换为“纯TensorFlow模型”,因此我发现该页面上的示例不起作用。从那里我看到我可以编写一些自定义代码,允许我加载pipeline
而不是处理模型,这似乎更容易。我还了解到我可以定义一个预测前和预测后的操作,这对于未来对数据进行预处理或后处理以满足客户需求可能很有用。我按照Google的指南进行操作,但遇到了一个问题,因为该服务仍处于测试阶段,而且一切都不稳定。这个问题在这里有详细描述。
第3步 – 在App Engine上进行测试
由于我熟悉Google的App Engine服务,所以我转向了它,但由于缺少系统依赖文件,导致TensorFlow安装出现问题。然后,我尝试了PyTorch,在F4_1G实例上可以工作,但不能处理同一实例上的超过2个请求,从性能上来说并不是很好。
第4步 – 在Cloud Run上进行测试
最后,我转向了Cloud Run,并使用了一个Docker镜像。我按照这个指南了解了它的工作原理。在Cloud Run中,我可以配置更高的内存和更多的vCPU来使用PyTorch进行预测。由于PyTorch似乎加载模型更快,所以我放弃了Tensorflow。
无服务器流水线的实现
最终的解决方案由四个不同的组件组成:
main.py
处理流水线的请求Dockerfile
用于创建将部署在Cloud Run上的镜像。- 具有
pytorch_model.bin
、config.json
和vocab.txt
的模型文件夹。- 模型:DistilBERT基础未大小写微调SST-2
- 要下载模型文件夹,请按照按钮中的说明进行操作。
- 不需要保留
rust_model.ot
或tf_model.h5
,因为我们将使用PyTorch。
requirement.txt
用于安装依赖项
main.py
中的内容非常简单。思路是接收一个包含两个字段的GET
请求。第一个是要分析的评论,第二个是用于“保护”服务的API密钥。第二个参数是可选的,我使用它来避免设置Cloud Run的oAuth2。提供这些参数后,我们加载基于模型distilbert-base-uncased-finetuned-sst-2-english
(上面提供的模型)构建的流水线。最后,将最佳匹配返回给客户端。
import os
from flask import Flask, jsonify, request
from transformers import pipeline
app = Flask(__name__)
model_path = "./model"
@app.route('/')
def classify_review():
review = request.args.get('review')
api_key = request.args.get('api_key')
if review is None or api_key != "MyCustomerApiKey":
return jsonify(code=403, message="bad request")
classify = pipeline("sentiment-analysis", model=model_path, tokenizer=model_path)
return classify("that was great")[0]
if __name__ == '__main__':
# This is used when running locally only. When deploying to Google Cloud
# Run, a webserver process such as Gunicorn will serve the app.
app.run(debug=False, host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))
然后是DockerFile
,它将用于创建服务的docker镜像。我们指定我们的服务使用python:3.7运行,还需要安装我们的要求。然后我们使用gunicorn
在端口5000
上处理我们的进程。
# Use Python37
FROM python:3.7
# Allow statements and log messages to immediately appear in the Knative logs
ENV PYTHONUNBUFFERED True
# Copy requirements.txt to the docker image and install packages
COPY requirements.txt /
RUN pip install -r requirements.txt
# Set the WORKDIR to be the folder
COPY . /app
# Expose port 5000
EXPOSE 5000
ENV PORT 5000
WORKDIR /app
# Use gunicorn as the entrypoint
CMD exec gunicorn --bind :$PORT main:app --workers 1 --threads 1 --timeout 0
重要的是注意参数--workers 1 --threads 1
,这意味着我只想在一个工作进程(= 1个进程)上执行我的应用程序,并且只有一个线程。这是因为我不希望同时启动两个实例,因为这可能会增加计费。其中一个缺点是,如果服务同时接收到两个请求,处理时间会更长。之后,我将线程限制为一个,因为加载模型到流水线中所需的内存使用量。如果我使用4个线程,我可能只有4 Gb / 4 = 1 Gb的内存来执行完整的流程,这是不够的,会导致内存错误。
最后,requirement.txt
文件
Flask==1.1.2
torch===1.7.1
transformers~=4.2.0
gunicorn>=20.0.0
部署说明
首先,你需要满足一些要求,例如在Google Cloud上有一个项目,启用计费并安装gcloud
命令行界面。你可以在Google的指南 – 开始之前中找到更多详细信息。
其次,我们需要构建docker镜像,并通过选择正确的项目(替换PROJECT-ID
)以及设置实例名称(如ai-customer-review
)将其部署到云端运行。你可以在Google的指南 – 部署中找到更多关于部署的信息。
gcloud builds submit --tag gcr.io/PROJECT-ID/ai-customer-review
gcloud run deploy --image gcr.io/PROJECT-ID/ai-customer-review --platform managed
几分钟后,你还需要将分配给Cloud Run实例的内存从256 MB升级到4 GB。要做到这一点,请转到你的项目的Cloud Run控制台。
在那里,你应该找到你的实例,点击它。
之后,你将在屏幕顶部看到一个蓝色按钮,标有“编辑和部署新版本”,点击它,然后你将被提示输入许多配置字段。在底部,你应该找到一个名为“Capacity”的部分,你可以在那里指定内存。
性能
从发送请求到处理请求,包括将模型加载到管道中以及进行预测,所需的时间少于五秒钟。冷启动可能需要额外的10秒左右。
通过预热模型,我们可以提高请求处理性能,这意味着在启动时加载模型而不是在每个请求上加载(例如使用全局变量),通过这样做,我们节省时间和内存使用。
成本
我使用Google定价模拟器根据Cloud Run实例的配置模拟了成本
对于我的微服务,我计划每月接近1,000个请求,乐观地说。根据我的使用情况,500个请求更有可能。这就是为什么在设计我的微服务时,我考虑了2,000个请求作为上限。由于请求数量很少,我并没有过多考虑可扩展性,但如果我的计费增加,我可能会重新考虑可扩展性。
然而,需要强调的是,你将为每个Gigabyte的构建镜像支付存储费用。每个月大约是€0.10每Gb,如果你不将所有版本保存在云端,这个费用是可以接受的,因为我的版本略高于1 Gb(Pytorch为700 Mb,模型为250 Mb)。
结论
通过使用Transformers的情感分析管道,我节省了大量时间。我不需要训练/微调模型,而是可以找到一个准备好用于生产并在我的系统中部署的模型。将来我可能会对其进行微调,但正如我在测试中展示的那样,准确性已经非常惊人!我本希望有一个“纯TensorFlow”模型,或者至少有一种在TensorFlow中加载它而不依赖Transformers的方法来使用AI平台。同时,拥有一个轻量级的版本也将是很好的。