Luigi commited on
Commit
9c6147f
·
1 Parent(s): a4c33c1

add divsere beam search and merge common prefixes

Browse files
Files changed (2) hide show
  1. README.md +14 -21
  2. app.py +71 -8
README.md CHANGED
@@ -11,27 +11,16 @@ license: mit
11
  short_description: Chinese input method accelerator
12
  ---
13
 
14
- ---
15
- title: Input Method Acceleration
16
- emoji: 💻
17
- colorFrom: blue
18
- colorTo: pink
19
- sdk: gradio
20
- sdk_version: 5.34.0
21
- app_file: app.py
22
- pinned: true
23
- license: mit
24
- short_description: Chinese input method accelerator
25
- ---
26
-
27
  # 台灣中文輸入法加速器(ZeroGPU + Gradio v5)
28
 
 
 
29
  ## 一、專案概述
30
- 本示範結合多種小型中文語言模型,並透過 Hugging Face 的 **ZeroGPU**(H200)即時執行文字生成,模擬中文輸入法中的候選詞建議功能。
31
 
32
  ## 二、主要功能
33
  1. **使用 GPU 生成建議**
34
- - 採用 **Beam Search**(`num_beams=M`)同時產出 M 條最可能的候選,下段建議即時回饋。
35
  2. **經典 IME 候選欄樣式**
36
  - 橫向滑動、點擊選字,模擬傳統輸入法使用體驗。
37
  3. **自動延展文字框**
@@ -42,24 +31,28 @@ short_description: Chinese input method accelerator
42
  - 手動/自動預測互補,按鈕常駐不隱藏。
43
  6. **消除重複建議**
44
  - 自動去重,保留首見建議,避免候選列表出現相同項目。
 
 
45
 
46
  ## 三、運作原理
47
- - 點擊「預測」或於文字變更時(若已開啟自動預測),函式會以 **Beam Search** 模式呼叫模型,並做以下處理:
48
- 1. 生成 m 條下文;
49
  2. 過濾空字串並轉繁體;
50
  3. 去重並保留順序;
51
- 4. 最後編號顯示於候選欄。
 
52
 
53
  ## 四、部署步驟
54
  1. 在 Hugging Face Spaces 建立新 Space,框架選 **Gradio SDK**。
55
  2. 在 **Hardware** 欄位選擇 **Zero GPU**(需 PRO 帳號)。
56
  3. 設定 Python 版本為 3.10.13。
57
- 4. 上傳 `app.py`、`requirements.txt`、更新後的 `README.md`。Spaces 會自動安裝相依套件。
58
- 5. 點擊 **Deploy**,即可線上體驗!
59
 
60
  ## 五、使用效益
61
  - **快速回應**:利用 GPU burst 加速生成速度。
 
62
  - **零門檻**:免本地 GPU,開發者與使用者皆可輕鬆試用。
63
- - **多模型對比**:可快速測試不同模型品質與效能。
64
 
65
  歡迎體驗高效、無痛的台灣中文輸入法下段建議 Demo!
 
11
  short_description: Chinese input method accelerator
12
  ---
13
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  # 台灣中文輸入法加速器(ZeroGPU + Gradio v5)
15
 
16
+ 結合多種小型中文語言模型,並透過 Hugging Face 的 **ZeroGPU** 即時生成候選,模擬中文輸入法下段建議功能。
17
+
18
  ## 一、專案概述
19
+ 本示範結合多種小型中文語言模型,並透過 Hugging Face 的 **ZeroGPU** 即時執行文字生成,模擬中文輸入法中的候選詞建議功能。
20
 
21
  ## 二、主要功能
22
  1. **使用 GPU 生成建議**
23
+ - 採用 **Beam Search**(`num_beams=M`),一次產出 M 條最可能的候選。
24
  2. **經典 IME 候選欄樣式**
25
  - 橫向滑動、點擊選字,模擬傳統輸入法使用體驗。
26
  3. **自動延展文字框**
 
31
  - 手動/自動預測互補,按鈕常駐不隱藏。
32
  6. **消除重複建議**
33
  - 自動去重,保留首見建議,避免候選列表出現相同項目。
