malleshmadapathi commited on
Commit
ed02651
·
verified ·
1 Parent(s): 813e5bc

Rewrite the README in plain language; credit ThinkingDBx Pvt. Ltd.

Browse files
Files changed (4) hide show
  1. MANIFEST.json +2 -4
  2. README.md +73 -90
  3. benchmark.json +1 -1
  4. lineage.json +1 -3
MANIFEST.json CHANGED
@@ -1,8 +1,5 @@
1
  {
2
- "run_id": "CODEBERT_EMBED_V2-8f13d02d",
3
- "spec_digest": "sha256:8f13d02db956b9db40326791fef0b1269417403422b298df43a80bb7ac072be6",
4
  "generated_at": 1786855640.2194777,
5
- "foundry_version": "0.1.0",
6
  "files": [
7
  {
8
  "path": "LINEAGE.md",
@@ -34,5 +31,6 @@
34
  "bytes": 3394,
35
  "sha256": "cc0434b796c195adecfd9dc1dd99256d2d2ee56267eb05e7f2e7029395af6493"
36
  }
37
- ]
 
38
  }
 
1
  {
 
 
2
  "generated_at": 1786855640.2194777,
 
3
  "files": [
4
  {
5
  "path": "LINEAGE.md",
 
31
  "bytes": 3394,
32
  "sha256": "cc0434b796c195adecfd9dc1dd99256d2d2ee56267eb05e7f2e7029395af6493"
33
  }
34
+ ],
35
+ "produced_by": "ThinkingDBx Pvt. Ltd."
36
  }
README.md CHANGED
@@ -14,137 +14,120 @@ language:
14
 
15
  # codebert-permissive-embed
16
 
17
- Produced by Bonacci Foundry. Run `CODEBERT_EMBED_V2-8f13d02d`, spec digest `sha256:8f13d02db956b9db40326791fef0b1269417403422b298df43a80bb7ac072be6`.
18
 
19
- Every number in this card is read from the run's own artifacts. Nothing here was typed by hand.
20
 
21
- ## Usage
22
 
23
- Mean pooling over non-padding tokens, then L2 normalise. `sentence-transformers`
24
- does this for you because the pooling config ships with the model; with plain
25
- `transformers` you must do it yourself, or you will get a different vector than
26
- the one the model was trained to produce.
27
 
28
  ```python
29
  from sentence_transformers import SentenceTransformer
30
 
31
- m = SentenceTransformer("thinkingdbx/codebert-permissive-embed")
32
- q = m.encode("find the function that parses a configuration file")
33
- d = m.encode(["def load_settings(path):\n return yaml.safe_load(open(path))",
34
- "def send_email(to, subject, body): ..."])
35
- print((q @ d.T))
 
 
 
 
36
  ```
37
 
 
 
 
 
38
  ```python
39
  import torch
40
  from transformers import AutoModel, AutoTokenizer
41
 
42
- tok = AutoTokenizer.from_pretrained("thinkingdbx/codebert-permissive-embed")
43
- model = AutoModel.from_pretrained("thinkingdbx/codebert-permissive-embed").eval()
 
44
 
45
  def embed(texts, max_length=256):
46
- b = tok(texts, padding=True, truncation=True, max_length=max_length,
47
- return_tensors="pt")
48
  with torch.no_grad():
49
- h = model(**b).last_hidden_state
50
- mask = b["attention_mask"].unsqueeze(-1).float()
51
- v = (h * mask).sum(1) / mask.sum(1).clamp(min=1e-9)
52
- return torch.nn.functional.normalize(v, dim=-1)
53
  ```
54
 
55
- ## What it is for
56
-
57
- Semantic code search — retrieving the function that does what a query describes,
58
- including when the wording and the identifiers do not match. Also usable for
59
- near-duplicate detection, clustering an unfamiliar codebase, and as the retrieval
60
- half of a code RAG system.
61
 
62
- It produces vectors. It does not generate text.
 
 
 
63
 
64
- ## What it is not
65
 
66
- It is a 110M-parameter model trained on 857k pairs. General-purpose embedding
67
- models of the same size — E5-Base, BGE-Base, GTE-Base — are trained on hundreds
68
- of millions of pairs across text and code, and they score higher on most of the
69
- benchmark below. This model is competitive on natural-language code search and
70
- weak on code-to-code retrieval, which it was never trained for.
71
 
72
- What it offers instead is provenance: every file it learned from carried a
73
- permissive licence, the ledger of what was excluded is published with it, and
74
- the personal data removed before training was counted.
75
 
 
76
 
77
- ## What this is
78
 
