MakeItMore commited on
Commit
da8de96
·
verified ·
1 Parent(s): 77dfe62

SpellSpeak Tone rc2.1

Browse files
MANIFEST.json CHANGED
@@ -1,21 +1,21 @@
1
  {
2
  "name": "SpellSpeak Tone",
3
- "release": "rc2",
4
- "package": "spellspeak-tone-rc2.1",
5
- "created": "2026-10-09T20:04:42Z",
6
  "contract": "line-tags-0.2",
7
  "files": {
8
  "README.md": {
9
- "bytes": 11515,
10
- "sha256": "ee6236cc892dc551326d980b2a05c49761f6c7d3a9b2fcc26d02a2940661f615"
11
  },
12
  "config.json": {
13
  "bytes": 1515,
14
  "sha256": "531d5558cd620780ac3fe02d2acf2aad960e768619440d48d8c0abf4b32fa182"
15
  },
16
  "example.py": {
17
- "bytes": 2603,
18
- "sha256": "10b5e50ddf13a34ff0e2f1dc5d822e1a6a9e6805ed674853bf630cfb3590ecbe"
19
  },
20
  "model.onnx": {
21
  "bytes": 111170339,
@@ -25,6 +25,10 @@
25
  "bytes": 111132591,
26
  "sha256": "d6809b08375415f0cd2bbc0282d9d3c8d8282b010001ee52559f7fae5b857e60"
27
  },
 
 
 
 
28
  "requirements.txt": {
29
  "bytes": 287,
30
  "sha256": "91061e9d80e2cdaf62f522debf73ebcefcfa88930d50c391142b0d73cd72faee"
@@ -54,8 +58,8 @@
54
  "sha256": "79774b330a98949865f3c0b22b1f72b5d9510effaa3d9635579c2b09ea9db04f"
55
  },
56
  "runtime/harness/expression/classifier.py": {
57
- "bytes": 6324,
58
- "sha256": "7a65e82ae9696beb659e6a4da8f0748c8937952f112dd327716ae20b093df934"
59
  },
60
  "runtime/harness/expression/decide.py": {
61
  "bytes": 1410,
 
1
  {
2
  "name": "SpellSpeak Tone",
3
+ "release": "rc2.1",
4
+ "package": "spellspeak-tone-rc2.2",
5
+ "created": "2026-10-09T22:16:39Z",
6
  "contract": "line-tags-0.2",
7
  "files": {
8
  "README.md": {
9
+ "bytes": 14297,
10
+ "sha256": "3013c4ff392150819362ac5c7735f894aff751aa3aa0b6f334948d3ecab40a3b"
11
  },
12
  "config.json": {
13
  "bytes": 1515,
14
  "sha256": "531d5558cd620780ac3fe02d2acf2aad960e768619440d48d8c0abf4b32fa182"
15
  },
16
  "example.py": {
17
+ "bytes": 2930,
18
+ "sha256": "91087ec1faa9557ccae9cf31d4550a4a983cb3bb334cafc884c411aa93f23f77"
19
  },
20
  "model.onnx": {
21
  "bytes": 111170339,
 
25
  "bytes": 111132591,
26
  "sha256": "d6809b08375415f0cd2bbc0282d9d3c8d8282b010001ee52559f7fae5b857e60"
27
  },
28
+ "model_fp16.onnx": {
29
+ "bytes": 55694715,
30
+ "sha256": "08201561726a6e80cf454ab57e786b268ee428d152dc9299f80941e541ad11d7"
31
+ },
32
  "requirements.txt": {
33
  "bytes": 287,
34
  "sha256": "91061e9d80e2cdaf62f522debf73ebcefcfa88930d50c391142b0d73cd72faee"
 
58
  "sha256": "79774b330a98949865f3c0b22b1f72b5d9510effaa3d9635579c2b09ea9db04f"
59
  },
60
  "runtime/harness/expression/classifier.py": {
61
+ "bytes": 7321,
62
+ "sha256": "4b9f54a4e3d9390f7b080996cc5cead459132a78835f93d0b0f734b53a8cc965"
63
  },
64
  "runtime/harness/expression/decide.py": {
65
  "bytes": 1410,
README.md CHANGED
@@ -20,7 +20,7 @@ tags:
20
  - dialogue
21
  ---
22
 
23
- # SpellSpeak Tone · RC2
24
 
25
  When several AI characters share one conversation, as in a game, an interactive story or any other multi-character voice experience, each of them needs a structured reading of every line: how the speaker sounds, what the line does to each person present, and whether it leaves a question open for someone else to answer. The language model voicing a character could produce that reading, but only through extra output tokens, training or tool calls. That adds latency to every turn, takes capacity from the dialogue, risks malformed output, and repeats the work for each character in the scene.
26
 
@@ -28,22 +28,30 @@ SpellSpeak Tone treats the reading as multi-task classification by a separate sm
28
 
29
  [Examples and source](https://github.com/spellspeak/models/tree/main/tone)
30
 
 
 
 
 
 
 
 
 
31
  | | |
32
  |---|---|
33
- | **Released** | 2026-10-09 · rc2 (package `spellspeak-tone-rc2.1`) |
34
  | **What it does** | Reads one line of dialogue and tags the speaker's emotion, the social act toward each person present, and the line's move in the conversation |
35
  | **What changed from rc1** | One new output per line, the move, from two extra encoder layers and a small head beside rc1's unchanged encoder, in the same pass. Every rc1 output (emotion, acts, intensities, backchannel, hostility, confidences) is rc1's, checked on every one of 3,754 test lines |
36
- | **Size** | 27.9M parameters (rc1's 23.6M plus 4.3M for the move) · 111 MB ONNX (fp32) |
37
- | **Speed** | p95 per line on 4 CPU threads (Apple M1 Max): 7.0 ms for 1 person, 7.9 for 4, 9.7 for 8 (rc1: 5.5, 6.6, 7.3). On 1 thread: 19 to 28 ms |
38
  | **Runtime** | ONNX Runtime (1.24 or later) and tokenizers, on CPU. A Python reference runtime ships with it |
39
- | **Files** | `model.opt.onnx` (the graph to run), `model.onnx` (the same graph unoptimized), `tokenizer.json` and `config.json`, with the reference runtime (`runtime/`), `example.py` and `requirements.txt`. `MANIFEST.json` lists every file with its size and sha256 |
40
  | **Licence** | Apache-2.0 |
41
 
42
  ## Quick start
43
 
44
  ```bash
45
  pip install -U huggingface_hub
46
- hf download spellspeak/tone --revision rc2 --local-dir spellspeak-tone
47
  cd spellspeak-tone
48
  pip install -r requirements.txt
49
  python example.py
@@ -70,6 +78,17 @@ player to Tomas: "Touch my horse again and you'll regret it."
70
 
71
  A group conversation can play Mara's answer first, add Tomas's rumour as a second voice, and drop the dodge and the "no idea".
72
 
 
 
 
 
 
 
 
 
 
 
 
73
  In your own code, with the downloaded folder as the working directory:
74
 
75
  ```python
@@ -79,7 +98,8 @@ sys.path.insert(0, "runtime")
79
  from contracts.schemas.line_tags import LineInput
80
  from harness.expression.classifier import LineClassifier
81
 
82
- tone = LineClassifier(".") # the folder with model.opt.onnx, tokenizer.json and config.json
 
83
  tags = tone.tag(LineInput(speaker="Wren", speaker_kind="npc", to="Tomas", targets=["Tomas", "Mara", "player"],
84
  text="Aye, I saw the whole thing.", previous="Tomas: Wren, you were there, weren't you?"))
85
  print(tags.exchange) # label='answers' confidence=0.9413
@@ -141,6 +161,16 @@ The same test lines, scored again without who a line is said to, without the lin
141
  - **Send who a line is said to when you know it.** Without it, a "you" in a group is read as aimed at everyone. On those lines, harmless pairs called hostile go from 2.1% to 17.6%.
142
  - **Send the line before for the move.** A bare "Yes." is an answer only after a question. Without the line before, "answered or still open" drops 15 points.
143
 
 
 
 
 
 
 
 
 
 
 
144
  ## How it was made
145
 
146
  - **Model:** MiniLM-L6 (`sentence-transformers/all-MiniLM-L6-v2` at 1110a24, Apache-2.0) with six small heads, unchanged from rc1. For the move, trainable copies of its top two layers read its fourth layer's output, and a small head reads them. The encoder itself was frozen, so every rc1 output is unchanged.
@@ -148,6 +178,7 @@ The same test lines, scored again without who a line is said to, without the lin
148
  - **Labels:** the majority vote of a committee of three large language models. 4,992 lines were labelled for the move.
149
  - **Lines:** our own game dialogue, Project Gutenberg dialogue, GoEmotions (Apache-2.0), Civil Comments (CC0), and lines written for this project by Qwen3.8-27B. The last include 95,000 of natural player speech, 48,000 aimed at sarcasm, doubling down and implied threats, and 9,126 short exchanges for the rarer moves: rumours, dodges, "don't know", closings, and exchanges between characters.
150
  - **Calibration:** the hostility threshold and the act and emotion curves are rc1's. A curve for the move's confidence was fitted on the dev set.
 
151
 
152
  ## Use and limits
153
 
@@ -157,6 +188,7 @@ The same test lines, scored again without who a line is said to, without the lin
157
  - **It misses things.** It gets "answered or still open" wrong about one time in six. It misses about two in three sarcastic jabs and about one in four hostile lines.
158
  - **Player lines are harder** than characters' lines for the move (macro-F1 0.74 against 0.81), and new settings harder still (0.71).
159
  - **About 30% slower than rc1**, because two extra encoder layers run for the move.
 
160
  - **It has only been tested in game settings.** Its test lines are committee-labelled generated and game dialogue, not logs from real players or from other multi-character voice experiences.
161
 
162
- The numbers come from the training repository's report for this release (`2026-10-09-linecls-r8-exchange.md`, at commit a31743c) and, for the emotion and act heads unchanged since rc1, `2026-10-08-linecls-r6-sarcasm.md` and `2026-10-08-linecls-r7-calibration.md`. The model files were packaged from git tag `spellspeak-tone-rc2` (commit 691b8e2). That repository is private.
 
20
  - dialogue
21
  ---
22
 
23
+ # SpellSpeak Tone · RC2.1
24
 
25
  When several AI characters share one conversation, as in a game, an interactive story or any other multi-character voice experience, each of them needs a structured reading of every line: how the speaker sounds, what the line does to each person present, and whether it leaves a question open for someone else to answer. The language model voicing a character could produce that reading, but only through extra output tokens, training or tool calls. That adds latency to every turn, takes capacity from the dialogue, risks malformed output, and repeats the work for each character in the scene.
26
 
 
28
 
29
  [Examples and source](https://github.com/spellspeak/models/tree/main/tone)
30
 
31
+ ## What is new in RC2.1
32
+
33
+ - **A 16-bit file at half the size, with the same answers.** `model_fp16.onnx` is rc2's model with its weights stored in 16 bits: 55.7 MB against 111.1 MB. On 5,204 test lines, read in all four columns with and without the optional inputs, at most one line in a column gets a different tag from full precision. No scorecard measure changes beyond noise.
34
+ - **The same speed, and no memory saved.** It computes in 32 bits. p95 per line for 8 people on 4 threads of an Apple M1 Max: 10.0 ms against 9.9 ms for full precision, timed side by side (1 thread: 29.4 against 29.5 ms). Resident memory: 222 MB against 201 MB. What it saves is the download and the disk.
35
+ - **Full precision is unchanged and stays the default.** `model.opt.onnx`, `model.onnx`, `tokenizer.json` and `config.json` are rc2's, byte for byte. Ask for the 16-bit file with `precision="fp16"`, or `python example.py --fp16`.
36
+
37
+ Full precision is the reference: every other number on this card is full precision's, and it is the file to keep for any further training.
38
+
39
  | | |
40
  |---|---|
41
+ | **Released** | 2026-10-09 · rc2.1 (package `spellspeak-tone-rc2.2`) |
42
  | **What it does** | Reads one line of dialogue and tags the speaker's emotion, the social act toward each person present, and the line's move in the conversation |
43
  | **What changed from rc1** | One new output per line, the move, from two extra encoder layers and a small head beside rc1's unchanged encoder, in the same pass. Every rc1 output (emotion, acts, intensities, backchannel, hostility, confidences) is rc1's, checked on every one of 3,754 test lines |
44
+ | **Size** | 27.9M parameters (rc1's 23.6M plus 4.3M for the move) · 111.1 MB ONNX in full precision (fp32), 55.7 MB with the weights in 16 bits (`model_fp16.onnx`) |
45
+ | **Speed** | p95 per line on 4 CPU threads (Apple M1 Max): 7.0 ms for 1 person, 7.9 for 4, 9.7 for 8 (rc1: 5.5, 6.6, 7.3). On 1 thread: 19 to 28 ms. The 16-bit file takes the same time |
46
  | **Runtime** | ONNX Runtime (1.24 or later) and tokenizers, on CPU. A Python reference runtime ships with it |
47
+ | **Files** | `model.opt.onnx` (the graph to run), `model.onnx` (the same graph unoptimized), `model_fp16.onnx` (the graph to run with its weights in 16 bits), `tokenizer.json` and `config.json`, with the reference runtime (`runtime/`), `example.py` and `requirements.txt`. `MANIFEST.json` lists every file with its size and sha256 |
48
  | **Licence** | Apache-2.0 |
49
 
50
  ## Quick start
51
 
52
  ```bash
53
  pip install -U huggingface_hub
54
+ hf download spellspeak/tone --revision rc2.1 --local-dir spellspeak-tone
55
  cd spellspeak-tone
56
  pip install -r requirements.txt
57
  python example.py
 
78
 
79
  A group conversation can play Mara's answer first, add Tomas's rumour as a second voice, and drop the dodge and the "no idea".
80
 
81
+ The small download leaves out the two full-precision graphs, about 56 MB in all, and runs the 16-bit file:
82
+
83
+ ```bash
84
+ hf download spellspeak/tone --revision rc2.1 --local-dir spellspeak-tone-small --exclude model.onnx --exclude model.opt.onnx
85
+ cd spellspeak-tone-small
86
+ pip install -r requirements.txt
87
+ python example.py --fp16
88
+ ```
89
+
90
+ It prints exactly the same output.
91
+
92
  In your own code, with the downloaded folder as the working directory:
93
 
94
  ```python
 
98
  from contracts.schemas.line_tags import LineInput
99
  from harness.expression.classifier import LineClassifier
100
 
101
+ tone = LineClassifier(".") # full precision (model.opt.onnx), the default
102
+ # tone = LineClassifier(".", precision="fp16") # the 16-bit file (model_fp16.onnx), for the small download
103
  tags = tone.tag(LineInput(speaker="Wren", speaker_kind="npc", to="Tomas", targets=["Tomas", "Mara", "player"],
104
  text="Aye, I saw the whole thing.", previous="Tomas: Wren, you were there, weren't you?"))
105
  print(tags.exchange) # label='answers' confidence=0.9413
 
161
  - **Send who a line is said to when you know it.** Without it, a "you" in a group is read as aimed at everyone. On those lines, harmless pairs called hostile go from 2.1% to 17.6%.
162
  - **Send the line before for the move.** A bare "Yes." is an answer only after a question. Without the line before, "answered or still open" drops 15 points.
163
 
164
+ ### The 16-bit file
165
+
166
+ The same 5,204 test lines, tagged by `model_fp16.onnx` and by full precision, in the same four columns:
167
+
168
+ | | As given | Without `to` | Without the line before | Without either |
169
+ |---|---|---|---|---|
170
+ | Lines with every tag the same as full precision | 100% | 100% | 99.98% (one move differs) | 99.98% (one act toward one person differs) |
171
+
172
+ Rounded as the tables above show them, every measure is the same with the 16-bit file. Calibration error moves by 0.0012 at most.
173
+
174
  ## How it was made
175
 
176
  - **Model:** MiniLM-L6 (`sentence-transformers/all-MiniLM-L6-v2` at 1110a24, Apache-2.0) with six small heads, unchanged from rc1. For the move, trainable copies of its top two layers read its fourth layer's output, and a small head reads them. The encoder itself was frozen, so every rc1 output is unchanged.
 
178
  - **Labels:** the majority vote of a committee of three large language models. 4,992 lines were labelled for the move.
179
  - **Lines:** our own game dialogue, Project Gutenberg dialogue, GoEmotions (Apache-2.0), Civil Comments (CC0), and lines written for this project by Qwen3.8-27B. The last include 95,000 of natural player speech, 48,000 aimed at sarcasm, doubling down and implied threats, and 9,126 short exchanges for the rarer moves: rumours, dodges, "don't know", closings, and exchanges between characters.
180
  - **Calibration:** the hostility threshold and the act and emotion curves are rc1's. A curve for the move's confidence was fitted on the dev set.
181
+ - **The 16-bit file:** full precision's graph with every weight tensor of 1,024 values or more stored in 16 bits and turned back into 32 bits by the graph itself. Inputs, outputs and arithmetic stay 32-bit, so the same runtime and the same calibration curves serve both files.
182
 
183
  ## Use and limits
184
 
 
188
  - **It misses things.** It gets "answered or still open" wrong about one time in six. It misses about two in three sarcastic jabs and about one in four hostile lines.
189
  - **Player lines are harder** than characters' lines for the move (macro-F1 0.74 against 0.81), and new settings harder still (0.71).
190
  - **About 30% slower than rc1**, because two extra encoder layers run for the move.
191
+ - **The 16-bit file saves download and disk, not time or memory.** It has been timed on CPU only.
192
  - **It has only been tested in game settings.** Its test lines are committee-labelled generated and game dialogue, not logs from real players or from other multi-character voice experiences.
193
 
194
+ The numbers come from the training repository's reports: for the 16-bit file, `2026-10-09-linecls-precision.md` (at commit 9498f60); for the model, `2026-10-09-linecls-r8-exchange.md` (at commit a31743c) and, for the emotion and act heads unchanged since rc1, `2026-10-08-linecls-r6-sarcasm.md` and `2026-10-08-linecls-r7-calibration.md`. The full-precision files were packaged from git tag `spellspeak-tone-rc2` (commit 691b8e2), the 16-bit file was built from them by the code at commit 0c8ed10, and this release was packaged from git tag `spellspeak-tone-rc2.2`. That repository is private.
example.py CHANGED
@@ -1,10 +1,11 @@
1
  """Tag a few lines of a group conversation with SpellSpeak Tone.
2
 
3
  pip install -r requirements.txt
4
- python example.py
 
5
 
6
- The model files (model.opt.onnx, model.onnx, tokenizer.json, config.json) are read from this folder. Without them, as in
7
- a git checkout, they are downloaded once from Hugging Face (spellspeak/tone, release rc2).
8
  """
9
  import pathlib
10
  import sys
@@ -15,13 +16,15 @@ sys.path.insert(0, str(HERE / "runtime"))
15
  from contracts.schemas.line_tags import LineInput # noqa: E402
16
  from harness.expression.classifier import LineClassifier # noqa: E402
17
 
18
- MODEL_FILES = ["model.opt.onnx", "model.onnx", "tokenizer.json", "config.json"]
 
 
19
  model_dir = HERE
20
  if not all((HERE / f).exists() for f in MODEL_FILES):
21
  from huggingface_hub import snapshot_download
22
 
23
- model_dir = snapshot_download("spellspeak/tone", revision="rc2", allow_patterns=MODEL_FILES)
24
- tone = LineClassifier(model_dir, threads=4)
25
 
26
  # Three characters and the player. Each line names who speaks, who it is to (None: the room) and the line before it.
27
  CAST = ["Mara", "Tomas", "Wren", "player"]
 
1
  """Tag a few lines of a group conversation with SpellSpeak Tone.
2
 
3
  pip install -r requirements.txt
4
+ python example.py # full precision: model.opt.onnx
5
+ python example.py --fp16 # the 16-bit file: model_fp16.onnx, half the size
6
 
7
+ The model files are read from this folder. Without them, as in a git checkout, they are downloaded once from Hugging
8
+ Face (spellspeak/tone, release rc2.1). With --fp16, only model_fp16.onnx, tokenizer.json and config.json are needed.
9
  """
10
  import pathlib
11
  import sys
 
16
  from contracts.schemas.line_tags import LineInput # noqa: E402
17
  from harness.expression.classifier import LineClassifier # noqa: E402
18
 
19
+ PRECISION = "fp16" if "--fp16" in sys.argv[1:] else "fp32"
20
+ MODEL_FILES = (["model_fp16.onnx", "tokenizer.json", "config.json"] if PRECISION == "fp16"
21
+ else ["model.opt.onnx", "model.onnx", "tokenizer.json", "config.json"])
22
  model_dir = HERE
23
  if not all((HERE / f).exists() for f in MODEL_FILES):
24
  from huggingface_hub import snapshot_download
25
 
26
+ model_dir = snapshot_download("spellspeak/tone", revision="rc2.1", allow_patterns=MODEL_FILES)
27
+ tone = LineClassifier(model_dir, threads=4, precision=PRECISION)
28
 
29
  # Three characters and the player. Each line names who speaks, who it is to (None: the room) and the line before it.
30
  CAST = ["Mara", "Tomas", "Wren", "player"]
model_fp16.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:08201561726a6e80cf454ab57e786b268ee428d152dc9299f80941e541ad11d7
3
+ size 55694715
runtime/harness/expression/classifier.py CHANGED
@@ -11,6 +11,10 @@ its hostility probability reaches tau (an invented grudge costs more than a miss
11
  r8 (line-tags-0.2): a model whose graph has an `exchange` output and whose config lists `exchanges` also returns the
12
  line's exchange move (asks, answers, hedges, doesnt_know, withholds, closes, other) with its confidence, as
13
  `LineTags02`. A model without it (RC1) returns `LineTags` exactly as before.
 
 
 
 
14
  """
15
  from __future__ import annotations
16
 
@@ -24,16 +28,29 @@ from harness.expression.decide import decide, summed_hostility
24
  from harness.expression.render import render, span_mask
25
 
26
 
 
 
 
 
27
  class LineClassifier:
28
- def __init__(self, model_dir: str | pathlib.Path, onnx_file: str | None = None, threads: int = 4):
29
- """`onnx_file` defaults to the transformer optimizer's graph when the export has one (r3 on: same outputs,
30
- a little faster), else the plain graph."""
 
31
  import onnxruntime as ort
32
  from tokenizers import Tokenizer
33
 
 
 
34
  d = pathlib.Path(model_dir)
 
 
 
 
 
35
  onnx_file = onnx_file or ("model.opt.onnx" if (d / "model.opt.onnx").exists() else "model.onnx")
36
  self.onnx_file = onnx_file
 
37
  self.config = json.loads((d / "config.json").read_text())
38
  self.tok = Tokenizer.from_file(str(d / "tokenizer.json"))
39
  self.tok.enable_truncation(self.config["max_len"])
 
11
  r8 (line-tags-0.2): a model whose graph has an `exchange` output and whose config lists `exchanges` also returns the
12
  line's exchange move (asks, answers, hedges, doesnt_know, withholds, closes, other) with its confidence, as
13
  `LineTags02`. A model without it (RC1) returns `LineTags` exactly as before.
14
+
15
+ Precision: full precision ("fp32") is the default and the reference. From release rc2.1 a folder may also hold
16
+ `model_fp16.onnx`, the same graph with its weights stored in 16 bits (half the size, computed in 32 bits), picked with
17
+ `precision="fp16"`.
18
  """
19
  from __future__ import annotations
20
 
 
28
  from harness.expression.render import render, span_mask
29
 
30
 
31
+ PRECISIONS = ("fp32", "fp16")
32
+ FP16_FILE = "model_fp16.onnx"
33
+
34
+
35
  class LineClassifier:
36
+ def __init__(self, model_dir: str | pathlib.Path, onnx_file: str | None = None, threads: int = 4, precision: str = "fp32"):
37
+ """`precision` picks the graph. "fp32" (the default): the transformer optimizer's graph when the export has one
38
+ (r3 on: same outputs, a little faster), else the plain graph. "fp16": `model_fp16.onnx`, the weights stored in
39
+ 16 bits. `onnx_file` names a graph directly and overrides `precision`."""
40
  import onnxruntime as ort
41
  from tokenizers import Tokenizer
42
 
43
+ if precision not in PRECISIONS:
44
+ raise ValueError(f"precision must be one of {PRECISIONS}, not {precision!r}")
45
  d = pathlib.Path(model_dir)
46
+ if onnx_file is None and precision == "fp16":
47
+ if not (d / FP16_FILE).exists():
48
+ raise FileNotFoundError(f"precision='fp16' needs {FP16_FILE} in {d}. It ships with release rc2.1 and later; "
49
+ "download it, or use precision='fp32'")
50
+ onnx_file = FP16_FILE
51
  onnx_file = onnx_file or ("model.opt.onnx" if (d / "model.opt.onnx").exists() else "model.onnx")
52
  self.onnx_file = onnx_file
53
+ self.precision = precision
54
  self.config = json.loads((d / "config.json").read_text())
55
  self.tok = Tokenizer.from_file(str(d / "tokenizer.json"))
56
  self.tok.enable_truncation(self.config["max_len"])