Model card for the v2-p5 republish: built-in reranker, honest CoIR + real-repo positioning, updated licenses (no mMARCO)
Browse files
README.md
CHANGED
|
@@ -13,65 +13,100 @@ tags:
|
|
| 13 |
- knowledge-distillation
|
| 14 |
pipeline_tag: feature-extraction
|
| 15 |
base_model:
|
|
|
|
| 16 |
- Alibaba-NLP/gte-modernbert-base
|
|
|
|
| 17 |
datasets:
|
| 18 |
-
-
|
| 19 |
-
-
|
| 20 |
-
-
|
| 21 |
-
- sentence-transformers/gooaq
|
| 22 |
-
- jinaai/negation-dataset
|
| 23 |
---
|
| 24 |
|
| 25 |
# code-daemon-embed-v1
|
| 26 |
|
| 27 |
-
A small, fast **code-embedding model** for semantic code search
|
| 28 |
-
units β function and method bodies, signatures, docstrings β and short natural-language queries
|
| 29 |
-
shared **768-dim** vector space.
|
| 30 |
-
|
| 31 |
-
It is **specialized for
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
- **Mean pooling fused into the graph** β the output is already pooled (`[batch, 768]`); just **L2-normalize**.
|
| 37 |
- Trained at sequence length **128** (length buckets s / m / l = seq **40 / 64 / 128**).
|
| 38 |
|
| 39 |
-
##
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
|
| 41 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
|
| 43 |
-
**
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
|
| 49 |
**Weak / out of scope:**
|
| 50 |
-
- **Long documents** β hard 128-token cap;
|
| 51 |
-
- **
|
| 52 |
-
|
| 53 |
-
|
|
|
|
| 54 |
|
| 55 |
-
Embed **queries and documents the same way** β no instruction prefix.
|
| 56 |
-
**256** or **512** dims (MRL) before normalizing.
|
| 57 |
|
| 58 |
## How it was made
|
| 59 |
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
|
| 67 |
## Built for speed
|
| 68 |
|
| 69 |
-
- **Short context by design** β max **128 tokens**
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
|
| 76 |
## Usage (standalone ONNX)
|
| 77 |
|
|
@@ -84,92 +119,92 @@ import onnxruntime as ort, sentencepiece as spm, numpy as np
|
|
| 84 |
sp = spm.SentencePieceProcessor(model_file="sentencepiece.bpe.model") # pad=0 unk=1 bos=2 eos=3
|
| 85 |
sess = ort.InferenceSession("model.onnx", providers=["CPUExecutionProvider"])
|
| 86 |
|
| 87 |
-
def embed(texts, max_len=128
|
| 88 |
ids = [[2, *sp.encode(t)[: max_len - 2], 3] for t in texts] # bos β¦ eos
|
| 89 |
L = max(len(x) for x in ids)
|
| 90 |
inp = np.array([x + [0] * (L - len(x)) for x in ids], dtype=np.int64) # pad=0
|
| 91 |
mask = (inp != 0).astype(np.int64)
|
| 92 |
-
out = sess.run(None, {"input_ids": inp, "attention_mask": mask})[0] # already
|
| 93 |
-
out = out[:, :mrl_dim] # MRL truncation (768/512/256)
|
| 94 |
return out / np.linalg.norm(out, axis=1, keepdims=True)
|
| 95 |
```
|
| 96 |
|
| 97 |
-
## What's in this repo
|
| 98 |
|
| 99 |
-
|
| 100 |
-
runtime and hardware; no compilation needed.
|
| 101 |
|
| 102 |
-
- **TensorRT** `*.engine` β NVIDIA
|
| 103 |
`code-daemon-embed-v1-{s,m,l}_{win_x64,linux_x64}_trt_sm_{86,89,120}.engine`
|
| 104 |
(sm_86 β RTX 30xx / A-series Β· sm_89 β RTX 40xx / L4 Β· sm_120 β RTX 50xx).
|
| 105 |
-
- **TVM** `*_tvm_vulkan.{dll,so}` β Vulkan fallback for non-TRT
|
| 106 |
- **OpenVINO** `*.xml` + `*.bin` β Intel **CPU / iGPU / NPU**, per bucket.
|
| 107 |
- **Metal** `*_tvm_metal.*` β Apple Silicon (macOS), per bucket.
|
| 108 |
-
- **Tokenizer** β `sentencepiece.bpe.model` (
|
| 109 |
`tokenizer_config.json`.
|
| 110 |
-
- **ONNX source** β `model.onnx` (+ `model.onnx.data`) FP32
|
| 111 |
|
| 112 |
-
|
|
|
|
| 113 |
|
| 114 |
-
|
| 115 |
-
CoIR's ten tasks β codeβcode translation, multi-turn dialogue, long problem-statements β exceed the
|
| 116 |
-
128-token / retrieval scope and are not shown.
|
| 117 |
|
| 118 |
-
|
| 119 |
-
|---|--:|---|
|
| 120 |
-
| codesearchnet (6-lang avg) | **73.17** | docstring / NL β code |
|
| 121 |
-
| stackoverflow-qa | 62.70 | short question β code |
|
| 122 |
-
| synthetic-text2sql | 61.32 | NL β SQL |
|
| 123 |
-
| codesearchnet-ccr (6-lang avg) | **57.30** | code β related code |
|
| 124 |
-
| codefeedback-st | 56.38 | NL instruction β code |
|
| 125 |
-
| cosqa | 35.51 | NL question β code (noisy / hard) |
|
| 126 |
-
| **Average** | **57.73** | |
|
| 127 |
|
| 128 |
-
|
| 129 |
-
|
| 130 |
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
|
|
|
|
|
|
| 134 |
|
| 135 |
-
|
| 136 |
-
> (27Γ smaller) tuned for short-code retrieval.
|
| 137 |
|
| 138 |
-
##
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 139 |
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
|
| 144 |
-
| OpenVINO INT4 | Intel NPU (NPU4) | ~574 emb/s |
|
| 145 |
-
| OpenVINO INT8 | Intel CPU (Core Ultra) | ~375 emb/s |
|
| 146 |
-
| OpenVINO β **all 3 in parallel** | iGPU + NPU + CPU concurrently | ~1,290 emb/s |
|
| 147 |
|
| 148 |
-
|
| 149 |
-
CPU) embed different batches at the same time and the throughputs add up. This is **not** OpenVINO's
|
| 150 |
-
`AUTO` mode (which picks a single device per inference). Measured on a Core Ultra (Lunar Lake) laptop;
|
| 151 |
-
the TensorRT figure is on the bucketed batch path.
|
| 152 |
|
| 153 |
## License & training data
|
| 154 |
|
| 155 |
Released under the **MIT license**.
|
| 156 |
|
| 157 |
-
The
|
| 158 |
-
standard practice for distilled embedding models, the
|
| 159 |
-
|
| 160 |
|
| 161 |
-
|
|
| 162 |
|---|---|
|
| 163 |
-
|
|
| 164 |
-
|
|
| 165 |
-
|
|
| 166 |
-
| `sentence-transformers/gooaq` | Apache-2.0 |
|
| 167 |
-
| `jinaai/negation-dataset` | see source repo |
|
| 168 |
|
| 169 |
-
|
| 170 |
-
|
| 171 |
-
this is **not legal advice**. A data-clean variant can be retrained without the mMARCO splits if needed.
|
| 172 |
|
| 173 |
## Attribution
|
| 174 |
|
| 175 |
-
|
|
|
|
|
|
|
|
|
| 13 |
- knowledge-distillation
|
| 14 |
pipeline_tag: feature-extraction
|
| 15 |
base_model:
|
| 16 |
+
- intfloat/multilingual-e5-base
|
| 17 |
- Alibaba-NLP/gte-modernbert-base
|
| 18 |
+
- Qwen/Qwen3-Reranker-4B
|
| 19 |
datasets:
|
| 20 |
+
- CoIR-Retrieval/cosqa
|
| 21 |
+
- CoIR-Retrieval/codesearchnet
|
| 22 |
+
- CoIR-Retrieval/stackoverflow-qa
|
|
|
|
|
|
|
| 23 |
---
|
| 24 |
|
| 25 |
# code-daemon-embed-v1
|
| 26 |
|
| 27 |
+
A small, fast **code-embedding model** for semantic code search over **real codebases**. It maps short
|
| 28 |
+
code units β function and method bodies, signatures, docstrings β and short natural-language queries
|
| 29 |
+
into a shared **768-dim** vector space.
|
| 30 |
+
|
| 31 |
+
It is **specialized for real retrieval traffic, not benchmark prose**: the training queries mirror how
|
| 32 |
+
agents and developers actually search a repository (short keyword-bag and behavior queries), and the
|
| 33 |
+
maximum sequence is **128 tokens**, trading long-context capability for high throughput and strong
|
| 34 |
+
quality on short units.
|
| 35 |
+
|
| 36 |
+
- **768-dim** embeddings (full width; no MRL truncation in this release).
|
| 37 |
+
- **~75.7M params** β XLM-RoBERTa architecture initialized from `multilingual-e5-base` with
|
| 38 |
+
**strided 12β8 layer truncation** and the vocabulary **pruned 250k β 22,739** pieces
|
| 39 |
+
(English + code coverage kept; the transformer layers see identical tokenizations for EN/code text).
|
| 40 |
+
- **A built-in reranker** β see below: cross-encoder ranking knowledge is distilled *into* the
|
| 41 |
+
embedding space, so the top of the ranking behaves like a reranked list at bi-encoder cost.
|
| 42 |
- **Mean pooling fused into the graph** β the output is already pooled (`[batch, 768]`); just **L2-normalize**.
|
| 43 |
- Trained at sequence length **128** (length buckets s / m / l = seq **40 / 64 / 128**).
|
| 44 |
|
| 45 |
+
## The built-in reranker (why the top of the ranking is sharp)
|
| 46 |
+
|
| 47 |
+
Classic bi-encoders compress each document into a vector *before* seeing the query, so they cannot do
|
| 48 |
+
the fine-grained pairwise comparison a cross-encoder reranker does. This model closes part of that gap
|
| 49 |
+
at training time instead of inference time:
|
| 50 |
|
| 51 |
+
- Hard negatives were mined for every training query (documents a strong retriever ranks high but wrong).
|
| 52 |
+
- **`Qwen/Qwen3-Reranker-4B`** (a cross-encoder) scored every (query, candidate) pair with graded
|
| 53 |
+
relevance logits.
|
| 54 |
+
- The student was trained with a **listwise-KL objective** to reproduce the reranker's *ranking
|
| 55 |
+
distribution* β not just "positive above negatives", but *how much* each near-miss should trail.
|
| 56 |
|
| 57 |
+
The result: reranker-flavored top-rank precision with **zero inference overhead** β no second model, no
|
| 58 |
+
second pass, no extra latency. In the production system this model was built for, enabling an actual
|
| 59 |
+
runtime reranker on top of it measured as *net-negative*: the distillation had already captured the
|
| 60 |
+
useful part.
|
| 61 |
+
|
| 62 |
+
## Where it's good β and where it isn't
|
| 63 |
+
|
| 64 |
+
**Strong (the design target):**
|
| 65 |
+
- **Real repository search** β short NL/keyword queries by developers and coding agents over an
|
| 66 |
+
indexed codebase ("git watcher head change reindex", "acquire database lock for project hash").
|
| 67 |
+
- **Natural-language β code** at short lengths; identifier and mixed queries.
|
| 68 |
+
- Complementing a lexical (BM25-style) channel in a hybrid retriever β it was trained *for* that role.
|
| 69 |
|
| 70 |
**Weak / out of scope:**
|
| 71 |
+
- **Long documents** β hard 128-token cap; not a long-context retriever.
|
| 72 |
+
- **Benchmark-style long problem statements** (competitive-programming prompts, multi-turn dialogue,
|
| 73 |
+
codeβcode translation) β deliberately out of scope, see the evaluation note.
|
| 74 |
+
- **General English prose** (medical / financial / news) β the pruned vocab and code specialization
|
| 75 |
+
trade general-text quality away.
|
| 76 |
|
| 77 |
+
Embed **queries and documents the same way** β no instruction prefix.
|
|
|
|
| 78 |
|
| 79 |
## How it was made
|
| 80 |
|
| 81 |
+
Three-teacher pipeline on a pretrained backbone (the full recipe and every ablation is documented in
|
| 82 |
+
the source project):
|
| 83 |
+
|
| 84 |
+
1. **Backbone**: `intfloat/multilingual-e5-base` (12L XLM-R retriever), **strided-truncated to 8 layers**
|
| 85 |
+
(keep {0,1,3,5,7,9,10,11}) with the embedding table pruned and re-indexed to a 22,739-piece
|
| 86 |
+
SentencePiece vocabulary in a raw-SP convention (pad=0 / unk=1 / bos=2 / eos=3).
|
| 87 |
+
2. **Dense representation distillation** from
|
| 88 |
+
**[`Alibaba-NLP/gte-modernbert-base`](https://huggingface.co/Alibaba-NLP/gte-modernbert-base)**
|
| 89 |
+
(MSE to the teacher's embeddings) over real repository entities in a front-loaded serve format
|
| 90 |
+
(semantics before identifiers, within the 128-token budget).
|
| 91 |
+
3. **Listwise-KL ranking distillation** from
|
| 92 |
+
**[`Qwen/Qwen3-Reranker-4B`](https://huggingface.co/Qwen/Qwen3-Reranker-4B)** cross-encoder scores
|
| 93 |
+
over mined hard negatives (12 kept per query) β the "built-in reranker".
|
| 94 |
+
4. **Diversity regularization**: ~26% of the grouped stream is out-of-domain code-retrieval pairs
|
| 95 |
+
(CoIR-derived). Measured to be the sweet spot: 0% loses deep recall, 50% dilutes the top.
|
| 96 |
+
Counter-intuitively, the *dissimilarity* of these rows is the active ingredient.
|
| 97 |
+
|
| 98 |
+
Training queries were generated few-shot in the style of **real agent search traffic** (short
|
| 99 |
+
keyword-bags, behavior descriptions, identifier fragments) with identifier-leak gating β not docstring
|
| 100 |
+
paraphrases. This is the main reason benchmark numbers below *understate* real-repo performance.
|
| 101 |
|
| 102 |
## Built for speed
|
| 103 |
|
| 104 |
+
- **Short context by design** β max **128 tokens**; the engines avoid wide dynamic-shape ranges.
|
| 105 |
+
- **Rectangular TensorRT profiles** β each length bucket is a *fixed* shape (min == opt == max):
|
| 106 |
+
**s** = batch 64 Γ seq 40 Β· **m** = batch 128 Γ seq 64 Β· **l** = batch 256 Γ seq 128.
|
| 107 |
+
- **Mean-pool + L2-friendly head fused into the graph** (one pass β `[B, 768]`).
|
| 108 |
+
- FP32/FP16 engines in this release (INT8 PTQ measurably hurts this checkpoint's top-rank precision;
|
| 109 |
+
a QAT INT8 variant is planned).
|
| 110 |
|
| 111 |
## Usage (standalone ONNX)
|
| 112 |
|
|
|
|
| 119 |
sp = spm.SentencePieceProcessor(model_file="sentencepiece.bpe.model") # pad=0 unk=1 bos=2 eos=3
|
| 120 |
sess = ort.InferenceSession("model.onnx", providers=["CPUExecutionProvider"])
|
| 121 |
|
| 122 |
+
def embed(texts, max_len=128):
|
| 123 |
ids = [[2, *sp.encode(t)[: max_len - 2], 3] for t in texts] # bos β¦ eos
|
| 124 |
L = max(len(x) for x in ids)
|
| 125 |
inp = np.array([x + [0] * (L - len(x)) for x in ids], dtype=np.int64) # pad=0
|
| 126 |
mask = (inp != 0).astype(np.int64)
|
| 127 |
+
out = sess.run(None, {"input_ids": inp, "attention_mask": mask})[0] # already pooled [B,768]
|
|
|
|
| 128 |
return out / np.linalg.norm(out, axis=1, keepdims=True)
|
| 129 |
```
|
| 130 |
|
| 131 |
+
## What's in this repo
|
| 132 |
|
| 133 |
+
Named per **runtime Γ GPU arch Γ OS Γ length-bucket** (the filenames are a loading contract β do not rename):
|
|
|
|
| 134 |
|
| 135 |
+
- **TensorRT** `*.engine` β NVIDIA:
|
| 136 |
`code-daemon-embed-v1-{s,m,l}_{win_x64,linux_x64}_trt_sm_{86,89,120}.engine`
|
| 137 |
(sm_86 β RTX 30xx / A-series Β· sm_89 β RTX 40xx / L4 Β· sm_120 β RTX 50xx).
|
| 138 |
+
- **TVM** `*_tvm_vulkan.{dll,so}` β Vulkan fallback for non-TRT GPUs, per bucket.
|
| 139 |
- **OpenVINO** `*.xml` + `*.bin` β Intel **CPU / iGPU / NPU**, per bucket.
|
| 140 |
- **Metal** `*_tvm_metal.*` β Apple Silicon (macOS), per bucket.
|
| 141 |
+
- **Tokenizer** β `sentencepiece.bpe.model` (raw-SP: pad=0 / unk=1 / bos=2 / eos=3, byte-fallback) +
|
| 142 |
`tokenizer_config.json`.
|
| 143 |
+
- **ONNX source** β `model.onnx` (+ `model.onnx.data`) FP32.
|
| 144 |
|
| 145 |
+
> Compiled engines for this release are being rebuilt and uploaded progressively; the ONNX + tokenizer
|
| 146 |
+
> are the always-present source of truth.
|
| 147 |
|
| 148 |
+
## Evaluation
|
|
|
|
|
|
|
| 149 |
|
| 150 |
+
### Real-repository retrieval (the design target)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 151 |
|
| 152 |
+
On a benchmark of **real agent search queries over a live indexed codebase** (80 captured queries,
|
| 153 |
+
multi-positive, file-level), the production hybrid retriever built on this model reaches:
|
| 154 |
|
| 155 |
+
| metric | value |
|
| 156 |
+
|---|--:|
|
| 157 |
+
| hit@5 | **0.73** |
|
| 158 |
+
| hit@1 | 0.44 |
|
| 159 |
+
| pool_recall@64 | 0.79 |
|
| 160 |
|
| 161 |
+
This is the metric the model is optimized for β short real-world queries against a real repository.
|
|
|
|
| 162 |
|
| 163 |
+
### CoIR (NDCG@10, full corpora) β out-of-domain reference
|
| 164 |
+
|
| 165 |
+
CoIR queries are largely docstrings and long problem statements β a different style from real repo
|
| 166 |
+
search traffic β so treat these as an *out-of-domain lower bound*: **on real queries in real
|
| 167 |
+
repositories the model performs substantially better than its CoIR positioning suggests** (see above).
|
| 168 |
+
Four of CoIR's ten tasks β codeβcode translation, multi-turn dialogue, long problem-statements β
|
| 169 |
+
exceed the 128-token / retrieval scope and are not shown. (~2k CoIR-derived rows were present in
|
| 170 |
+
training as diversity regularization; overlap with test splits was not audited.)
|
| 171 |
+
|
| 172 |
+
| CoIR task | NDCG@10 | Pattern |
|
| 173 |
+
|---|--:|---|
|
| 174 |
+
| synthetic-text2sql | **62.59** | NL β SQL |
|
| 175 |
+
| stackoverflow-qa | 50.82 | short question β code |
|
| 176 |
+
| codefeedback-st | 47.42 | NL instruction β code |
|
| 177 |
+
| codesearchnet (6-lang avg) | 42.68 | docstring / NL β code |
|
| 178 |
+
| codesearchnet-ccr (6-lang avg) | 40.95 | code β related code |
|
| 179 |
+
| cosqa | 20.75 | NL question β code (noisy / hard) |
|
| 180 |
+
| **Average** | **44.20** | |
|
| 181 |
|
| 182 |
+
Per language β codesearchnet (NLβcode): python **66.80**, go 51.30, java 38.77, php 38.16, js 32.17, ruby 28.90.
|
| 183 |
+
Per language β codesearchnet-ccr (codeβcode): js **47.72**, ruby 45.28, java 42.05, python 38.43, php 36.60, go 35.64.
|
| 184 |
+
|
| 185 |
+
## Performance (embeddings / sec)
|
|
|
|
|
|
|
|
|
|
| 186 |
|
| 187 |
+
Being re-measured for this release's engines β table will be updated with the engine upload.
|
|
|
|
|
|
|
|
|
|
| 188 |
|
| 189 |
## License & training data
|
| 190 |
|
| 191 |
Released under the **MIT license**.
|
| 192 |
|
| 193 |
+
The backbone (`intfloat/multilingual-e5-base`) is MIT; the teachers (`gte-modernbert-base`,
|
| 194 |
+
`Qwen3-Reranker-4B`) are Apache-2.0. As is standard practice for distilled embedding models, the
|
| 195 |
+
**weights are released under MIT**. Training corpus, for transparency:
|
| 196 |
|
| 197 |
+
| Data | License note |
|
| 198 |
|---|---|
|
| 199 |
+
| Repository entity texts + synthetic search queries over an MIT-licensed codebase | MIT |
|
| 200 |
+
| CoIR-derived code-retrieval pairs (~26% diversity stream) | per-subset CoIR licenses (research benchmark) |
|
| 201 |
+
| Teacher embeddings / scores (gte-modernbert, Qwen3-Reranker-4B) | Apache-2.0 teachers |
|
|
|
|
|
|
|
| 202 |
|
| 203 |
+
Unlike the previous release, **no MS MARCO / mMARCO data** was used β the earlier non-commercial
|
| 204 |
+
caveat no longer applies. This is **not legal advice**.
|
|
|
|
| 205 |
|
| 206 |
## Attribution
|
| 207 |
|
| 208 |
+
Backbone: [intfloat/multilingual-e5-base](https://huggingface.co/intfloat/multilingual-e5-base) (MIT).
|
| 209 |
+
Dense teacher: [Alibaba-NLP/gte-modernbert-base](https://huggingface.co/Alibaba-NLP/gte-modernbert-base) (Apache-2.0).
|
| 210 |
+
Ranking teacher: [Qwen/Qwen3-Reranker-4B](https://huggingface.co/Qwen/Qwen3-Reranker-4B) (Apache-2.0).
|