v2: 13 MB browser build (int8 download, float compute), export/compress scripts, onnx evals
Browse files- .gitattributes +1 -0
- v2/compress.py +120 -0
- v2/eval.py +28 -0
- v2/export.py +58 -0
- v2/metrics/tinynext-v2-float-onnx.json +411 -0
- v2/metrics/tinynext-v2-q8-onnx.json +411 -0
- v2/train.py +50 -16
- v2/web/config.json +16 -0
- v2/web/graph.onnx +3 -0
- v2/web/parity.json +16 -0
- v2/web/tokenizer.json +0 -0
- v2/web/weights.json +1 -0
- v2/web/weights.q8 +3 -0
.gitattributes
CHANGED
|
@@ -34,3 +34,4 @@ saved_model/**/* 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
|
| 36 |
hero.png 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
|
| 36 |
hero.png filter=lfs diff=lfs merge=lfs -text
|
| 37 |
+
v2/web/weights.q8 filter=lfs diff=lfs merge=lfs -text
|
v2/compress.py
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# /// script
|
| 2 |
+
# requires-python = ">=3.11,<3.14"
|
| 3 |
+
# dependencies = ["onnx>=1.17", "numpy<3", "onnxruntime>=1.20"]
|
| 4 |
+
# ///
|
| 5 |
+
"""Shrinks a float ONNX model for download without changing how it runs.
|
| 6 |
+
|
| 7 |
+
The browser computes in float32 (onnxruntime-web's int8 kernels are several times slower than its float ones), so
|
| 8 |
+
only the download is compressed: every large weight is stored as int8 with a float32 scale per block of 64 values.
|
| 9 |
+
The page expands them back to float32 and hands them to onnxruntime-web as the model's external data.
|
| 10 |
+
|
| 11 |
+
Writes, next to each other:
|
| 12 |
+
graph.onnx the model graph; large weights point into "weights.f32" (external data)
|
| 13 |
+
weights.q8 int8 values, then float32 scales, tensor by tensor
|
| 14 |
+
weights.json for each tensor: where its int8 values and scales start, its shape, and where it goes in weights.f32
|
| 15 |
+
|
| 16 |
+
uv run compress.py v2-release/browser/model.onnx v2-release/web
|
| 17 |
+
"""
|
| 18 |
+
|
| 19 |
+
import json
|
| 20 |
+
import sys
|
| 21 |
+
from pathlib import Path
|
| 22 |
+
|
| 23 |
+
import numpy as np
|
| 24 |
+
import onnx
|
| 25 |
+
from onnx import numpy_helper
|
| 26 |
+
from onnx.external_data_helper import set_external_data
|
| 27 |
+
|
| 28 |
+
BLOCK = 64
|
| 29 |
+
MIN_ELEMENTS = 4096 # smaller tensors (norm weights) stay inside the graph as float32
|
| 30 |
+
EXTERNAL = "weights.f32"
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
def quantize(values: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
|
| 34 |
+
"""Symmetric int8 with one scale per BLOCK consecutive values."""
|
| 35 |
+
flat = values.astype(np.float32).ravel()
|
| 36 |
+
padded = np.pad(flat, (0, (-len(flat)) % BLOCK)).reshape(-1, BLOCK)
|
| 37 |
+
scales = np.abs(padded).max(axis=1) / 127
|
| 38 |
+
scales[scales == 0] = 1
|
| 39 |
+
q = np.clip(np.round(padded / scales[:, None]), -127, 127).astype(np.int8)
|
| 40 |
+
return q.ravel()[: len(flat)], scales.astype(np.float32)
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
def dequantize(q: np.ndarray, scales: np.ndarray, count: int) -> np.ndarray:
|
| 44 |
+
padded = np.pad(q.astype(np.float32), (0, (-count) % BLOCK)).reshape(-1, BLOCK)
|
| 45 |
+
return (padded * scales[:, None]).ravel()[:count]
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
def dedupe_transposes(model) -> None:
|
| 49 |
+
"""The output layer reuses the embedding table, but export stores a transposed copy. Keep one and transpose it
|
| 50 |
+
in the graph instead, which saves about 2.6 MB of download."""
|
| 51 |
+
from onnx import helper
|
| 52 |
+
|
| 53 |
+
graph = model.graph
|
| 54 |
+
arrays = {t.name: numpy_helper.to_array(t) for t in graph.initializer if t.dims and np.prod(t.dims) >= MIN_ELEMENTS}
|
| 55 |
+
for name, values in list(arrays.items()):
|
| 56 |
+
if values.ndim != 2:
|
| 57 |
+
continue
|
| 58 |
+
for other, candidate in arrays.items():
|
| 59 |
+
if other != name and candidate.shape == values.T.shape and np.array_equal(candidate, values.T):
|
| 60 |
+
transposed = f"{other}_transposed"
|
| 61 |
+
graph.node.insert(0, helper.make_node("Transpose", [other], [transposed], perm=[1, 0], name=transposed))
|
| 62 |
+
for node in graph.node:
|
| 63 |
+
node.input[:] = [transposed if i == name else i for i in node.input]
|
| 64 |
+
graph.initializer.remove(next(t for t in graph.initializer if t.name == name))
|
| 65 |
+
print(f"stored {name} as a transpose of {other}")
|
| 66 |
+
return
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
def compress(src: Path, out: Path) -> dict:
|
| 70 |
+
out.mkdir(parents=True, exist_ok=True)
|
| 71 |
+
model = onnx.load(str(src))
|
| 72 |
+
dedupe_transposes(model)
|
| 73 |
+
manifest, q8 = [], bytearray()
|
| 74 |
+
f32_offset = 0
|
| 75 |
+
for tensor in model.graph.initializer:
|
| 76 |
+
values = numpy_helper.to_array(tensor)
|
| 77 |
+
if values.dtype != np.float32 or values.size < MIN_ELEMENTS:
|
| 78 |
+
continue
|
| 79 |
+
q, scales = quantize(values)
|
| 80 |
+
entry = {"name": tensor.name, "shape": list(values.shape), "count": int(values.size), "f32_offset": f32_offset,
|
| 81 |
+
"q_offset": len(q8), "scale_offset": len(q8) + len(q) + (-len(q)) % 4}
|
| 82 |
+
q8 += q.tobytes()
|
| 83 |
+
q8 += b"\0" * ((-len(q8)) % 4) # keep scales 4-byte aligned for Float32Array views
|
| 84 |
+
q8 += scales.tobytes()
|
| 85 |
+
manifest.append(entry)
|
| 86 |
+
# Point the graph at weights.f32, which the browser builds by expanding weights.q8.
|
| 87 |
+
if not tensor.HasField("raw_data"):
|
| 88 |
+
tensor.raw_data = values.astype(np.float32).tobytes()
|
| 89 |
+
tensor.ClearField("float_data")
|
| 90 |
+
set_external_data(tensor, location=EXTERNAL, offset=f32_offset, length=values.size * 4)
|
| 91 |
+
tensor.ClearField("raw_data")
|
| 92 |
+
tensor.data_location = onnx.TensorProto.EXTERNAL
|
| 93 |
+
f32_offset += values.size * 4
|
| 94 |
+
onnx.save_model(model, str(out / "graph.onnx"))
|
| 95 |
+
(out / "weights.q8").write_bytes(bytes(q8))
|
| 96 |
+
(out / "weights.json").write_text(json.dumps({"block": BLOCK, "f32_bytes": f32_offset, "tensors": manifest}))
|
| 97 |
+
return {"graph_mb": round((out / "graph.onnx").stat().st_size / 1e6, 3), "weights_q8_mb": round(len(q8) / 1e6, 2),
|
| 98 |
+
"expanded_mb": round(f32_offset / 1e6, 2), "tensors": len(manifest)}
|
| 99 |
+
|
| 100 |
+
|
| 101 |
+
def expand(out: Path) -> Path:
|
| 102 |
+
"""What the browser does: rebuild weights.f32 from weights.q8. Used here to check accuracy."""
|
| 103 |
+
meta = json.loads((out / "weights.json").read_text())
|
| 104 |
+
raw = (out / "weights.q8").read_bytes()
|
| 105 |
+
f32 = np.zeros(meta["f32_bytes"] // 4, np.float32)
|
| 106 |
+
for t in meta["tensors"]:
|
| 107 |
+
q = np.frombuffer(raw, np.int8, t["count"], t["q_offset"])
|
| 108 |
+
blocks = (t["count"] + meta["block"] - 1) // meta["block"]
|
| 109 |
+
scales = np.frombuffer(raw, np.float32, blocks, t["scale_offset"])
|
| 110 |
+
f32[t["f32_offset"] // 4: t["f32_offset"] // 4 + t["count"]] = dequantize(q, scales, t["count"])
|
| 111 |
+
path = out / EXTERNAL
|
| 112 |
+
f32.tofile(path)
|
| 113 |
+
return path
|
| 114 |
+
|
| 115 |
+
|
| 116 |
+
if __name__ == "__main__":
|
| 117 |
+
src, out = Path(sys.argv[1]), Path(sys.argv[2])
|
| 118 |
+
print(json.dumps(compress(src, out), indent=1))
|
| 119 |
+
expand(out)
|
| 120 |
+
print(f"expanded {out / EXTERNAL} for checking")
|
v2/eval.py
CHANGED
|
@@ -352,6 +352,30 @@ def hf_causal_lm(name: str, repo: str) -> TokenLM:
|
|
| 352 |
return TokenLM(name, next_logits, encode, texts, stops)
|
| 353 |
|
| 354 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 355 |
# ---- Scoring ---------------------------------------------------------------------------------------------------
|
| 356 |
|
| 357 |
|
|
@@ -446,6 +470,8 @@ def main():
|
|
| 446 |
parser.add_argument("--model", help="Name for the metrics file")
|
| 447 |
parser.add_argument("--onnx", help="A character-level GRU exported like enron-autocomplete")
|
| 448 |
parser.add_argument("--hf", help="A Hugging Face causal LM to evaluate, e.g. HuggingFaceTB/SmolLM2-135M")
|
|
|
|
|
|
|
| 449 |
parser.add_argument("--max-pauses", type=int, default=1000, help="Per domain and scenario")
|
| 450 |
parser.add_argument("--table", action="store_true", help="Print a comparison of every metrics/*.json")
|
| 451 |
args = parser.parse_args()
|
|
@@ -457,6 +483,8 @@ def main():
|
|
| 457 |
model: Model = CharGRU(args.model, args.onnx)
|
| 458 |
elif args.hf:
|
| 459 |
model = hf_causal_lm(args.model, args.hf)
|
|
|
|
|
|
|
| 460 |
else:
|
| 461 |
parser.error("Pass --onnx, --hf or --table. train.py evaluates its own model through score().")
|
| 462 |
all_pauses = pauses(load_eval_set(), args.max_pauses)
|
|
|
|
| 352 |
return TokenLM(name, next_logits, encode, texts, stops)
|
| 353 |
|
| 354 |
|
| 355 |
+
def onnx_token_lm(name: str, folder: str, fim: bool) -> TokenLM:
|
| 356 |
+
"""A tinynext v2 export: graph.onnx + weights.f32 (compressed, expanded) or model.onnx, plus tokenizer.json."""
|
| 357 |
+
import onnxruntime as ort
|
| 358 |
+
from tokenizers import Tokenizer
|
| 359 |
+
|
| 360 |
+
folder = Path(folder)
|
| 361 |
+
graph = folder / "graph.onnx" if (folder / "graph.onnx").exists() else folder / "model.onnx"
|
| 362 |
+
session = ort.InferenceSession(str(graph), providers=["CPUExecutionProvider"])
|
| 363 |
+
config = json.loads((folder / "config.json").read_text())
|
| 364 |
+
tokenizer = Tokenizer.from_file(str(folder / "tokenizer.json"))
|
| 365 |
+
empty = np.zeros((config["layers"], 1, config["heads"], 0, config["dim"] // config["heads"]), np.float32)
|
| 366 |
+
|
| 367 |
+
def next_logits(ids, cache):
|
| 368 |
+
past_k, past_v = cache if cache else (empty, empty)
|
| 369 |
+
logits, k, v = session.run(None, {"input_ids": np.array([ids], np.int64), "past_k": past_k, "past_v": past_v})
|
| 370 |
+
return logits[0], (k, v)
|
| 371 |
+
|
| 372 |
+
special = len(config["special_tokens"])
|
| 373 |
+
texts = [tokenizer.decode([i], skip_special_tokens=False) if i >= special else "" for i in range(config["vocab"])]
|
| 374 |
+
encode = lambda text: tokenizer.encode(text).ids or [0]
|
| 375 |
+
prompt = (lambda prefix, suffix: prefix if not suffix else [2, *suffix, 1, *prefix, 3]) if fim else None
|
| 376 |
+
return TokenLM(name, next_logits, encode, texts, set(range(special)), prompt=prompt)
|
| 377 |
+
|
| 378 |
+
|
| 379 |
# ---- Scoring ---------------------------------------------------------------------------------------------------
|
| 380 |
|
| 381 |
|
|
|
|
| 470 |
parser.add_argument("--model", help="Name for the metrics file")
|
| 471 |
parser.add_argument("--onnx", help="A character-level GRU exported like enron-autocomplete")
|
| 472 |
parser.add_argument("--hf", help="A Hugging Face causal LM to evaluate, e.g. HuggingFaceTB/SmolLM2-135M")
|
| 473 |
+
parser.add_argument("--onnx-lm", help="Folder with a tinynext v2 ONNX export, config.json and tokenizer.json")
|
| 474 |
+
parser.add_argument("--no-fim", action="store_true", help="With --onnx-lm: the model wasn't trained to fill in the middle")
|
| 475 |
parser.add_argument("--max-pauses", type=int, default=1000, help="Per domain and scenario")
|
| 476 |
parser.add_argument("--table", action="store_true", help="Print a comparison of every metrics/*.json")
|
| 477 |
args = parser.parse_args()
|
|
|
|
| 483 |
model: Model = CharGRU(args.model, args.onnx)
|
| 484 |
elif args.hf:
|
| 485 |
model = hf_causal_lm(args.model, args.hf)
|
| 486 |
+
elif args.onnx_lm:
|
| 487 |
+
model = onnx_token_lm(args.model, args.onnx_lm, fim=not args.no_fim)
|
| 488 |
else:
|
| 489 |
parser.error("Pass --onnx, --hf or --table. train.py evaluates its own model through score().")
|
| 490 |
all_pauses = pauses(load_eval_set(), args.max_pauses)
|
v2/export.py
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# /// script
|
| 2 |
+
# requires-python = ">=3.11,<3.14"
|
| 3 |
+
# dependencies = [
|
| 4 |
+
# "torch>=2.6,<2.8",
|
| 5 |
+
# "numpy<3",
|
| 6 |
+
# "tokenizers>=0.20",
|
| 7 |
+
# "onnx>=1.17",
|
| 8 |
+
# "onnxruntime>=1.20",
|
| 9 |
+
# "safetensors>=0.4",
|
| 10 |
+
# "huggingface_hub>=0.30",
|
| 11 |
+
# ]
|
| 12 |
+
# ///
|
| 13 |
+
"""Re-exports a trained tinynext checkpoint to browser ONNX (float and int8) with train.py's export, without retraining.
|
| 14 |
+
|
| 15 |
+
uv run export.py --weights v2-release/v2 --out v2-release/browser
|
| 16 |
+
"""
|
| 17 |
+
|
| 18 |
+
import argparse
|
| 19 |
+
import importlib.util
|
| 20 |
+
import json
|
| 21 |
+
import sys
|
| 22 |
+
from pathlib import Path
|
| 23 |
+
|
| 24 |
+
import torch
|
| 25 |
+
from safetensors.torch import load_file
|
| 26 |
+
from tokenizers import Tokenizer
|
| 27 |
+
|
| 28 |
+
HERE = Path(__file__).parent
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
def load(name: str):
|
| 32 |
+
spec = importlib.util.spec_from_file_location(name, HERE / f"{'eval' if name == 'tinynext_eval' else name}.py")
|
| 33 |
+
module = importlib.util.module_from_spec(spec)
|
| 34 |
+
sys.modules[name] = module
|
| 35 |
+
spec.loader.exec_module(module)
|
| 36 |
+
return module
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
def main():
|
| 40 |
+
parser = argparse.ArgumentParser()
|
| 41 |
+
parser.add_argument("--weights", required=True, help="Folder with model.safetensors, config.json, tokenizer.json")
|
| 42 |
+
parser.add_argument("--out", required=True)
|
| 43 |
+
args = parser.parse_args()
|
| 44 |
+
train, ev = load("train"), load("tinynext_eval")
|
| 45 |
+
weights, out = Path(args.weights), Path(args.out)
|
| 46 |
+
out.mkdir(parents=True, exist_ok=True)
|
| 47 |
+
|
| 48 |
+
config = json.loads((weights / "config.json").read_text())
|
| 49 |
+
model = train.TinyNext(config["vocab"], config["dim"], config["layers"], config["heads"], config["ffn"])
|
| 50 |
+
model.load_state_dict(load_file(weights / "model.safetensors"))
|
| 51 |
+
tokenizer = Tokenizer.from_file(str(weights / "tokenizer.json"))
|
| 52 |
+
report = train.export(model, out, torch.device("cpu"), train.parity_prompts(ev, tokenizer))
|
| 53 |
+
(out / "export.json").write_text(json.dumps(report, indent=1))
|
| 54 |
+
print(json.dumps(report, indent=1))
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
if __name__ == "__main__":
|
| 58 |
+
main()
|
v2/metrics/tinynext-v2-float-onnx.json
ADDED
|
@@ -0,0 +1,411 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"model": "tinynext-v2-float-onnx",
|
| 3 |
+
"sees_after": true,
|
| 4 |
+
"cutoffs": {
|
| 5 |
+
"0.3": {
|
| 6 |
+
"articles/typing": {
|
| 7 |
+
"pauses": 300,
|
| 8 |
+
"shown": 0.1833,
|
| 9 |
+
"right": 0.5818,
|
| 10 |
+
"avg_right_chars": 6.03,
|
| 11 |
+
"multiword_shown": 0.0733,
|
| 12 |
+
"multiword_right": 0.4545,
|
| 13 |
+
"saved_with_tab": 0.0536,
|
| 14 |
+
"saved_word_by_word": 0.0594
|
| 15 |
+
},
|
| 16 |
+
"articles/editing": {
|
| 17 |
+
"pauses": 300,
|
| 18 |
+
"shown": 0.13,
|
| 19 |
+
"right": 0.6923,
|
| 20 |
+
"avg_right_chars": 5.93,
|
| 21 |
+
"multiword_shown": 0.0533,
|
| 22 |
+
"multiword_right": 0.6875,
|
| 23 |
+
"saved_with_tab": 0.0444,
|
| 24 |
+
"saved_word_by_word": 0.0464
|
| 25 |
+
},
|
| 26 |
+
"messages/typing": {
|
| 27 |
+
"pauses": 300,
|
| 28 |
+
"shown": 0.3067,
|
| 29 |
+
"right": 0.6087,
|
| 30 |
+
"avg_right_chars": 7.71,
|
| 31 |
+
"multiword_shown": 0.1933,
|
| 32 |
+
"multiword_right": 0.569,
|
| 33 |
+
"saved_with_tab": 0.12,
|
| 34 |
+
"saved_word_by_word": 0.1408
|
| 35 |
+
},
|
| 36 |
+
"messages/editing": {
|
| 37 |
+
"pauses": 300,
|
| 38 |
+
"shown": 0.2833,
|
| 39 |
+
"right": 0.5059,
|
| 40 |
+
"avg_right_chars": 6.53,
|
| 41 |
+
"multiword_shown": 0.14,
|
| 42 |
+
"multiword_right": 0.5,
|
| 43 |
+
"saved_with_tab": 0.0781,
|
| 44 |
+
"saved_word_by_word": 0.0919
|
| 45 |
+
},
|
| 46 |
+
"email/typing": {
|
| 47 |
+
"pauses": 300,
|
| 48 |
+
"shown": 0.2367,
|
| 49 |
+
"right": 0.5915,
|
| 50 |
+
"avg_right_chars": 5.43,
|
| 51 |
+
"multiword_shown": 0.0667,
|
| 52 |
+
"multiword_right": 0.45,
|
| 53 |
+
"saved_with_tab": 0.0633,
|
| 54 |
+
"saved_word_by_word": 0.0722
|
| 55 |
+
},
|
| 56 |
+
"email/editing": {
|
| 57 |
+
"pauses": 300,
|
| 58 |
+
"shown": 0.2367,
|
| 59 |
+
"right": 0.5915,
|
| 60 |
+
"avg_right_chars": 5.57,
|
| 61 |
+
"multiword_shown": 0.0933,
|
| 62 |
+
"multiword_right": 0.5357,
|
| 63 |
+
"saved_with_tab": 0.065,
|
| 64 |
+
"saved_word_by_word": 0.0703
|
| 65 |
+
}
|
| 66 |
+
},
|
| 67 |
+
"0.4": {
|
| 68 |
+
"articles/typing": {
|
| 69 |
+
"pauses": 300,
|
| 70 |
+
"shown": 0.15,
|
| 71 |
+
"right": 0.6889,
|
| 72 |
+
"avg_right_chars": 6.03,
|
| 73 |
+
"multiword_shown": 0.0567,
|
| 74 |
+
"multiword_right": 0.5882,
|
| 75 |
+
"saved_with_tab": 0.0519,
|
| 76 |
+
"saved_word_by_word": 0.055
|
| 77 |
+
},
|
| 78 |
+
"articles/editing": {
|
| 79 |
+
"pauses": 300,
|
| 80 |
+
"shown": 0.0967,
|
| 81 |
+
"right": 0.7586,
|
| 82 |
+
"avg_right_chars": 5.82,
|
| 83 |
+
"multiword_shown": 0.0367,
|
| 84 |
+
"multiword_right": 0.9091,
|
| 85 |
+
"saved_with_tab": 0.0356,
|
| 86 |
+
"saved_word_by_word": 0.0358
|
| 87 |
+
},
|
| 88 |
+
"messages/typing": {
|
| 89 |
+
"pauses": 300,
|
| 90 |
+
"shown": 0.2367,
|
| 91 |
+
"right": 0.7465,
|
| 92 |
+
"avg_right_chars": 7.23,
|
| 93 |
+
"multiword_shown": 0.13,
|
| 94 |
+
"multiword_right": 0.6667,
|
| 95 |
+
"saved_with_tab": 0.1064,
|
| 96 |
+
"saved_word_by_word": 0.1161
|
| 97 |
+
},
|
| 98 |
+
"messages/editing": {
|
| 99 |
+
"pauses": 300,
|
| 100 |
+
"shown": 0.17,
|
| 101 |
+
"right": 0.6275,
|
| 102 |
+
"avg_right_chars": 6.38,
|
| 103 |
+
"multiword_shown": 0.0733,
|
| 104 |
+
"multiword_right": 0.6364,
|
| 105 |
+
"saved_with_tab": 0.0567,
|
| 106 |
+
"saved_word_by_word": 0.0658
|
| 107 |
+
},
|
| 108 |
+
"email/typing": {
|
| 109 |
+
"pauses": 300,
|
| 110 |
+
"shown": 0.19,
|
| 111 |
+
"right": 0.7368,
|
| 112 |
+
"avg_right_chars": 5.48,
|
| 113 |
+
"multiword_shown": 0.0467,
|
| 114 |
+
"multiword_right": 0.5714,
|
| 115 |
+
"saved_with_tab": 0.0639,
|
| 116 |
+
"saved_word_by_word": 0.0678
|
| 117 |
+
},
|
| 118 |
+
"email/editing": {
|
| 119 |
+
"pauses": 300,
|
| 120 |
+
"shown": 0.16,
|
| 121 |
+
"right": 0.6875,
|
| 122 |
+
"avg_right_chars": 5.27,
|
| 123 |
+
"multiword_shown": 0.06,
|
| 124 |
+
"multiword_right": 0.6111,
|
| 125 |
+
"saved_with_tab": 0.0483,
|
| 126 |
+
"saved_word_by_word": 0.0514
|
| 127 |
+
}
|
| 128 |
+
},
|
| 129 |
+
"0.5": {
|
| 130 |
+
"articles/typing": {
|
| 131 |
+
"pauses": 300,
|
| 132 |
+
"shown": 0.1133,
|
| 133 |
+
"right": 0.7647,
|
| 134 |
+
"avg_right_chars": 5.92,
|
| 135 |
+
"multiword_shown": 0.0367,
|
| 136 |
+
"multiword_right": 0.6364,
|
| 137 |
+
"saved_with_tab": 0.0428,
|
| 138 |
+
"saved_word_by_word": 0.0436
|
| 139 |
+
},
|
| 140 |
+
"articles/editing": {
|
| 141 |
+
"pauses": 300,
|
| 142 |
+
"shown": 0.0833,
|
| 143 |
+
"right": 0.8,
|
| 144 |
+
"avg_right_chars": 5.4,
|
| 145 |
+
"multiword_shown": 0.0267,
|
| 146 |
+
"multiword_right": 0.875,
|
| 147 |
+
"saved_with_tab": 0.03,
|
| 148 |
+
"saved_word_by_word": 0.0303
|
| 149 |
+
},
|
| 150 |
+
"messages/typing": {
|
| 151 |
+
"pauses": 300,
|
| 152 |
+
"shown": 0.1767,
|
| 153 |
+
"right": 0.8113,
|
| 154 |
+
"avg_right_chars": 7.12,
|
| 155 |
+
"multiword_shown": 0.0967,
|
| 156 |
+
"multiword_right": 0.7241,
|
| 157 |
+
"saved_with_tab": 0.085,
|
| 158 |
+
"saved_word_by_word": 0.0917
|
| 159 |
+
},
|
| 160 |
+
"messages/editing": {
|
| 161 |
+
"pauses": 300,
|
| 162 |
+
"shown": 0.1233,
|
| 163 |
+
"right": 0.7297,
|
| 164 |
+
"avg_right_chars": 6.37,
|
| 165 |
+
"multiword_shown": 0.0567,
|
| 166 |
+
"multiword_right": 0.6471,
|
| 167 |
+
"saved_with_tab": 0.0478,
|
| 168 |
+
"saved_word_by_word": 0.0561
|
| 169 |
+
},
|
| 170 |
+
"email/typing": {
|
| 171 |
+
"pauses": 300,
|
| 172 |
+
"shown": 0.1367,
|
| 173 |
+
"right": 0.8049,
|
| 174 |
+
"avg_right_chars": 5.48,
|
| 175 |
+
"multiword_shown": 0.0267,
|
| 176 |
+
"multiword_right": 0.75,
|
| 177 |
+
"saved_with_tab": 0.0503,
|
| 178 |
+
"saved_word_by_word": 0.0514
|
| 179 |
+
},
|
| 180 |
+
"email/editing": {
|
| 181 |
+
"pauses": 300,
|
| 182 |
+
"shown": 0.13,
|
| 183 |
+
"right": 0.7436,
|
| 184 |
+
"avg_right_chars": 5.07,
|
| 185 |
+
"multiword_shown": 0.0367,
|
| 186 |
+
"multiword_right": 0.5455,
|
| 187 |
+
"saved_with_tab": 0.0408,
|
| 188 |
+
"saved_word_by_word": 0.0431
|
| 189 |
+
}
|
| 190 |
+
},
|
| 191 |
+
"0.6": {
|
| 192 |
+
"articles/typing": {
|
| 193 |
+
"pauses": 300,
|
| 194 |
+
"shown": 0.1,
|
| 195 |
+
"right": 0.8,
|
| 196 |
+
"avg_right_chars": 6.0,
|
| 197 |
+
"multiword_shown": 0.0267,
|
| 198 |
+
"multiword_right": 0.75,
|
| 199 |
+
"saved_with_tab": 0.04,
|
| 200 |
+
"saved_word_by_word": 0.04
|
| 201 |
+
},
|
| 202 |
+
"articles/editing": {
|
| 203 |
+
"pauses": 300,
|
| 204 |
+
"shown": 0.0533,
|
| 205 |
+
"right": 0.9375,
|
| 206 |
+
"avg_right_chars": 5.67,
|
| 207 |
+
"multiword_shown": 0.02,
|
| 208 |
+
"multiword_right": 1.0,
|
| 209 |
+
"saved_with_tab": 0.0236,
|
| 210 |
+
"saved_word_by_word": 0.0236
|
| 211 |
+
},
|
| 212 |
+
"messages/typing": {
|
| 213 |
+
"pauses": 300,
|
| 214 |
+
"shown": 0.14,
|
| 215 |
+
"right": 0.881,
|
| 216 |
+
"avg_right_chars": 6.57,
|
| 217 |
+
"multiword_shown": 0.0733,
|
| 218 |
+
"multiword_right": 0.8182,
|
| 219 |
+
"saved_with_tab": 0.0675,
|
| 220 |
+
"saved_word_by_word": 0.0708
|
| 221 |
+
},
|
| 222 |
+
"messages/editing": {
|
| 223 |
+
"pauses": 300,
|
| 224 |
+
"shown": 0.0767,
|
| 225 |
+
"right": 0.7391,
|
| 226 |
+
"avg_right_chars": 6.18,
|
| 227 |
+
"multiword_shown": 0.04,
|
| 228 |
+
"multiword_right": 0.5,
|
| 229 |
+
"saved_with_tab": 0.0292,
|
| 230 |
+
"saved_word_by_word": 0.0375
|
| 231 |
+
},
|
| 232 |
+
"email/typing": {
|
| 233 |
+
"pauses": 300,
|
| 234 |
+
"shown": 0.0967,
|
| 235 |
+
"right": 0.8966,
|
| 236 |
+
"avg_right_chars": 5.73,
|
| 237 |
+
"multiword_shown": 0.02,
|
| 238 |
+
"multiword_right": 1.0,
|
| 239 |
+
"saved_with_tab": 0.0414,
|
| 240 |
+
"saved_word_by_word": 0.0414
|
| 241 |
+
},
|
| 242 |
+
"email/editing": {
|
| 243 |
+
"pauses": 300,
|
| 244 |
+
"shown": 0.0833,
|
| 245 |
+
"right": 0.92,
|
| 246 |
+
"avg_right_chars": 4.96,
|
| 247 |
+
"multiword_shown": 0.0133,
|
| 248 |
+
"multiword_right": 0.75,
|
| 249 |
+
"saved_with_tab": 0.0317,
|
| 250 |
+
"saved_word_by_word": 0.0328
|
| 251 |
+
}
|
| 252 |
+
},
|
| 253 |
+
"0.7": {
|
| 254 |
+
"articles/typing": {
|
| 255 |
+
"pauses": 300,
|
| 256 |
+
"shown": 0.07,
|
| 257 |
+
"right": 0.9524,
|
| 258 |
+
"avg_right_chars": 5.7,
|
| 259 |
+
"multiword_shown": 0.0167,
|
| 260 |
+
"multiword_right": 1.0,
|
| 261 |
+
"saved_with_tab": 0.0317,
|
| 262 |
+
"saved_word_by_word": 0.0317
|
| 263 |
+
},
|
| 264 |
+
"articles/editing": {
|
| 265 |
+
"pauses": 300,
|
| 266 |
+
"shown": 0.03,
|
| 267 |
+
"right": 0.8889,
|
| 268 |
+
"avg_right_chars": 5.12,
|
| 269 |
+
"multiword_shown": 0.0033,
|
| 270 |
+
"multiword_right": 1.0,
|
| 271 |
+
"saved_with_tab": 0.0114,
|
| 272 |
+
"saved_word_by_word": 0.0114
|
| 273 |
+
},
|
| 274 |
+
"messages/typing": {
|
| 275 |
+
"pauses": 300,
|
| 276 |
+
"shown": 0.11,
|
| 277 |
+
"right": 0.9394,
|
| 278 |
+
"avg_right_chars": 6.23,
|
| 279 |
+
"multiword_shown": 0.05,
|
| 280 |
+
"multiword_right": 0.8667,
|
| 281 |
+
"saved_with_tab": 0.0536,
|
| 282 |
+
"saved_word_by_word": 0.0544
|
| 283 |
+
},
|
| 284 |
+
"messages/editing": {
|
| 285 |
+
"pauses": 300,
|
| 286 |
+
"shown": 0.0633,
|
| 287 |
+
"right": 0.7895,
|
| 288 |
+
"avg_right_chars": 6.13,
|
| 289 |
+
"multiword_shown": 0.0333,
|
| 290 |
+
"multiword_right": 0.6,
|
| 291 |
+
"saved_with_tab": 0.0256,
|
| 292 |
+
"saved_word_by_word": 0.0328
|
| 293 |
+
},
|
| 294 |
+
"email/typing": {
|
| 295 |
+
"pauses": 300,
|
| 296 |
+
"shown": 0.0667,
|
| 297 |
+
"right": 0.85,
|
| 298 |
+
"avg_right_chars": 5.41,
|
| 299 |
+
"multiword_shown": 0.0067,
|
| 300 |
+
"multiword_right": 1.0,
|
| 301 |
+
"saved_with_tab": 0.0256,
|
| 302 |
+
"saved_word_by_word": 0.0256
|
| 303 |
+
},
|
| 304 |
+
"email/editing": {
|
| 305 |
+
"pauses": 300,
|
| 306 |
+
"shown": 0.06,
|
| 307 |
+
"right": 0.9444,
|
| 308 |
+
"avg_right_chars": 4.71,
|
| 309 |
+
"multiword_shown": 0.0033,
|
| 310 |
+
"multiword_right": 1.0,
|
| 311 |
+
"saved_with_tab": 0.0222,
|
| 312 |
+
"saved_word_by_word": 0.0222
|
| 313 |
+
}
|
| 314 |
+
}
|
| 315 |
+
},
|
| 316 |
+
"examples": [
|
| 317 |
+
{
|
| 318 |
+
"domain": "articles",
|
| 319 |
+
"scenario": "typing",
|
| 320 |
+
"before": "elipads, IFR approaches, and a separate float plane dock alo",
|
| 321 |
+
"suggestion": "ng the",
|
| 322 |
+
"truth": "ng the Fraser Rive",
|
| 323 |
+
"right": true
|
| 324 |
+
},
|
| 325 |
+
{
|
| 326 |
+
"domain": "articles",
|
| 327 |
+
"scenario": "editing",
|
| 328 |
+
"before": " where he met his wife, Kisa, a graduate of the University o",
|
| 329 |
+
"suggestion": "f Illinois",
|
| 330 |
+
"truth": "f Colorado. Sasaki the",
|
| 331 |
+
"right": false
|
| 332 |
+
},
|
| 333 |
+
{
|
| 334 |
+
"domain": "articles",
|
| 335 |
+
"scenario": "editing",
|
| 336 |
+
"before": "ing any kind of direct discrimination that was prominent els",
|
| 337 |
+
"suggestion": "ewhere.",
|
| 338 |
+
"truth": "ewhere in the count",
|
| 339 |
+
"right": false
|
| 340 |
+
},
|
| 341 |
+
{
|
| 342 |
+
"domain": "messages",
|
| 343 |
+
"scenario": "typing",
|
| 344 |
+
"before": "T's ability to generate coherent and contextually relevant r",
|
| 345 |
+
"suggestion": "esponses",
|
| 346 |
+
"truth": "esponses is based on",
|
| 347 |
+
"right": true
|
| 348 |
+
},
|
| 349 |
+
{
|
| 350 |
+
"domain": "messages",
|
| 351 |
+
"scenario": "typing",
|
| 352 |
+
"before": " prioritize the development of tools and models that are des",
|
| 353 |
+
"suggestion": "igned to",
|
| 354 |
+
"truth": "igned to be inclusiv",
|
| 355 |
+
"right": true
|
| 356 |
+
},
|
| 357 |
+
{
|
| 358 |
+
"domain": "messages",
|
| 359 |
+
"scenario": "editing",
|
| 360 |
+
"before": "e at which a population is growing.\nL'Hopital's rule can als",
|
| 361 |
+
"suggestion": "o be used to",
|
| 362 |
+
"truth": "o be used to solve probl",
|
| 363 |
+
"right": true
|
| 364 |
+
},
|
| 365 |
+
{
|
| 366 |
+
"domain": "email",
|
| 367 |
+
"scenario": "typing",
|
| 368 |
+
"before": "lt time but am confident that I would make an excellent addi",
|
| 369 |
+
"suggestion": "tion to",
|
| 370 |
+
"truth": "tion to your team f",
|
| 371 |
+
"right": true
|
| 372 |
+
},
|
| 373 |
+
{
|
| 374 |
+
"domain": "email",
|
| 375 |
+
"scenario": "typing",
|
| 376 |
+
"before": ". I recommend we agree. Although, we are in the content deve",
|
| 377 |
+
"suggestion": "lopment",
|
| 378 |
+
"truth": "lopment phase the t",
|
| 379 |
+
"right": true
|
| 380 |
+
},
|
| 381 |
+
{
|
| 382 |
+
"domain": "email",
|
| 383 |
+
"scenario": "editing",
|
| 384 |
+
"before": "ured products and marketing of electricity for the United St",
|
| 385 |
+
"suggestion": "ates",
|
| 386 |
+
"truth": "ates ? Actively ",
|
| 387 |
+
"right": true
|
| 388 |
+
},
|
| 389 |
+
{
|
| 390 |
+
"domain": "email",
|
| 391 |
+
"scenario": "editing",
|
| 392 |
+
"before": "I'm not sure what you are looking for. The Early Termination",
|
| 393 |
+
"suggestion": " Log",
|
| 394 |
+
"truth": " Date is one of ",
|
| 395 |
+
"right": false
|
| 396 |
+
},
|
| 397 |
+
{
|
| 398 |
+
"domain": "email",
|
| 399 |
+
"scenario": "editing",
|
| 400 |
+
"before": " action is necessary as contractually we are coming to the e",
|
| 401 |
+
"suggestion": "nd of",
|
| 402 |
+
"truth": "nd of the accepta",
|
| 403 |
+
"right": true
|
| 404 |
+
}
|
| 405 |
+
],
|
| 406 |
+
"latency_ms": {
|
| 407 |
+
"p50": 25.37,
|
| 408 |
+
"p95": 77.65,
|
| 409 |
+
"note": "Measured in this eval process, not in a browser."
|
| 410 |
+
}
|
| 411 |
+
}
|
v2/metrics/tinynext-v2-q8-onnx.json
ADDED
|
@@ -0,0 +1,411 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"model": "tinynext-v2-q8-onnx",
|
| 3 |
+
"sees_after": true,
|
| 4 |
+
"cutoffs": {
|
| 5 |
+
"0.3": {
|
| 6 |
+
"articles/typing": {
|
| 7 |
+
"pauses": 300,
|
| 8 |
+
"shown": 0.1767,
|
| 9 |
+
"right": 0.5849,
|
| 10 |
+
"avg_right_chars": 6.0,
|
| 11 |
+
"multiword_shown": 0.0733,
|
| 12 |
+
"multiword_right": 0.4545,
|
| 13 |
+
"saved_with_tab": 0.0517,
|
| 14 |
+
"saved_word_by_word": 0.0575
|
| 15 |
+
},
|
| 16 |
+
"articles/editing": {
|
| 17 |
+
"pauses": 300,
|
| 18 |
+
"shown": 0.13,
|
| 19 |
+
"right": 0.6923,
|
| 20 |
+
"avg_right_chars": 5.93,
|
| 21 |
+
"multiword_shown": 0.0533,
|
| 22 |
+
"multiword_right": 0.6875,
|
| 23 |
+
"saved_with_tab": 0.0444,
|
| 24 |
+
"saved_word_by_word": 0.0464
|
| 25 |
+
},
|
| 26 |
+
"messages/typing": {
|
| 27 |
+
"pauses": 300,
|
| 28 |
+
"shown": 0.3,
|
| 29 |
+
"right": 0.6333,
|
| 30 |
+
"avg_right_chars": 7.65,
|
| 31 |
+
"multiword_shown": 0.1933,
|
| 32 |
+
"multiword_right": 0.569,
|
| 33 |
+
"saved_with_tab": 0.1211,
|
| 34 |
+
"saved_word_by_word": 0.1403
|
| 35 |
+
},
|
| 36 |
+
"messages/editing": {
|
| 37 |
+
"pauses": 300,
|
| 38 |
+
"shown": 0.2767,
|
| 39 |
+
"right": 0.5181,
|
| 40 |
+
"avg_right_chars": 6.53,
|
| 41 |
+
"multiword_shown": 0.14,
|
| 42 |
+
"multiword_right": 0.5,
|
| 43 |
+
"saved_with_tab": 0.0781,
|
| 44 |
+
"saved_word_by_word": 0.0919
|
| 45 |
+
},
|
| 46 |
+
"email/typing": {
|
| 47 |
+
"pauses": 300,
|
| 48 |
+
"shown": 0.2333,
|
| 49 |
+
"right": 0.5857,
|
| 50 |
+
"avg_right_chars": 5.46,
|
| 51 |
+
"multiword_shown": 0.0667,
|
| 52 |
+
"multiword_right": 0.45,
|
| 53 |
+
"saved_with_tab": 0.0622,
|
| 54 |
+
"saved_word_by_word": 0.0714
|
| 55 |
+
},
|
| 56 |
+
"email/editing": {
|
| 57 |
+
"pauses": 300,
|
| 58 |
+
"shown": 0.2333,
|
| 59 |
+
"right": 0.6,
|
| 60 |
+
"avg_right_chars": 5.57,
|
| 61 |
+
"multiword_shown": 0.0933,
|
| 62 |
+
"multiword_right": 0.5357,
|
| 63 |
+
"saved_with_tab": 0.065,
|
| 64 |
+
"saved_word_by_word": 0.0703
|
| 65 |
+
}
|
| 66 |
+
},
|
| 67 |
+
"0.4": {
|
| 68 |
+
"articles/typing": {
|
| 69 |
+
"pauses": 300,
|
| 70 |
+
"shown": 0.1467,
|
| 71 |
+
"right": 0.6818,
|
| 72 |
+
"avg_right_chars": 6.0,
|
| 73 |
+
"multiword_shown": 0.0567,
|
| 74 |
+
"multiword_right": 0.5882,
|
| 75 |
+
"saved_with_tab": 0.05,
|
| 76 |
+
"saved_word_by_word": 0.0531
|
| 77 |
+
},
|
| 78 |
+
"articles/editing": {
|
| 79 |
+
"pauses": 300,
|
| 80 |
+
"shown": 0.0967,
|
| 81 |
+
"right": 0.7586,
|
| 82 |
+
"avg_right_chars": 5.82,
|
| 83 |
+
"multiword_shown": 0.0367,
|
| 84 |
+
"multiword_right": 0.9091,
|
| 85 |
+
"saved_with_tab": 0.0356,
|
| 86 |
+
"saved_word_by_word": 0.0358
|
| 87 |
+
},
|
| 88 |
+
"messages/typing": {
|
| 89 |
+
"pauses": 300,
|
| 90 |
+
"shown": 0.24,
|
| 91 |
+
"right": 0.7361,
|
| 92 |
+
"avg_right_chars": 7.26,
|
| 93 |
+
"multiword_shown": 0.1333,
|
| 94 |
+
"multiword_right": 0.65,
|
| 95 |
+
"saved_with_tab": 0.1069,
|
| 96 |
+
"saved_word_by_word": 0.1167
|
| 97 |
+
},
|
| 98 |
+
"messages/editing": {
|
| 99 |
+
"pauses": 300,
|
| 100 |
+
"shown": 0.17,
|
| 101 |
+
"right": 0.6275,
|
| 102 |
+
"avg_right_chars": 6.38,
|
| 103 |
+
"multiword_shown": 0.0733,
|
| 104 |
+
"multiword_right": 0.6364,
|
| 105 |
+
"saved_with_tab": 0.0567,
|
| 106 |
+
"saved_word_by_word": 0.0658
|
| 107 |
+
},
|
| 108 |
+
"email/typing": {
|
| 109 |
+
"pauses": 300,
|
| 110 |
+
"shown": 0.1867,
|
| 111 |
+
"right": 0.75,
|
| 112 |
+
"avg_right_chars": 5.48,
|
| 113 |
+
"multiword_shown": 0.0467,
|
| 114 |
+
"multiword_right": 0.5714,
|
| 115 |
+
"saved_with_tab": 0.0639,
|
| 116 |
+
"saved_word_by_word": 0.0678
|
| 117 |
+
},
|
| 118 |
+
"email/editing": {
|
| 119 |
+
"pauses": 300,
|
| 120 |
+
"shown": 0.1667,
|
| 121 |
+
"right": 0.68,
|
| 122 |
+
"avg_right_chars": 5.26,
|
| 123 |
+
"multiword_shown": 0.06,
|
| 124 |
+
"multiword_right": 0.6111,
|
| 125 |
+
"saved_with_tab": 0.0497,
|
| 126 |
+
"saved_word_by_word": 0.0528
|
| 127 |
+
}
|
| 128 |
+
},
|
| 129 |
+
"0.5": {
|
| 130 |
+
"articles/typing": {
|
| 131 |
+
"pauses": 300,
|
| 132 |
+
"shown": 0.11,
|
| 133 |
+
"right": 0.7879,
|
| 134 |
+
"avg_right_chars": 5.81,
|
| 135 |
+
"multiword_shown": 0.0333,
|
| 136 |
+
"multiword_right": 0.7,
|
| 137 |
+
"saved_with_tab": 0.0419,
|
| 138 |
+
"saved_word_by_word": 0.0425
|
| 139 |
+
},
|
| 140 |
+
"articles/editing": {
|
| 141 |
+
"pauses": 300,
|
| 142 |
+
"shown": 0.0833,
|
| 143 |
+
"right": 0.8,
|
| 144 |
+
"avg_right_chars": 5.4,
|
| 145 |
+
"multiword_shown": 0.0267,
|
| 146 |
+
"multiword_right": 0.875,
|
| 147 |
+
"saved_with_tab": 0.03,
|
| 148 |
+
"saved_word_by_word": 0.0303
|
| 149 |
+
},
|
| 150 |
+
"messages/typing": {
|
| 151 |
+
"pauses": 300,
|
| 152 |
+
"shown": 0.18,
|
| 153 |
+
"right": 0.7963,
|
| 154 |
+
"avg_right_chars": 6.98,
|
| 155 |
+
"multiword_shown": 0.1,
|
| 156 |
+
"multiword_right": 0.7,
|
| 157 |
+
"saved_with_tab": 0.0833,
|
| 158 |
+
"saved_word_by_word": 0.09
|
| 159 |
+
},
|
| 160 |
+
"messages/editing": {
|
| 161 |
+
"pauses": 300,
|
| 162 |
+
"shown": 0.1233,
|
| 163 |
+
"right": 0.7297,
|
| 164 |
+
"avg_right_chars": 6.37,
|
| 165 |
+
"multiword_shown": 0.0567,
|
| 166 |
+
"multiword_right": 0.6471,
|
| 167 |
+
"saved_with_tab": 0.0478,
|
| 168 |
+
"saved_word_by_word": 0.0561
|
| 169 |
+
},
|
| 170 |
+
"email/typing": {
|
| 171 |
+
"pauses": 300,
|
| 172 |
+
"shown": 0.14,
|
| 173 |
+
"right": 0.7857,
|
| 174 |
+
"avg_right_chars": 5.48,
|
| 175 |
+
"multiword_shown": 0.0267,
|
| 176 |
+
"multiword_right": 0.75,
|
| 177 |
+
"saved_with_tab": 0.0503,
|
| 178 |
+
"saved_word_by_word": 0.0514
|
| 179 |
+
},
|
| 180 |
+
"email/editing": {
|
| 181 |
+
"pauses": 300,
|
| 182 |
+
"shown": 0.1267,
|
| 183 |
+
"right": 0.7632,
|
| 184 |
+
"avg_right_chars": 5.07,
|
| 185 |
+
"multiword_shown": 0.0367,
|
| 186 |
+
"multiword_right": 0.5455,
|
| 187 |
+
"saved_with_tab": 0.0408,
|
| 188 |
+
"saved_word_by_word": 0.0431
|
| 189 |
+
}
|
| 190 |
+
},
|
| 191 |
+
"0.6": {
|
| 192 |
+
"articles/typing": {
|
| 193 |
+
"pauses": 300,
|
| 194 |
+
"shown": 0.0967,
|
| 195 |
+
"right": 0.7931,
|
| 196 |
+
"avg_right_chars": 5.96,
|
| 197 |
+
"multiword_shown": 0.0267,
|
| 198 |
+
"multiword_right": 0.75,
|
| 199 |
+
"saved_with_tab": 0.0381,
|
| 200 |
+
"saved_word_by_word": 0.0381
|
| 201 |
+
},
|
| 202 |
+
"articles/editing": {
|
| 203 |
+
"pauses": 300,
|
| 204 |
+
"shown": 0.05,
|
| 205 |
+
"right": 0.9333,
|
| 206 |
+
"avg_right_chars": 5.79,
|
| 207 |
+
"multiword_shown": 0.02,
|
| 208 |
+
"multiword_right": 1.0,
|
| 209 |
+
"saved_with_tab": 0.0225,
|
| 210 |
+
"saved_word_by_word": 0.0225
|
| 211 |
+
},
|
| 212 |
+
"messages/typing": {
|
| 213 |
+
"pauses": 300,
|
| 214 |
+
"shown": 0.1467,
|
| 215 |
+
"right": 0.8864,
|
| 216 |
+
"avg_right_chars": 6.54,
|
| 217 |
+
"multiword_shown": 0.0733,
|
| 218 |
+
"multiword_right": 0.8182,
|
| 219 |
+
"saved_with_tab": 0.0708,
|
| 220 |
+
"saved_word_by_word": 0.0742
|
| 221 |
+
},
|
| 222 |
+
"messages/editing": {
|
| 223 |
+
"pauses": 300,
|
| 224 |
+
"shown": 0.0767,
|
| 225 |
+
"right": 0.7391,
|
| 226 |
+
"avg_right_chars": 6.18,
|
| 227 |
+
"multiword_shown": 0.04,
|
| 228 |
+
"multiword_right": 0.5,
|
| 229 |
+
"saved_with_tab": 0.0292,
|
| 230 |
+
"saved_word_by_word": 0.0375
|
| 231 |
+
},
|
| 232 |
+
"email/typing": {
|
| 233 |
+
"pauses": 300,
|
| 234 |
+
"shown": 0.1,
|
| 235 |
+
"right": 0.8667,
|
| 236 |
+
"avg_right_chars": 5.73,
|
| 237 |
+
"multiword_shown": 0.02,
|
| 238 |
+
"multiword_right": 1.0,
|
| 239 |
+
"saved_with_tab": 0.0414,
|
| 240 |
+
"saved_word_by_word": 0.0414
|
| 241 |
+
},
|
| 242 |
+
"email/editing": {
|
| 243 |
+
"pauses": 300,
|
| 244 |
+
"shown": 0.09,
|
| 245 |
+
"right": 0.8889,
|
| 246 |
+
"avg_right_chars": 4.92,
|
| 247 |
+
"multiword_shown": 0.0133,
|
| 248 |
+
"multiword_right": 0.75,
|
| 249 |
+
"saved_with_tab": 0.0328,
|
| 250 |
+
"saved_word_by_word": 0.0339
|
| 251 |
+
}
|
| 252 |
+
},
|
| 253 |
+
"0.7": {
|
| 254 |
+
"articles/typing": {
|
| 255 |
+
"pauses": 300,
|
| 256 |
+
"shown": 0.0667,
|
| 257 |
+
"right": 0.95,
|
| 258 |
+
"avg_right_chars": 5.63,
|
| 259 |
+
"multiword_shown": 0.0167,
|
| 260 |
+
"multiword_right": 1.0,
|
| 261 |
+
"saved_with_tab": 0.0297,
|
| 262 |
+
"saved_word_by_word": 0.0297
|
| 263 |
+
},
|
| 264 |
+
"articles/editing": {
|
| 265 |
+
"pauses": 300,
|
| 266 |
+
"shown": 0.03,
|
| 267 |
+
"right": 0.8889,
|
| 268 |
+
"avg_right_chars": 5.12,
|
| 269 |
+
"multiword_shown": 0.0033,
|
| 270 |
+
"multiword_right": 1.0,
|
| 271 |
+
"saved_with_tab": 0.0114,
|
| 272 |
+
"saved_word_by_word": 0.0114
|
| 273 |
+
},
|
| 274 |
+
"messages/typing": {
|
| 275 |
+
"pauses": 300,
|
| 276 |
+
"shown": 0.1133,
|
| 277 |
+
"right": 0.9412,
|
| 278 |
+
"avg_right_chars": 6.22,
|
| 279 |
+
"multiword_shown": 0.05,
|
| 280 |
+
"multiword_right": 0.8667,
|
| 281 |
+
"saved_with_tab": 0.0553,
|
| 282 |
+
"saved_word_by_word": 0.0561
|
| 283 |
+
},
|
| 284 |
+
"messages/editing": {
|
| 285 |
+
"pauses": 300,
|
| 286 |
+
"shown": 0.0633,
|
| 287 |
+
"right": 0.7895,
|
| 288 |
+
"avg_right_chars": 5.93,
|
| 289 |
+
"multiword_shown": 0.03,
|
| 290 |
+
"multiword_right": 0.5556,
|
| 291 |
+
"saved_with_tab": 0.0247,
|
| 292 |
+
"saved_word_by_word": 0.0319
|
| 293 |
+
},
|
| 294 |
+
"email/typing": {
|
| 295 |
+
"pauses": 300,
|
| 296 |
+
"shown": 0.0667,
|
| 297 |
+
"right": 0.85,
|
| 298 |
+
"avg_right_chars": 5.41,
|
| 299 |
+
"multiword_shown": 0.0067,
|
| 300 |
+
"multiword_right": 1.0,
|
| 301 |
+
"saved_with_tab": 0.0256,
|
| 302 |
+
"saved_word_by_word": 0.0256
|
| 303 |
+
},
|
| 304 |
+
"email/editing": {
|
| 305 |
+
"pauses": 300,
|
| 306 |
+
"shown": 0.06,
|
| 307 |
+
"right": 0.9444,
|
| 308 |
+
"avg_right_chars": 4.71,
|
| 309 |
+
"multiword_shown": 0.0033,
|
| 310 |
+
"multiword_right": 1.0,
|
| 311 |
+
"saved_with_tab": 0.0222,
|
| 312 |
+
"saved_word_by_word": 0.0222
|
| 313 |
+
}
|
| 314 |
+
}
|
| 315 |
+
},
|
| 316 |
+
"examples": [
|
| 317 |
+
{
|
| 318 |
+
"domain": "articles",
|
| 319 |
+
"scenario": "typing",
|
| 320 |
+
"before": "elipads, IFR approaches, and a separate float plane dock alo",
|
| 321 |
+
"suggestion": "ng the",
|
| 322 |
+
"truth": "ng the Fraser Rive",
|
| 323 |
+
"right": true
|
| 324 |
+
},
|
| 325 |
+
{
|
| 326 |
+
"domain": "articles",
|
| 327 |
+
"scenario": "editing",
|
| 328 |
+
"before": " where he met his wife, Kisa, a graduate of the University o",
|
| 329 |
+
"suggestion": "f Illinois",
|
| 330 |
+
"truth": "f Colorado. Sasaki the",
|
| 331 |
+
"right": false
|
| 332 |
+
},
|
| 333 |
+
{
|
| 334 |
+
"domain": "articles",
|
| 335 |
+
"scenario": "editing",
|
| 336 |
+
"before": "ing any kind of direct discrimination that was prominent els",
|
| 337 |
+
"suggestion": "ewhere.",
|
| 338 |
+
"truth": "ewhere in the count",
|
| 339 |
+
"right": false
|
| 340 |
+
},
|
| 341 |
+
{
|
| 342 |
+
"domain": "messages",
|
| 343 |
+
"scenario": "typing",
|
| 344 |
+
"before": "T's ability to generate coherent and contextually relevant r",
|
| 345 |
+
"suggestion": "esponses",
|
| 346 |
+
"truth": "esponses is based on",
|
| 347 |
+
"right": true
|
| 348 |
+
},
|
| 349 |
+
{
|
| 350 |
+
"domain": "messages",
|
| 351 |
+
"scenario": "typing",
|
| 352 |
+
"before": " prioritize the development of tools and models that are des",
|
| 353 |
+
"suggestion": "igned to",
|
| 354 |
+
"truth": "igned to be inclusiv",
|
| 355 |
+
"right": true
|
| 356 |
+
},
|
| 357 |
+
{
|
| 358 |
+
"domain": "messages",
|
| 359 |
+
"scenario": "editing",
|
| 360 |
+
"before": "e at which a population is growing.\nL'Hopital's rule can als",
|
| 361 |
+
"suggestion": "o be used to",
|
| 362 |
+
"truth": "o be used to solve probl",
|
| 363 |
+
"right": true
|
| 364 |
+
},
|
| 365 |
+
{
|
| 366 |
+
"domain": "email",
|
| 367 |
+
"scenario": "typing",
|
| 368 |
+
"before": "lt time but am confident that I would make an excellent addi",
|
| 369 |
+
"suggestion": "tion to",
|
| 370 |
+
"truth": "tion to your team f",
|
| 371 |
+
"right": true
|
| 372 |
+
},
|
| 373 |
+
{
|
| 374 |
+
"domain": "email",
|
| 375 |
+
"scenario": "typing",
|
| 376 |
+
"before": ". I recommend we agree. Although, we are in the content deve",
|
| 377 |
+
"suggestion": "lopment",
|
| 378 |
+
"truth": "lopment phase the t",
|
| 379 |
+
"right": true
|
| 380 |
+
},
|
| 381 |
+
{
|
| 382 |
+
"domain": "email",
|
| 383 |
+
"scenario": "editing",
|
| 384 |
+
"before": "ured products and marketing of electricity for the United St",
|
| 385 |
+
"suggestion": "ates",
|
| 386 |
+
"truth": "ates ? Actively ",
|
| 387 |
+
"right": true
|
| 388 |
+
},
|
| 389 |
+
{
|
| 390 |
+
"domain": "email",
|
| 391 |
+
"scenario": "editing",
|
| 392 |
+
"before": "I'm not sure what you are looking for. The Early Termination",
|
| 393 |
+
"suggestion": " Log",
|
| 394 |
+
"truth": " Date is one of ",
|
| 395 |
+
"right": false
|
| 396 |
+
},
|
| 397 |
+
{
|
| 398 |
+
"domain": "email",
|
| 399 |
+
"scenario": "editing",
|
| 400 |
+
"before": " action is necessary as contractually we are coming to the e",
|
| 401 |
+
"suggestion": "nd of",
|
| 402 |
+
"truth": "nd of the accepta",
|
| 403 |
+
"right": true
|
| 404 |
+
}
|
| 405 |
+
],
|
| 406 |
+
"latency_ms": {
|
| 407 |
+
"p50": 25.25,
|
| 408 |
+
"p95": 75.94,
|
| 409 |
+
"note": "Measured in this eval process, not in a browser."
|
| 410 |
+
}
|
| 411 |
+
}
|
v2/train.py
CHANGED
|
@@ -275,6 +275,7 @@ class TinyNext(nn.Module):
|
|
| 275 |
self.embed = nn.Embedding(vocab, dim)
|
| 276 |
self.blocks = nn.ModuleList(Block(dim, heads, ffn) for _ in range(layers))
|
| 277 |
self.norm = RMSNorm(dim)
|
|
|
|
| 278 |
self.head_dim = dim // heads
|
| 279 |
inverse = 1.0 / (10000 ** (torch.arange(0, self.head_dim, 2).float() / self.head_dim))
|
| 280 |
self.register_buffer("inverse_frequency", inverse, persistent=False)
|
|
@@ -298,7 +299,7 @@ class TinyNext(nn.Module):
|
|
| 298 |
x, k, v = block(x, cos, sin, None if past_k is None else past_k[index], None if past_v is None else past_v[index], mask)
|
| 299 |
new_k.append(k)
|
| 300 |
new_v.append(v)
|
| 301 |
-
logits = self.norm(x) @ self.embed.weight.T
|
| 302 |
return logits, torch.stack(new_k), torch.stack(new_v)
|
| 303 |
|
| 304 |
|
|
@@ -414,46 +415,79 @@ def as_token_lm(ev, name: str, model: TinyNext, tokenizer, device, fim: bool = T
|
|
| 414 |
return ev.TokenLM(name, next_logits, encode, texts, set(range(len(SPECIAL))), prompt=prompt)
|
| 415 |
|
| 416 |
|
| 417 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 418 |
import onnxruntime as ort
|
| 419 |
from onnxruntime.quantization import QuantType, quantize_dynamic
|
| 420 |
|
| 421 |
model = model.float().eval().to("cpu")
|
|
|
|
| 422 |
cfg = model.config
|
| 423 |
head_dim = cfg["dim"] // cfg["heads"]
|
| 424 |
-
|
| 425 |
-
empty
|
| 426 |
-
# Trace with a non-empty cache so no shape gets fixed at zero; the checks below run with an empty one.
|
| 427 |
with torch.no_grad():
|
| 428 |
_, trace_k, trace_v = model(torch.tensor([[1, 2]]))
|
| 429 |
float_path, int8_path = output / "model.onnx", output / "model_int8.onnx"
|
| 430 |
torch.onnx.export(
|
| 431 |
-
BrowserStep(model), (
|
| 432 |
input_names=["input_ids", "past_k", "past_v"], output_names=["logits", "present_k", "present_v"],
|
| 433 |
dynamic_axes={"input_ids": {1: "length"}, "past_k": {3: "past"}, "past_v": {3: "past"},
|
| 434 |
"present_k": {3: "total"}, "present_v": {3: "total"}},
|
| 435 |
dynamo=False,
|
| 436 |
)
|
| 437 |
-
quantize_dynamic(float_path, int8_path, weight_type=QuantType.QInt8, op_types_to_quantize=["MatMul"])
|
| 438 |
|
| 439 |
-
|
| 440 |
-
|
| 441 |
-
|
| 442 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 443 |
for name, path in (("float", float_path), ("int8", int8_path)):
|
| 444 |
session = ort.InferenceSession(str(path), providers=["CPUExecutionProvider"])
|
| 445 |
-
|
| 446 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 447 |
timings = []
|
| 448 |
for _ in range(200):
|
| 449 |
began = time.perf_counter()
|
| 450 |
-
|
| 451 |
timings.append((time.perf_counter() - began) * 1000)
|
| 452 |
report[name] = {
|
| 453 |
"megabytes": round(path.stat().st_size / 1e6, 2),
|
| 454 |
-
"
|
|
|
|
| 455 |
"cached_step_ms_p50_cpu": round(float(np.median(timings)), 3),
|
| 456 |
}
|
|
|
|
| 457 |
model.to(device)
|
| 458 |
return report
|
| 459 |
|
|
@@ -620,7 +654,7 @@ def main():
|
|
| 620 |
(output / "metrics").mkdir(exist_ok=True)
|
| 621 |
(output / "metrics" / f"{args.name}.json").write_text(json.dumps(scored, indent=1))
|
| 622 |
tracker.log(headline(scored))
|
| 623 |
-
exported = export(model, output, device)
|
| 624 |
|
| 625 |
config = {
|
| 626 |
**model.config, "parameters": parameters, "seq": args.seq, "special_tokens": dict(zip(SPECIAL, range(len(SPECIAL)))),
|
|
|
|
| 275 |
self.embed = nn.Embedding(vocab, dim)
|
| 276 |
self.blocks = nn.ModuleList(Block(dim, heads, ffn) for _ in range(layers))
|
| 277 |
self.norm = RMSNorm(dim)
|
| 278 |
+
self.head = None # set only for export: an untied copy of the output weights, so int8 quantization covers it
|
| 279 |
self.head_dim = dim // heads
|
| 280 |
inverse = 1.0 / (10000 ** (torch.arange(0, self.head_dim, 2).float() / self.head_dim))
|
| 281 |
self.register_buffer("inverse_frequency", inverse, persistent=False)
|
|
|
|
| 299 |
x, k, v = block(x, cos, sin, None if past_k is None else past_k[index], None if past_v is None else past_v[index], mask)
|
| 300 |
new_k.append(k)
|
| 301 |
new_v.append(v)
|
| 302 |
+
logits = self.norm(x) @ (self.embed.weight.T if self.head is None else self.head)
|
| 303 |
return logits, torch.stack(new_k), torch.stack(new_v)
|
| 304 |
|
| 305 |
|
|
|
|
| 415 |
return ev.TokenLM(name, next_logits, encode, texts, set(range(len(SPECIAL))), prompt=prompt)
|
| 416 |
|
| 417 |
|
| 418 |
+
def parity_prompts(ev, tokenizer, count: int = 300) -> list[list[int]]:
|
| 419 |
+
"""Real text from the eval set, cut at random points, as token prompts."""
|
| 420 |
+
rng = random.Random(0)
|
| 421 |
+
texts = [p for domain in ev.load_eval_set().values() for doc in domain for p in doc]
|
| 422 |
+
prompts = []
|
| 423 |
+
for text in rng.sample(texts, min(count, len(texts))):
|
| 424 |
+
ids = tokenizer.encode(text[: rng.randint(40, len(text))]).ids[-300:]
|
| 425 |
+
if len(ids) >= 4:
|
| 426 |
+
prompts.append(ids)
|
| 427 |
+
return prompts
|
| 428 |
+
|
| 429 |
+
|
| 430 |
+
def greedy_tokens(step, ids: list[int], empty, steps: int) -> list[int]:
|
| 431 |
+
"""Prompt, then `steps` cached greedy steps; returns the top token at each point."""
|
| 432 |
+
logits, k, v = step(np.array([ids]), empty, empty)
|
| 433 |
+
tops = [int(logits.argmax())]
|
| 434 |
+
for _ in range(steps):
|
| 435 |
+
logits, k, v = step(np.array([[tops[-1]]]), k, v)
|
| 436 |
+
tops.append(int(logits.argmax()))
|
| 437 |
+
return tops
|
| 438 |
+
|
| 439 |
+
|
| 440 |
+
def export(model: TinyNext, output: Path, device, prompts: list[list[int]]) -> dict:
|
| 441 |
+
"""Float and int8 ONNX for the browser, checked against PyTorch on real prompts over several cached steps."""
|
| 442 |
import onnxruntime as ort
|
| 443 |
from onnxruntime.quantization import QuantType, quantize_dynamic
|
| 444 |
|
| 445 |
model = model.float().eval().to("cpu")
|
| 446 |
+
model.head = nn.Parameter(model.embed.weight.detach().T.contiguous().clone())
|
| 447 |
cfg = model.config
|
| 448 |
head_dim = cfg["dim"] // cfg["heads"]
|
| 449 |
+
empty = np.zeros((cfg["layers"], 1, cfg["heads"], 0, head_dim), np.float32)
|
| 450 |
+
# Trace with a non-empty cache so no shape gets fixed at zero; the checks below start from an empty one.
|
|
|
|
| 451 |
with torch.no_grad():
|
| 452 |
_, trace_k, trace_v = model(torch.tensor([[1, 2]]))
|
| 453 |
float_path, int8_path = output / "model.onnx", output / "model_int8.onnx"
|
| 454 |
torch.onnx.export(
|
| 455 |
+
BrowserStep(model), (torch.tensor([[5, 6, 7]]), trace_k, trace_v), float_path, opset_version=17,
|
| 456 |
input_names=["input_ids", "past_k", "past_v"], output_names=["logits", "present_k", "present_v"],
|
| 457 |
dynamic_axes={"input_ids": {1: "length"}, "past_k": {3: "past"}, "past_v": {3: "past"},
|
| 458 |
"present_k": {3: "total"}, "present_v": {3: "total"}},
|
| 459 |
dynamo=False,
|
| 460 |
)
|
| 461 |
+
quantize_dynamic(float_path, int8_path, weight_type=QuantType.QInt8, op_types_to_quantize=["MatMul", "Gather"], per_channel=True)
|
| 462 |
|
| 463 |
+
@torch.no_grad()
|
| 464 |
+
def torch_step(ids, k, v):
|
| 465 |
+
past = None if k.shape[3] == 0 else (torch.from_numpy(k), torch.from_numpy(v))
|
| 466 |
+
logits, nk, nv = model(torch.from_numpy(ids), *(past or (None, None)))
|
| 467 |
+
return logits[0, -1].numpy(), nk.numpy(), nv.numpy()
|
| 468 |
+
|
| 469 |
+
expected = [greedy_tokens(torch_step, ids, empty, 4) for ids in prompts]
|
| 470 |
+
report = {"parity_prompts": len(prompts), "parity_steps_per_prompt": 5}
|
| 471 |
for name, path in (("float", float_path), ("int8", int8_path)):
|
| 472 |
session = ort.InferenceSession(str(path), providers=["CPUExecutionProvider"])
|
| 473 |
+
onnx_step = lambda ids, k, v: (lambda out: (out[0][0], out[1], out[2]))(
|
| 474 |
+
session.run(None, {"input_ids": ids.astype(np.int64), "past_k": k, "past_v": v}))
|
| 475 |
+
got = [greedy_tokens(onnx_step, ids, empty, 4) for ids in prompts]
|
| 476 |
+
first = np.mean([g[0] == e[0] for g, e in zip(got, expected)])
|
| 477 |
+
all_steps = np.mean([g == e for g, e in zip(got, expected)])
|
| 478 |
+
_, pk, pv = onnx_step(np.array([prompts[0]]), empty, empty)
|
| 479 |
timings = []
|
| 480 |
for _ in range(200):
|
| 481 |
began = time.perf_counter()
|
| 482 |
+
onnx_step(np.array([[8]]), pk, pv)
|
| 483 |
timings.append((time.perf_counter() - began) * 1000)
|
| 484 |
report[name] = {
|
| 485 |
"megabytes": round(path.stat().st_size / 1e6, 2),
|
| 486 |
+
"same_first_token": round(float(first), 4),
|
| 487 |
+
"same_five_greedy_tokens": round(float(all_steps), 4),
|
| 488 |
"cached_step_ms_p50_cpu": round(float(np.median(timings)), 3),
|
| 489 |
}
|
| 490 |
+
model.head = None
|
| 491 |
model.to(device)
|
| 492 |
return report
|
| 493 |
|
|
|
|
| 654 |
(output / "metrics").mkdir(exist_ok=True)
|
| 655 |
(output / "metrics" / f"{args.name}.json").write_text(json.dumps(scored, indent=1))
|
| 656 |
tracker.log(headline(scored))
|
| 657 |
+
exported = export(model, output, device, parity_prompts(ev, tokenizer))
|
| 658 |
|
| 659 |
config = {
|
| 660 |
**model.config, "parameters": parameters, "seq": args.seq, "special_tokens": dict(zip(SPECIAL, range(len(SPECIAL)))),
|
v2/web/config.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"vocab": 8192,
|
| 3 |
+
"dim": 320,
|
| 4 |
+
"layers": 8,
|
| 5 |
+
"heads": 5,
|
| 6 |
+
"ffn": 864,
|
| 7 |
+
"parameters": 12539200,
|
| 8 |
+
"seq": 512,
|
| 9 |
+
"special_tokens": {
|
| 10 |
+
"<|endoftext|>": 0,
|
| 11 |
+
"<|pre|>": 1,
|
| 12 |
+
"<|suf|>": 2,
|
| 13 |
+
"<|mid|>": 3
|
| 14 |
+
},
|
| 15 |
+
"prompt": "No text after the cursor: the text before it. Otherwise: <|suf|> after <|pre|> before <|mid|>."
|
| 16 |
+
}
|
v2/web/graph.onnx
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:e63c34d5f6882b6c9d7dda768ea6009edc831f26f5e7a800161a54a204f521d7
|
| 3 |
+
size 194807
|
v2/web/parity.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"parity_prompts": 300,
|
| 3 |
+
"parity_steps_per_prompt": 5,
|
| 4 |
+
"float": {
|
| 5 |
+
"megabytes": 60.81,
|
| 6 |
+
"same_first_token": 1.0,
|
| 7 |
+
"same_five_greedy_tokens": 1.0,
|
| 8 |
+
"cached_step_ms_p50_cpu": 1.2
|
| 9 |
+
},
|
| 10 |
+
"int8": {
|
| 11 |
+
"megabytes": 15.64,
|
| 12 |
+
"same_first_token": 0.55,
|
| 13 |
+
"same_five_greedy_tokens": 0.33,
|
| 14 |
+
"cached_step_ms_p50_cpu": 0.71
|
| 15 |
+
}
|
| 16 |
+
}
|
v2/web/tokenizer.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
v2/web/weights.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"block": 64, "f32_bytes": 50135040, "tensors": [{"name": "model.embed.weight", "shape": [8192, 320], "count": 2621440, "f32_offset": 0, "q_offset": 0, "scale_offset": 2621440}, {"name": "onnx::MatMul_1554", "shape": [320, 960], "count": 307200, "f32_offset": 10485760, "q_offset": 2785280, "scale_offset": 3092480}, {"name": "onnx::MatMul_1571", "shape": [320, 320], "count": 102400, "f32_offset": 11714560, "q_offset": 3111680, "scale_offset": 3214080}, {"name": "onnx::MatMul_1572", "shape": [320, 1728], "count": 552960, "f32_offset": 12124160, "q_offset": 3220480, "scale_offset": 3773440}, {"name": "onnx::MatMul_1573", "shape": [864, 320], "count": 276480, "f32_offset": 14336000, "q_offset": 3808000, "scale_offset": 4084480}, {"name": "onnx::MatMul_1574", "shape": [320, 960], "count": 307200, "f32_offset": 15441920, "q_offset": 4101760, "scale_offset": 4408960}, {"name": "onnx::MatMul_1591", "shape": [320, 320], "count": 102400, "f32_offset": 16670720, "q_offset": 4428160, "scale_offset": 4530560}, {"name": "onnx::MatMul_1592", "shape": [320, 1728], "count": 552960, "f32_offset": 17080320, "q_offset": 4536960, "scale_offset": 5089920}, {"name": "onnx::MatMul_1593", "shape": [864, 320], "count": 276480, "f32_offset": 19292160, "q_offset": 5124480, "scale_offset": 5400960}, {"name": "onnx::MatMul_1594", "shape": [320, 960], "count": 307200, "f32_offset": 20398080, "q_offset": 5418240, "scale_offset": 5725440}, {"name": "onnx::MatMul_1611", "shape": [320, 320], "count": 102400, "f32_offset": 21626880, "q_offset": 5744640, "scale_offset": 5847040}, {"name": "onnx::MatMul_1612", "shape": [320, 1728], "count": 552960, "f32_offset": 22036480, "q_offset": 5853440, "scale_offset": 6406400}, {"name": "onnx::MatMul_1613", "shape": [864, 320], "count": 276480, "f32_offset": 24248320, "q_offset": 6440960, "scale_offset": 6717440}, {"name": "onnx::MatMul_1614", "shape": [320, 960], "count": 307200, "f32_offset": 25354240, "q_offset": 6734720, "scale_offset": 7041920}, {"name": "onnx::MatMul_1631", "shape": [320, 320], "count": 102400, "f32_offset": 26583040, "q_offset": 7061120, "scale_offset": 7163520}, {"name": "onnx::MatMul_1632", "shape": [320, 1728], "count": 552960, "f32_offset": 26992640, "q_offset": 7169920, "scale_offset": 7722880}, {"name": "onnx::MatMul_1633", "shape": [864, 320], "count": 276480, "f32_offset": 29204480, "q_offset": 7757440, "scale_offset": 8033920}, {"name": "onnx::MatMul_1634", "shape": [320, 960], "count": 307200, "f32_offset": 30310400, "q_offset": 8051200, "scale_offset": 8358400}, {"name": "onnx::MatMul_1651", "shape": [320, 320], "count": 102400, "f32_offset": 31539200, "q_offset": 8377600, "scale_offset": 8480000}, {"name": "onnx::MatMul_1652", "shape": [320, 1728], "count": 552960, "f32_offset": 31948800, "q_offset": 8486400, "scale_offset": 9039360}, {"name": "onnx::MatMul_1653", "shape": [864, 320], "count": 276480, "f32_offset": 34160640, "q_offset": 9073920, "scale_offset": 9350400}, {"name": "onnx::MatMul_1654", "shape": [320, 960], "count": 307200, "f32_offset": 35266560, "q_offset": 9367680, "scale_offset": 9674880}, {"name": "onnx::MatMul_1671", "shape": [320, 320], "count": 102400, "f32_offset": 36495360, "q_offset": 9694080, "scale_offset": 9796480}, {"name": "onnx::MatMul_1672", "shape": [320, 1728], "count": 552960, "f32_offset": 36904960, "q_offset": 9802880, "scale_offset": 10355840}, {"name": "onnx::MatMul_1673", "shape": [864, 320], "count": 276480, "f32_offset": 39116800, "q_offset": 10390400, "scale_offset": 10666880}, {"name": "onnx::MatMul_1674", "shape": [320, 960], "count": 307200, "f32_offset": 40222720, "q_offset": 10684160, "scale_offset": 10991360}, {"name": "onnx::MatMul_1691", "shape": [320, 320], "count": 102400, "f32_offset": 41451520, "q_offset": 11010560, "scale_offset": 11112960}, {"name": "onnx::MatMul_1692", "shape": [320, 1728], "count": 552960, "f32_offset": 41861120, "q_offset": 11119360, "scale_offset": 11672320}, {"name": "onnx::MatMul_1693", "shape": [864, 320], "count": 276480, "f32_offset": 44072960, "q_offset": 11706880, "scale_offset": 11983360}, {"name": "onnx::MatMul_1694", "shape": [320, 960], "count": 307200, "f32_offset": 45178880, "q_offset": 12000640, "scale_offset": 12307840}, {"name": "onnx::MatMul_1711", "shape": [320, 320], "count": 102400, "f32_offset": 46407680, "q_offset": 12327040, "scale_offset": 12429440}, {"name": "onnx::MatMul_1712", "shape": [320, 1728], "count": 552960, "f32_offset": 46817280, "q_offset": 12435840, "scale_offset": 12988800}, {"name": "onnx::MatMul_1713", "shape": [864, 320], "count": 276480, "f32_offset": 49029120, "q_offset": 13023360, "scale_offset": 13299840}]}
|
v2/web/weights.q8
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:b74d19232900fda1c0e1cdcd1113a4825cc05874805796e138edf778b8053dde
|
| 3 |
+
size 13317120
|