<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          為 ModelArts JupyterLab 擼一個漢化插件

          共 10547字,需瀏覽 22分鐘

           ·

          2021-03-13 22:39

          ?

          如何持續(xù)輸出?是一直困擾著我的難題。想來想去,原來是因為沒有輸入,對,就是每天沒有學(xué)習(xí)新的知識;造成的后果也不言而喻--工作七年了經(jīng)驗值接近零!今天偶然看到一個小工具的源碼,打開了我的思路,因此,我想為 ModelArts JupyterLab 打造一款專屬 Chrome 插件!當(dāng)然此方法理論上適合任何定制化漢化(或多語言)插件,請看 Copy 攻城獅如何 Copy !

          ?

          背景概要

          • 什么是 ModelArts?
            ModelArts 是華為云一站式 AI 開發(fā)平臺,涵蓋了 AI 應(yīng)用開發(fā)中數(shù)據(jù)準(zhǔn)備、訓(xùn)練、評估、部署全流程和端、邊、云全場景;小白開發(fā)者可以借助 ModelArts 輕輕松松從零到一開發(fā)屬于自己的 AI 應(yīng)用,像 Copy 攻城獅本大獅使用 ModelArts 不費吹灰之力就完成了“螞蟻牙黑”的視頻合成[1];大神工程師使用 ModelArts 能“煉丹好好煉丹煉好丹”,也不乏一些高端應(yīng)用,比如 @Tianyi_Li 實現(xiàn)的“自動駕駛[2]”。當(dāng)然,借力 ModelArts,AI 在各行各業(yè)實現(xiàn)了賦能,比如通過 ModelArts 自動學(xué)習(xí)能力構(gòu)建并完善聲音模型實現(xiàn)雨林的盜伐監(jiān)聽,實現(xiàn)了保護雨林的 AI 應(yīng)用;借助 ModelArts 的海量數(shù)據(jù)預(yù)處理及智能標(biāo)注、大規(guī)模分布式訓(xùn)練及深度學(xué)習(xí),實現(xiàn)優(yōu)質(zhì)的個性化內(nèi)容精準(zhǔn)觸達(dá)……如果您想初步了解 ModelArts,希望我的歷史博文發(fā)揮作用--云享 MindTalks 第十三期:ModelArts 讓 AI 應(yīng)用開發(fā)更簡單[3]

          • 什么是 JupyterLab?
            JupyterLab 是Project Jupyter[4]的下一代基于 Web 的用戶界面,用于 Jupyter Notebook、代碼和數(shù)據(jù)的基于 Web 的交互式開發(fā)環(huán)境,而Project Jupyter[5]的存在是為了開發(fā)跨多種編程語言的交互式計算的開源軟件,開放標(biāo)準(zhǔn)和服務(wù)。常常用在數(shù)據(jù)科學(xué)、科學(xué)計算和機器學(xué)習(xí)中的各種工作流程,因此也經(jīng)常被用作 AI 應(yīng)用開發(fā)及數(shù)據(jù)分析的輔助工具。而 ModelArts JupyterLab 是常用的開發(fā)環(huán)境,您可以用來學(xué)習(xí)機器學(xué)習(xí)中的數(shù)學(xué)[6](PS:本大獅計劃跟老齊前輩學(xué)習(xí)學(xué)習(xí)),可以玩玩爬蟲[7]或者數(shù)據(jù)可視化……不過對于“English is very pool”的我,面對 JupyterLab 全英文的操作界面,尤其是我開了 Google 翻譯插件之后,我徹底懵圈了!看法?跑?吉特?神翻譯啊!怎么辦?

          • 機緣巧合
            有時候靈感就來源于“跨界”。最近計劃實現(xiàn)一個野生動物保護的公益小程序,需要自己畫原型并設(shè)計 UI,了解到目前最流行最推薦的工具是 Figma[8](是念費伽馬嗎?),當(dāng)然,同樣是全英文,不過國內(nèi)硬核玩家已經(jīng)編寫了漢化小插件--FigmaCN[9],這是中文 Figma 插件,由設(shè)計師人工翻譯校驗。通過下載查看 FigmaCN 的源碼,我了解到原來“開發(fā)”漢化的 Chrome 插件這么簡單,于是就有了漢化 ModelArts JupyterLab 的想法,剛好也查了資料,了解到目前 JupyterLab 3.0+已經(jīng)有中文插件可以使用,是由一位熱心老外貢獻(xiàn)的--jupyterlab-language-pack-zh-CN[10],不過似乎體驗還有待優(yōu)化。不過,ModelArts 上的 JupyterLab 暫時是 2.0 的版本,因此我萌生了自己制作漢化插件的想法,希望通過漢化之后的 JupyterLab 學(xué)習(xí)更多的技巧。Just Do IT!

          文檔先行

          套用一句老話:“道路千萬條,文檔第一條”。開發(fā)不看文檔,那是真的牛;開發(fā)不寫文檔,也是真的牛!當(dāng)我想開發(fā) Chrome 插件的時候,第一條路可能最合適的就是看官方的開發(fā)文檔了--擴展程序開發(fā)文檔[11]。據(jù)我多年的 HW 開發(fā)經(jīng)驗,閱讀文檔時,您可能就會看到一個“Hello World”;當(dāng)然,Chrome 插件開發(fā)也不例外。開發(fā) Chrome 插件您可能需要掌握 WEB 開發(fā)的三大劍--HTML、CSS、JavaScript,根據(jù)文檔,并參考開源庫GoogleChrome/chrome-extensions-samples[12],開始我們的 Chrome 插件“Hello World 之旅"(順便給官方文檔提了一個**PR[13]**)。

          目前 Chrome 插件的主程序已經(jīng)更新到 V3 版本了,使用 MV3 的擴展將在安全性,隱私性和性能方面得到增強;此外還可以使用 MV3 中采用的更多現(xiàn)代開放式 Web 技術(shù),例如 Service Workers 和 Promise。因此,我們基于第三代 Chrome 插件開發(fā)。

          先新建一個目錄,取名為Hello World,包含三個文件--background.jshello.htmlmanifest.json,從后綴名可以看出一些端倪,.json是配置文件也是插件的描述文件,.js是邏輯代碼文件,.html是頁面文件;這是一個簡單的插件雛形。具體代碼如下:

          Hello World
           
           
           

          簡單的代碼,實現(xiàn)的功能就是安裝完插件就打開 hello.html ,要想預(yù)覽效果需要將本地瀏覽器的插件應(yīng)用開啟開發(fā)者模式。官方文檔給出的步驟如下:
          ① chrome://extensions 在瀏覽器中導(dǎo)航到。您還可以通過點擊多功能框右上角的 Chrome 菜單,將鼠標(biāo)懸停在“更多工具”上,然后選擇擴展程序來訪問此頁面。
          ② 選中“開發(fā)人員模式”旁邊的框。
          ③ 單擊“加載解壓縮的擴展名”,然后為“ Hello 擴展名”擴展名選擇目錄。

          編寫插件

          我們先來看看 MV3 規(guī)定的 manifest.json 改如何編寫,打開文檔mv3/manifest[14],您就能看到一份 json,必填的字段:

            "manifest_version": 3,        // 使用MV3必填 3
            "name""My Extension",       // 插件名稱
            "version""versionString",   // 插件版本

          其他的參數(shù)按需填寫,其中我比較關(guān)心的是圖標(biāo)及其他文件加載,了解到 icons 字段可以定義圖標(biāo),content_scripts可以注入內(nèi)容腳本,background可注入后臺腳本,值得注意的是 MV3 相比 MV2,不再無法加載 JavaScript 或 Wasm 文件之類的遠(yuǎn)程代碼,也就是說我們所有的邏輯必須在本地完成(暫時這么理解)。因此,我的配置文件如下:

          {
            "name""StartAI",
            "version""0.1",
            "manifest_version"3,
            "short_name""StartAI",
            "description""ModelArts 工具集,JupyterLab 漢化插件,學(xué)AI就用 ModelArts,學(xué)AI就上 huaweicloud.ai。",
            "homepage_url""http://huaweicloud.ai",
            "icons": {
              "16""images/icon16.png",
              "24""images/icon24.png",
              "32""images/icon32.png",
              "48""images/icon48.png",
              "128""images/icon128.png"
            },
            "background": {
              "service_worker""background.js"
            },
            "content_scripts": [
              {
                "matches": ["*://notebook01-modelarts-cnnorth4.huaweicloud.com/*"],
                "js": ["js/content.js"],
                "run_at""document_end",
                "all_frames"true
              }
            ]
          }

          重點介紹一下content_scripts,這里配置的是我們的核心邏輯,這段配置的大概含義是:當(dāng)瀏覽器訪問的 url 匹配到 matches 字段中的網(wǎng)站時,等待頁面加載完成,執(zhí)行我們的核心邏輯。通過上面的配置文件,也大概猜的出我們這個插件的目錄結(jié)構(gòu):

          hello-world
          ├─ images
          │ ├─ icon128.png
          │ ├─ icon16.png
          │ ├─ icon24.png
          │ ├─ icon32.png
          │ └─ icon48.png
          ├─ js
          │ └─ content.js
          ├─ background.js
          └─ manifest.json

          background.js中寫的是安裝插件成功時打開一個新的 tab,顯示我們想要顯示的內(nèi)容,如引導(dǎo)頁:

          chrome.runtime.onInstalled.addListener(async () => {
            // 此處可打開本地頁面
            // let url = chrome.runtime.getURL("hello.html");
            // let tab = await chrome.tabs.create({ url });
            // console.log(`Created tab ${tab.id}`);
            chrome.tabs.create({
              url"http://huaweicloud.ai",
            });
          });

          點擊插件中心 Update 按鈕之后,就會打開我們設(shè)置的網(wǎng)頁,當(dāng)匹配到我們預(yù)設(shè)的網(wǎng)站時,插件就被激活,明顯會看到圖標(biāo)被點亮。看了半天,似乎發(fā)現(xiàn)原來 Chrome 插件開發(fā)這么簡單!

          接著就是核心邏輯--漢化,思路是通過MutationObserver[15]監(jiān)聽 DOM 何時更改,DOM 的任何變動,比如節(jié)點的增減、屬性的變動、文本內(nèi)容的變動,這個 API 都可以捕獲到,因此當(dāng)我們在頁面上進(jìn)行操作時,都能實時動態(tài)翻譯我們匹配好的內(nèi)容。代碼實現(xiàn)如下:

          // contant.js

          // 定義臨時空數(shù)組
          let allData = [];
          // 中英文匹配
          const jsonData = {
              // "": {
              //     "domain": "jupyterlab",
              //     "language": "zh-CN",
              //     "plural_forms": "nplurals=1; plural=0;",
              //     "version": "3.0.0b4"
              // },
             "\nConnected: %1": [
                 "\n\u5df2\u8fde\u63a5: %1"
             ],
             "\nCreated: %1": [
                 "\n\u521b\u5efa\u65f6\u95f4\uff1a%1"
             ],
             // …… 此處省略 2400 行,詳見 https://github.com/jupyterlab/language-packs
          }

          // 處理數(shù)據(jù),形如:[["File", "文件"],["Edit","編輯"]]
          allData = Object.keys(jsonData).map(item=>([item,jsonData[item][0]]))

          // 引入觀察器 MutationObserver
          let MutationObserver = window.MutationObserver || window.WebKitMutationObserver;

          // 觀察器的配置(需要觀察什么變動)
          let MutationObserverConfig = {
            childListtrue,
            subtreetrue,
            attributeFilter: ["data-label"],
            characterDatatrue,
          };

          // 創(chuàng)建一個觀察器實例并傳入回調(diào)函數(shù)
          let observer = new MutationObserver(function (mutations{
            let treeWalker = document.createTreeWalker(
              document.body,
              NodeFilter.SHOW_ALL,
              {
                acceptNodefunction (node{
                  if (node.nodeType === 3 || node.hasAttribute("data-label")) {
                    return NodeFilter.FILTER_ACCEPT;
                  } else {
                    return NodeFilter.FILTER_SKIP;
                  }
                },
              },
              false
            );

            // 映射中文
            let dataMap = new Map();
            for (i in jsonData) {
              if (i && !dataMap.has(i)) {
                dataMap.set(i, jsonData[i][0]);
              }
            }
             allData.forEach(([key, val]) => {
               if (key && !dataMap.has(key)) {
                 dataMap.set(key, val);
               }
             });
            let currentNode = treeWalker.currentNode;

            //  替換
            while (currentNode) {
              if (currentNode.nodeType === 3) {
                let key1 = currentNode.textContent;
                if (dataMap.has(key1)) currentNode.textContent = dataMap.get(key1);
              } else {
                let key2 = currentNode.getAttribute("data-label");
                if (dataMap.has(key2))
                  currentNode.setAttribute("data-label", dataMap.get(key2));
              }

              currentNode = treeWalker.nextNode();
            }
          });

          // 開始觀察目標(biāo)節(jié)點
          observer.observe(document.body, MutationObserverConfig);

          最終的效果還算滿意,基本能夠使用全部已有的翻譯數(shù)據(jù),當(dāng)然,源數(shù)據(jù)中存在未翻譯項,比如["Notebook":["NoteBook"]],這樣的數(shù)據(jù)會導(dǎo)致插件異常,從而使頁面卡死,具體什么原因還沒排查到,大概是因為死循環(huán)了,無意中踩過了這個坑。

          發(fā)布

          最后的發(fā)布,我不太愿意談太多,主要不想給 Google 打廣告,因為發(fā)布需要象征性的收取 5 刀,因此您可能需要全球信用卡。具體步驟如下:上傳應(yīng)用程序的過程很簡單:

          • 將應(yīng)用程序的根目錄(包含 manifest.json 文件的文件夾)壓縮為.zip 文件。
          • 交錢開通資格。
          • 去到控制臺單擊添加新項目。
          • 接受條款和服務(wù)協(xié)議。
          • 使用“選擇文件”對話框在系統(tǒng)中查找.zip 文件并選擇。
          • 其他信息維護及測試。

          截止發(fā)稿,Copy 攻城獅翻箱倒柜還沒找著信用卡,就先到這,待 Notebook 一鍵分享功能開發(fā)完畢之后再注冊發(fā)布。

          小結(jié)

          總得來說,收獲不少。一是解決了當(dāng)前的需求,二是產(chǎn)出了一篇“水文”,三是貢獻(xiàn)了一個 PR(Markdown 特供)。

          源碼地址:hu-qi/StartAI[16] (https://github.com/hu-qi/StartAI[17])

          Reference

          [1]

          “螞蟻牙黑”的視頻合成: https://bbs.huaweicloud.com/blogs/245794

          [2]

          自動駕駛: https://bbs.huaweicloud.com/blogs/226039

          [3]

          云享 MindTalks 第十三期:ModelArts 讓 AI 應(yīng)用開發(fā)更簡單: https://bbs.huaweicloud.com/blogs/246212

          [4]

          Project Jupyter: https://jupyter.org/

          [5]

          Project Jupyter: https://jupyter.org/

          [6]

          機器學(xué)習(xí)中的數(shù)學(xué): http://www.itdiffer.com/

          [7]

          玩玩爬蟲: https://bbs.huaweicloud.com/blogs/174634

          [8]

          Figma: https://figma.com/

          [9]

          FigmaCN: https://cn.figma.cool/

          [10]

          jupyterlab-language-pack-zh-CN: https://github.com/jupyterlab/language-packs

          [11]

          擴展程序開發(fā)文檔: https://developer.chrome.com/docs/extensions/

          [12]

          GoogleChrome/chrome-extensions-samples: https://github.com/GoogleChrome/chrome-extensions-samples

          [13]

          PR: https://github.com/GoogleChrome/developer.chrome.com/pull/521

          [14]

          mv3/manifest: https://developer.chrome.com/docs/extensions/mv3/manifest/

          [15]

          MutationObserver: https://developer.mozilla.org/zh-CN/docs/Web/API/MutationObserver

          [16]

          hu-qi/StartAI: https://github.com/hu-qi/StartAI

          [17]

          https://github.com/hu-qi/StartAI: https://github.com/hu-qi/StartAI





          瀏覽 31
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  青青草丝袜视频 | 一级内射片| 国产av色婷婷 | 熟女一区二区三区 | 成人女人毛片18女人毛片 |