用Flask构建一个AI翻译服务

缘起

首先,看一段代码,只有几行Python语句却完成了AI翻译的功能。

#!/usr/bin/python3

import sys
from transformers import MarianMTModel, MarianTokenizer

def translate(word_list):
    model_name = "Helsinki-NLP/opus-mt-en-zh"
    tokenizer = MarianTokenizer.from_pretrained(model_name)
    model = MarianMTModel.from_pretrained(model_name)
    translated = model.generate(**tokenizer(word_list, return_tensors="pt", padding=True))
    for res in [tokenizer.decode(t, skip_special_tokens=True) for t in translated]:
        print(res)

if __name__ == "__main__":
    translate(sys.argv[1:])

这里可以看到,只要调用这个tranlate函数,向它传递一个英语词汇的list,就能返回一个翻译好的中文词汇列表。这里的词汇指的是单词、词组或句子。

不过这个函数有个问题,就是运行起来比较慢。因为它需要加载 tokenizer 和 model. 这最快也要5-6秒;如果这个程序是跑在docker里面,就更慢了,可能要十几甚至几十秒。
(这些tokenizer和model可以由pip install得到,这个在后面再详细介绍。)

所以,总不能每次翻译都要把tokenizer和model都加载一遍。解决的办法也有多种。比如写一个类,在类的实例初始化的时候就把这些加载好,后面调translate函数的时候自然就快了。不过这篇博文里想介绍的方法是,利用一个Python的轻量级的web框架来提供一个Http的服务,从而可以向这个Http服务提出REST请求以获得翻译服务。

第1步 建立virtualenv环境

写Python应用程序的第一步总是建立virtualenv环境,为了避免和本地系统的Python库冲突的情况。

运行以下命令

virtualenv FlaskServer
cd FlaskServer
source bin/activate

注意,本博文的程序基于Linux系统运行。如果在Windows上,则以上的激活命令是不同的。
另外,如果没有安装 virtualenv, 则需要运行pip3 install virtualenv命令进行安装。

第2步 安装必要的库

第二步就是在virtualenv环境下安装必要的library了。
这里需要的库包括翻译模型相关的库以及Flask.

pip install transformers sentencepiece sacremoses
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu
pip install Flask

第3步 设计REST请求及返回

我们希望一次能翻译多个单词或词组或句子。那么就需要向翻译服务提供一个list;相应的,翻译之后,也就会返回一个list.
例子如下:

POST /translate 

# request body example 
{
  "target_words": ["Hello, what's you name", "I am good", "How are you"]
}

# response example
{
  "translated_words": ["xx", "xxx", "xx"]
}

第4步 完成Flask代码

Flask是一个轻量级的框架。我们只需要撰写很少的代码,即可实现以上的POST请求的backend处理部分。
具体代码如下,假设Python文件名为 hello.py

#!/usr/bin/python3

# Run: flask run -h  -p 7979

from flask import Flask, request
from transformers import MarianMTModel, MarianTokenizer

app = Flask(__name__)

model_name = "Helsinki-NLP/opus-mt-en-zh"
tokenizer = MarianTokenizer.from_pretrained(model_name)
model = MarianMTModel.from_pretrained(model_name)


@app.route("/")
def hello_world():
    return "

Hello, World!

"
@app.post("/translate") def translate(): data = request.get_json() word_list = data.get('target_words') translated = model.generate(**tokenizer(word_list, return_tensors="pt", padding=True)) key = 'translated_words' result = { key: [tokenizer.decode(t, skip_special_tokens=True) for t in translated] } print(result) return result if __name__ == '__main__': app.run(host='10.111.222.111',port=7979,debug=True)

从以上代码可以看出,我们在http服务器启动的时候加载了tokenizer和model,而将来接收到 POST /translate请求的时候,translate()函数里的翻译动作的耗时就很短了。

第5步 启动Flask服务器

这一步仍是在virtualenv环境下,运行以下命令

export FLASK_APP=hello.py
export FLASK_ENV=development
flask run -h 10.111.222.111 -p 7979

如果对以上命令不熟悉或容易遗忘,可以查看 flask --helpflask run --help以获得帮助。
这里指定 7979 端口号,是为了避免机器上有其他程序已经占用了Flask的默认端口5000.

至此,我们的翻译服务已经提供好了,下面就是对它进行测试了。

第6步 利用 cURL 发送 POST 翻译请求

运行以下命令

curl -X POST "http://10.111.222.111:7979/translate" -H "Content-Type: application/json" -d'{"target_words": ["clean", "how are you"]}' | jq

注意,这里必须使用 jq程序帮助解析。如果不使用jq,则cURL返回的response的内容会直接显示为像 “\u6d01” 这样的字符串形式,并不会将其按照UTF-解码。
下面是实际的执行效果。

curl -X POST "http://10.111.222.111:7979/translate" -H "Content-Type: application/json; charset=UTF-8" -d'{"target_words": ["clean", "how are you"]}' | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   121  100    79  100    42    121     64 --:--:-- --:--:-- --:--:--   186
{
  "translated_words": [
    "清洁",
    "你好吗?"
  ]
}

实测结果,响应速度非常之快,即使包括网络延迟,也不到1秒。

(END)

你可能感兴趣的:(深度学习,#,Python,flask,人工智能,python)