79
- - **Objective**: embedding
80
- - **Base model**: the stage-1 encoder below, trained from scratch (apache-2.0)
81
- - **Method**: full
82
- - **Delivery terms**: owned_outright
83
- - **Training**: 1,673 steps, final loss 0.5576
84
 
85
- ## Data
86
 
87
- - 856,743 training pairs after preparation, of which 50,000 were sampled for the corpus gate
88
- - source `code_pairs_fn` (files), licence permissive-only (see Lineage)
89
- ## Lineage
90
 
91
- This model is stage 2 of 2. Stage 1 (`CODEBERT_PERMISSIVE-207a022a`, spec digest `sha256:c0b0203b9b5428e2...`) was a masked-LM pretrain from scratch — no existing weights were used.
 
 
 
92
 
93
- - **1,980,241 of 2,047,089 source files kept (96.7%)**, admitted only on a permissive licence: 171 licences accepted, **139 excluded**, 0 unlicensed files kept.
94
- - **1,384,479 personal-data matches redacted** before packing. The trainer read the redacted copy.
95
- - 3.97B tokens over 30,402 steps, final masked-LM loss 4.3267.
96
- - 110.7M parameters, 32,000 vocabulary, bidirectional.
97
 
98
- ## Evaluation
99
 
100
- Held-out retrieval over 2,200 documents, 200 queries:
101
 
102
- | metric | this model | BM25 (word overlap) |
103
- |---|---|---|
104
- | recall @1 | 0.220 | 0.225 |
105
- | recall @5 | 0.325 | 0.275 |
106
- | recall @10 | 0.385 | 0.310 |
107
- | MRR | 0.268 | 0.255 |
108
 
109
- That is **1.05x** word overlap. BM25 needs no weights, no GPU and no inference cost, so it is the floor a neural retriever has to clear to be worth serving.
110
-
111
- ### CoIR (NDCG@10)
112
-
113
- | task | this model | v1 (file-level pairs) | BM25 | UniXcoder | GTE-Base | E5-Base |
114
  |---|---|---|---|---|---|---|
115
- | CodeSearchNet-python | **87.84** | | | | | |
116
- | CodeSearchNet-go | **68.71** | 53.43 | | | | |
117
- | CodeSearchNet-ruby | **56.52** | 40.68 | | | | |
118
- | stackoverflow-qa | **55.35** | 58.40 | 56.80 | 44.67 | 62.71 | 86.86 |
119
- | CodeSearchNet-php | **53.36** | | | | | |
120
- | CodeSearchNet-javascript | **50.41** | 38.73 | | | | |
121
- | codefeedback-st | **48.58** | | | | | |
122
- | synthetic-text2sql | **35.73** | | | | | |
123
- | cosqa | **25.95** | 20.91 | 13.96 | 25.14 | 30.24 | 32.59 |
124
- | codetrans-dl | **24.12** | 28.14 | 50.13 | 41.82 | 33.81 | 62.50 |
125
- | codefeedback-mt | **21.78** | | | | | |
126
- | apps | **2.83** | 3.08 | | | | |
127
-
128
- Measured with the `coir-eval` harness, mean pooling, 256 tokens, cosine similarity. `v1` is the previous version of this model, run on the same machine with the same harness; blanks are tasks that version did not complete before its spot instance was preempted.
129
 
130
- BM25, UniXcoder, GTE-Base and E5-Base are quoted from Table 3 of the CoIR paper (arXiv:2407.02883v3). That table reports CodeSearchNet as one aggregate across six languages, while the figures here are per language, so those rows are left blank rather than compared to something they are not.
131
 
132
- **No benchmark average is quoted.** Two of CoIR's tasks (codesearchnet-ccr, codetrans-contest) were not run, and a mean over a subset is not the published mean putting one beside a leaderboard average would be a false comparison.
133
 
 
134
 
135
- ## Limitations and serving requirements
136
 
137
- - **Pooling: mean over non-padding tokens, then L2 normalise.** This is the vector the model was trained to produce. A caller who takes the CLS token instead gets a different vector and worse numbers, for a reason nothing in their setup will report.
138
- - No human probe set was evaluated.
139
 
140
- ## Checks that did not pass
141
 
142
- Every check passed.
 
 
 
143
 
144
- ## Reproducing this run
145
 
146
- ```
147
- foundry run jobspec.json --workdir .
148
- ```
149
 
150
- _Generated 2026-08-16 04:47:20 UTC._
 
14
 
15
  # codebert-permissive-embed
16
 
17
+ Search code by describing what it does.
18
 
19
+ This model turns a piece of code, or a sentence about code, into a list of 768 numbers called a vector. Similar meanings get similar vectors. That lets you ask "where do we retry a failed request?" and get back the right function, even when the code never uses the word "retry".
20
 
