赞
踩
https://modelscope.cn/models/damo/nlp_csanmt_translation_en2zh/summary
https://modelscope.cn/docs/%E6%A8%A1%E5%9E%8B%E7%9A%84%E5%AF%BC%E5%87%BA
根据官网上的信息进行环境配置,我在这块吃了很多亏,特别是docker镜像,不知道为什么我在镜像中就是不好用。本地需要装的包主要有三个:
这是我最终跑通的包的版本:
python 3.8.18
tensorflow 2.13.0
pytorch 2.1.0 py3.8_cuda12.1_cudnn8.9.2_0 pytorch
modelscope 1.9.5 pypi_0 pypi
其它的包可能会缺失一些,但是缺啥就pip install 啥就好,无关痛痒的问题。
也可以尝试一下使用docker(但是我失败了):
docker pull registry.cn-beijing.aliyuncs.com/modelscope-repo/modelscope:ubuntu20.04-py38-torch2.0.1-tf2.13.0-1.9.5
这个有些坑,官方的模型下载这个代码很难找,希望以后文档慢慢变得更加友好吧:
from modelscope import snapshot_download
model_dir = snapshot_download("damo/nlp_csanmt_translation_en2zh", revision = "v1.0.1",cache_dir="./model")
就使用这两行代码就可以将模型下载到当前位置。
下面的是官方示例的转换代码,会将模型转换为SavedModel 格式:
from modelscope.models import Model
model_id = 'damo/nlp_csanmt_translation_en2zh'
model = Model.from_pretrained(model_id)
from modelscope.exporters import TfModelExporter
output_files = TfModelExporter.from_model(model).export_saved_model(output_dir='./CSANMT')
print(output_files) # {'model': '/tmp'}
这里有个很坑的地方,官方提供了SavedModel 格式的模型的转换和调用代码,但是它的输入和输出都是编码的数组,并没有提供如何将输入的文本编码以及将输出内容解码的代码,我是通过看pipeline源码,仿造他们的preprocess和postprocess写的:
import tensorflow as tf
from modelscope.models.base import Model
from modelscope.utils.constant import ModelFile, Tasks
from modelscope.utils.config import Config
from sacremoses import MosesDetokenizer, MosesPunctNormalizer, MosesTokenizer
from subword_nmt import apply_bpe
from modelscope.outputs import OutputKeys
import numpy as np
import time
if tf.__version__ >= '2.0':
tf = tf.compat.v1
tf.disable_eager_execution()
cfg_dir = "./model/damo/nlp_csanmt_translation_en2zh/configuration.json"
cfg = Config.from_file(cfg_dir)
src_vocab_dir = "./model/damo/nlp_csanmt_translation_en2zh/src_vocab.txt"
# _src_vocab 是一个字典,key是英文src_vocab.txt中的一行,value是index,length = 49998, _trg_rvocab同理
_src_vocab = dict([
(w.strip(), i) for i, w in enumerate(open(src_vocab_dir))
])
trg_vocab_dir = "./model/damo/nlp_csanmt_translation_en2zh/trg_vocab.txt"
_trg_rvocab = dict([
(i, w.strip()) for i, w in enumerate(open(trg_vocab_dir))
])
input_wids = tf.placeholder(
dtype=tf.int64, shape=[None, None], name='input_wids')
output = {}
_src_lang = cfg['preprocessor']['src_lang'] #en
_tgt_lang = cfg['preprocessor']['tgt_lang'] #zh
_src_bpe_path = "./model/damo/nlp_csanmt_translation_en2zh/bpe.en"
_punct_normalizer = MosesPunctNormalizer(lang=_src_lang)
_tok = MosesTokenizer(lang=_src_lang)
_detok = MosesDetokenizer(lang=_tgt_lang)
_bpe = apply_bpe.BPE(open(_src_bpe_path))
input = ["How are you?", "OK, I am fine. Thank you! And you?", "Do you know where you are?", "Mr.Zhang test firstly!"] input = [_punct_normalizer.normalize(item) for item in input] aggressive_dash_splits = True if (_src_lang in ['es', 'fr'] and _tgt_lang == 'en') or (_src_lang == 'en' and _tgt_lang in ['es', 'fr']): aggressive_dash_splits = False input_tok = [ _tok.tokenize( item, return_str=True, aggressive_dash_splits=aggressive_dash_splits) for item in input ] input_bpe = [ _bpe.process_line(item).strip().split() for item in input_tok ] MAX_LENGTH = max([len(item) for item in input_bpe])#200 input_ids = np.array([[ _src_vocab[w] if w in _src_vocab else cfg['model']['src_vocab_size'] - 1 for w in item ] + [0] * (MAX_LENGTH - len(item)) for item in input_bpe])
tf_config = tf.ConfigProto(allow_soft_placement=True) sess = tf.Session(graph=tf.Graph(), config=tf_config) # Restore model from the saved_modle file, that is exported by TensorFlow estimator. MetaGraphDef = tf.saved_model.loader.load(sess, ['serve'], './CSANMT') # SignatureDef protobuf SignatureDef_map = MetaGraphDef.signature_def SignatureDef = SignatureDef_map['translation_signature'] # TensorInfo protobuf X_TensorInfo = SignatureDef.inputs['input_wids'] y_TensorInfo = SignatureDef.outputs['output_seqs'] X = tf.saved_model.utils.get_tensor_from_tensor_info( X_TensorInfo, sess.graph) y = tf.saved_model.utils.get_tensor_from_tensor_info( y_TensorInfo, sess.graph) sttime = time.time() outputs = sess.run(y, feed_dict={X: input_ids})
x, y, z = outputs.shape translation_out = [] for i in range(x): output_seqs = outputs[i] wids = list(output_seqs[0]) + [0] wids = wids[:wids.index(0)] translation = ' '.join([ _trg_rvocab[wid] if wid in _trg_rvocab else '<unk>' for wid in wids ]).replace('@@ ', '').replace('@@', '') translation_out.append(_detok.detokenize(translation.split())) translation_out = '<SENT_SPLIT>'.join(translation_out) result = {OutputKeys.TRANSLATION: translation_out} endtime = time.time() print(result)
以上就是一整套本地调用翻译的全部流程,将它们按顺序放在一整个脚本中就可以顺利翻译了。
import tensorflow as tf from modelscope.models.base import Model from modelscope.utils.constant import ModelFile, Tasks from modelscope.utils.config import Config from sacremoses import MosesDetokenizer, MosesPunctNormalizer, MosesTokenizer from subword_nmt import apply_bpe from modelscope.outputs import OutputKeys import numpy as np from loguru import logger from flask import Flask, request if tf.__version__ >= '2.0': tf = tf.compat.v1 tf.disable_eager_execution() app = Flask(__name__) def load_model(): cfg_dir = "./model/damo/nlp_csanmt_translation_en2zh/configuration.json" cfg = Config.from_file(cfg_dir) # model = tf.saved_model.load("/path/to/your/exported/model") src_vocab_dir = "/home/sc/vscode/trans/model/damo/nlp_csanmt_translation_en2zh/src_vocab.txt" # _src_vocab 是一个字典,key是英文src_vocab.txt中的一行,value是index,length = 49998, _trg_vocab同理 global _src_vocab, _trg_vocab _src_vocab = dict([ (w.strip(), i) for i, w in enumerate(open(src_vocab_dir)) ]) trg_vocab_dir = "/home/sc/vscode/trans/model/damo/nlp_csanmt_translation_en2zh/trg_vocab.txt" _trg_vocab = dict([ (i, w.strip()) for i, w in enumerate(open(trg_vocab_dir)) ]) global _src_lang, _tgt_lang _src_lang = cfg['preprocessor']['src_lang'] #en _tgt_lang = cfg['preprocessor']['tgt_lang'] #zh _src_bpe_path = "/home/sc/vscode/trans/model/damo/nlp_csanmt_translation_en2zh/bpe.en" global _punct_normalizer, _tok, _detok, _bpe _punct_normalizer = MosesPunctNormalizer(lang=_src_lang) _tok = MosesTokenizer(lang=_src_lang) _detok = MosesDetokenizer(lang=_tgt_lang) _bpe = apply_bpe.BPE(open(_src_bpe_path)) global sess tf_config = tf.ConfigProto(allow_soft_placement=True) sess = tf.Session(graph=tf.Graph(), config=tf_config) MetaGraphDef = tf.saved_model.loader.load(sess, ['serve'], '/home/sc/vscode/trans/CSANMT') SignatureDef_map = MetaGraphDef.signature_def SignatureDef = SignatureDef_map['translation_signature'] X_TensorInfo = SignatureDef.inputs['input_wids'] y_TensorInfo = SignatureDef.outputs['output_seqs'] global X, y X = tf.saved_model.utils.get_tensor_from_tensor_info(X_TensorInfo, sess.graph) y = tf.saved_model.utils.get_tensor_from_tensor_info(y_TensorInfo, sess.graph) # return sess def preprocess_input(data): input = [_punct_normalizer.normalize(item) for item in data] aggressive_dash_splits = True if (_src_lang in ['es', 'fr'] and _tgt_lang == 'en') or (_src_lang == 'en' and _tgt_lang in ['es', 'fr']): aggressive_dash_splits = False input_tok = [ _tok.tokenize( item, return_str=True, aggressive_dash_splits=aggressive_dash_splits) for item in input ] input_bpe = [ _bpe.process_line(item).strip().split() for item in input_tok ] MAX_LENGTH = max([len(item) for item in input_bpe]) input_ids = np.array([[ _src_vocab[w] if w in _src_vocab else cfg['model']['src_vocab_size'] - 1 for w in item ] + [0] * (MAX_LENGTH - len(item)) for item in input_bpe]) return input_ids def postprocess(data): x, y, z = data.shape translation_out = [] for i in range(x): output_seqs = data[i] wids = list(output_seqs[0]) + [0] wids = wids[:wids.index(0)] translation = ' '.join([ _trg_vocab[wid] if wid in _trg_vocab else '<unk>' for wid in wids ]).replace('@@ ', '').replace('@@', '') translation_out.append(_detok.detokenize(translation.split())) translation_out = ''.join(translation_out) return {OutputKeys.TRANSLATION: translation_out} @app.route('/predict', methods=['POST']) def predict(): logger.info("接受到POST请求,开始翻译...") data = request.get_json() input_ids = preprocess_input(data['text']) outputs = sess.run(y, feed_dict={X: input_ids}) return postprocess(outputs) if __name__ == '__main__': load_model() app.run(port=6006)
import requests import json import time url = "http://127.0.0.1:6006/predict" # 准备请求数据 data = {"text":["How are you?", "What's wrong with you?", "May I help you?", "Today is a good day!"]} json_data = json.dumps(data) start = time.time() # 发送 POST 请求 response = requests.post(url, data=json_data, headers={"Content-Type": "application/json"}) end = time.time() # 获取并解码返回的数据 if response.status_code == 200: returned_data = response.content.decode("unicode_escape") print("Returned Data:", returned_data) print("time is ", end - start) else: print("Error:", response.status_code, response.text)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。