一位匠人的中州韻——專訪Rime輸入法作者佛振(圖靈訪談)

盼盼姐發表於2014-07-28

弓辰,號佛振,出身地是河南鄭州以北十里弓家寨,在北平做碼農。佛振是「Rime/中州韻」輸入法引擎的開發者,它不僅僅是一個輸入法,也是一個輸入法演算法框架,這一套演算法支援了拼音、雙拼、注音、五筆、倉頡等所有音碼和形碼輸入法。Rime還支援了許多種方言拼音,如吳語、粵語,甚至中古漢語。「IT學生界大神」BYVoid曾在其部落格撰文怒贊「Rime/中州韻」,使得這個原本默默無聞、志在用十年磨礪的專案在一個小圈子裡迅速傳開。佛振四年前加入百度PC輸入法開發團隊,但他並沒有放棄自己的「業餘作品」,而是將其發揚光大,針對Windows、Linux、Mac三大平臺提供了不同的發行版,Windows版「小狼毫」,Mac版「鼠須管」,Linux版「中州韻」。佛振認為程式碼和文學的共同點在於「強大的表現力」,匠人和作品,在佛振這裡有一個什麼樣的故事?

一位匠人的中州韻——專訪Rime輸入法作者佛振(圖靈訪談)

當時只道是神奇

“對一個匠人來說,創作一件有情調的作品,一定是出於對精湛技藝的追求。如果僅僅是為了現實目的,固然可以寫出高質量的軟體,程式碼本身卻容易缺乏靈氣。”

問:你是如何學程式設計的?

幼時只道符號神奇,喜歡獨個寫寫畫畫,樂此不疲。中學時業餘愛好是鑽研速記學以及程式設計術。

問:請您簡單介紹一下開發中州韻輸入法的經過。

大學畢業後一邊從事Web開發的工作,一邊構思一種將速錄機鍵盤的並擊工作方式在PC鍵盤上實現的技術,後來製成軟體《宮保拼音》。此後賦閒一段時間,又在民辦高校兼職,擔任過C++、Java教師。這幾年裡一直在使用開源的Linux系統,Linux桌面先後有SCIM和IBus這樣優秀的輸入法框架推出,這使得以往被視為十分專業化的輸入法開發技術,對普通的開源軟體開發者觸手可及了。受此鼓舞,我從2009年開始設計和編寫一款輸入法,用來驗證自己對輸入法的理解和構想,並融合後來學習到的漢語音韻學知識,使他支援古音和方言輸入。這就是後來稱作「Rime/中州韻」的輸入法。

2010年我加入百度,從事百度PC輸入法的開發。這段歲月自有一份艱辛,也得到很大的鍛鍊。隊友們都是Windows開發高手,我向他們學到了不少。欣喜的是大公司畢竟是規範得多,週末都很少會組織加班的。於是在休息時間我又把滿滿的熱情投入到週末小製作上來。

在朋友們的幫助下,最初執行在Linux上的Rime輸入法,成功移植到了Windows和Mac平臺。程式碼和設計也不斷完善,演算法庫由Python語言轉為C++後,程式效能和操作體驗都有顯著提升,有幸得到了身邊朋友們的肯定。

問:設計「Rime/中州韻」的初衷是什麼?

為吾等輸入法愛好者設計一個智慧的輸入法平臺。

寫輸入法的人往往打字不快:有感於效率低下,卻不思勤學苦練,反倒生出改進輸入工具的念頭。故事通常都是這樣的。

過去,許多輸入法構造簡單,可以在一套通用的輸入法平臺軟體上實現。其代表有倉頡碼、五筆字型、鄭碼等等。後來的輸入法發明人只須制定一套完備的編碼規則,按規則為字詞一一設定編碼即可運作。使用者則需要依靠腦力強記規則,在錄入時把文字翻譯成要在鍵盤上打出的程式碼。

