WIlfLin commited on
Commit
eb970af
·
verified ·
1 Parent(s): 40189a8

Add pre-model letter-spelling normalization helper and usage

Browse files
Files changed (3) hide show
  1. README.md +31 -0
  2. input-preprocessing.json +19 -0
  3. input_preprocessing.py +36 -0
README.md CHANGED
@@ -98,6 +98,37 @@ FP32 主参数和优化器、BF16 autocast,发布权重为 BF16。约 7.52 亿
98
  历史定义与计数保存在 [history/step400/token-metrics.json](history/step400/token-metrics.json)。
99
  上游公开的 94.8% 缺少足够的评分细节,不能声称这些本地指标是官方同口径复现。
100
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  ## 推理示例
102
 
103
  验证环境为 PyTorch 2.10、Transformers 5.3。使用附带 tokenizer/chat template,关闭 thinking,输入带控制行。
 
98
  历史定义与计数保存在 [history/step400/token-metrics.json](history/step400/token-metrics.json)。
99
  上游公开的 94.8% 缺少足够的评分细节,不能声称这些本地指标是官方同口径复现。
100
 
101
+ ## 拼读英文的模型前预处理
102
+
103
+ 应用可先合并拼读字母,再把文本交给模型。这是应用层规则,**不包含在模型权重中**,也不是生成结束后的替换。
104
+ 附带的 [input_preprocessing.py](input_preprocessing.py) 只依赖 Python 标准库(Python 3.11+)。
105
+
106
+ - `C-H-A-T-G-P-T` → `CHATGPT`
107
+ - `A S T R A` → `ASTRA`
108
+ - 保留字母顺序和大小写;`C-L-E-A-U-D-E` 合并为 `CLEAUDE`,不会擅自改成 `Claude`。
109
+ - 通常合并三个及以上单字母;两个大写、空格分隔的字母也可合并,例如 `A I`。
110
+ - 不跨越换行,不改写代码字面量、网址、邮箱和路径。两个字母的连字符表达式 `X-Y` 保持原样。
111
+
112
+ 先下载脚本到应用目录:
113
+
114
+ ```bash
115
+ hf download WIlfLin/S1-mini-Chinese input_preprocessing.py --local-dir .
116
+ ```
117
+
118
+ 在构造模型消息之前调用:
119
+
120
+ ```python
121
+ from input_preprocessing import normalize_spelled_letters
122
+
123
+ transcript = "我今天试用A S T R A。"
124
+ model_input, spelling_runs = normalize_spelled_letters(transcript)
125
+ # model_input == "我今天试用ASTRA。"
126
+ # 将 model_input 放在下面推理示例的 user 控制行之后,再调用模型。
127
+ ```
128
+
129
+ 应用的原文模式应跳过这一步。连续字母也可能表示独立变量,规则无法完全判断语义;代码片段会跳过,其他歧义交给模型。
130
+ 此前 400 条测试表是原始模型输出,不包含此预处理。权重没有因增加此脚本而变化。
131
+
132
  ## 推理示例
133
 
134
  验证环境为 PyTorch 2.10、Transformers 5.3。使用附带 tokenizer/chat template,关闭 thinking,输入带控制行。
input-preprocessing.json ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "version": "spelled_letter_runs-v1",
3
+ "stage": "before model_messages, not after generation",
4
+ "enabled_by_application": true,
5
+ "model_weights_unchanged": true,
6
+ "weights_sha256": "54602b3a2e0c484fe7ae796a4290969d3a1cc58e099c83e59948fe94889150a0",
7
+ "supported": [
8
+ "tight hyphen-separated single letters",
9
+ "horizontal-space-separated single letters"
10
+ ],
11
+ "literal_exclusions": [
12
+ "inline/fenced code",
13
+ "URLs",
14
+ "emails",
15
+ "paths",
16
+ "assignments"
17
+ ],
18
+ "not_applied_to_published_public400_raw_model_metrics": true
19
+ }
input_preprocessing.py ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Join dictated single-letter runs before the text model, never after it."""
2
+ import re
3
+
4
+ # Horizontal whitespace only: distinct lines/paragraphs are not one spelling run.
5
+ _RUN = re.compile(r'(?<![A-Za-z0-9_./:@+\-])(?>[A-Za-z](?:(?:[-‐‑‒–—]|[ \t\u00a0]+)[A-Za-z])+)(?![A-Za-z0-9_./:@+\-])')
6
+ _LITERAL = re.compile(
7
+ r'```[\s\S]*?(?:```|\Z)|`[^`\n]*(?:`|\Z)'
8
+ r'|https?://[^\s,。!?;、)]+'
9
+ r'|[A-Za-z0-9._%+\-]+@[A-Za-z0-9.\-]+\.[A-Za-z]{2,}'
10
+ r'|(?:~/|/)[A-Za-z0-9_./~\-]+'
11
+ r'|\b[A-Za-z_]\w*\s*(?:==|!=|<=|>=|:=|[+*/\-]?=)\s*[^;\n,。]+'
12
+ )
13
+
14
+
15
+ def spelled_letter_runs(text):
16
+ """Yield unambiguous-enough spelling spans, preserving order and case.
17
+
18
+ Three or more separate letters, or two uppercase space-separated letters.
19
+ A two-letter hyphenated expression such as X-Y is left alone.
20
+ Literal code, paths, URLs and emails are not interpreted as dictation.
21
+ """
22
+ literals=[m.span() for m in _LITERAL.finditer(text)]
23
+ for match in _RUN.finditer(text):
24
+ a,b=match.span()
25
+ if any(a<end and b>start for start,end in literals):continue
26
+ letters=re.findall('[A-Za-z]',match[0])
27
+ if len(letters)<3 and not (all(c.isupper() for c in letters) and re.search('[ \t\u00a0]',match[0])):continue
28
+ yield a,b,''.join(letters)
29
+
30
+
31
+ def normalize_spelled_letters(text):
32
+ pieces=[];position=0;count=0
33
+ for start,end,word in spelled_letter_runs(text):
34
+ pieces.extend([text[position:start],word]);position=end;count+=1
35
+ pieces.append(text[position:])
36
+ return ''.join(pieces),count