34
+ 7. **多樣性設置**
35
+ - 在「進階設定」中可調整 **Beam 群組數**(`num_beam_groups`)與 **多樣性懲罰**(`diversity_penalty`),以控制輸出建議的多樣性。
36
 
37
  ## 三、運作原理
38
+ - 點擊「預測」或於文字變更時(若已開啟自動預測),函式會以 **Diverse Beam Search** 模式呼叫模型,並做以下處理:
39
+ 1. 生成 m 條下文(可透過 `num_beam_groups` 與 `diversity_penalty` 提高多樣性);
40
  2. 過濾空字串並轉繁體;
41
  3. 去重並保留順序;
42
+ 4. 合併共享的前綴片段作為建議,提高候選精簡度;
43
+ 5. 更新候選列表。
44
 
45
  ## 四、部署步驟
46
  1. 在 Hugging Face Spaces 建立新 Space,框架選 **Gradio SDK**。
47
  2. 在 **Hardware** 欄位選擇 **Zero GPU**(需 PRO 帳號)。
48
  3. 設定 Python 版本為 3.10.13。
49
+ 4. 上傳 `app.py`、`requirements.txt`、`README.md`,Spaces 會自動安裝相依套件。
50
+ 5. 點擊 **Deploy** 即可線上體驗!
51
 
52
  ## 五、使用效益
53
  - **快速回應**:利用 GPU burst 加速生成速度。
54
+ - **多樣化候選**:透過 Diverse Beam Search 與共同前綴合併,提供更具多樣性和精簡性的建議。
55
  - **零門檻**:免本地 GPU,開發者與使用者皆可輕鬆試用。
56
+ - **多模型對比**:可快速測試不同模型品質與效能。
57
 
58
  歡迎體驗高效、無痛的台灣中文輸入法下段建議 Demo!
app.py CHANGED
@@ -1,3 +1,4 @@
 
1
  import spaces
2
  import gradio as gr
3
  from gradio import update
@@ -24,7 +25,35 @@ MODEL_LIST = [
24
  "Epiculous/Violet_Twilight-v0.2",
25
  ]
26
 
27
- @lru_cache(maxsize=None)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  def get_pipeline(model_name):
29
  tok = AutoTokenizer.from_pretrained(model_name)