如今已不再是輸入法「萬碼奔騰」的時代,然而仁人志士發明和改進輸入法的熱情不減。由於網際網路和行動網路的興起,作為資訊處理基礎工具的輸入法重新受到重視,不斷向高效、易用、智慧化發展。其代表是智慧拼音輸入法。輸入過程中的許多環節改由輸入法程式完成,極大地減輕了使用者的思維負擔。

隨之,輸入法開發技術也越來越複雜。因為缺少關鍵的智慧演算法,輸入法設計者再也無法利用老舊的輸入法平臺,創作出符合時代水準的輸入法了。我研究的一些問題,如方言輸入,技術上與智慧拼音輸入十分相似。可是當時的智慧拼音輸入法大都針對《漢語拼音》而設計,無法輕易地將拼音方案更換為其他方言。若用傳統的碼錶式輸入法平臺實現,則因同音字多,逢詞必選,效率十分低下。

惱恨構想中的輸入法難以實現,我終於下決心開發一款聰明而善變的輸入法軟體。希望通過Rime使輸入法的個性化變得簡易,與我有類似需要的用家可以盡情發揮創造力,找出最適合自己的打字方式。

問:在「Rime/中州韻」輸入法上投入了這麼多的時間和精力,你有什麼收穫?

對我個人而言,為創作這款開源軟體投入了大量精力,也不全然是「不務正業」,心想借此練練技術也是好的。因此創作中不僅滿足於實現功能就算完,許多技術細節都反覆推想過。

冥冥中天意憐我青春都耗在這上面了,此前能在百度得了工作,以至目前從事的工作,都與開發過這個開源輸入法有莫大關係。某雖不才,此外便一無所長,總算還沒有悲劇到飢寒交迫的地步吧。

問:你對古漢語和方言是不是有特殊的感情?背後的原因是什麼?

不是。

我想每個人,特別是遠離家鄉的遊子,對自己的家鄉話都是有感情的。

我的母語是中原官話,母親卻講北京話,小時候每回從老家歸來她都要糾正我的口音。以至於一些字詞在家鄉話裡的說法我都記不真切,須求證於祖父母。祖父曰:「過去都覺得土話土,實際上這裡頭也通有講究叻。」這話的意味,直到學習了一些語言學知識才得到印證。

原來每一種漢語方言都有一套嚴整的音韻系統,對照古代的雅言我們可以發現他們各自發展演化的軌跡。普通話是官定的標準音,但比之方言並無「特殊」之處。

我發現一些優秀的軟體,非常注重本地化,努力讓不同地域、不同語言、不同文化背景的使用者感受到公平的對待。輸入法是人機互動的重要一環,如何能貼近用家的直覺,尊重不同的語言習慣和輸入偏好?我的解法是儘量將程式寫得通用,給使用者以足夠多的選擇。

對一個匠人來說,創作一件有情調的作品,一定是出於對精湛技藝的追求。如果僅僅是為了現實目的,固然可以寫出高質量的軟體,程式碼本身卻容易缺乏靈氣。程式碼的藝術和美,與文學略有共通之處,在於強大的表現力。缺乏靈氣的程式碼只顧平鋪直敘,是沒有生命力的機械;好的程式碼越是簡單明瞭,越是做得到更多事情。

程式設計的樂趣在於享受這份創造的快感:他不只是在敲程式碼,而是在開動腦筋調教程式,增益其所不能。甚至會有一刻在心中大呼:終於不再像菜鳥一樣寫程式了!誰願做只會搬磚的碼農?定要像設計師那樣思考,才稱得上有手藝的編碼匠。

二〇〇八年我辭去搬磚的工作,立志練好技術,將來上Google、Facebook謀職,做個有技巧的碼農。修煉的方式,就是完成一個有挑戰、來源於真實需求的軟體作品。於是醞釀已久的輸入法開發計劃在來年開工了。

問:能向對古漢語和方言(感興趣)的朋友們推薦一些書籍嗎?

這個問題我本來回答不了,因為我對音韻學只是泛泛地涉獵,瞭解十分粗淺。幸而通過開發Rime輸入法認識了一些語言學和中文專業的朋友,他們向我這樣的外行推薦一本丁聲樹撰文、李榮製表的《漢語音韻講義》做入門書。「這本書吃透了,對於熟悉切韻音系、切韻與現代音(包括一些方言)的對應關係是非常有幫助的。」

