subdiox commited on
Commit
3d52f4f
ยท
0 Parent(s):

genmai 1.0.0

Browse files
Files changed (7) hide show
  1. .gitattributes +35 -0
  2. README.md +127 -0
  3. config.json +36 -0
  4. model-coreml.zip +3 -0
  5. model.safetensors +3 -0
  6. tokenizer.json +0 -0
  7. tokenizer_config.json +12 -0
.gitattributes ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: cc-by-sa-4.0
3
+ language: ja
4
+ base_model: Miwa-Keita/zenz-v2.5-medium
5
+ pipeline_tag: text-generation
6
+ tags:
7
+ - japanese
8
+ - input-method
9
+ - kana-kanji-conversion
10
+ ---
11
+ # genmai-310M
12
+
13
+ A Japanese **kana-kanji conversion** model: it converts a reading (katakana) into Japanese text, optionally
14
+ conditioned on the text before the cursor. It is the AI converter of the macOS input method
15
+ [genmai](https://github.com/subdiox/genmai-ime), which runs it on device with Core ML (`model-coreml.zip`).
16
+
17
+ - Architecture: GPT-2, character-level vocabulary, 24 layers, 1024 hidden, 310M parameters
18
+ - Smaller variant (90M, distilled from this model, about twice as fast): [subdiox/genmai-90M](https://huggingface.co/subdiox/genmai-90M)
19
+ - Base model: [Miwa-Keita/zenz-v2.5-medium](https://huggingface.co/Miwa-Keita/zenz-v2.5-medium) (CC BY-SA 4.0)
20
+
21
+ ## Files
22
+
23
+ Releases are git tags (`v1.0.0`); use a tag to pin a version. `main` is the latest release.
24
+
25
+ | file | contents |
26
+ |---|---|
27
+ | `model.safetensors` | fp32 weights in the Hugging Face GPT-2 layout (1.2 GB), for transformers |
28
+ | `config.json` | GPT-2 config; the prompt format is recorded as `"genmai_prompt_format": "zenzlc"` |
29
+ | `tokenizer.json`, `tokenizer_config.json` | the tokenizer |
30
+ | `model-coreml.zip` | what the genmai input method runs: the model as stateful Core ML packages for the Apple Neural Engine (283 MB; see below): `genmai_0.mlpackage` (layers 0โ€“11) and `genmai_1.mlpackage` (layers 12โ€“23 and the head), int8 weights, and `genmai_coreml.json` (static shapes: `format` `genmai-coreml-1`, `prompt_slots` 256, `output_steps` 64, `rows` 5, `prefill_chunk` 32, `chunks` 2) |
31
+
32
+ ```python
33
+ from transformers import AutoModelForCausalLM, AutoTokenizer
34
+ m = AutoModelForCausalLM.from_pretrained("subdiox/genmai-310M", revision="v1.0.0")
35
+ tok = AutoTokenizer.from_pretrained("subdiox/genmai-310M", revision="v1.0.0")
36
+ x = tok("<s>\uee00" + "ใƒใƒใƒใƒใ‚ฌใ‚คใ‚ฟใ‚คใƒฉใ‚ทใ‚ค" + "\uee01", return_tensors="pt", add_special_tokens=False)
37
+ y = m.generate(**x, num_beams=5, num_return_sequences=5, length_penalty=0.0, max_new_tokens=64)
38
+ print([tok.decode(s[x.input_ids.shape[1]:], skip_special_tokens=True) for s in y]) # ๆฏใฏๆญฏใŒ็—›ใ„ใ‚‰ใ—ใ„, ...
39
+ ```
40
+
41
+ Rank beams by the plain sum of log-probabilities (`length_penalty=0.0`): with transformers' default length
42
+ normalisation, long degenerate outputs such as ใƒใƒใƒใƒใ‚ฌใ‚คใ‚ฟใ‚คใ‚‰ใ—ใ„ can win.
43
+
44
+ ## Prompt format (`zenzlc`)
45
+
46
+ Left context first (up to the last 500 characters), then the reading, then the output:
47
+
48
+ ```
49
+ <s>[U+EE02]{left context}[U+EE00]{reading in katakana}[U+EE01]{output}</s>
50
+ ```
51
+
52
+ `[U+EE0x]` are the private-use marker characters U+EE02 (context), U+EE00 (input) and U+EE01 (output).
53
+ Without context the `[U+EE02]{left context}` part is omitted. Spaces are written as U+3000 and newlines are
54
+ removed. `config.json` records the format name (`genmai_prompt_format`). Decode with beam search (genmai uses 5 beams) and stop at EOS;
55
+ long readings are split at ใ€ใ€‚ into chunks of at most 40 characters, each decoded after the previous output.
56
+
57
+ ## Core ML (Apple Neural Engine)
58
+
59
+ `model-coreml.zip` holds the same model converted with coremltools 9 (macOS 15 / iOS 18 or later) for the genmai
60
+ input method's Core ML decoder. A package with all 24 layers does not load on the Neural Engine, so the model is
61
+ split into two packages; each has two functions that share the package's states (per layer, keys and values in
62
+ fp16):
63
+
64
+ - `prefill`: 32 prompt tokens written to prompt slots `start ..< start + 32` (`mask` (32, 256) additive). Inputs of
65
+ `genmai_0`: `ids`, `pos` (1, 32) int32, `start` (1,) int32, `mask`; of `genmai_1`: `hidden` (1, 32, 1024) fp16 (the
66
+ output of `genmai_0`), `start`, `mask`. Outputs: `hidden` (`genmai_0`), `logp` (32, 6000) (`genmai_1`).
67
+ - `decode`: one token for each of 5 beams. Inputs of `genmai_0`: `tok` (5, 1) int32, `pos` (1,) int32; of
68
+ `genmai_1`: `hidden` (5, 1, 1024) fp16; both: `wsel` (320, 5) / `keep` (320, 1), `pmask` (1, 256) / `smask` (5, 320)
69
+ fp16 additive. Beam r's token of step t is stored at output slot t ยท 5 + r (`wsel` is the one-hot placement, `keep`
70
+ = 1 โˆ’ its row sums); each beam attends to the prompt slots in `pmask` and to its ancestors' slots in `smask`.
71
+
72
+ The Neural Engine computes in fp16 (at most 65504), which this model exceeds: its residual stream reaches about 81k
73
+ and one attention head of the second layer has logits up to about 500k. The packages are reparametrized exactly to stay in
74
+ range: the residual stream is scaled by 0.25 (embeddings and the attention / MLP output projections ร— 0.25, layer
75
+ norm epsilon ร— 1/16; the head uses the unscaled embeddings), and attention logits are computed / 256 (folded into the
76
+ query weights), the row maximum subtracted and the result ร— 256 before the softmax. Linear weights are int8
77
+ (symmetric, per channel), the rest fp16. The conversion script is `Tools/coreml/genmai_coreml.py` of
78
+ [genmai-ime](https://github.com/subdiox/genmai-ime) (`--chunks 2 --residual-scale 0.25 --score-scale 256`).
79
+
80
+ On an M4 Pro (5 beams): top-1 accuracy (exact) 94.1 / 93.0 / 78.6 % on everyday sentences / AJIMEE / hard sentences
81
+ (the weights in 8 bits on the GPU: 93.1 / 92.5 / 78.6 %, top-1 identical on 96โ€“98.5 % of the items); process
82
+ footprint 80โ€“140 MB; a whole everyday sentence converts in a median 113 ms, the input method's conversion key (which
83
+ converts while you type) answers in a median 30 / 39 ms (everyday sentences / AJIMEE). The first load compiles the model for the Neural Engine
84
+ (about 20 s; macOS caches the result).
85
+
86
+ ## Training
87
+
88
+ Fine-tuned from zenz-v2.5-medium in several stages on (reading, text) pairs:
89
+
90
+ 1. ~6M automatically read sentences from Japanese Wikipedia, FineWeb-2 (Japanese), Aozora Bunko and Diet
91
+ minutes (readings by UniDic with corrections learned from reviewed samples);
92
+ 2. long left context (up to 500 characters);
93
+ 3. reading/surface pairs of the Mozc dictionary (dictionary_oss) and sentences containing rare dictionary words;
94
+ 4. curated data: hand-checked items, synthetic sentences and homophone sets generated with Claude, and
95
+ LLM-judged corrections, with replay of the earlier data;
96
+ 5. training with an auxiliary next-character language-model loss on the real text before the cursor (so the
97
+ model learns how words are used in running text, not only the conversions).
98
+
99
+ The release is a single model after one more round of stage 5 on ~1M further pairs.
100
+
101
+ ## Evaluation
102
+
103
+ Top-1 accuracy, beam size 5, bf16; candidates whose reading does not match the input are dropped. AJIMEE, everyday
104
+ sentences and ime_v1 dev are judged leniently (orthographic variants accepted); homophones = word-level accuracy
105
+ on held-out homophone sentences; hard = 28 sentences written to stress an IME (exact match up to orthography).
106
+
107
+ | set | genmai-310M (bf16) | Zenzai (zenz-v3.2-small, azooKey settings) |
108
+ |---|---|---|
109
+ | AJIMEE-Bench (200) | 95.0 % | 85.5 % |
110
+ | everyday sentences (101) | 98.0 % | 97.0 % |
111
+ | ime_v1 dev (544) | 93.6 % | โ€“ |
112
+ | homophone sentences (1,607) | 93.1 % | โ€“ |
113
+ | average of the four | 94.9 % | โ€“ |
114
+ | hard IME sentences (28) | 22 / 28 | โ€“ |
115
+
116
+ ## Limitations
117
+
118
+ - Readings that repeat one sound (ใใ—ใ‚ƒใฎใใ—ใ‚ƒใŒใใ—ใ‚ƒใงใใ—ใ‚ƒใ—ใŸ) tend to map every occurrence to the same word
119
+ or drop part of the reading.
120
+ - Rare proper nouns and fine homophone distinctions (็‰นๅพด/็‰น้•ท, ่ฟฝๅŠ/่ฟฝๆฑ‚) are still error-prone.
121
+ - The model copies the left context strongly: a wrong conversion earlier in the context can be repeated.
122
+
123
+ ## License and attribution
124
+
125
+ CC BY-SA 4.0. The training data include Wikipedia (CC BY-SA), FineWeb-2 (ODC-By), Aozora Bunko, the National
126
+ Diet minutes, and the Mozc dictionary (BSD-3-Clause, Copyright Google Inc.; contains data derived from IPAdic,
127
+ Copyright Nara Institute of Science and Technology).
config.json ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "activation_function": "gelu_pytorch_tanh",
3
+ "add_cross_attention": false,
4
+ "architectures": [
5
+ "GPT2LMHeadModel"
6
+ ],
7
+ "attn_pdrop": 0.0,
8
+ "bos_token_id": 2,
9
+ "dtype": "float32",
10
+ "embd_pdrop": 0.0,
11
+ "eos_token_id": 3,
12
+ "initializer_range": 0.02,
13
+ "layer_norm_epsilon": 1e-05,
14
+ "model_type": "gpt2",
15
+ "n_ctx": 1024,
16
+ "n_embd": 1024,
17
+ "n_head": 16,
18
+ "n_inner": null,
19
+ "n_layer": 24,
20
+ "n_positions": 1024,
21
+ "pad_token_id": 1,
22
+ "reorder_and_upcast_attn": false,
23
+ "resid_pdrop": 0.0,
24
+ "scale_attn_by_inverse_layer_idx": false,
25
+ "scale_attn_weights": true,
26
+ "summary_activation": null,
27
+ "summary_first_dropout": 0.1,
28
+ "summary_proj_to_labels": true,
29
+ "summary_type": "cls_index",
30
+ "summary_use_proj": true,
31
+ "tie_word_embeddings": true,
32
+ "transformers_version": "5.20.0",
33
+ "use_cache": false,
34
+ "vocab_size": 6000,
35
+ "genmai_prompt_format": "zenzlc"
36
+ }
model-coreml.zip ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:da2a6e1a9fbf0729c84b8497462ae4ffaf8b2dd2b74c808f3de971b5643ef3ff
3
+ size 282924021
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d44679bed94faf1e8baa4edf7a4d0bc57c5664d8094afb7688feed98fc0f279b
3
+ size 1238046208
tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
tokenizer_config.json ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "add_prefix_space": false,
3
+ "backend": "tokenizers",
4
+ "bos_token": "<s>",
5
+ "clean_up_tokenization_spaces": true,
6
+ "eos_token": "</s>",
7
+ "errors": "replace",
8
+ "model_max_length": 1000000000000000019884624838656,
9
+ "pad_token": "[PAD]",
10
+ "tokenizer_class": "GPT2Tokenizer",
11
+ "unk_token": "[UNK]"
12
+ }