feat(script_translator): learn new phrases automatically from segmentations
Feature
feat(script_translator): learn new phrases automatically from segmentations
-
separate new phrases by segmentations rather than using the sentence as a whole, while committing into user_dictionary
-
join adjacent segments if the result is no longer than core_word_length
-
ignore the phrases which are longer than max_word_length
Examples
在整句輸入時,通過斷句(由光標或選詞等產生)學習新詞,而不是學習整句作為新詞,然後寫入用戶詞典。
例如: 在下表中,句子中的符號‘|’,表示斷句的位置;且參數max_word_length和core_word_length,分別配置為7和4.
| 學習的新詞 | 整句輸入時的斷句 | 記錄的詞數 |
|---|---|---|
| 去畫 | 一旦嘗試|去|畫|示意圖 | 3 |
| 和式 | 總是比把除數寫成|和式|要更方便些 | 2 (忽略 1) |
| 它 | 它|是我的一個東西 | 2 |
| 它 | 要做的就是簡化|它 | 2 |
| 有歧義 | 這是|有歧義| 的一句話 | 3 |
| 他們是 | 我知道|他們|是|可愛的人 | 3 |
說明:
- 斷句產生的多個相鄰片段(segment),如果合併後長度不超過
core_word_length,將會合併成一個詞;其餘每個片段(segment)生成一個詞。 - 產生的詞,如果長度不超過
max_word_length,則記錄到用戶詞典中,尤其是作為學到的新詞;否則,只更新其構成元素(elements)的權重。 - 產生的詞彙,通過音節或codes數,計算詞長。
- 參數
core_word_length生效的取值,不超過參數max_word_length的取值。 - 該功能默認關閉;也就是,配置參數
max_word_length或core_word_length為大於0的值時,從斷句片段學習新詞的功能開啟,否則維持原來行為方式。
Unit test
- [x] Done
Manual test
- [x] Done
Code Review
- Unit and manual test pass
- GitHub Action CI pass
- At least one contributor reviews and votes
- Can be merged clean without conflicts
- PR will be merged by rebase upstream base
Additional Info
@lotem This may be a useful feature. Please check if it is needed generally.
還沒細看。
我最初對分詞的構想是,空格確認可以看作分詞的標誌。 把空格確認上屏的一段文字當作用戶詞記錄。 「語句流」模式,則是以空格確認爲界分詞。 不管是不是語法意義上的詞,至少空格對應的是語流中的一處停頓。 但是數字選重則不一定,因爲:遇到字不對,必須要選,此處不一定是詞的邊界。
所舉的例子,固然用分段學習的策略更好;我認爲需要觀察反例,因爲不可避免的選字,而學到不完整的片段。
fluency editor模式下,如果整句輸入方式,即一次性輸入整句的拼音,然後空格上屏,如果其中有推測不符合預期,再回過頭來進一步通過光標斷句和人工選詞調整,回顧式調整的方式,此時中間鍵入的空格似乎是被看作為了選詞動作(kSelected),只有最後空格被看作了確認(kConfirmed)。這裡的處理邏輯,應該是和express editor類似的。而新學習詞彙或短語的邊界,原始行為應該是通過確認或當前語言不可識別字符來標記的。
根據嘗試fluency和express editor的體驗,底層基於script_translator處理詞彙合併或新詞學習的邏輯應該是相同的;而且也都分為逐詞輸入方式和整句輸入方式。逐詞輸入的方式(包括短語),RIME處理已經可堪稱完美了;當前主要考慮,整句輸入方式。
-
漢語的核心詞彙,通常為二、三、或四字詞,最長七個字以包括七言古詩的詩句。自動記錄更長的整句、短語或詞彙,就沒有必要了。
-
整句輸入時,最流暢的方式可能是,直接輸入整個句子的音節,引擎能以高正確率推斷出所使應使用的字詞。類似那些在線輸入法的使用方式。 如果有些字詞沒有正確推斷出來,則需要通過斷句或選詞干預調整推斷選詞。目前通過長度控制是否繼續合併人工選詞;如果能夠區分是否為光標斷句,而光標斷句內人工選詞自動合併,以控制用戶期望引擎學習的新詞、短語或片段,可能就更好了。
-
如果能提高整句輸入時推測的準確率,即使記錄的詞彙或短語有不完整片段,也應該是可接受的。
-
最後,用戶可以配置是否打開這個功能。
在整句輸入方式下,要高正確率推測出預期中的字詞,並且在推測失敗的情況下,能夠提供光標斷句和人工選詞干預的機制,這確實是一個極為困難的任務。即使目前那些基於大語言模型的主流在線輸入法,也很難做到完全準確的推斷出用戶預期的字詞,而且在沒有準確推斷出正確字詞的情況下,它們也不能如同RIME引擎一樣,可提供讓用戶能夠通過光標斷句或人工選詞干預的能力。
值得研究。 @rime/engine
這個值得做,也是我曾經想做的。 餘下的就是具體實現,請羣裏的編程算法高手再把把關。
另一個思路是不認新詞,而記錄用戶輸入的字級二元關係,早先寫過,效果似乎也不錯。
呼喚 @rime/engine 小夥伴們,誰有興趣來鑑定鑑定?
贊同「從句子中得到詞語」的想法:
- 所有收集到的「片段」,均來自用戶實際輸入,因此假設用戶會再次輸入類似的句子,下次就還能用到。
- 這裏的 tradeoff 是,片段應該多長?起始點和終止點在哪裏?
- 考慮到「選字點」表示之前組句失敗,因此起始點和終止點放在選字點附近是合理的。
- 再考慮到用戶實際輸入的習慣(這裏指我自己的習慣),詞的邊界往往也會選字。
- 假設新詞邊界一定有一次選字,選字點是 $s_1, s_2, ..., s_{10}$,其中有一些是邊界(比如說 $s_3, s_7$),那麼只要把這些邊界內的 segment 合併起來( $[s_1..s_3], [s_4..s_7], [s_8..s_{10}]$ )就是“新詞”。
一些疑問:
-
沒理解錯的話,組詞使用的是貪心算法。使用相同的參數,這句話 若嘗試|去|畫|示意圖 看起來會學習到「若嘗試去」和「畫示意圖」?不過這個結果看起來也沒什麼問題。但我在想是不是順便把「去畫」也學習上會比較好?
另外我做了一些測試。設置
core_word_length=2,max_word_length=10,然後輸入 zi ji guan lian,首選是「自己關聯」,然後我依次選了「字」、「級」和「關聯」,成功造出了「字級」這個詞,但無論我如何重複這個過程,或直接選「字級」和「關聯」,都無法造出「字級關聯」這整個詞,這是符合預期的嗎? -
另外感覺選項名有點難以理解,兩個選項似乎都是某種上界。
max_word_length是否可以看作與本 PR 核心功能無關的正交功能? -
(也許還可以和 commit history 結合。)
一些疑問:
- 沒理解錯的話,組詞使用的是貪心算法。使用相同的參數,這句話 若嘗試|去|畫|示意圖 看起來會學習到「若嘗試去」和「畫示意圖」?不過這個結果看起來也沒什麼問題。但我在想是不是順便把「去畫」也學習上會比較好?
更新的PR,採用滑動窗口拼接新詞,將產生所有可能符合長度條件新詞。這樣 若嘗試|去|畫|示意圖 將學習到「若嘗試去」「去畫」「畫示意圖」
另外我做了一些測試。設置
core_word_length=2,max_word_length=10,然後輸入 zi ji guan lian,首選是「自己關聯」,然後我依次選了「字」、「級」和「關聯」,成功造出了「字級」這個詞,但無論我如何重複這個過程,或直接選「字級」和「關聯」,都無法造出「字級關聯」這整個詞,這是符合預期的嗎?
參數 core_word_length, 控制由選詞拼接而成新詞的長度上限。所以當core_word_length=2時,將會合併「字級」。此時會因為「字級」頻率遠低於其同碼詞「自己」,所以將產生“無論如何重複“這個過程,都無法造出「字級關聯」這個整詞的表象。 這是符合預期的行為。
在更新後PR中,若core_word_length=4將會同時合併出「字級」「級關聯」「字級關聯」等詞彙。
- 另外感覺選項名有點難以理解,兩個選項似乎都是某種上界。
max_word_length是否可以看作與本 PR 核心功能無關的正交功能?
更新的PR,使core_word_length功能和max_word_length功能正交,可單獨開啟。
- 功能默認關閉。
- 配置正值
core_word_length時,打開從片段學習新詞的功能,採用滑動窗口機制。 - 配置正值
max_word_length時,打開學詞的新詞用戶長度上限控制;超過新詞只更新構成元素,不記錄該詞。 - 若這兩個參數都配置了正值,則
core_word_length實際取值將不超過max_word_length。
參數名core_word_length意為這些不超過該長度的詞為「核心詞彙」,需要從選詞合併。有些詞彙未經過選詞而由引擎推斷產生,那麼這些詞彙長度可以超過「核心詞彙」,因其可由引擎推斷產生(其表現為一個單一的片段),故不看作是核心詞彙。
新產生的用戶詞彙,無論是否核心詞彙,其長度均不可超過「最大詞彙長度」,由配置max_word_length控制。
- (也許還可以和 commit history 結合。)
优秀啊。
忽然想到我曾写死一段两字词、三字词逐字选择后造词、不给字调频的特判逻辑。
⿱艸㞢佬的肯定!
感謝 @bgzhao66 改進的算法。 我還沒試……最近時間不夠。 粗略瀏覽了代碼,非常漂亮,給我的感覺靠譜。
大家都可以建議建議,哪些方案適合用這個算法。