如果想更加系統深入地學習,可參考蔡子文同學的音韻學入門推薦書目

音韻學研究者能夠根據各種線索大致還原出古音的面貌。除了以上書籍,我再推薦古韻Polyhedron君錄製的《中古漢語語音教程》。看網路視訊學習中古音,相當別開生面。

還有BYVoid君製作的韻典網,提供了包括《廣韻》在內多部古代韻書的線上查詢工具。

對輸入法作者來說,有女同車和Polyhedron整理的《廣韻全字表》是一份極其有用的資料。許多方言輸入法利用這份字表從漢字的中古音推匯出現代音,作為方言碼錶的模板,省去了大量注音工作。

佛振的中州韻

“開發Rime輸入法之前的數年間,我花了不少心思推敲、改進並擊按鍵的排布,使容易擊發的按鍵組合對應常用的音節,並且儘量反映出語音內在的規律性,減少需要記憶的內容。”

問:「Rime/中州韻」的開發設計過程中,程式設計方面最大的難點是什麼?語言方面最大的難點是什麼?

程式設計本身不難,難的是將問題抽象。要用一套程式碼支援多種多樣的輸入法,甚至是未曾發明出來的,首先得抽象出一個通用的模型,然後拆分出一個最小的框架和一組完成單一功能的元件,以供按需組合,構成形態各異的輸入法引擎。

至此問題只解決了一半,還有一個目標是讓使用者能夠直接控制這部引擎,而不必進行嚴肅的程式設計。為此我選取了類似JSON而語法更加簡潔靈活的YAML語言,在其基礎上定義了一套領域專用語言(DSL),稱為「Rime輸入方案」。在輸入方案文字中,使用者只須列舉為輸入法引擎選配的功能元件,並設定各元件所需的引數,便得以精確描述輸入法的行為。

設計一個通用性強的拼音輸入法框架,需要對語音系統的知識有比較全面的瞭解,避免受制於有限的經驗作出設計上的失誤。例如漢語拼音裡面聲母、韻母的劃分,可以在輸入法中加以利用:用聲母建立索引實現簡拼的功能,為聲母、韻母分別設定模糊音輸入的功能。然而這樣寫出的程式會喪失一部分通用性,因為不同方言的語音系統有差異,觀察和研究《漢語拼音方案》所得的結論,很可能不夠普遍化;用在其他語言裡,或者用來處理基於字形的輸入法,甚至聲母、韻母的概念都完全不適用了。語言學知識幫我判斷哪些語音規律有必要反映在輸入法程式裡,哪些不夠普遍化,需要尋求更通用的解法。

最終語言學問題可以轉化為技術問題啦。Rime有項基於正規表示式的「拼寫運算」技術,它設計的目的是用來描述語音的演變規則。把兩個音系之間的對應規則用技術語言描述出來,我們就可以將一套古音輸入法改造成各地方言的輸入法,或是把一種方言輸入法轉換成臨近的方言。又因為正規表示式本質上是做字串處理而與語音無關,所以「拼寫運算」可以用於更廣泛的場景,統一地解決為各種音系定義簡拼、模糊音、基於規則的糾錯、標註聲調符號、定義雙拼方案、不同拼音系統之間的轉換等諸多問題。

問:通過設計開發「Rime/中州韻」輸入法,你驗證了哪些重要的理解和構想?

一是設計一套通用的音節切分演算法。音節的變體形式如簡拼、模糊音,都可以用一套規則描述。

我曾參加過一次主題為「拼音切分演算法」的線上討論,和幾個主要開源輸入法Fcitx、ibus-pinyin、libpinyin以及SunPinyin的開發者一起提出了這個構想。設想無論拼音方案是漢語拼音、注音或是其他的拼寫方案,輸入法都可以對演算法不加修改而做到將連續的輸入串以音節為單位做切分。音節切分是拼音輸入法做詞典查詢之前的必要步驟。這個構想恰恰也是設計一個通用拼音輸入法的前提。那次討論後一年多,我才最終通過完成「拼寫運算」的設計和開發,驗證了這個構想。

