faxenoff commited on
Commit
0eeaf19
Β·
verified Β·
1 Parent(s): 6039839

compiled artefacts from win_x64 (sm_120)

Browse files
.gitattributes CHANGED
@@ -36,3 +36,7 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
36
  tokenizer.json filter=lfs diff=lfs merge=lfs -text
37
  code-daemon-denoise-v1-s_b64_s40_win_x64_tvm_vulkan.dll filter=lfs diff=lfs merge=lfs -text
38
  code-daemon-denoise-v1-s_win_x64_trt_sm_120.engine filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
36
  tokenizer.json filter=lfs diff=lfs merge=lfs -text
37
  code-daemon-denoise-v1-s_b64_s40_win_x64_tvm_vulkan.dll filter=lfs diff=lfs merge=lfs -text
38
  code-daemon-denoise-v1-s_win_x64_trt_sm_120.engine filter=lfs diff=lfs merge=lfs -text
39
+ code-daemon-denoise-v1-s_linux_x64_trt11.0_sm_120.engine filter=lfs diff=lfs merge=lfs -text
40
+ code-daemon-denoise-v1-s_win_x64_trt11.0_sm_120.engine filter=lfs diff=lfs merge=lfs -text
41
+ code-daemon-denoise-v1_linux_x64_tvm0.25_vulkan.so filter=lfs diff=lfs merge=lfs -text
42
+ code-daemon-denoise-v1_win_x64_tvm0.25_vulkan.dll filter=lfs diff=lfs merge=lfs -text
README.md CHANGED
@@ -4,97 +4,192 @@ language:
4
  - en
5
  - ru
6
  tags:
7
- - feature-extraction
8
  - text-classification
 
 
9
  - denoising
10
  - multilingual
 
 
11
  - openvino
12
  - tensorrt
13
- pipeline_tag: feature-extraction
14
  base_model:
15
  - intfloat/multilingual-e5-small
16
  ---
17
 
18
  # code-daemon-denoise-v1
19
 
