在 Google Cloud Run 上提供 GPT2 的 Flask 应用程序不保留下载的文件?

问题描述

我有一个在 Google Cloud Run 上运行的 Flask 应用程序,它需要下载一个大型模型(来自 Huggingface 的 GPT-2)。这需要一段时间来下载,所以我试图设置它只在部署时下载,然后只为后续访问提供服务。也就是说,我的主要烧瓶应用程序 app.py 导入的脚本中有以下代码

import torch
# from transformers import GPT2Tokenizer,GPT2LMHeadModel
from transformers import AutoTokenizer,AutoModelWithLMHead
# disable gradient calculation - Useful for inference
torch.set_grad_enabled(False)

# Check if gpu or cpu
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

# Load tokenizer and model
try:
    tokenizer = AutoTokenizer.from_pretrained("./gpt2-xl")
    model = AutoModelWithLMHead.from_pretrained("./gpt2-xl")
except Exception as e:

    print('no model found! Downloading....')
    
    AutoTokenizer.from_pretrained('gpt2').save_pretrained('./gpt2-xl')
    AutoModelWithLMHead.from_pretrained('gpt2').save_pretrained('./gpt2-xl')
    tokenizer = AutoTokenizer.from_pretrained("./gpt2-xl")
    model = AutoModelWithLMHead.from_pretrained("./gpt2-xl")

model = model.to(device)

这基本上是尝试加载下载的模型,如果失败,它会下载模型的新副本。我将自动缩放设置为最小值 1,我认为这意味着某些东西将始终在运行,因此即使在活动之后下载的文件也会保留。但是,当某些人尝试使用它时,它必须重新下载模型,该模型会冻结应用程序。我正在尝试重新创建类似这个应用程序 https://text-generator-gpt2-app-6q7gvhilqq-lz.a.run.app/ 的东西,它似乎没有相同的加载时间问题。在烧瓶应用程序本身中,我有以下内容

@app.route('/')
@cross_origin()
def index():
    prompt = wp[random.randint(0,len(wp)-1)]
    res = generate(prompt,size=75)
    generated = res.split(prompt)[-1] + '\n \n...TO BE CONTINUED'
    #generated = prompt
    return flask.render_template('main.html',prompt = prompt,output = generated)

if __name__ == "__main__":
    app.run(host='0.0.0.0',debug=True,port=PORT)

但它似乎每隔几个小时重新下载一次模型......我怎样才能避免让应用程序重新下载模型并且让那些想要尝试的人不让应用程序冻结?

解决方法

当容器实例停止时,写入文件系统的数据不会持久存在。

Cloud Run 生命周期是 HTTP 请求和 HTTP 响应之间的时间。重叠的请求会延长此生命周期。一旦发送了最终的 HTTP 响应,您的容器就可以停止。

Cloud Run 实例可以在不同的硬件(集群)上运行。一个实例不会与另一个实例具有相同的临时数据。可以移动实例。您下载大文件并将其保存到内存文件系统的策略不会始终如一。

Filesystem access

另请注意,文件系统在内存中,这意味着您需要有额外的内存来存储文件。