做為這個系列的第一篇正式技術文章,我想從復刻開源專案開始。
還記得最早接觸的第一份翻譯軟體是 Dr. Eye ,那時候不需要翻字典就能做到中文、英文、日文翻譯,想想還是相當令人興奮。後來隨著網路的崛起,越來越多雲端服務商也參與這場戰爭,Google 就是其中一家重要的廠商。不過他們的翻譯也不是一開始就很優秀,還記得唸書的時候,教授耳提面命論文摘要絕對不要使用 Google 翻譯,那個內容只能用慘不忍賭來形容,但這幾年 Google 的翻譯品質是越來越好,
拜深度學習既傳統的二維影像,一路到NLP 技術的突破,再加上網際網路發展所累積的大量的訓練語料等,這些機緣巧合正好成了模型訓練上最棒的資料來源。相比早年死板板的翻譯品質,ChatGPT 翻譯出來的內容品質相對優秀,這也可見人類對於這項需求寄予的厚望與科技帶來的技術突破。
說了這麼多,到底怎麼搭載我們第一個離線翻譯引擎?這時當然就要藉助 Hugging Face 尋覓有沒有合適的方案。
我們可以在上方的導引欄中切換到Models ,並利用左側的過濾條件將搜尋結果現縮在 NLP 中的 Translation 這一欄位。
我們先挑 『Helsinki-NLP/ opus-my-zh-en 』這個模型著手。
我們點擊之後可以看到這個庫的模型卡(Model Card)介紹
可以看到這個模型最主要是可以將中文內容翻譯成英文。右側你也可以實際輸入一些文字來測試他的翻譯效果。細節我們先不特別說明,我們先試著在本地跑起來這個服務。
方法其實跟 Git 很像,點開來就可以看到這個儲存庫的下載指令
方便使用,我把內容轉換成文字,如下:
git lfs install
git clone https://huggingface.co/Helsinki-NLP/opus-mt-zh-en
要特別提醒一定得先安裝 git lfs 這套工具。因為通常模型的檔案都很大,一般的 git 工具是沒有辦法直接這樣下載下來的。
基本上前置作業就完成,剩下的問題是如何載入模型,並且把要翻譯的內容轉換成符合模型的輸入,再透過模型進行推論,最後把推論得結果轉換成人看得懂得文字輸出。
我們直接先上代碼。
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
tokenizer = AutoTokenizer.from_pretrained("./opus-mt-zh-en")
model = AutoModelForSeq2SeqLM.from_pretrained("./opus-mt-zh-en")
text = '今天是聖誕節,祝大家聖誕快樂!'
# 直接使用 tokenizer 將文本轉換成模型需要的格式
inputs = tokenizer(text, return_tensors="pt", padding=True, truncation=True, max_length=512)
# 使用模型進行翻譯
translation = model.generate(**inputs)
# 將翻譯結果轉換為文本
result = tokenizer.decode(translation[0], skip_special_tokens=True)
# 印出翻譯結果
print(result) #It's Christmas. Merry Christmas to you all!
我把大方向的逐行程式碼註解放上來。接著稍微說明一下運行的概念:
其實 transformer 這個套件把很多麻煩事情都解決,要運行這個專案只需要先把模型下載後,接著透過 AutoTokenizer 這個類別就能把這個預先訓練的模型給載入。模型載入之後,我們就可以來處理要作為輸入的文字,標準程序是得將文字轉換成向量,也就是所謂的 word to verctor ,我們會將文字Encode 後,送入模型進行推論,這樣就很像圖像處理中,常見的VAE 網路,先Encode、推論再Decode 獲得結果。以前這個動作也滿麻煩的,現在在套件加持下也變成一行代碼的事情。另一個有意思的是在推論這個環節,在 Transformer 的模型推論用的關鍵函式是 generate() ,我們把前面 encode 的文字作為參數送入就能進行運算。最後我們再把運算的結果做Decode 就能看到翻譯的結果。
我們再次梳理一下:
- 入必要的庫:
- 使用
transformers
庫中的AutoTokenizer
和AutoModelForSeq2SeqLM
來處理文本和模型。
- 使用
- 載入模型:
- 使用
AutoTokenizer.from_pretrained
和AutoModelForSeq2SeqLM.from_pretrained
來載入預訓練的模型。這裡的"./opus-mt-zh-en"
指的是已經下載到本地的模型。
- 使用
- 處理要翻譯的文本:
- 這段程式碼中的
text
變量包含了要被翻譯的中文文本。
- 這段程式碼中的
- 文本轉換:
- 使用
tokenizer
將文本轉換成模型所需的格式。這裡包括了將文本轉換成向量(word to vector)的過程,並將其編碼(Encode)為模型可以處理的格式。
- 使用
- 使用模型進行推論:
- 透過模型的
generate
函數,將編碼後的文本送入模型進行翻譯。
- 透過模型的
- 解碼並輸出結果:
- 最後,使用
tokenizer.decode
將翻譯結果從向量形式轉換回可讀的文字。
- 最後,使用
如果眼尖的讀者應該有發現:示意API的中文其實是『簡體中文』,但我這邊使用的測試資料是『繁體中文』,理論上這樣產生的編碼是不一樣的,為什麼翻譯出來的效果其實還不差?我想這應該也是 AI 在大數據資料泛化性造成的影響,雖然簡體中文與繁體中文存在些差異,但在訓練資料中,稍稍弭平兩者間的差距。 進一步來說,通常我們在訓練模型時,我們會加入一些變異資料來提高模型的泛化性。儘管簡體中文與繁體中文在文字上頭的差異,但根本上其兩者的語意是相近的。一個訓練良好的模型能夠識別這些語言變體之間的相關性,並且有效地進行翻譯。這種能力不僅提高了翻譯的準確性,也增強了模型對新數據和少見語言變體的泛化能力。
如此一來這樣就搞定,我們可以把他搭載成 Flask 服務,透過 RESTful API 的架構就可以把這套中翻英的功能搭建在自己本地,隨時為自己服務。