另一個構想是將專業速錄鍵盤多鍵並擊的工作原理應用到普通電腦鍵盤,從而創造一種高效、省力、富有節奏感的輸入方式。

這項小發明叫做「宮保拼音/Combo Pinyin」,它將一組按鍵同時按下、由不同的按鍵組合產生不同的拼音音節。看似主鍵盤區的字元按鍵可以產生的組合遠遠多於拼音中的音節數,然而其中能按照指法用雙手舒適地擊出的組合數並不寬裕。開發Rime輸入法之前的數年間,我花了不少心思推敲、改進並擊按鍵的排布,使容易擊發的按鍵組合對應常用的音節,並且儘量反映出語音內在的規律性,減少需要記憶的內容。

最終的設計很多地方都符合音韻學原理:聲母按發音部位分組,排列在鍵盤左半區;g,k,h與j,q,x在與韻母的搭配上存在互補關係,因此這兩組聲母共存於一組按鍵;韻母的結構中,介音和韻尾變化多,而韻腹變化少,因此介音i,u,ü由最靈活的右手食指控制,便於與其他手指形成組合,韻腹的母音則安排在較不靈活的拇指和無名指;韻尾-i, -u交叉排列在與介音i,u相對的行,可以輕鬆地用食指、中指並擊得到韻母iu, ui,這是考慮到普通話裡相同的母音不會同時出現在介音和韻尾的位置上,也就是說不存在*iei, *uou這類組合。

問:在百度PC輸入法開發團隊中你的作用是什麼?百度輸入法有沒有受到“小狼毫”輸入法的影響?

我有幸在百度PC輸入法立項的時候加入這個團隊,接到的第一個任務是開發一個高質量的輸入法詞庫,這包括利用百度強大的中文資源構建雲輸入詞庫、訓練語言模型、根據PC輸入法的需要進行裁剪等資料處理工作。後來我又擔任輸入法前端邏輯和新功能的開發。

百度擁有小團隊無法比擬的資源,其工作方法也十分高效和民主,每個人的意見都得到充分表達和客觀評估,而在團隊的決策中發揮作用。起初我雖負責後端詞庫的研發,也一起參加前端輸入法架構設計的討論,分享了此前設計和開發Rime輸入法的經驗。最終開發團隊一致決定採用與業界主流的做法炯然不同,而多見於開源輸入法的前後端分離架構。Rime亦是得益於這種架構,保證了平臺一致性,而且簡化了設計,降低了開發難度。

問:相反,從百度輸入法中,「Rime/中州韻」有沒有找到可以借鑑的地方?

印象最深刻的是百度輸入法專業的測試團隊,他們為輸入法設計了專門的測試工具和工作方法。測試通過後,還有一套嚴密的流程控制產品上線和跟蹤使用者反饋。吾儕的小製作嘛,因為可調教的選項眾多,往往測試不充分,帶著問題上線也是有的。後來我學到一招,為「小狼毫」增設了一個手動升級的通道,在全量推送新版本之前,先給有經驗的使用者試用「搶鮮版」,以期提前發現並及時修復可能存在的嚴重問題。

後來我還負責維護百度輸入法的工程配置和構建指令碼。編譯、數字簽名、打安裝包乃至自動上線的一整套操作,不僅用自動化指令碼實現,還支援許多引數用來滿足不同安裝渠道的定製需求。我想到,構建過程的自動化,對於開源軟體更加重要了,因為開源合作者更難保證使用一致的開發環境。由此受到啟發,我也改進了「小狼毫」在Windows平臺的編譯流程,用指令碼簽出程式碼、檢測編譯依賴、構建第三方庫,取代原先需要手工操作的眾多步驟。結果這個專案的參與度真的有所提高。可見開源不只是把原始碼釋出出去,還需要各種努力讓原始碼對別人更有用。

