• 用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:])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    这里可以看到,只要调用这个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
    
    • 1
    • 2
    • 3

    注意,本博文的程序基于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
    
    • 1
    • 2
    • 3

    第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"]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    第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)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    从以上代码可以看出,我们在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
    
    • 1
    • 2
    • 3

    如果对以上命令不熟悉或容易遗忘,可以查看 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
    
    • 1

    注意,这里必须使用 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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

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

    (END)

  • 相关阅读:
    TS中的info用法
    Http与Restful之间的关系
    python的几种数据类型的花样玩法(一)
    Abbexa小鼠Asprosin ELISA试剂盒,体外定量测量好帮手!
    华为OD机考算法题:机器人活动区域
    C++中的各种“虚“-- 虚函数、纯虚函数、虚继承、虚基类、虚析构、纯虚析构、抽象类讲解
    基于SSM的垃圾分类管理系统源码
    北京工商大学计算机考研资料汇总
    【机器学习】树模型预剪枝和后剪枝
    thymeleaf,bootstrap-fileinput 多文件上传
  • 原文地址:https://blog.csdn.net/nirendao/article/details/133840663