From: jaekuk, lee Date: Wed, 31 Mar 2021 01:41:20 +0000 (+0900) Subject: [NMT] native node module for NMT so wrapping X-Git-Tag: submit/tizen/20210915.160018^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F06%2F256206%2F30;p=platform%2Fframework%2Fweb%2Fwrtjs.git [NMT] native node module for NMT so wrapping It uses NMT shared libraries provided by On Device AI F/W. Using API set provided by this module, it can translate the contents of web app. Supportive API Set - init - uninit - setPath - translate - getAvailableSourceLanguage - getAvailableTargetLanguageList - isDirectionAvailable - getModelList nmt feature is supported by default for public profile. If using nmt feature for the other profiles, use nmt option. $ ./tizen/build/build_tv.sh --nmt Related patch: https://review.tizen.org/gerrit/#/c/platform/framework/web/chromium-efl/+/253460 Change-Id: I0aaa9d822b89c1632ac09a29623b88c5eeb3c554 Signed-off-by: jaekuk, lee --- diff --git a/BUILD.gn b/BUILD.gn old mode 100644 new mode 100755 index 1a9e2122..62f9de22 --- a/BUILD.gn +++ b/BUILD.gn @@ -27,10 +27,22 @@ toolchain("gcc") { command = "touch {{output}}" description = "STAMP {{output}}" } + tool("solink") { + soname = "{{target_output_name}}{{output_extension}}" + rpath = "-Wl,-soname,$soname" + command = "g++ -shared {{ldflags}} {{inputs}} {{solibs}} {{libs}} $rpath -o {{output}}" + outputs = [ + "{{root_out_dir}}/$soname", + ] + output_prefix = "lib" + default_output_extension = ".so" + description = "link {{output}}" + } } group("wrt_group") { deps = [ "//loader:wrt-loader", + "//wrt_feature/nmt_service:nmt", ] } diff --git a/packaging/wrtjs.spec b/packaging/wrtjs.spec index 4d6c1e73..1e5a9411 100755 --- a/packaging/wrtjs.spec +++ b/packaging/wrtjs.spec @@ -19,9 +19,14 @@ Source: %{name}-%{version}.tar.gz %define _use_d2d 1 %endif +# The nmt is public feature +%if "%{?profile}" != "tv" && "%{?profile}" != "wearable" && "%{?_with_da_profile}" != "1" + %define _use_nmt 1 +%endif + BuildRequires: pkgconfig(chromium-efl) -%if "%{?profile}" != "tv" +%if "%{?profile}" != "tv" || 0%{?_use_nmt} BuildRequires: ninja BuildRequires: pkgconfig(dlog) %endif @@ -81,6 +86,14 @@ Web Runtime Engine based on Electron ninja -C %{_outdir} wrt-loader %endif +%if 0%{?_use_nmt} +%if "%{?profile}" == "tv" + %define _outdir $PWD/out + ./build/tools/gn gen %{_outdir} +%endif + ninja -C %{_outdir} nmt +%endif + ./build/tools/node ./node_modules/.bin/tsc absolute_appdir=$PWD/%{app_dir} (cd wrt_app/ && find . -type f ! -name '*.ts' -exec cp --parents {} ${absolute_appdir} \;) @@ -180,6 +193,12 @@ cp -r %{app_dir}/* %{buildroot}%{_resourcedir}/ rm -f %{buildroot}/%{_d2d_wgt_file_name} %endif +%if 0%{?_use_nmt} + install -m 0644 wrt_feature/nmt_service/node_modules/nmt/lib/%{ARCHITECTURE}/* "%{buildroot}"%{_libdir}/ + install -d %{buildroot}%{_datadir}/wrt/feature/nmt_service/node_modules + install -m 0644 "%{_outdir}"/libnmt.node %{buildroot}%{_datadir}/wrt/feature/nmt_service/node_modules/ +%endif + %pre export CHROMIUM_REVISION= if [ -f "%{_datadir}/chromium-efl/version" ]; then @@ -238,6 +257,17 @@ rm -fr %{buildroot} %endif %{_datadir}/wrtjs/version %{_libdir}/%{crosswalk_extensions_service}/plugins.json + +%if 0%{?_use_nmt} + %{_libdir}/libmanager.so + %{_libdir}/libsentencepiece.so.0 + %{_libdir}/libsr_odnmt.so + %{_libdir}/libsrcb_bpe.so + %{_libdir}/libsrcb_langid.so + %{_libdir}/libtransformer.so + %{_datadir}/wrt/feature/nmt_service/node_modules/libnmt.node +%endif + %{_resourcedir}/* %if 0%{?__package_signing} %{WRTJS_APP_DIR}/author-signature.xml diff --git a/tizen/build/common.sh b/tizen/build/common.sh index c62935ab..15c4f848 100755 --- a/tizen/build/common.sh +++ b/tizen/build/common.sh @@ -29,6 +29,7 @@ function setupAndExecuteTargetBuild() { local LOCAL_BUILD=1 local PROFILE local USE_D2D + local USE_NMT local USE_TPK local -a ARGS @@ -42,6 +43,9 @@ function setupAndExecuteTargetBuild() { --d2d) USE_D2D=1 ;; + --nmt) + USE_NMT=1 + ;; --standard*) PROFILE=tz_$(echo $1 | sed 's/--//g') ;; @@ -73,6 +77,9 @@ function setupAndExecuteTargetBuild() { if [ "$USE_D2D" == "1" ]; then ARGS+=(--define "_use_d2d 1") fi + if [ "$USE_NMT" == "1" ]; then + ARGS+=(--define "_use_nmt 1") + fi if [ "$USE_TPK" == "1" ]; then ARGS+=(--define "_use_tpk 1") if [ "$USE_TPK_UPGRADE" == "1" ] && [ $platform == "tv" ]; then diff --git a/wrt_app/common/config-search-paths.ts b/wrt_app/common/config-search-paths.ts old mode 100644 new mode 100755 index 20be3087..8555917f --- a/wrt_app/common/config-search-paths.ts +++ b/wrt_app/common/config-search-paths.ts @@ -7,6 +7,8 @@ const originalResolveFilename = Module._resolveFilename; Module._resolveFilename = function (request: string, parent: NodeModule, isMain: boolean) { if (request === 'addonapi' && process.type) return path.join(__dirname, '..', 'addon', process.type as string, 'addonapi.js'); + else if (request === 'node-nmt') + return path.join(__dirname, '..', '..', 'feature/nmt_service/node_modules', 'libnmt.node'); else return originalResolveFilename(request, parent, isMain); } diff --git a/wrt_feature/nmt_service/BUILD.gn b/wrt_feature/nmt_service/BUILD.gn new file mode 100755 index 00000000..607558b3 --- /dev/null +++ b/wrt_feature/nmt_service/BUILD.gn @@ -0,0 +1,32 @@ +shared_library("nmt") { + output_name = "nmt" + output_extension = "node" + libs = [ + "dlog", + "chromium-impl", + "manager", + "sr_odnmt", + "srcb_bpe", + "srcb_langid", + "transformer", + ] + lib_dirs = [ + "/usr/share/chromium-efl/lib", + "node_modules/nmt/lib/armv7l" + ] + include_dirs = [ + "/usr/include/node", + "/usr/include/v8", + "node_modules/nmt/inc", + ] + sources = [ + "node_modules/nmt/nmt.cpp", + "node_modules/nmt/nmt.h", + "node_modules/nmt/inc/translator.h", + ] + ldflags = [ + "-shared", + "-Wl,--export-dynamic" + ] + cflags = ["-fPIC"] +} diff --git a/wrt_feature/nmt_service/node_modules/nmt/inc/translator.h b/wrt_feature/nmt_service/node_modules/nmt/inc/translator.h new file mode 100755 index 00000000..225e72f4 --- /dev/null +++ b/wrt_feature/nmt_service/node_modules/nmt/inc/translator.h @@ -0,0 +1,33 @@ +#include + +#include +#include +#include + +using namespace std; + +class Manager; + +namespace SrOnDeviceNmt { + +class Translator { + public: + Translator(); + Translator(vector path); + + ~Translator() { clear(); }; + void setPath(vector modelpath); + void setDetectorPath(string modelpath); + string translate(string inputSequence, string srcLang, string tgtLang); + string detectLanguage(string tgtLang, string inputSequence, bool verbose); + vector getAvailableSourceLanguageList(); + vector getAvailableTargetLanguageList(string srcLang); + int isDirectionAvailable(string srcLang, string tgtLang); + private: + void clear(); + vector path; + std::shared_ptr manager; + bool check_model(); +}; + +} // namespace SrOnDeviceNmt diff --git a/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libmanager.so b/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libmanager.so new file mode 100755 index 00000000..2c926fc8 Binary files /dev/null and b/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libmanager.so differ diff --git a/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libsentencepiece.so.0 b/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libsentencepiece.so.0 new file mode 100755 index 00000000..2cb5987f Binary files /dev/null and b/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libsentencepiece.so.0 differ diff --git a/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libsr_odnmt.so b/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libsr_odnmt.so new file mode 100755 index 00000000..8743df0d Binary files /dev/null and b/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libsr_odnmt.so differ diff --git a/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libsrcb_bpe.so b/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libsrcb_bpe.so new file mode 100755 index 00000000..5a75dea5 Binary files /dev/null and b/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libsrcb_bpe.so differ diff --git a/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libsrcb_langid.so b/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libsrcb_langid.so new file mode 100755 index 00000000..82a618d9 Binary files /dev/null and b/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libsrcb_langid.so differ diff --git a/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libtransformer.so b/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libtransformer.so new file mode 100755 index 00000000..020e3189 Binary files /dev/null and b/wrt_feature/nmt_service/node_modules/nmt/lib/armv7l/libtransformer.so differ diff --git a/wrt_feature/nmt_service/node_modules/nmt/nmt.cpp b/wrt_feature/nmt_service/node_modules/nmt/nmt.cpp new file mode 100755 index 00000000..c71ec8e5 --- /dev/null +++ b/wrt_feature/nmt_service/node_modules/nmt/nmt.cpp @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include "nmt.h" +#include "translator.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "WRT_SERVICE_NMT" + +using namespace node; +using namespace v8; +using namespace std; +using namespace SrOnDeviceNmt; + +namespace wrt { +namespace service { + +static void logd(const char* tag, const char* format, ...){ + va_list args; + va_start(args, format); + LOG_VA(LOG_DEBUG, tag, format, args); + va_end(args); +} + +static NMT *_nmt = NULL; +static Translator translator; + +static map> model_list = { + {"bg", {"Bulgarian", "rmE8Va3gon"}}, + {"cs", {"Czech", "o9i8ZKUGk4"}}, + {"de", {"German", "cwzIAj3oJT"}}, + {"es", {"Spanish", "4KKRqmCg5x"}}, + {"fr", {"French", "0HEUtxuBp6"}}, + {"it", {"Italian", "6io0TjUf1z"}}, + {"ko", {"Korean", "UkFnQa8EAT"}}, + {"nl", {"Dutch", "bjPxXxwt5E"}}, + {"pl", {"Polish", "wgjC6UsLUJ"}}, + {"pt", {"Portuguese", "356EJyAM9o"}}, + {"ru", {"Russian", "mq7ZH7ehh0"}}, + {"zh", {"Chinese", "OJ981RFTyA"}}, +}; + +NMT::NMT(){ +} + +NMT::~NMT(){ +}; + +void NMT::Init(){ + logd(LOG_TAG, __PRETTY_FUNCTION__); +} + +void NMT::Uninit(){ + logd(LOG_TAG, __PRETTY_FUNCTION__); +} + +void NMT::SetPath(){ + logd(LOG_TAG, __PRETTY_FUNCTION__); + vector data_paths; + for(map>::iterator iter = model_list.begin(); iter != model_list.end(); ++iter ){ + string modelPath = "/opt/usr/globalapps/" + iter->second.second + "/shared/res/assets"; + if(access(modelPath.c_str(), 0) != -1) + data_paths.push_back(modelPath); + } + translator.setPath(data_paths); +} + +static void NMTinit(const FunctionCallbackInfo& /*args*/){ + logd(LOG_TAG, __PRETTY_FUNCTION__); + if (_nmt == NULL) { + _nmt = new NMT(); + } + _nmt->Init(); + _nmt->SetPath(); +} + +static void NMTuninit(const FunctionCallbackInfo& /*args*/){ + logd(LOG_TAG, __PRETTY_FUNCTION__); + if (_nmt != NULL) { + _nmt->Uninit(); + delete _nmt; + _nmt = NULL; + } +} + +static void NMTsetPath(const FunctionCallbackInfo& args){ + logd(LOG_TAG, __PRETTY_FUNCTION__); + if (_nmt == NULL) { + _nmt = new NMT(); + _nmt->Init(); + } + Isolate* isolate = args.GetIsolate(); + HandleScope scope(isolate); + _nmt->SetPath(); + args.GetReturnValue().Set(Undefined(isolate)); + +} + +static void NMTtranslate(const FunctionCallbackInfo& args){ + logd(LOG_TAG, __PRETTY_FUNCTION__); + if (_nmt == NULL) { + _nmt = new NMT(); + _nmt->Init(); + } + Isolate* isolate = args.GetIsolate(); + HandleScope scope(isolate); + if(args.Length() != 3 || !args[0]->IsString() || !args[1]->IsString() || !args[2]->IsString()) { + logd(LOG_TAG, "Invalid Argument"); + return; + } + + string str0(*String::Utf8Value(isolate, args[0])); + string str1(*String::Utf8Value(isolate, args[1])); + string str2(*String::Utf8Value(isolate, args[2])); + + string transResult = translator.translate(str0, str1, str2); + args.GetReturnValue().Set(String::NewFromUtf8(isolate, transResult.c_str()).ToLocalChecked()); +} + +static void NMTgetAvailableSourceLanguageList(const FunctionCallbackInfo& args){ + logd(LOG_TAG, __PRETTY_FUNCTION__); + if (_nmt == NULL) { + _nmt = new NMT(); + _nmt->Init(); + } + Isolate* isolate = args.GetIsolate(); + HandleScope scope(isolate); + + vector sourcelist = translator.getAvailableSourceLanguageList(); + if (sourcelist.size()) { + Local array = Array::New(isolate, sourcelist.size()); + int idx = 0; + for (auto it = sourcelist.begin(); it != sourcelist.end(); ++it) { + array->Set(isolate->GetCurrentContext(), Integer::New(isolate, idx++), String::NewFromUtf8(isolate, it->c_str()).ToLocalChecked()); + } + args.GetReturnValue().Set(array); + } + else { + logd(LOG_TAG, "Invalid Result"); + args.GetReturnValue().Set(Undefined(isolate)); + } +} + +static void NMTgetAvailableTargetLanguageList(const FunctionCallbackInfo& args){ + logd(LOG_TAG, __PRETTY_FUNCTION__); + if (_nmt == NULL) { + _nmt = new NMT(); + _nmt->Init(); + } + Isolate* isolate = args.GetIsolate(); + HandleScope scope(isolate); + if(args.Length() != 1 || !args[0]->IsString()) { + logd(LOG_TAG, "Invalid Argument"); + return; + } + + string str(*String::Utf8Value(isolate, args[0])); + vector targetlist = translator.getAvailableTargetLanguageList(str); + if (targetlist.size()) { + Local array = Array::New(isolate, targetlist.size()); + int idx = 0; + for (auto it = targetlist.begin(); it != targetlist.end(); ++it) { + array->Set(isolate->GetCurrentContext(), Integer::New(isolate, idx++), String::NewFromUtf8(isolate, it->c_str()).ToLocalChecked()); + } + args.GetReturnValue().Set(array); + } + else { + logd(LOG_TAG, "Invalid Result"); + args.GetReturnValue().Set(Undefined(isolate)); + } +} + +static void NMTisDirectionAvailable(const FunctionCallbackInfo& args){ + logd(LOG_TAG, __PRETTY_FUNCTION__); + if (_nmt == NULL) { + _nmt = new NMT(); + _nmt->Init(); + } + Isolate* isolate = args.GetIsolate(); + HandleScope scope(isolate); + if(args.Length() != 2 || !args[0]->IsString() || !args[1]->IsString()) { + logd(LOG_TAG, "Invalid Argument"); + return; + } + + string str0(*String::Utf8Value(isolate, args[0])); + string str1(*String::Utf8Value(isolate, args[1])); + int avail = translator.isDirectionAvailable(str0, str1); + args.GetReturnValue().Set(avail); + +} + +static void NMTgetModelList(const FunctionCallbackInfo& args){ + logd(LOG_TAG, __PRETTY_FUNCTION__); + if (_nmt == NULL) { + _nmt = new NMT(); + _nmt->Init(); + } + Isolate* isolate = args.GetIsolate(); + HandleScope scope(isolate); + + if (model_list.size()) { + string modelListResult, modelData; + for (auto it = model_list.begin(); it != model_list.end(); ++it) { + if (it != model_list.begin()) + modelData = modelData + ","; + modelData = modelData + "{\"model\":\""+it->first+"\",\"name\":\""+it->second.first+"\",\"pkgId\":\""+it->second.second+"\"}"; + } + modelListResult = "{\"modelList\":[" +modelData + "]}"; + args.GetReturnValue().Set(String::NewFromUtf8(isolate, modelListResult.c_str()).ToLocalChecked()); + } + else { + logd(LOG_TAG, "Invalid Result"); + args.GetReturnValue().Set(Undefined(isolate)); + } +} + + +static void init(Handle target) { + NODE_SET_METHOD(target, "init", NMTinit); + NODE_SET_METHOD(target, "uninit", NMTuninit); + NODE_SET_METHOD(target, "setPath", NMTsetPath); + NODE_SET_METHOD(target, "translate", NMTtranslate); + NODE_SET_METHOD(target, "getAvailableSourceLanguageList", NMTgetAvailableSourceLanguageList); + NODE_SET_METHOD(target, "getAvailableTargetLanguageList", NMTgetAvailableTargetLanguageList); + NODE_SET_METHOD(target, "isDirectionAvailable", NMTisDirectionAvailable); + NODE_SET_METHOD(target, "getModelList", NMTgetModelList); +} + +NODE_MODULE(nmt, init); + +} // namespace service +} // namespace wrt diff --git a/wrt_feature/nmt_service/node_modules/nmt/nmt.h b/wrt_feature/nmt_service/node_modules/nmt/nmt.h new file mode 100755 index 00000000..7a659eb0 --- /dev/null +++ b/wrt_feature/nmt_service/node_modules/nmt/nmt.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WRT_SERVICE_NODE_NMT_H_ +#define WRT_SERVICE_NODE_NMT_H_ + +#include +#include +using namespace std; + +namespace wrt { +namespace service { + +class NMT { +public: + NMT(); + virtual ~NMT(); + void Init(); + void Uninit(); + void SetPath(); +private: +}; + +} // namespace service +} // namespace wrt + +#endif // WRT_SERVICE_NODE_NMT_H_