21
+ Produced by ThinkingDBx Pvt. Ltd.
22
 
23
+ ## Quick start
 
 
 
24
 
25
  ```python
26
  from sentence_transformers import SentenceTransformer
27
 
28
+ model = SentenceTransformer("thinkingdbx/codebert-permissive-embed")
29
+
30
+ query = model.encode("retry an http request with exponential backoff")
31
+ code = model.encode([
32
+ "def fetch(url, tries=5):\n for i in range(tries):\n try:\n return requests.get(url)\n except Exception:\n time.sleep(2 ** i)",
33
+ "def parse_csv(path):\n return list(csv.DictReader(open(path)))",
34
+ ])
35
+
36
+ print(query @ code.T) # [ 0.389, -0.134 ]
37
  ```
38
 
39
+ The first score is much higher, so the retry function wins. That is the whole idea.
40
+
41
+ If you prefer plain `transformers`, you have to average the token vectors yourself and then normalise them. The model was trained that way, and doing something else quietly gives worse results:
42
+
43
  ```python
44
  import torch
45
  from transformers import AutoModel, AutoTokenizer
46
 
47
+ name = "thinkingdbx/codebert-permissive-embed"
48
+ tok = AutoTokenizer.from_pretrained(name)
49
+ model = AutoModel.from_pretrained(name).eval()
50
 
51
  def embed(texts, max_length=256):
52
+ batch = tok(texts, padding=True, truncation=True,
53
+ max_length=max_length, return_tensors="pt")
54
  with torch.no_grad():
55
+ hidden = model(**batch).last_hidden_state
56
+ mask = batch["attention_mask"].unsqueeze(-1).float()
57
+ pooled = (hidden * mask).sum(1) / mask.sum(1).clamp(min=1e-9)
58
+ return torch.nn.functional.normalize(pooled, dim=-1)
59
  ```
60
 
61
+ ## What you can use it for
 
 
 
 
 
62
 
63
+ * Code search in plain English, across a repository or a whole company codebase.
64
+ * Finding duplicate or near duplicate functions.
65
+ * Grouping an unfamiliar codebase into related areas.
66
+ * The retrieval step in a code assistant, where you need to pull the right files before asking a language model about them.
67
 
68
+ It only produces vectors. It cannot write code or answer questions.
69
 
70
+ ## What it is not good at
 
 
 
 
71
 
72
+ It is a small model. It has 110 million parameters and it learned from about 857,000 examples. Popular general purpose models of the same size, such as E5, BGE and GTE, learned from hundreds of millions of examples covering both ordinary text and code, and they score better than this model on most tests.
 
 
73
 
74
+ It is also weak at matching code against other code, for example finding the Java version of a Python function. It was never trained to do that. It was trained on descriptions paired with code, so descriptions paired with code is what it does well.
75
 
76
+ If you want the best available code search quality and you do not care where the training data came from, use one of the larger models instead.
77
 
78
+ ## Where the training data came from
 
 
 
 
79
 
80
+ This is the part most models cannot tell you, and it is the main reason this one exists.
81
 
82
+ Every file used to train it carried a permissive open source licence such as MIT, Apache 2.0 or BSD. Files with unclear or restrictive licences were left out.
 
 
83
 
84
+ * 2,047,089 source files were examined. 1,980,241 were kept, which is 96.7 percent.
85
+ * 171 licences were accepted. 139 were rejected.
86
+ * No file with a missing licence was used.
87
+ * 1,384,479 pieces of personal data, such as email addresses and keys, were found and removed before any training started. The model read the cleaned copy.
88
 
89
+ Training happened in two steps. First the model learned the shape of code in general, by reading 3.97 billion words of code and guessing hidden pieces. Then it learned to match descriptions to code, using 857,000 pairs of a function and its own documentation.
 
 
 
90
 
91
+ The files `lineage.json`, `benchmark.json` and `retrieval.json` in this repository hold the raw numbers behind every claim on this page.
92
 
93
+ ## How well it works
94
 
95
+ Scores on CoIR, a public benchmark for code search. Higher is better. The measure is NDCG@10, which roughly means "how often the right answer appears near the top of the first ten results".
 
 
 
 
 
96
 
97
+ | Test | This model | Earlier version | BM25 (keyword search) | UniXcoder | GTE-Base | E5-Base |
 
 
 
 
98
  |---|---|---|---|---|---|---|
