使用Transformers库中可用的最新赫尔辛基NLP模型来创建标准化的机器翻译服务
在企业环境中需要机器翻译。 至关重要的是,跨国公司必须能够与世界各地的人们共享多种语言的文档,便笺,电子邮件和其他文本。
可以说,更为重要的是需要在全球化的同时使信息民主化。 无论您使用哪种口头语言,您都应该使用与主要口语(例如英语)相同的开源出版物,医疗保健信息,工具和知识。
> I made this in powerpoint. It's horrible.
幸运的是,机器翻译已经存在了一段时间-我们中的许多人已经使用google翻译来在线确认某物的内容,或者只是听起来聪明而世俗。 如果您有需要扩展的翻译需求,Azure,AWS和GCP都提供消耗性API,每百万个字符仅需10美元,即可支持数千种语言对(一对语言由源语言和目标语言组成)。
在开源空间中,已经进行了无数种跨多种语言的机器学习工作,并且人们早就能够训练自己的机器翻译模型。 但是,大多数方法在建模方法和支持的语言数量方面似乎是完全不同的(在我自己的幼稚评估中)。
最近,Huggingface从赫尔辛基大学发布了1,000多种预训练的语言模型。 对于希望创建自己的AWS或Google翻译API的人来说,这从未如此简单。 所以,我想我会利用别人的辛勤工作。 这相当于"让我们在Flask API和Docker镜像中包装机器学习",但无论如何,它都很有趣。 我们开始做吧。
Huggingface在将SOTA(最先进的)模型用于简单的Python API中以实现像我这样的复制+粘贴编码器方面所做的出色工作。 要在本地翻译文本,您只需要点安装变压器,然后使用以下来自变压器文档的代码段即可。
这将下载所需的模型并转换源文本->目标文本。 有了这种格式的大量支持语言,将其抛入dockerized flask应用程序并每天调用它是非常容易的,但是我们确实有很多额外的工作要做……
随时关注git repo。
当您初始化上述模型时,如果本地没有所需的文件,则转换器将下载所需的文件。 这对于本地使用来说是很棒的,但是在使用Docker容器时却不是。 由于容器的存储是短暂的,因此每次我们退出容器时,我们都会丢失所有模型,而下次需要重新下载所有模型。
为了避免这种情况,我们可以单独处理模型下载并将模型作为卷安装。 这也使我们可以更好地控制我们希望我们的服务从一开始就支持的语言。 Huggingface在S3上托管了所有必要的文件,因此我们可以对此进行标准化…
然后创建一个简单的命令行实用程序来下载它们:
酷。 现在,我们可以通过一个命令下载所需的模型。 以日语->英语为例。
python download_models.py –source ja –target zh
默认情况下,这会将它们下载到名为data的目录中,因此只需检查以确保存在。
现在,我们有了更好的方法来管理我们支持的语言,让我们先解决问题的实质,然后再使用类和相关方法来管理我们的翻译。
我们在这里需要几个功能:
· 翻译给定源语言和目标语言(duh)的文本
· 将我们没有的模型加载和管理到内存中(我用一个简单的字典)
· 获得支持的语言(我们为此应用程序下载了哪些语言?)
由于变压器对用户友好,因此几乎无需花费任何时间就可以将此功能包装到轻量级类中供我们使用。
此类已使用我们用于保存模型并自行处理其余部分的路径进行了初始化。 如果我们收到翻译请求,但内存中没有该模型,则会调用load_models将其加载到self.models字典中。 这将检查我们的数据目录以查看是否具有该模型,并返回一条消息以告知我们是否这样做。
现在我们需要做的就是将其包装在flask中,以便可以对其进行HTTP调用。
要使用它,只需运行python App.py,然后调用该服务即可。 要检查其是否正常运行,您可以卷曲localhost:5000或使用更复杂的工具(例如Postman)。 我在这里使用Flask服务器,但您希望生产Web服务器在实际的任何地方都可以使用它。
现在,我们的应用程序可以使用基本的Python,我们希望使其能够与Docker或docker-compose一起使用,以便我们可以根据需要扩展和扩展它。 我们为此使用的实际Dockerfile非常简单。 我们只需要确保在连接了卷的情况下运行该服务,以便该服务已经可以访问数据。
我通常会使用较小的基本图片,但说实话,我不想调试:
生成并运行命令:
docker build -t machine-translation-service .
docker run -p 5000:5000 -v $(pwd)/data:/app/data -it machine-translation-service
同样,我们可以通过调用服务来测试端点。 如果我下载了en-> fr之类的语言路线,则应该可以使用curl进行以下API调用:
curl --location --request POST 'http://localhost:5000/translate'
--header 'Content-Type: application/json'
--data-raw '{ "text":"hello", "source":"en", "target":"fr"}'
我将服务包装在一个小烧瓶API中,甚至"正确地"将其制成可以以可重现方式扩展的Docker容器。 但是,我想分享一些使用此方法的问题。
这些翻译模型非常大(每个模型大约300MB)。 即使数据/模型是单独下载的,我们仍然需要在内存中加载我们要支持的每种语言对,而对于单个容器,这很快就会变得一发不可收拾。
因此,为什么不创建一个可配置的映像,我们可以使用它来使用docker-compose为每个服务启动一个容器? 这样一来,每对语言就可以提供一项服务,并且每对语言都可以根据需求的增长而单独扩展。 然后,我们可以编写一个公开的API,将请求传递给网络中的所有容器。
免责声明:至此,我才开始进行化妆,但我丝毫不相信这是最佳方法-但我想知道我能走多远。
为了开始工作,我对目录做了一些修改。 要查看它,您可以探索我制作的git上的分支:
代理的目的是将请求重定向到启动的每个机器翻译服务。 这将是唯一公开的端点。 我为支持en-> fr翻译的服务制作了一个快速的docker-compose文件。
每个翻译服务都具有相同的env变量(我应该只制作一个.env文件),相同的命令和包含我们模型的相同卷。 可以使用yaml自动化或类似方法来更好地扩展此功能,但我还没有到达那里。
在那之后,我只是对代理的/ translate端点做了一些难看的工作,以便根据需要构造请求的服务端点。 当用户向该公开服务发出请求时,它将向该容器内只能访问的其他容器发出另一个请求。
我们要做的就是建立基础映像。
cd translation_basedocker build -t translation_base
然后启动服务。
docker-compose up
这是使用POSTMAN的输出截图。
这里不做深入探讨,但是合理的下一步是将其带入kubernetes以实现真正的规模。 一个简单的起点是使用kompose CLI将docker-compose转换为kubernetes YAML。 在macOS上:
$brew install kompose
$kompose convert
INFO Kubernetes file "translation-proxy-service.yaml" created
INFO Kubernetes file "en-fr-deployment.yaml" created
INFO Kubernetes file "en-fr-claim0-persistentvolumeclaim.yaml" created
INFO Kubernetes file "fr-en-deployment.yaml" created
INFO Kubernetes file "fr-en-claim0-persistentvolumeclaim.yaml" created
INFO Kubernetes file "translation-proxy-deployment.yaml" created
这会创建一些YAML文件,您需要这些文件才能将服务和部署扩展到K8。
这是fr-en服务的示例部署:
一旦配置了kubernetes集群,就可以kubectl apply -f $ FILENAME来创建服务,部署和持久卷声明。
当然,还有更多的工作要做,还要创建更多的kubernetes对象,但是我想为任何实际想要扩展此范围的人提供一个简单的入门。
我希望Huggingface能够继续构建工具(以及专门的研究人员训练的模型)继续为智能机器学习提供公平的访问权限。 开放式机器翻译的努力不仅为研究领域做出了贡献,而且使全世界都可以使用一种语言编写极其重要的资源。
我不知道自己托管这些庞大的模型是否比使用AWS或Google Translate API便宜一半,而且我也没有探索其质量。 但这很有趣,希望可以为您提供可用的数千种SOTA机器学习模型为您提供的知识。
(本文翻译自Kyle Gallatin的文章《Build Your Own Machine Translation Service with Transformers》,参考:
https://towardsdatascience.com/build-your-own-machine-translation-service-with-transformers-d0709df0791b)