RowletQwQ commited on
Commit
cfb6957
·
verified ·
1 Parent(s): 3cda059

JevCodeLocator-0.6B

Browse files
.gitattributes CHANGED
@@ -1,35 +1,2 @@
1
- *.7z filter=lfs diff=lfs merge=lfs -text
2
- *.arrow filter=lfs diff=lfs merge=lfs -text
3
- *.bin filter=lfs diff=lfs merge=lfs -text
4
- *.bz2 filter=lfs diff=lfs merge=lfs -text
5
- *.ckpt filter=lfs diff=lfs merge=lfs -text
6
- *.ftz filter=lfs diff=lfs merge=lfs -text
7
- *.gz filter=lfs diff=lfs merge=lfs -text
8
- *.h5 filter=lfs diff=lfs merge=lfs -text
9
- *.joblib filter=lfs diff=lfs merge=lfs -text
10
- *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
- *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
- *.model filter=lfs diff=lfs merge=lfs -text
13
- *.msgpack filter=lfs diff=lfs merge=lfs -text
14
- *.npy filter=lfs diff=lfs merge=lfs -text
15
- *.npz filter=lfs diff=lfs merge=lfs -text
16
- *.onnx filter=lfs diff=lfs merge=lfs -text
17
- *.ot filter=lfs diff=lfs merge=lfs -text
18
- *.parquet filter=lfs diff=lfs merge=lfs -text
19
- *.pb filter=lfs diff=lfs merge=lfs -text
20
- *.pickle filter=lfs diff=lfs merge=lfs -text
21
- *.pkl filter=lfs diff=lfs merge=lfs -text
22
- *.pt filter=lfs diff=lfs merge=lfs -text
23
- *.pth filter=lfs diff=lfs merge=lfs -text
24
- *.rar filter=lfs diff=lfs merge=lfs -text
25
  *.safetensors filter=lfs diff=lfs merge=lfs -text
26
- saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
- *.tar.* filter=lfs diff=lfs merge=lfs -text
28
- *.tar filter=lfs diff=lfs merge=lfs -text
29
- *.tflite filter=lfs diff=lfs merge=lfs -text
30
- *.tgz filter=lfs diff=lfs merge=lfs -text
31
- *.wasm filter=lfs diff=lfs merge=lfs -text
32
- *.xz filter=lfs diff=lfs merge=lfs -text
33
- *.zip 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
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  *.safetensors filter=lfs diff=lfs merge=lfs -text
2
+ tokenizer/tokenizer.json filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ __pycache__/
2
+ *.pyc
LICENSE ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright 2025 OpenAI
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
NOTICE ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ JevCodeLocator-0.6B
2
+ Copyright 2026 the JevCodeLocator authors
3
+
4
+ This product includes model weights derived from:
5
+
6
+ Qwen/Qwen3-0.6B
7
+ Copyright 2025 Alibaba Cloud
8
+ Licensed under the Apache License, Version 2.0
9
+ https://huggingface.co/Qwen/Qwen3-0.6B
10
+
11
+ The inference code in this repository (modeling_jev.py, inference_example.py,
12
+ patch_tokenizer_for_transformers4.py) is original work, licensed under the
13
+ Apache License, Version 2.0.
14
+
15
+ Training data was produced programmatically (tree-sitter chunking, doc-comment /
16
+ symbol / constant query generation, compact candidate summaries) from
17
+ open-source repositories. See the section "Training data and licensing" in
18
+ README.md for the repository list and their licenses. No source file from those
19
+ repositories is redistributed here.
README.md CHANGED
@@ -1,3 +1,177 @@
1
  ---
 
 
 
 
2
  license: apache-2.0
 
 
 
 
 
 
 
 
 
3
  ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ language:
3
+ - en
4
+ - zh
5
+ library_name: pytorch
6
  license: apache-2.0
7
+ base_model: Qwen/Qwen3-0.6B
8
+ tags:
9
+ - code-localization
10
+ - code-search
11
+ - code-retrieval
12
+ - reranker
13
+ - qwen3
14
+ - set-attention
15
+ pipeline_tag: text-ranking
16
  ---