30
  mdl = AutoModelForCausalLM.from_pretrained(
@@ -34,15 +63,20 @@ def get_pipeline(model_name):
34
  return pipeline("text-generation", model=mdl, tokenizer=tok, device=0)
35
 
36
  @spaces.GPU
37
- def suggest_next(text, model_name, k, m):
38
  """
39
- 使用 Beam Search 產生 m 條候選,並一次更新候選列表,轉繁體並去除重複。
 
 
 
40
  """
41
  gen_pipe = get_pipeline(model_name)
42
  outs = gen_pipe(
43
  text,
44
  max_new_tokens=k,
45
  num_beams=m,
 
 
46
  num_return_sequences=m,
47
  do_sample=False,
48
  early_stopping=True
@@ -56,8 +90,11 @@ def suggest_next(text, model_name, k, m):
56
  for s in suggestions:
57
  if s not in unique_suggestions:
58
  unique_suggestions.append(s)
59
- # 不編號,直接顯示文字
60
- return update(choices=unique_suggestions, value=None)
 
 
 
61
 
62
 
63
  def append_suggestion(current, choice):
@@ -170,16 +207,42 @@ with gr.Blocks(css=custom_css) as demo:
170
  m_slider = gr.Slider(
171
  minimum=1, maximum=30, step=1, value=30, label="M(建議數/Beam 數)"
172
  )
 
 
 
 
 
 
 
 
173
 
174
  # 綁定事件
175
  predict_button.click(
176
  fn=suggest_next,
177
- inputs=[input_text, model_selector, k_slider, m_slider],
 
 
 
 
 
 
 
178
  outputs=suggestions,
179
  )
180
  input_text.change(
181
- fn=lambda txt, mdl, k, m, auto: suggest_next(txt, mdl, k, m) if auto else update(choices=[], value=None),
182
- inputs=[input_text, model_selector, k_slider, m_slider, auto_predict],
 
 
 
 
 
 
 
 
 
 
 
183
  outputs=suggestions,
184
  )
185
  suggestions.change(
 
1
+ # app.py
2
  import spaces
3
  import gradio as gr
4
  from gradio import update
 
25
  "Epiculous/Violet_Twilight-v0.2",
26
  ]
27
 
28
+ def merge_common_prefixes(suggestions, min_len=2):
29
+ """
30
+ 合併具有共同前綴的建議:
31
+ - 找出所有長度 ≥ min_len 的共同前綴
32
+ - 將這些前綴作為新建議,移除原有被合併的項目
33
+ """
34
+ prefixes = []
35
+ to_remove = set()
36
+
37
+ for i in range(len(suggestions)):
38
+ for j in range(i+1, len(suggestions)):
39
+ s1, s2 = suggestions[i], suggestions[j]
40
+ # 計算字元級共同前綴
41
+ common = ''.join(c1 for c1, c2 in zip(s1, s2) if c1 == c2)
42
+ if len(common) >= min_len:
43
+ prefixes.append(common)
44
+ to_remove.update([s1, s2])
45
+
46
+ # 去重前綴
47
+ unique_prefixes = []
48
+ for p in prefixes:
49
+ if p not in unique_prefixes:
50
+ unique_prefixes.append(p)
51
+
52
+ # 剩下沒有被合併的建議
53
+ remainder = [s for s in suggestions if s not in to_remove]
54
+ return unique_prefixes + remainder
55
+
56
+ @lru_cache(maxsize=8)
57
  def get_pipeline(model_name):
58
  tok = AutoTokenizer.from_pretrained(model_name)
59
  mdl = AutoModelForCausalLM.from_pretrained(
 
63
  return pipeline("text-generation", model=mdl, tokenizer=tok, device=0)
64
 
65
  @spaces.GPU
66
+ def suggest_next(text, model_name, k, m, num_beam_groups, diversity_penalty):
67
  """
68
+ 使用 Diverse Beam Search 產生 m 條候選:
69
+ - num_beams = m
70
+ - num_beam_groups, diversity_penalty 可調整多樣性
71
+ 之後轉繁體、去重、合併共同前綴後回傳。
72
  """
73
  gen_pipe = get_pipeline(model_name)
74
  outs = gen_pipe(
75
  text,
76
  max_new_tokens=k,
77
  num_beams=m,
78
+ num_beam_groups=num_beam_groups,
79
+ diversity_penalty=diversity_penalty,
80
  num_return_sequences=m,
81
  do_sample=False,
82
  early_stopping=True
 
90
  for s in suggestions:
91
  if s not in unique_suggestions:
92
  unique_suggestions.append(s)
93
+
94
+ # 合併共同前綴
95
+ final_suggestions = merge_common_prefixes(unique_suggestions, min_len=2)
96
+
97
+ return update(choices=final_suggestions, value=None)
98
 
99
 
100
  def append_suggestion(current, choice):
 
207
  m_slider = gr.Slider(
208
  minimum=1, maximum=30, step=1, value=30, label="M(建議數/Beam 數)"
209
  )
210
+ group_slider = gr.Slider(
211
+ minimum=1, maximum=30, step=1, value=30,
212
+ label="Beam 群組數 (num_beam_groups)"
213
+ )
214
+ diversity_penalty_slider = gr.Slider(
215
+ minimum=0.0, maximum=2.0, step=0.1, value=1.0,
216
+ label="多樣性懲罰 (diversity_penalty)"
217
+ )
218
 
219
  # 綁定事件
220
  predict_button.click(
221
  fn=suggest_next,
222
+ inputs=[
223
+ input_text,
224
+ model_selector,
225
+ k_slider,
226
+ m_slider,
227
+ group_slider,
228
+ diversity_penalty_slider
229
+ ],
230
  outputs=suggestions,
231
  )
232
  input_text.change(
233
+ fn=lambda txt, mdl, k, m, g, d, auto: (
234
+ suggest_next(txt, mdl, k, m, g, d)
235
+ if auto else update(choices=[], value=None)
236
+ ),
237
+ inputs=[
238
+ input_text,
239
+ model_selector,
240
+ k_slider,
241
+ m_slider,
242
+ group_slider,
243
+ diversity_penalty_slider,
244
+ auto_predict
245
+ ],
246
  outputs=suggestions,
247
  )
248
  suggestions.change(