問:對於輸入法產品,大型開發團隊(如百度)和小型團隊或個人在開發流程上有什麼不同?相應造成各自哪些產品上的優缺點?

我不精於這方面的思考,只管猜猜看吧。

首先是產品的定位不同,造成最終的產品形態千差萬別。

大團隊分工明確,流程嚴謹,產品的每一個功能在開發之前都由產品人員做調研和設計,保證對結果有明確預期。從反面看,穩健意味著少有大的驚喜。小團隊更加靈活,能快速適應變化,敢於做更多嘗試。難的是風險控制,結果容易受偶然因素的影響……還有一個不利因素是資源有限。Rime的許多功能設計,都為此作出妥協,力求用低成本實現不俗的效果。

反正寫開源軟體和在大公司開發產品,除了碼程式碼這項操作比較類似,兩者真是大有不同呢。

更多人的中州韻

“我近來都在檢討,參與開源,哪些地方沒做對。檢討完,也就有了未來的方向。”

問:作為一個開源專案,Rime的程式碼來源都有哪些?

Rime的程式碼包含一個C++的核心演算法庫、一個用來維護輸入方案和詞典檔案的資料集、以及分別為Linux、Mac、Windows平臺開發的輸入法前端。

俺的主張是不重複造輪子,除非需要把輪子造得更圓。為了同時保證開發效率和軟體的品質,Rime引用了大量的開源程式庫。例如用yaml-cpp做YAML檔案的解析、用darts-clone提供詞典中的trie樹結構、用kyotocabinet做為支援使用者詞典的資料庫、用opencc做高質量的漢字繁簡轉換。為了把好的功能提供給更多使用者,第三方庫的程式碼能否跨平臺,是一個重要的選擇標準。Boost庫提供的正規表示式、檔案系統操作、程式間通訊、執行緒處理等設施,解決了很多跨平臺的麻煩。正因為在這些優秀開源軟體的基礎上開發,Rime才得以集中精力解決前人未曾解決的輸入法難題。

我和Zou Xu同學一起完成了Rime演算法庫的大部分程式碼。這個輸入法逐漸為人所知後,收到不少朋友提交的patch,或是修復程式漏洞,或是新增新的功能。Windows和Mac平臺上,輸入法介面的許多重要特性,如對候選字排版的控制以及配色主題支援,都靠網友們幫忙開發。Linux系統上的fcitx-rime繫結則是由Fcitx輸入法團隊獨立完成的。

Rime收錄的輸入方案包含了一些開放版權的輸入法如倉頡碼、五筆86版、五筆畫、粵拼等,還有一些網友創作的輸入法如各種雙拼方案、宮保拼音、吳語上海話、蘇州話拼音、中古漢語拼音……Rime用家的創造力是令人讚歎的,我們只能從中選取有代表性的幾例隨輸入法一起釋出。

而詞典資料部分更是彙集了許多人的勞動。Rime最初使用的詞彙表,來源於Google開源的Android拼音詞典,以及CC-CEDICT漢英詞典。為了做到傳統漢字和簡化字並蓄,我又對照新酷音輸入法(Chewing)及開放中文轉換(opencc)的詞庫,對所有詞彙的傳統字形做了修正。輸入法釋出後,不斷根據網友的反饋查漏補缺,更有瑾昀、雪齋、攴君等幾位仁兄,持續地提交使用中發現的錯字、錯音,並整理新增了許多有用的詞彙。多虧了諸君努力,雖然我們受限於資源只能維護一個小而精的詞庫,但其品質還是得到了用家認可。

問:在開發過程中,收到過哪些重要的反饋?其中有沒有哪些影響了開發設計的思路?

有不少呢。

早期的版本曾用Python語言編碼、用SQLite資料庫構建詞典,輸入法的響應速度不佳。連城同學是把我招進百度的面試官,也是Rime最早的使用者之一。他建議我嘗試改用執行效率更高的C++。依計重寫Rime的過程中,針對響應速度的優化成了我時刻關注的問題。譬如,根據輸入法使用中的特點,有效候選結果常有成百上千個,而最初展現給使用者的候選詞只有不足十個,於是詞典的結構做了針對性的設計,詞典查詢運用生成器模式惰性取詞,這對控制響應時間和資源佔用都有很大幫助。