17
+
18
+ # JevCodeLocator-0.6B
19
+
20
+ A 0.6B **code localizer**. Given a repository and a natural-language query (an issue, a symptom, a
21
+ symbol, an error message, or a described behavior), it reranks candidate code locations and returns a
22
+ ranked list of `path:start-end` chunks together with a file-level ranking.
23
+
24
+ The model is a **reranker**, not a retriever: a cheap sparse retriever (BM25 plus symbol/path channels)
25
+ produces a shortlist of K candidates and the model scores all of them in a single forward pass. There
26
+ are no embeddings and no vector index. On an entry-level 6 GB GPU it runs in roughly 0.4 s at K=8 and
27
+ 0.9 s at K=16, which makes it usable as a local first-stage localizer for coding agents.
28
+
29
+ ## Architecture
30
+
31
+ ```
32
+ state (task / repo / candidate_count / query) + candidate texts ("path:start-end: summary")
33
+ │
34
+ ├─ one leaf-token path per candidate ──► Qwen3-0.6B backbone
35
+ │ (last hidden state at the EOS of each path)
36
+ ├─ LayerNorm → Linear(d, 1) per-candidate logit z_i
37
+ └─ set-attention over the K candidates:
38
+ u = Linear(d + 1, 128)([h_i ; log K])
39
+ mixed = MultiheadAttention(u, u, u) (key-padding mask for empty slots)
40
+ z_i += Linear(128, 1)(tanh(u + mixed))
41
+ │
42
+ └─ softmax over the K candidates
43
+ ```
44
+
45
+ The scalar head alone can rank candidates independently; the zero-initialized set-attention
46
+ correction is what makes a candidate's score depend on the **whole shortlist** (for example,
47
+ suppressing a cluster of look-alike test files in favour of the implementation file).
48
+
49
+ ## Training
50
+
51
+ Three consecutive fine-tuning stages on top of `Qwen/Qwen3-0.6B`:
52
+
53
+ | stage | training data | steps | notes |
54
+ |---|---|---:|---|
55
+ | 1 | Python programmatic queries, K≤16, file-level auxiliary loss λ=0.30 | 600 | base localizer |
56
+ | 2 | + Go / TypeScript-JavaScript / C++ / Rust / C# / PHP programmatic queries; 12,274 rows, K=16 BM25 pools with the gold candidate forced in | 600 | doc-comment queries oversampled 2×, backbone LR 1e-5 |
57
+ | 3 | continuation of stage 2 on 18,688 rows | 600 | final checkpoint |
58
+
59
+ - Objective: cross-entropy against the gold candidate (`gold_distribution`) plus the file-level
60
+ auxiliary loss (weight 0.30).
61
+ - Candidate text is identical at training and serving time: a compact summary consisting of the path,
62
+ the signature and the first lines of the chunk.
63
+ - A Python replay set (2,286 rows) is kept in every round so that Python behaviour does not regress.
64
+ - Training queries are generated programmatically from doc comments, symbol names and constants.
65
+ No human-written query set was used for training.
66
+
67
+ ## Evaluation
68
+
69
+ Frozen held-out pools: 200 queries per repository, K=8, gold candidate forced into the pool.
70
+ `file@1` is the share of queries whose gold **file** is ranked first. The baseline is the same model
71
+ before the multilingual stages (stage 1 only).
72
+
73
+ | evaluation set | language | baseline | **this model** |
74
+ |---|---|---:|---:|
75
+ | service repository, ~1.3k files | Go | 0.700 | **0.945** |
76
+ | ML framework core, ~2k chunks | C++ | 0.730 | **0.870** |
77
+ | agent CLI, ~20k chunks | Rust | 0.900 | 0.925 |
78
+ | API service, ~5k chunks | TypeScript | 0.795 | 0.855 |
79
+ | language server, ~600 chunks | C++ | 0.974 | 0.989 |
80
+ | held-out dev set, 460 queries | Python | 0.839 | 0.843 |
81
+
82
+ Restricted to semantic (doc-comment) queries, `file@1`: Go 0.524 → **0.913**, C++ 0.629 → 0.814,
83
+ TypeScript 0.667 → 0.758, Rust 0.833 → 0.875.
84
+
85
+ On a set of five hand-checked, real reverse-proxy questions about a large Go service (K=16, FP32):
86
+ **gold-file recall@1 = 1.000, recall@3 = 1.000, recall@5 = 1.000.** Latency on an entry-level 6 GB
87
+ GPU: 0.40–0.44 s (K=8), ~0.83 s (K=16).
88
+
89
+ ## Usage
90
+
91
+ ```bash
92
+ pip install torch transformers safetensors
93
+ python inference_example.py # runs on this directory
94
+ ```
95
+
96
+ ```python
97
+ import torch
98
+
99
+ from modeling_jev import load_jev_model, score_candidates
100
+
101
+ model, tok = load_jev_model(".", device="cuda" if torch.cuda.is_available() else "cpu",
102
+ dtype=torch.float32)
103
+
104
+ candidates = {
105
+ "src/auth/session.py:41-88": "def create_session(user, password) | validates credentials ...",
106
+ "src/db/pool.py:12-60": "def connect(dsn, max_size) | opens the database pool ...",
107
+ }
108
+
109
+ for key, prob in score_candidates(model, tok, "where are credentials validated?", candidates):
110
+ print(f"{prob:.4f} {key}")
111
+ ```
112
+
113
+ `score_candidates` returns the candidates ranked by probability. Summing the probabilities of all
114
+ candidates that belong to the same file gives the file-level ranking.
115
+
116
+ ## Files
117
+
118
+ | file | contents |
119
+ |---|---|
120
+ | `model.safetensors` | full model: 322 tensors (`backbone.*` plus the decision head); sha256 `fb06ba6ac6d30c395912ebd156723a0739afdd260f9b44f85c56b074c68b8a98` |
121
+ | `config.json` | model configuration (`architectures: JevDecisionModel`) and training hyperparameters |
122
+ | `backbone_config/config.json` | Qwen3-0.6B backbone configuration |
123
+ | `tokenizer/` | tokenizer files (`tokenizer_config.json` is in the `transformers>=5` format) |
124
+ | `head.safetensors` | the 12 decision-head tensors only (803 KB), for custom runtimes |
125
+ | `modeling_jev.py` | self-contained model class, loader and scoring helper |
126
+ | `inference_example.py` | runnable reranking example |
127
+ | `patch_tokenizer_for_transformers4.py` | converts `tokenizer_config.json` to the 4.x format |
128
+ | `LICENSE`, `NOTICE` | Apache-2.0 and attribution |
129
+
130
+ ## Intended use and limitations
131
+
132
+ - **Use it as a reranker.** It selects among the candidates it is given; if the retriever's shortlist
133
+ does not contain the gold file, the model cannot recover it. Pool recall is the ceiling.
134
+ - Trained on programmatically generated queries (doc comments, symbols, constants) with a small amount
135
+ of issue-style data mixed in. Free-form questions work but are the hardest distribution.
136
+ - Language coverage: Python, Go, TypeScript/JavaScript, C, C++, Rust, C#, PHP, Java, Ruby, Bash. The
137
+ chunker used to build candidates is tree-sitter based; other languages are untested.
138
+ - Candidate text is a compact summary, so very long functions are effectively truncated.
139
+ - Not instruction-tuned, not a chat model, no safety tuning. Do not use it to make decisions about
140
+ code it cannot see.
141
+
142
+ ## Training data and licensing
143
+
144
+ The weights in this repository are released under **Apache-2.0**, the same license as the base model
145
+ [Qwen/Qwen3-0.6B](https://huggingface.co/Qwen/Qwen3-0.6B) (Apache-2.0, Copyright 2025 Alibaba Cloud).
146
+ The inference code here (`modeling_jev.py`, `inference_example.py`,
147
+ `patch_tokenizer_for_transformers4.py`) is original work under the same license; see `LICENSE` and
148
+ `NOTICE`.
149
+
150
+ Training rows are generated programmatically: a tree-sitter chunker extracts code locations, queries
151
+ are derived from doc comments, symbol names and constants, and the candidate text is a compact summary
152
+ of the chunk. **No source file from any repository is redistributed in this repository.**
153
+
154
+ Licenses of the source repositories used for training and evaluation data:
155
+
156
+ | license | sources |
157
+ |---|---|
158
+ | MIT | 6 repositories (Go / TypeScript / Python tooling) |
159
+ | Apache-2.0 | 3 repositories (C++ / Go / Rust) |
160
+ | GPL-3.0 | 2 repositories |
161
+ | LGPL-3.0 | 2 repositories |
162
+ | AGPL-3.0 | 1 repository |
163
+ | non-commercial custom license | 1 repository |
164
+ | license not declared in the checkout used | 6 repositories |
165
+
166
+ A detailed list of the source repositories is available on request.
167
+
168
+ Notes:
169
+
170
+ - The weights are not a redistribution of those repositories, and the model does not reproduce training
171
+ code verbatim: it only scores candidate locations supplied by the caller. Whether copyleft-licensed
172
+ training data extends to model weights is legally unsettled in most jurisdictions.
173
+ - **Commercial use**: the training mix includes one AGPL-3.0 project and one non-commercial project. For
174
+ a commercially clean release, retrain without those two (and preferably without the GPL/LGPL
175
+ projects); the data pipeline is deterministic and reproducible.
176
+ - You remain responsible for complying with the licenses of the code you run the model on.
177
+ - This section is provenance information, not legal advice.
backbone_config/config.json ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "Qwen3ForCausalLM"
4
+ ],
5
+ "attention_bias": false,
6
+ "attention_dropout": 0.0,
7
+ "bos_token_id": 151643,
8
+ "dtype": "float32",
9
+ "eos_token_id": 151645,
10
+ "head_dim": 128,
11
+ "hidden_act": "silu",
12
+ "hidden_size": 1024,
13
+ "initializer_range": 0.02,
14
+ "intermediate_size": 3072,
15
+ "layer_types": [
16
+ "full_attention",
17
+ "full_attention",
18
+ "full_attention",
19
+ "full_attention",
20
+ "full_attention",
21
+ "full_attention",
22
+ "full_attention",
23
+ "full_attention",
24
+ "full_attention",
25
+ "full_attention",
26
+ "full_attention",
27
+ "full_attention",
28
+ "full_attention",
29
+ "full_attention",
30
+ "full_attention",
31
+ "full_attention",
32
+ "full_attention",
33
+ "full_attention",
34
+ "full_attention",
35
+ "full_attention",
36
+ "full_attention",
37
+ "full_attention",
38
+ "full_attention",
39
+ "full_attention",
40
+ "full_attention",
41
+ "full_attention",
42
+ "full_attention",
43
+ "full_attention"
44
+ ],
45
+ "max_position_embeddings": 40960,
46
+ "max_window_layers": 28,
47
+ "model_type": "qwen3",
48
+ "num_attention_heads": 16,
49
+ "num_hidden_layers": 28,
50
+ "num_key_value_heads": 8,
51
+ "pad_token_id": null,
52
+ "rms_norm_eps": 1e-06,
53
+ "rope_parameters": {
54
+ "rope_theta": 1000000,
55
+ "rope_type": "default"
56
+ },
57
+ "sliding_window": null,
58
+ "tie_word_embeddings": true,
59
+ "transformers_version": "5.17.0",
60
+ "use_cache": false,
61
+ "use_sliding_window": false,
62
+ "vocab_size": 151936
63
+ }
config.json ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "JevDecisionModel"
4
+ ],
5
+ "model_type": "jev-decision",
6
+ "base_model": "Qwen/Qwen3-0.6B",
7
+ "backbone_model_type": "qwen3",
8
+ "backbone_config_path": "backbone_config",
9
+ "head_weights": "head.safetensors",
10
+ "set_head": "attention",
11
+ "task": "closed-set choice over candidate code locations (path:start-end)",
12
+ "candidate_input": "state (task/repo/candidate_count/query) + per-candidate summary text",
13
+ "languages": [
14
+ "python",
15
+ "go",
16
+ "typescript",
17
+ "javascript",
18
+ "c",
19
+ "cpp",
20
+ "rust",
21
+ "csharp",
22
+ "php",
23
+ "java",
24
+ "ruby",
25
+ "bash"
26
+ ],
27
+ "max_length": 2048,
28
+ "parameter_count": 596250498,
29
+ "parameter_storage": "float32",
30
+ "forward_autocast": "bfloat16",
31
+ "objective": "gold_distribution",
32
+ "file_loss_weight": 0.3,
33
+ "file_target_mode": "primary",
34
+ "loss": "ce",
35
+ "steps": 600,
36
+ "batch_questions": 32,
37
+ "microbatch_questions": 4,
38
+ "max_microbatch_tokens": 32768,
39
+ "backbone_lr": 3e-06,
40
+ "head_lr": 5e-05,
41
+ "lr_warmup_frac": 0.05,
42
+ "lr_min_frac": 0.1,
43
+ "precision": "bf16",
44
+ "gradient_checkpointing": true,
45
+ "train_questions": 18688,
46
+ "seed": 41,
47
+ "set_head_hidden": 128,
48
+ "set_head_heads": 4,
49
+ "num_parameters": 596250498
50
+ }
head.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1376fbe5f045eebb1f30a2d7542b4247ae9bcfab2726c324d73ff5b6bebcbfa2
3
+ size 803304
inference_example.py ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Minimal end-to-end example for JevCodeLocator-0.6B.
2
+
3
+ python inference_example.py
4
+
5
+ Shows the intended serving pattern: a cheap retriever (BM25 / symbol search)
6
+ produces a shortlist of `path:start-end` candidates, and this model reranks them
7
+ with one forward pass.
8
+ """
9
+ from __future__ import annotations
10
+
11
+ import sys
12
+ from pathlib import Path
13
+
14
+ import torch
15
+
16
+ from modeling_jev import load_jev_model, score_candidates
17
+
18
+ # Directory containing model.safetensors + config.json (default: this folder).
19
+ CHECKPOINT = sys.argv[1] if len(sys.argv) > 1 else str(Path(__file__).resolve().parent)
20
+
21
+ # A shortlist as a retriever would produce it: key = path:start-end, value = compact summary.
22
+ CANDIDATES = {
23
+ "src/auth/session.py:41-88": "def create_session(user, password) | validates credentials against the user store and returns a signed session token",
24
+ "src/db/pool.py:12-60": "def connect(dsn, max_size) | opens and configures the database connection pool",
25
+ "src/api/routes/login.py:18-35": "def login_handler(request) | parses the JSON body and calls create_session, mapping failures to HTTP 401",
26
+ "src/auth/tokens.py:7-29": "def sign(payload, key) | HMAC-signs a payload with the application secret",
27
+ "docs/auth.md:1-40": "Authentication overview and deployment notes",
28
+ }
29
+
30
+ QUERY = "where are user credentials validated before a session token is created?"
31
+
32
+
33
+ def main() -> None:
34
+ device = "cuda" if torch.cuda.is_available() else "cpu"
35
+ model, tokenizer = load_jev_model(CHECKPOINT, device=device, dtype=torch.float32)
36
+ ranked = score_candidates(model, tokenizer, QUERY, CANDIDATES, repo="example", max_length=2048)
37
+ print(f"query: {QUERY}\n")
38
+ for rank, (key, prob) in enumerate(ranked, 1):
39
+ print(f"{rank}. {prob:.4f} {key}")
40
+
41
+ # File-level aggregation: sum the probabilities of all candidates in one file.
42
+ files: dict[str, float] = {}
43
+ for key, prob in ranked:
44
+ files[key.rsplit(":", 1)[0]] = files.get(key.rsplit(":", 1)[0], 0.0) + prob
45
+ print("\nfile ranking:")
46
+ for path, score in sorted(files.items(), key=lambda kv: -kv[1]):
47
+ print(f" {score:.4f} {path}")
48
+
49
+
50
+ if __name__ == "__main__":
51
+ main()
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:fb06ba6ac6d30c395912ebd156723a0739afdd260f9b44f85c56b074c68b8a98
3
+ size 2385039280
modeling_jev.py ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Self-contained inference code for JevCodeLocator-0.6B.
2
+
3
+ The model is a Qwen3-0.6B backbone followed by a small set-attention head that
4
+ scores a *set* of candidate code locations (``path:start-end``) against a query:
5
+
6
+ backbone(last hidden state at EOS of each candidate path)
7
+ -> LayerNorm -> scalar head (per-candidate logit)
8
+ -> set-attention over the K candidates (context-dependent correction)
9
+
10
+ One forward pass scores every candidate at once; no embeddings or vector index
11
+ are involved. Candidate text is the compact summary produced by the data
12
+ pipeline (``path | signature + first lines``).
13
+
14
+ Example
15
+ -------
16
+ >>> from modeling_jev import load_jev_model, score_candidates
17
+ >>> model, tok = load_jev_model("JevCodeLocator-0.6B", device="cuda")
18
+ >>> cands = {
19
+ ... "src/auth.py:10-42": "def login(user, pwd) | validates credentials and returns a session token",
20
+ ... "src/db.py:5-30": "def connect(dsn) | opens a database connection pool",
21
+ ... }
22
+ >>> for key, prob in score_candidates(model, tok, "where are credentials validated?", cands):
23
+ ... print(f"{prob:.4f} {key}")
24
+ """
25
+ from __future__ import annotations
26
+
27
+ import json
28
+ from pathlib import Path
29
+ from typing import Dict, List, Sequence, Tuple
30
+
31
+ import torch
32
+ import torch.nn.functional as F
33
+ from torch import nn
34
+
35
+ INSTRUCTIONS = ("Select the single code location (file path and line range) that best answers the query. "
36
+ "Each option is a candidate location; its text includes a compact signature/code summary. "
37
+ "Only use the state and the option texts.")
38
+
39
+
40
+ class JevDecisionModel(nn.Module):
41
+ """Qwen3 backbone + LayerNorm/scalar head + set-attention over candidates."""
42
+
43
+ def __init__(self, backbone: nn.Module, set_head: str = "attention") -> None:
44
+ super().__init__()
45
+ self.backbone = backbone
46
+ hidden = backbone.config.hidden_size
47
+ self.norm = nn.LayerNorm(hidden)
48
+ self.scalar = nn.Linear(hidden, 1)
49
+ nn.init.normal_(self.scalar.weight, std=0.02)
50
+ nn.init.zeros_(self.scalar.bias)
51
+ self.set_head = set_head
52
+ if set_head == "attention":
53
+ self.set_project = nn.Linear(hidden + 1, 128)
54
+ self.set_attention = nn.MultiheadAttention(128, 4, dropout=0.0, batch_first=True)
55
+ self.set_output = nn.Linear(128, 1)
56
+ nn.init.zeros_(self.set_output.weight)
57
+ nn.init.zeros_(self.set_output.bias)
58
+
59
+ def forward(self, examples: Sequence[dict], pad_token: int):
60
+ """examples: [{leaf_tokens: [[int, ...], ...], candidate_ids: [...], type: "choice"}]."""
61
+ paths = [ids for ex in examples for ids in ex["leaf_tokens"]]
62
+ device = self.scalar.weight.device
63
+ lengths = torch.tensor([len(ids) for ids in paths], device=device)
64
+ width = int(lengths.max())
65
+ tokens = torch.full((len(paths), width), pad_token, dtype=torch.long, device=device)
66
+ for i, ids in enumerate(paths):
67
+ tokens[i, :len(ids)] = torch.tensor(ids, device=device)
68
+ attention = torch.arange(width, device=device)[None, :] < lengths[:, None]
69
+ hidden = self.backbone(input_ids=tokens, attention_mask=attention,
70
+ use_cache=False).last_hidden_state
71
+ leaves = hidden[torch.arange(len(paths), device=device), lengths - 1]
72
+ kmax = max(len(ex["candidate_ids"]) for ex in examples)
73
+ h = leaves.new_zeros((len(examples), kmax, leaves.shape[-1]))
74
+ valid = torch.zeros((len(examples), kmax), dtype=torch.bool, device=device)
75
+ offset = 0
76
+ for i, ex in enumerate(examples):
77
+ n = len(ex["leaf_tokens"])
78
+ h[i, :n] = leaves[offset:offset + n]
79
+ valid[i, :len(ex["candidate_ids"])] = True
80
+ offset += n
81
+ h = self.norm(h)
82
+ z = self.scalar(h).squeeze(-1).float()
83
+ choice = torch.tensor([i for i, ex in enumerate(examples) if ex["type"] == "choice"], device=device)
84
+ if self.set_head == "attention" and len(choice):
85
+ log_k = valid[choice].sum(-1).float().log()[:, None, None].expand(-1, kmax, 1)
86
+ u = self.set_project(torch.cat([h[choice], log_k.to(h.dtype)], dim=-1))
87
+ mixed, _ = self.set_attention(u, u, u, key_padding_mask=~valid[choice], need_weights=False)
88
+ delta = self.set_output(torch.tanh(u + mixed)).squeeze(-1).float()
89
+ z = z.index_add(0, choice, delta)
90
+ out = []
91
+ for i, ex in enumerate(examples):
92
+ if ex["type"] == "boolean":
93
+ out.append(F.pad(torch.stack([z[i, 0] * 0, z[i, 0]]), (0, kmax - 2)))
94
+ else:
95
+ out.append(z[i])
96
+ return torch.stack(out).masked_fill(~valid, -1e9), valid
97
+
98
+
99
+ def load_jev_model(checkpoint_dir: str | Path, device: str = "cuda", dtype=torch.float32):
100
+ """Load the backbone, head weights and tokenizer from a checkpoint directory."""
101
+ from safetensors.torch import load_file
102
+ from transformers import AutoConfig, AutoModel, AutoTokenizer
103
+
104
+ root = Path(checkpoint_dir).expanduser().resolve()
105
+ cfg = json.loads((root / "config.json").read_text(encoding="utf-8"))
106
+ body_config = AutoConfig.from_pretrained(str(root / "backbone_config"), local_files_only=True)
107
+ backbone = AutoModel.from_config(body_config, attn_implementation="sdpa")
108
+ model = JevDecisionModel(backbone, set_head=cfg.get("set_head", "attention"))
109
+ weights = root / "model.safetensors"
110
+ if not weights.is_file():
111
+ weights = root / "best.safetensors"
112
+ missing, unexpected = model.load_state_dict(load_file(str(weights)), strict=False)
113
+ if any(k.startswith("backbone.") or k.startswith("norm.") or k.startswith("scalar.") for k in missing):
114
+ raise RuntimeError(f"checkpoint is missing head/backbone weights: {list(missing)[:5]}")
115
+ model = model.to(device=device, dtype=dtype).eval()
116
+ tokenizer = AutoTokenizer.from_pretrained(str(root / "tokenizer"), local_files_only=True)
117
+ return model, tokenizer
118
+
119
+
120
+ def prepare_examples(payload: dict, tokenizer, max_length: int = 2048) -> List[dict]:
121
+ """Encode state + candidate texts into one leaf-token path per candidate."""
122
+ if tokenizer.eos_token_id is None:
123
+ raise ValueError("tokenizer has no eos_token_id")
124
+ examples = []
125
+ for row in payload["states"]:
126
+ for qid, q in row["questions"].items():
127
+ ids = list(q["criteria"])
128
+ texts = [f"{key}: {q['criteria'][key]}" for key in ids]
129
+ segments = [f"State:\n{row['state']}\n",
130
+ f"Question type: choice\nQuestion:\n{q.get('instructions', INSTRUCTIONS)}\n"]
131
+ prefix = sum([tokenizer.encode(t, add_special_tokens=False) for t in segments], [])
132
+ leaves = [prefix + tokenizer.encode(f"Candidate:\n{t}\nDecision:", add_special_tokens=False)
133
+ + [tokenizer.eos_token_id] for t in texts]
134
+ largest = max(map(len, leaves))
135
+ if largest > max_length:
136
+ raise ValueError(f"{row['id']}:{qid} candidate path is {largest} tokens > max_length={max_length}")
137
+ examples.append({"id": f"{row['id']}:{qid}", "state_id": row["id"], "qid": qid,
138
+ "type": "choice", "candidate_ids": ids, "candidate_texts": texts,
139
+ "leaf_tokens": leaves})
140
+ return examples
141
+
142
+
143
+ @torch.inference_mode()
144
+ def score_candidates(model, tokenizer, query: str, candidates: Dict[str, str],
145
+ repo: str = "repo", max_length: int = 2048) -> List[Tuple[str, float]]:
146
+ """Return [(candidate_key, probability)] sorted by probability, best first.
147
+
148
+ ``candidates`` maps ``path:start-end`` -> compact summary text; order is preserved
149
+ in the input but the returned list is ranked by the model.
150
+ """
151
+ state = ("task: fast_context_code_location\n"
152
+ f"repo: {repo}\n"
153
+ f"candidate_count: {len(candidates)}\n"
154
+ "query:\n"
155
+ f"{query}\n")
156
+ row = {"id": "query", "state": state,
157
+ "questions": {"q_loc": {"type": "choice", "instructions": INSTRUCTIONS, "criteria": dict(candidates)}}}
158
+ ex = prepare_examples({"states": [row]}, tokenizer, max_length)[0]
159
+ logits, valid = model([ex], tokenizer.pad_token_id)
160
+ probs = logits[0, :len(ex["candidate_ids"])].float().softmax(-1).tolist()
161
+ return sorted(zip(ex["candidate_ids"], probs), key=lambda kv: -kv[1])
patch_tokenizer_for_transformers4.py ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Convert the tokenizer config from the transformers>=5 format to the 4.x format.
3
+
4
+ `transformers` 5 stores `extra_special_tokens` as a list of token strings; 4.x
5
+ expects a mapping. Run once if you use transformers 4.x:
6
+
7
+ python patch_tokenizer_for_transformers4.py tokenizer/tokenizer_config.json
8
+ """
9
+ from __future__ import annotations
10
+
11
+ import json
12
+ import sys
13
+ from pathlib import Path
14
+
15
+
16
+ def main() -> None:
17
+ path = Path(sys.argv[1] if len(sys.argv) > 1 else "tokenizer/tokenizer_config.json")
18
+ cfg = json.loads(path.read_text(encoding="utf-8"))
19
+ extra = cfg.get("extra_special_tokens")
20
+ if isinstance(extra, list):
21
+ cfg["extra_special_tokens"] = {token: token for token in extra}
22
+ path.write_text(json.dumps(cfg, ensure_ascii=False, indent=2), encoding="utf-8")
23
+ print(f"patched {path}: extra_special_tokens list -> dict ({len(cfg['extra_special_tokens'])} entries)")
24
+ elif isinstance(extra, dict):
25
+ print(f"{path}: already in 4.x format")
26
+ else:
27
+ print(f"{path}: no extra_special_tokens field, nothing to do")
28
+
29
+
30
+ if __name__ == "__main__":
31
+ main()
tokenizer/chat_template.jinja ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {%- if tools %}
2
+ {{- '<|im_start|>system\n' }}
3
+ {%- if messages[0].role == 'system' %}
4
+ {{- messages[0].content + '\n\n' }}
5
+ {%- endif %}
6
+ {{- "# Tools\n\nYou may call one or more functions to assist with the user query.\n\nYou are provided with function signatures within <tools></tools> XML tags:\n<tools>" }}
7
+ {%- for tool in tools %}
8
+ {{- "\n" }}
9
+ {{- tool | tojson }}
10
+ {%- endfor %}
11
+ {{- "\n</tools>\n\nFor each function call, return a json object with function name and arguments within <tool_call></tool_call> XML tags:\n<tool_call>\n{\"name\": <function-name>, \"arguments\": <args-json-object>}\n</tool_call><|im_end|>\n" }}
12
+ {%- else %}
13
+ {%- if messages[0].role == 'system' %}
14
+ {{- '<|im_start|>system\n' + messages[0].content + '<|im_end|>\n' }}
15
+ {%- endif %}
16
+ {%- endif %}
17
+ {%- set ns = namespace(multi_step_tool=true, last_query_index=messages|length - 1) %}
18
+ {%- for message in messages[::-1] %}
19
+ {%- set index = (messages|length - 1) - loop.index0 %}
20
+ {%- if ns.multi_step_tool and message.role == "user" and message.content is string and not(message.content.startswith('<tool_response>') and message.content.endswith('</tool_response>')) %}
21
+ {%- set ns.multi_step_tool = false %}
22
+ {%- set ns.last_query_index = index %}
23
+ {%- endif %}
24
+ {%- endfor %}
25
+ {%- for message in messages %}
26
+ {%- if message.content is string %}
27
+ {%- set content = message.content %}
28
+ {%- else %}
29
+ {%- set content = '' %}
30
+ {%- endif %}
31
+ {%- if (message.role == "user") or (message.role == "system" and not loop.first) %}
32
+ {{- '<|im_start|>' + message.role + '\n' + content + '<|im_end|>' + '\n' }}
33
+ {%- elif message.role == "assistant" %}
34
+ {%- set reasoning_content = '' %}
35
+ {%- if message.reasoning_content is string %}
36
+ {%- set reasoning_content = message.reasoning_content %}
37
+ {%- else %}
38
+ {%- if '</think>' in content %}
39
+ {%- set reasoning_content = content.split('</think>')[0].rstrip('\n').split('<think>')[-1].lstrip('\n') %}
40
+ {%- set content = content.split('</think>')[-1].lstrip('\n') %}
41
+ {%- endif %}
42
+ {%- endif %}
43
+ {%- if loop.index0 > ns.last_query_index %}
44
+ {%- if loop.last or (not loop.last and reasoning_content) %}
45
+ {{- '<|im_start|>' + message.role + '\n<think>\n' + reasoning_content.strip('\n') + '\n</think>\n\n' + content.lstrip('\n') }}
46
+ {%- else %}
47
+ {{- '<|im_start|>' + message.role + '\n' + content }}
48
+ {%- endif %}
49
+ {%- else %}
50
+ {{- '<|im_start|>' + message.role + '\n' + content }}
51
+ {%- endif %}
52
+ {%- if message.tool_calls %}
53
+ {%- for tool_call in message.tool_calls %}
54
+ {%- if (loop.first and content) or (not loop.first) %}
55
+ {{- '\n' }}
56
+ {%- endif %}
57
+ {%- if tool_call.function %}
58
+ {%- set tool_call = tool_call.function %}
59
+ {%- endif %}
60
+ {{- '<tool_call>\n{"name": "' }}
61
+ {{- tool_call.name }}
62
+ {{- '", "arguments": ' }}
63
+ {%- if tool_call.arguments is string %}
64
+ {{- tool_call.arguments }}
65
+ {%- else %}
66
+ {{- tool_call.arguments | tojson }}
67
+ {%- endif %}
68
+ {{- '}\n</tool_call>' }}
69
+ {%- endfor %}
70
+ {%- endif %}
71
+ {{- '<|im_end|>\n' }}
72
+ {%- elif message.role == "tool" %}
73
+ {%- if loop.first or (messages[loop.index0 - 1].role != "tool") %}
74
+ {{- '<|im_start|>user' }}
75
+ {%- endif %}
76
+ {{- '\n<tool_response>\n' }}
77
+ {{- content }}
78
+ {{- '\n</tool_response>' }}
79
+ {%- if loop.last or (messages[loop.index0 + 1].role != "tool") %}
80
+ {{- '<|im_end|>\n' }}
81
+ {%- endif %}
82
+ {%- endif %}
83
+ {%- endfor %}
84
+ {%- if add_generation_prompt %}
85
+ {{- '<|im_start|>assistant\n' }}
86
+ {%- if enable_thinking is defined and enable_thinking is false %}
87
+ {{- '<think>\n\n</think>\n\n' }}
88
+ {%- endif %}
89
+ {%- endif %}
tokenizer/tokenizer.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:be75606093db2094d7cd20f3c2f385c212750648bd6ea4fb2bf507a6a4c55506
3
+ size 11422650
tokenizer/tokenizer_config.json ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "add_prefix_space": false,
3
+ "backend": "tokenizers",
4
+ "bos_token": null,
5
+ "clean_up_tokenization_spaces": false,
6
+ "eos_token": "<|im_end|>",
7
+ "errors": "replace",
8
+ "extra_special_tokens": [
9
+ "<|im_start|>",
10
+ "<|im_end|>",
11
+ "<|object_ref_start|>",
12
+ "<|object_ref_end|>",
13
+ "<|box_start|>",
14
+ "<|box_end|>",
15
+ "<|quad_start|>",
16
+ "<|quad_end|>",
17
+ "<|vision_start|>",
18
+ "<|vision_end|>",
19
+ "<|vision_pad|>",
20
+ "<|image_pad|>",
21
+ "<|video_pad|>"
22
+ ],
23
+ "model_max_length": 131072,
24
+ "pad_token": "<|endoftext|>",
25
+ "split_special_tokens": false,
26
+ "tokenizer_class": "Qwen2Tokenizer",
27
+ "unk_token": null
28
+ }