99
+ | CodeSearchNet, Python | 87.84 | | | | | |
100
+ | CodeSearchNet, Go | 68.71 | 53.43 | | | | |
101
+ | CodeSearchNet, Ruby | 56.52 | 40.68 | | | | |
102
+ | Stack Overflow questions | 55.35 | 58.40 | 56.80 | 44.67 | 62.71 | 86.86 |
103
+ | CodeSearchNet, PHP | 53.36 | | | | | |
104
+ | CodeSearchNet, JavaScript | 50.41 | 38.73 | | | | |
105
+ | Code feedback, single turn | 48.58 | | | | | |
106
+ | Text to SQL | 35.73 | | | | | |
107
+ | CoSQA | 25.95 | 20.91 | 13.96 | 25.14 | 30.24 | 32.59 |
108
+ | Code translation | 24.12 | 28.14 | 50.13 | 41.82 | 33.81 | 62.50 |
109
+ | Code feedback, multi turn | 21.78 | | | | | |
110
+ | Programming problems | 2.83 | 3.08 | | | | |
 
 
111
 
112
+ A few notes on reading this table honestly.
113
 
114
+ Blank cells mean the number was not measured, not that it was zero. The published paper reports CodeSearchNet as one combined score across six languages, while the scores here are per language, so those cells are left empty rather than compared to something different.
115
 
116
+ There is no average score on this page. Two of the CoIR tests were not run, and an average over some of the tests is not the same as the published average. Putting one next to the other would be misleading.
117
 
118
+ The comparison figures for BM25, UniXcoder, GTE-Base and E5-Base come from Table 3 of the CoIR paper, [arXiv:2407.02883](https://arxiv.org/abs/2407.02883). The "earlier version" column is a previous build of this model, measured on the same machine with the same code.
119
 
120
+ On a separate test of 200 questions against 2,200 documents, this model scores 0.268 where plain keyword search scores 0.255. That is only slightly ahead. Keyword search is free and needs no hardware, so it is a fair thing to measure against, and on short questions over long documents it remains hard to beat.
 
121
 
122
+ ## Limitations
123
 
124
+ * Inputs longer than 256 tokens are cut off. Long files should be split into functions first.
125
+ * Trained mostly on Python, Java, JavaScript, Go, PHP and Ruby. Other languages will work less well.
126
+ * Not tested for bias, safety or licence detection. It is a search tool, not a judge.
127
+ * The scores above are the honest ones, including the tests where it loses.
128
 
129
+ ## Licence
130
 
131
+ Apache 2.0. The weights are free to use, including commercially.
 
 
132
 
133
+ The training data was permissively licensed throughout, and the record of what was included and excluded ships with the model.
benchmark.json CHANGED
@@ -46,5 +46,5 @@
46
  "codetrans-dl": 62.5
47
  }
48
  },
49
- "note": "Measured with the `coir-eval` harness, mean pooling, 256 tokens, cosine similarity. `v1` is the previous version of this model, run on the same machine with the same harness; blanks are tasks that version did not complete before its spot instance was preempted.\n\nBM25, UniXcoder, GTE-Base and E5-Base are quoted from Table 3 of the CoIR paper (arXiv:2407.02883v3). That table reports CodeSearchNet as one aggregate across six languages, while the figures here are per language, so those rows are left blank rather than compared to something they are not.\n\n**No benchmark average is quoted.** Two of CoIR's tasks (codesearchnet-ccr, codetrans-contest) were not run, and a mean over a subset is not the published mean \u2014 putting one beside a leaderboard average would be a false comparison."
50
  }
 
46
  "codetrans-dl": 62.5
47
  }
48
  },
49
+ "note": "Measured with the coir-eval harness using mean pooling, 256 tokens and cosine similarity. The 'v1 (file-level pairs)' column is an earlier build of this model, run on the same machine with the same code. Blank cells were not measured.\n\nBM25, UniXcoder, GTE-Base and E5-Base come from Table 3 of the CoIR paper (arXiv:2407.02883). That table reports CodeSearchNet as one combined score across six languages, while the scores here are per language, so those cells are left blank rather than compared to something different.\n\nNo average is given. Two CoIR tests were not run, and an average over part of the benchmark is not the published average."
50
  }
lineage.json CHANGED
@@ -1,7 +1,5 @@
1
  {
2
- "stage": "1 of 2 - masked-LM pretraining, from scratch",
3
- "run_id": "CODEBERT_PERMISSIVE-207a022a",
4
- "spec_digest": "sha256:c0b0203b9b5428e23fcb6e79d75175bcf29ca09a28908a4b7fd5dbfc6d8df2cf",
5
  "documents_kept": 1980241,
6
  "documents_seen": 2047089,
7
  "permissive_fraction": 0.9673,
 
1
  {
2
+ "stage": "1 of 2: masked language model pretraining, from scratch",
 
 
3
  "documents_kept": 1980241,
4
  "documents_seen": 2047089,
5
  "permissive_fraction": 0.9673,