「小狼毫」0.9釋出後,Rime的開發和使用者有了更多互動。我也更深地瞭解到眾人對輸入法的期待是如何地多樣。有時我只當是牽就使用者的提議而增加一個新特性,誰知一旦新版本釋出出去,竟又生出許多意想之外的玩法。誰能想到輸入碼反查,這一發自上世紀的輸入法技術,還能將輸入法活用,當作查詢古漢語音韻的工具書呢。不管你懂沒懂啊,我是大開眼界了。

問:多數人認為「Rime/中州韻」輸入法是一種小眾輸入法,這裡的“小眾”是一些具備什麼特點的使用者?

有幾類人愛用。

一是學習和研究語言文字的朋友。他們在學習和工作中要用到傳統漢字,相比依賴於簡繁轉換的輸入法,Rime用字更準確,而且能夠兼顧大陸、港臺等地用字習慣的差異。這些朋友還根據自己的需要,創造了用來輸入國際音標、外文字母、乃至藏文、彝文等少數民族語文的輸入方案。整合到Rime之後,能夠在行文中方便地切換輸入語言。

一是致力於方言傳承和保護的朋友。Rime可以幫助他們用較少的勞動,製作出自己家鄉話的輸入法,並且不難達到與《漢語拼音》輸入法一致的效果。 一是輸入法愛好者,輸入法一向用自家釀造(DIY)的,甚麼輸入法平臺,早都耍得有模樣;終於又有了新的玩具,還能使用拼寫運算,那是必須折騰一番的。

一是苦命的Linux用家,若不滿意預設拼音輸入法的效果,可選擇的替代品真的不多。Rime處理好了一些其他開源輸入法未曾關注的細節,例如候選詞的編輯操作、學習調頻策略等。恰如其分地營造出「好使」的錯覺。

還有純粹的geek技術高手,Rime提供高度可定製性正對胃口;對工具的要求就是輕巧快速,用開源再不必憂心隱私洩露。

最讓我吃驚的是,剛釋出代號為「鼠須管」的Mac版本時,受用家推崇的原因竟然是它「速度快、在Macbook電腦上不會卡頓」……始料未及的反饋,佛振無言以對。幸運的是後來的新款Macbook配備了高速SSD硬碟,幫助其他使用者解決了輸入法卡頓的困擾。

我勉強總結出一個共同點,Rime用家是懂輸入法、善用工具的一批人。非此不可容忍它存在的種種不足。

問:很多人都很期待Rime的移動版本,在未來你有這方面的計劃嗎?

我近來都在檢討,參與開源,哪些地方沒做對。檢討完,也就有了未來的方向。

舉例來說,先時花了不少力氣為Rime實現一個Windows前端,以求用有限的代價儘早推出「小狼毫」。但是Windows輸入法與軟體的相容性問題是出名地多,至今還有很多疑難雜症未能解決。假使當初不急於造這個輪子,而是設法找到一個有前景的開源實現,並參與改進,那麼就能憑藉眾多開源高手的智慧解決這些棘手的問題,我們為「小狼毫」所作的開發,也會對開源社群更有用些。

術業有專攻,受限於精力和技術廣度,以一人之力決計無法在方方面面都做到足夠好。開源協作的模式是每個開發者專注於自己擅長的領域,將成果作為可複用的程式碼開放給協作者。

今後我會更加專注於Rime的核心演算法(已在做針對移動平臺的優化),還要完善API、文件和輔助工具,使這個程式庫對開發者更加友好:讓關注功能的開發者能夠理解程式碼並動手作出改進,讓專業的移動平臺開發者能夠利用Rime的API輕鬆地構建各個移動平臺的輸入法。若能如此,Rime在開源之路上就獲得了大成功。


更多精彩,加入圖靈訪談微信!

相關文章