20
- A tiny, fast **bilingual (EN + RU) word denoiser** β€” it decides whether a single word form is a
21
- **meaningful technical term** (keep) or **noise / ballast** (drop). It ships with the
22
- [UltraCode](https://github.com/faxenoff/ultracode) MCP server, where it runs in the knowledge-graph pipeline: classifying the UNKNOWN word forms harvested from a codebase's docs/identifiers so the search vocabulary stays clean.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
 
24
- - **Frozen encoder** β€” [`intfloat/multilingual-e5-small`](https://huggingface.co/intfloat/multilingual-e5-small)
25
- (XLM-RoBERTa, 384-dim), **no weight changes**. Mean-pooling + L2-norm are baked into the graph.
26
- - **Trained linear head** β€” a logistic-regression probe (scikit-learn) over the 384-dim embedding,
27
- **folded with its input scaler into a single affine** `P(keep) = sigmoid(wΒ·e + b)`. Ships as
28
- `denoise_head.json` (`{dim, w[384], b, strip_threshold}`) β€” no Python at runtime; the daemon does the dot product in-process.
29
- - **Vocab-pruned** β€” the 250k-token SentencePiece vocab is cut by character class to **Latin + Cyrillic + punctuation (142k tokens)**, lossless for EN + RU, dropping the INT8 weights from ~121 MB to **~76 MB**. The pruned-vocab id map is folded into a remap-Gather at the model input.
30
 
31
- ## How it was made
 
32
 
33
- 1. **Encoder**: export the frozen mE5-small to ONNX with mean-pool + L2-norm fused, prune the embedding table to the kept character classes, and PTQ-quantize to INT8 (NNCF) for OpenVINO.
34
- 2. **Head**: embed a bilingual word-label set (EN: WordNet/BNC mid-frequency lemmas; RU:
35
- Taiga/OpenCorpora/Nerus mid-Zipf) plus per-language manual gold, fit
36
- `LogisticRegression(class_weight="balanced")`, then **fold** `StandardScaler` + LR into one `(w, b)`. A `strip_threshold` (default **0.95**) trades strip precision vs recall.
37
 
38
- Words are embedded with a fixed `"vocab: "` prefix (the daemon pads every candidate word the same
39
- way) so very short inputs are not dropped by batch de-duplication β€” the head is trained on the
40
- **prefixed** embeddings, so reproduce the prefix for standalone use.
 
41
 
42
- ## Built for speed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
 
44
- - **Short, single-word inputs** β€” one length bucket only: **batch 64 Γ— seq 40** (`-s_…_b64_s40`).
45
- - **INT8** weights (OpenVINO CPU); the embedding **mean-pool + L2-norm are fused** into the graph so
46
- the output is already `[batch, 384]`.
47
- - **CPU-first by design** β€” on the daemon it runs on OpenVINO CPU and is moved to a discrete GPU
48
- (TensorRT / TVM) only when the card is large (β‰₯12 GB total VRAM) with free room.
49
 
50
- ## Intended use
 
 
 
 
51
 
52
- Per-word "is this a technical term?" classification for cleaning a search vocabulary. Encode a word
53
- (with the `"vocab: "` prefix) with the bundled SentencePiece + mE5-small, then apply the linear head:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
 
55
  ```python
56
- import onnxruntime as ort, sentencepiece as spm, numpy as np, json
57
 
58
  sp = spm.SentencePieceProcessor(model_file="sentencepiece.bpe.model")
59
  sess = ort.InferenceSession("model.onnx", providers=["CPUExecutionProvider"])
60
- head = json.load(open("denoise_head.json")) # {dim, w[dim], b, strip_threshold}
61
  w, b, thr = np.array(head["w"], np.float32), head["b"], head["strip_threshold"]
62
 
63
  def p_keep(words, max_len=40):
64
  toks = [[2, *sp.encode("vocab: " + x)[: max_len - 2], 3] for x in words] # bos … eos
65
  L = max(len(t) for t in toks)
66
- ids = np.array([t + [0] * (L - len(t)) for t in toks], dtype=np.int64) # pad=0
67
  mask = (ids != 0).astype(np.int64)
68
- emb = sess.run(None, {"input_ids": ids, "attention_mask": mask})[0] # mean-pooled+L2 [B,384]
69
- return 1.0 / (1.0 + np.exp(-(emb @ w + b))) # P(keep)
70
 
71
  scores = p_keep(["mutex", "tensorrt", "поТалуйста", "asdfgh"])
72
- # keep where score >= thr ; the rest is ballast
73
  ```
74
 
75
- ## What's in this repo
 
76
 
77
- Pre-compiled, ready-to-run engines named per **runtime Γ— GPU arch Γ— OS** (single `s` bucket):
78
 
79
- - **OpenVINO** `*_ov_cpu_int8_b64_s40.{xml,bin}` β€” Intel/AMD/any CPU, INT8 (the default lane).
80
- - **TensorRT** `*_{win_x64,linux_x64}_trt_sm_{86,89,120}.engine` β€” NVIDIA, BF16 (optional GPU lane;
81
- the INT8 lane is OV CPU β€” this remap-baked SentencePiece ONNX isn't compatible with generic INT8 PTQ).
82
- - **TVM** `*_b64_s40_{win_x64,…}_tvm_vulkan.{dll,so}` β€” Vulkan fallback (optional GPU lane).
83
- - **Head** β€” `denoise_head.json` (the trained affine; required).
84
- - **Tokenizer** β€” `sentencepiece.bpe.model` (+ `tokenizer_config.json`). The daemon feeds raw
85
- SentencePiece ids; the fairseq +1 offset and pruned-vocab remap are baked into the ONNX.
86
- - **ONNX source** β€” `model.onnx` (FP32, pruned, mean-pool + L2-norm + remap fused) β€” the build
87
- source for the TRT/TVM engines and for standalone `onnxruntime` use.
88
 
89
- ## Evaluation
90
 
91
- On a frozen held-out word set (EN + RU): **SAFE F1 β‰ˆ 0.79**, BALLAST F1 β‰ˆ 0.84, strip precision β‰ˆ
92
- 0.88 at `strip_threshold = 0.95`. The INT8 vocab-pruned build matches the full-vocab FP build (F1 0.79
93
- vs 0.79) at 38 % of the size.
 
 
94
 
95
- ## License & attribution
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
 
97
  The encoder weights are **[`intfloat/multilingual-e5-small`](https://huggingface.co/intfloat/multilingual-e5-small)**
98
- (Apache-2.0), redistributed here in compiled form **unchanged**; this repo is therefore released under
99
- **Apache-2.0**. The linear head and the build/quantization tooling are original to UltraCode. Backbone:
100
- XLM-RoBERTa. Not legal advice.
 
 
 
 
4
  - en
5
  - ru
6
  tags:
 
7
  - text-classification
8
+ - feature-extraction
9
+ - vocabulary-filtering
10
  - denoising
11
  - multilingual
12
+ - quantized
13
+ - int8
14
  - openvino
15
  - tensorrt
16
+ pipeline_tag: text-classification
17
  base_model:
18
  - intfloat/multilingual-e5-small
19
  ---
20
 
21
  # code-daemon-denoise-v1
22
 
23
+ A **bilingual (EN + RU) word filter**: given one word form, it answers whether that word is a
24
+ **meaningful technical term** worth keeping in a search vocabulary, or **ballast** to drop.
25
+
26
+ It is deliberately small and one-purpose. A frozen `multilingual-e5-small` encoder produces a
27
+ 384-dim vector, and a **single trained affine** turns that vector into `P(keep)`. No fine-tuning of
28
+ the encoder, no classification head with its own weights to load β€” the entire learned decision is
29
+ 384 numbers and a bias, shipped as a 6 KB JSON file.
30
+
31
+ That buys throughput: **~800 words/sec on a CPU core**, **~17 800/sec on a laptop GPU**.
32
+
33
+ ```python
34
+ emb = session.run(None, {"input_ids": ids, "attention_mask": mask})[0] # [B, 384] pooled + L2
35
+ p_keep = 1 / (1 + np.exp(-(emb @ w + b))) # the whole classifier
36
+ ```
37
+
38
+ ---
39
+
40
+ ## 1. What it is for
41
 
42
+ Vocabulary hygiene. Harvest every word form out of a codebase β€” identifiers, doc prose, comments,
43
+ commit messages β€” and most of what you get is not worth indexing: inflected function words, chopped
44
+ identifier fragments, transliteration noise, boilerplate. Keeping them inflates a search vocabulary
45
+ and dilutes term statistics; dropping them by frequency alone throws away rare-but-real technical
46
+ terms, which are exactly the ones worth searching for.
 
47
 
48
+ This model makes that call per word, in both English and Russian, at a rate that keeps up with a
49
+ full-repository scan.
50
 
51
+ **Suited to**
52
+ - Filtering a harvested vocabulary before indexing.
53
+ - Any per-token keep/drop decision over short, single-word inputs.
54
+ - Mixed EN/RU corpora β€” including Cyrillic identifiers and comments.
55
 
56
+ **Not suited to**
57
+ - Sentences or phrases. Inputs are single word forms; the sequence budget is 40 tokens.
58
+ - Languages outside Latin/Cyrillic scripts β€” the vocabulary was pruned to those on purpose.
59
+ - Domain term-vs-stopword calls outside software; the label set is technical-corpus flavoured.
60
 
61
+ ---
62
+
63
+ ## 2. Architecture
64
+
65
+ | | |
66
+ |---|---|
67
+ | Encoder | [`intfloat/multilingual-e5-small`](https://huggingface.co/intfloat/multilingual-e5-small) β€” XLM-RoBERTa, **frozen, unchanged** |
68
+ | Embedding dim | 384, mean-pooled and L2-normalised **inside the graph** |
69
+ | Vocabulary | **142k** pieces, pruned from 250k by character class (Latin + Cyrillic + punctuation) |
70
+ | Classifier | one affine: `P(keep) = sigmoid(wΒ·e + b)`, `w ∈ ℝ³⁸⁴` |
71
+ | Sequence | 40 tokens, batch 64 |
72
+ | Inputs | `input_ids`, `attention_mask` |
73
+ | Output | `[batch, 384]` β€” pooled, normalised, ready for the dot product |
74
+
75
+ ### Two decisions that make it small
76
+
77
+ **The encoder is frozen.** The head is a logistic regression fitted on top of fixed embeddings, then
78
+ folded β€” its `StandardScaler` and the LR coefficients are multiplied out into a single `(w, b)` pair.
79
+ There is no scikit-learn at inference, and no second model to keep in sync: the decision boundary is
80
+ a dot product you can apply in any language.
81
+
82
+ **The vocabulary is pruned by script.** Cutting the 250k multilingual SentencePiece table to the
83
+ Latin + Cyrillic + punctuation pieces removes ~43% of the rows, and the embedding table is most of
84
+ this model's weight. The pruned-vocab id remap is baked into the graph as a Gather at the input, so
85
+ callers still feed ordinary SentencePiece ids and never see the mapping. INT8 weights drop from
86
+ ~121 MB to **~76 MB** β€” lossless for the two languages it targets, because nothing outside those
87
+ scripts was reachable anyway.
88
+
89
+ ### The `"vocab: "` prefix
90
+
91
+ Words are embedded with a fixed `"vocab: "` prefix. The head was trained on prefixed embeddings, so
92
+ **reproduce the prefix** for standalone use or the decision boundary will not line up.
93
+
94
+ ---
95
 
96
+ ## 3. How it was made
 
 
 
 
97
 
98
+ 1. **Encoder** β€” export the frozen mE5-small to ONNX with mean-pooling and L2-norm fused into the
99
+ graph, prune the embedding table to the kept character classes, and PTQ-quantize to INT8 (NNCF).
100
+ 2. **Head** β€” embed a bilingual labelled word set (English: WordNet / BNC mid-frequency lemmas;
101
+ Russian: Taiga / OpenCorpora / Nerus mid-Zipf) plus per-language hand-checked gold, fit
102
+ `LogisticRegression(class_weight="balanced")`, then fold the scaler and the LR into one affine.
103
 
104
+ `strip_threshold` (default **0.95**) sets where you cut. It is high on purpose: dropping a real
105
+ technical term is the expensive error, keeping a bit of ballast is not.
106
+
107
+ ---
108
+
109
+ ## 4. Speed
110
+
111
+ Measured on one laptop: Intel Core Ultra 9 275HX / NVIDIA RTX 5060 Laptop, batch 64 Γ— seq 40.
112
+
113
+ | lane | per batch | throughput | per word |
114
+ |---|--:|--:|--:|
115
+ | **TensorRT FP16, RTX 5060 Laptop** | **3.60 ms** | **17 790 words/s** | 0.056 ms |
116
+ | **OpenVINO INT8, CPU** | **80.4 ms** | **796 words/s** | 1.26 ms |
117
+ | ONNX Runtime FP32, CPU | 188 ms | 341 words/s | 2.93 ms |
118
+
119
+ The INT8 CPU lane is the intended default β€” 800 words/sec is enough to filter a repository's whole
120
+ harvested vocabulary in seconds without touching a GPU, and it is 2.3Γ— the unquantized ONNX path.
121
+ The GPU lane exists for hosts that have spare VRAM anyway.
122
+
123
+ ---
124
+
125
+ ## 5. Standalone use
126
 
127
  ```python
128
+ import json, numpy as np, onnxruntime as ort, sentencepiece as spm
129
 
130
  sp = spm.SentencePieceProcessor(model_file="sentencepiece.bpe.model")
131
  sess = ort.InferenceSession("model.onnx", providers=["CPUExecutionProvider"])
132
+ head = json.load(open("denoise_head.json")) # {dim, w[384], b, strip_threshold}
133
  w, b, thr = np.array(head["w"], np.float32), head["b"], head["strip_threshold"]
134
 
135
  def p_keep(words, max_len=40):
136
  toks = [[2, *sp.encode("vocab: " + x)[: max_len - 2], 3] for x in words] # bos … eos
137
  L = max(len(t) for t in toks)
138
+ ids = np.array([t + [0] * (L - len(t)) for t in toks], dtype=np.int64) # pad = 0
139
  mask = (ids != 0).astype(np.int64)
140
+ emb = sess.run(None, {"input_ids": ids, "attention_mask": mask})[0] # [B, 384]
141
+ return 1.0 / (1.0 + np.exp(-(emb @ w + b)))
142
 
143
  scores = p_keep(["mutex", "tensorrt", "поТалуйста", "asdfgh"])
144
+ keep = scores >= thr
145
  ```
146
 
147
+ The ONNX bakes in the fairseq `+1` id offset and the pruned-vocab remap, so feed raw SentencePiece
148
+ ids β€” do not remap them yourself.
149
 
150
+ ---
151
 
152
+ ## 6. Evaluation
 
 
 
 
 
 
 
 
153
 
154
+ On a frozen held-out bilingual word set, at `strip_threshold = 0.95`:
155
 
156
+ | metric | value |
157
+ |---|--:|
158
+ | SAFE (keep) F1 | **0.79** |
159
+ | BALLAST (drop) F1 | **0.84** |
160
+ | Strip precision | **0.88** |
161
 
162
+ The INT8 vocab-pruned build scores the same as the full-vocabulary FP build (F1 0.79 vs 0.79) at
163
+ 38% of the size β€” the pruning removes rows the two target languages never reach, so there is nothing
164
+ to lose by it.
165
+
166
+ Strip precision is the number to watch if you tune the threshold: it says how often a word the model
167
+ drops really was ballast.
168
+
169
+ ---
170
+
171
+ ## 7. What is in this repo
172
+
173
+ - **OpenVINO INT8** β€” `code-daemon-denoise-v1-s_ov2026.2_{cpu,igpu_lnl}_int8_b64_s40.{xml,bin}` β€” the
174
+ default lane (CPU) and an Intel iGPU build.
175
+ - **OpenVINO INT4, NPU** β€” `code-daemon-denoise-v1-s_ov2026.2_npu_int4_b16_s40.{xml,bin}` β€” weight-only
176
+ INT4 at batch 16 for Intel NPUs.
177
+ - **TensorRT FP16** β€” `code-daemon-denoise-v1-s_{win_x64,linux_x64}_trt11.0_sm_120.engine`.
178
+ - **TVM Vulkan** β€” `code-daemon-denoise-v1_{win_x64,linux_x64}_tvm0.25_vulkan.{dll,so}` β€” GPU fallback
179
+ for non-NVIDIA hardware.
180
+ - **Head** β€” `denoise_head.json`. **Required**: the ONNX alone emits embeddings, not a decision.
181
+ - **Tokenizer** β€” `sentencepiece.bpe.model`, `tokenizer_config.json`.
182
+ - **ONNX** β€” `model.onnx`, FP32, pruned, with mean-pool + L2-norm + id-remap fused. The build source
183
+ for every engine above and the path for standalone `onnxruntime` use.
184
+
185
+ ---
186
+
187
+ ## 8. License & attribution
188
 
189
  The encoder weights are **[`intfloat/multilingual-e5-small`](https://huggingface.co/intfloat/multilingual-e5-small)**
190
+ (Apache-2.0), redistributed here in compiled form **unchanged**; this repository is therefore
191
+ released under **Apache-2.0**. The trained head and the build/quantization tooling are original.
192
+ Backbone: XLM-RoBERTa. Not legal advice.
193
+
194
+ Used by the [UltraCode](https://github.com/faxenoff/ultracode) code assistant, though nothing about
195
+ the model is specific to it.
code-daemon-denoise-v1-s_linux_x64_trt11.0_sm_120.engine ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:85b1b7cc8dbbafabd233b69f8aa5e5324efd7ffd91b934967784fa8a060a5159
3
+ size 157032332
code-daemon-denoise-v1-s_ov2026.2_cpu_int8_b64_s40.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4de341144ca02c3c1a83e46e76044f2465f0a552d0a69bac2c4bc469604edc22
3
+ size 79105245
code-daemon-denoise-v1-s_ov2026.2_cpu_int8_b64_s40.xml ADDED
The diff for this file is too large to render. See raw diff
 
code-daemon-denoise-v1-s_ov2026.2_igpu_lnl_int8_b64_s40.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4de341144ca02c3c1a83e46e76044f2465f0a552d0a69bac2c4bc469604edc22
3
+ size 79105245
code-daemon-denoise-v1-s_ov2026.2_igpu_lnl_int8_b64_s40.xml ADDED
The diff for this file is too large to render. See raw diff
 
code-daemon-denoise-v1-s_ov2026.2_npu_int4_b16_s40.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8ae5a768b271ed4c7b6b01489ea821c66730aae14d14af297d3b414f9cd234f9
3
+ size 68668863
code-daemon-denoise-v1-s_ov2026.2_npu_int4_b16_s40.xml ADDED
The diff for this file is too large to render. See raw diff
 
code-daemon-denoise-v1-s_win_x64_trt11.0_sm_120.engine ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ab8c8235b0af77d50ef0358166a4177be33949e424b29cc5b91d0ac1aba4b9d1
3
+ size 157001948
code-daemon-denoise-v1_linux_x64_tvm0.25_vulkan.so ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:cceaae57b2d913510d1fa16f83887c61634e0c784432ed606b6dfdd3e724e3ae
3
+ size 331723344
code-daemon-denoise-v1_win_x64_tvm0.25_vulkan.dll ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c377dce734bd31868ec6162747006f33c79c2e171c0903362842739fb62179a3
3
+ size 331560448
manifest.json ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model_id": "code-daemon-denoise-v1",
3
+ "dimension": 384,
4
+ "max_tokens": 40,
5
+ "quantization": "int8",
6
+ "targets": [
7
+ "openvino",
8
+ "tensorrt",
9
+ "tvm"
10
+ ],
11
+ "runtime_tags": {
12
+ "trt": "trt11.0",
13
+ "ov": "ov2026.2",
14
+ "tvm": "tvm0.25",
15
+ "mlx_dir": "model_gpu_mlx0.22"
16
+ },
17
+ "compiled_at": "2026-08-03T14:52:07Z",
18
+ "compiled_by": "models/_compile"
19
+ }