mlboydaisuke commited on
Commit
8c86316
·
verified ·
1 Parent(s): b2c6c89

Mirror of mlboydaisuke/Qwen3-Reranker-0.6B-CoreAI

Browse files
.gitattributes CHANGED
@@ -33,3 +33,5 @@ saved_model/**/* 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
 
 
 
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
36
+ qwen3-reranker-0.6b_float16_s512_static.aimodel/main.mlirb filter=lfs diff=lfs merge=lfs -text
37
+ tokenizer/tokenizer.json filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: apache-2.0
3
+ base_model: Qwen/Qwen3-Reranker-0.6B
4
+ tags:
5
+ - coreai
6
+ - text-ranking
7
+ - reranker
8
+ - apple-silicon
9
+ - on-device
10
+ language:
11
+ - multilingual
12
+ pipeline_tag: text-ranking
13
+ ---
14
+
15
+ > **Mirror** of [`mlboydaisuke/Qwen3-Reranker-0.6B-CoreAI`](https://huggingface.co/mlboydaisuke/Qwen3-Reranker-0.6B-CoreAI) — the canonical repo ([CoreAI Model Zoo](https://github.com/john-rocky/coreai-model-zoo)). Updates land there first.
16
+
17
+
18
+ # Qwen3-Reranker-0.6B — Core AI export
19
+
20
+ [Qwen/Qwen3-Reranker-0.6B](https://huggingface.co/Qwen/Qwen3-Reranker-0.6B) as a single static
21
+ Core AI graph for macOS 27 / iOS 27. The **cross-encoder** that closes the on-device RAG loop —
22
+ embed (with [Qwen3-Embedding-0.6B-CoreAI](https://huggingface.co/mlboydaisuke/Qwen3-Embedding-0.6B-CoreAI))
23
+ → **rerank** → generate, all local and private.
24
+
25
+ A cross-encoder reads one `query + document` sequence and asks the LM a yes/no question; the
26
+ relevance score is the softmax weight on **"yes"** vs **"no"** at the final token. So it keeps the
27
+ LM head (the embedder drops it), but it's still a plain `.aimodel` run via `AIModel.run` — one
28
+ forward, no generation. The scoring tail (gather last token → head on that one position → 2-way
29
+ softmax) is baked in-graph.
30
+
31
+ ## Graph contract
32
+
33
+ | | name | shape | dtype |
34
+ |---|---|---|---|
35
+ | input | `input_ids` | [1, 512] | int32 (right-padded; pad id 151643) |
36
+ | input | `attention_mask` | [1, 512] | int32 (1 = real, 0 = padding) |
37
+ | output | `probs` | [1, 2] | fp16, `softmax([no, yes])` — **relevance = `probs[0,1]` = P(yes)** |
38
+
39
+ ## Host recipe
40
+
41
+ Format the pair exactly like the upstream model card, then right-pad to 512:
42
+
43
+ ```python
44
+ import coreai.runtime as rt, numpy as np
45
+ from transformers import AutoTokenizer
46
+
47
+ tok = AutoTokenizer.from_pretrained("tokenizer")
48
+ PREFIX = ("<|im_start|>system\nJudge whether the Document meets the requirements based on the "
49
+ "Query and the Instruct provided. Note that the answer can only be \"yes\" or "
50
+ "\"no\".<|im_end|>\n<|im_start|>user\n")
51
+ SUFFIX = "<|im_end|>\n<|im_start|>assistant\n<think>\n\n</think>\n\n"
52
+ INSTR = "Given a web search query, retrieve relevant passages that answer the query"
53
+
54
+ m = await rt.AIModel.load("qwen3-reranker-0.6b_float16_s512_static.aimodel",
55
+ rt.SpecializationOptions.from_preferred_compute_unit_kind(rt.ComputeUnitKind.gpu()))
56
+ fn = m.load_function("main")
57
+
58
+ def score(query, doc, S=512):
59
+ body = f"<Instruct>: {INSTR}\n<Query>: {query}\n<Document>: {doc}"
60
+ ids = (tok.encode(PREFIX, add_special_tokens=False)
61
+ + tok.encode(body, add_special_tokens=False)
62
+ + tok.encode(SUFFIX, add_special_tokens=False))
63
+ n = len(ids); ids = ids + [151643] * (S - n)
64
+ mask = [1] * n + [0] * (S - n)
65
+ res = await fn({"input_ids": rt.NDArray(np.asarray([ids], np.int32)),
66
+ "attention_mask": rt.NDArray(np.asarray([mask], np.int32))})
67
+ return float(res["probs"].numpy()[0, 1]) # P(yes) = relevance; sort candidates by this
68
+ ```
69
+
70
+ The instruction is swappable per task (the model is instruction-aware). Right-pad is equivalent to
71
+ the upstream left-pad + `logits[:, -1]` (the graph reads the true last token from the mask).
72
+
73
+ ### Swift — [CoreAIKit](https://github.com/john-rocky/coreai-kit)
74
+
75
+ Downloads this repo on first use and formats the pair in-process:
76
+
77
+ ```swift
78
+ import CoreAIKitEmbeddings
79
+
80
+ let reranker = try await Reranker(model: .qwen3Reranker0_6B)
81
+ let ranked = try await reranker.rerank(
82
+ query: "What is the capital of Japan?",
83
+ documents: ["Tokyo is the capital of Japan.", "Python is a programming language."])
84
+ // ranked[0].document is most relevant; ranked[i].score is P(yes) in [0, 1]
85
+ ```
86
+
87
+ ## Bundle layout
88
+
89
+ ```
90
+ qwen3-reranker-0.6b_float16_s512_static.aimodel (~1.1 GB, fp16)
91
+ tokenizer/ (HF tokenizer files)
92
+ reference.json (pairs, scores, prompt scaffolding)
93
+ ```
94
+
95
+ ## Parity
96
+
97
+ Precision **fp16**. Verified against the official `AutoModelForCausalLM` scoring (fp32): the
98
+ in-graph wrapper reproduces P(yes) **exactly** (|Δ| = 0.00000 over 6 relevant/irrelevant pairs),
99
+ relevant pairs 0.98–1.00 vs irrelevant ≈ 0.0000, ranking preserved. On the Core AI GPU delegate
100
+ the `.aimodel` matches the torch reference within **|Δ| < 0.0005** end-to-end. Measured **45.7 ms
101
+ per pair-score** on an M4 Max GPU (512 grid).
102
+
103
+ ## License
104
+
105
+ Apache-2.0 (upstream model and code are Apache-2.0). Conversion script:
106
+ [`conversion/export_qwen3_reranker.py`](https://github.com/john-rocky/coreai-model-zoo/blob/main/conversion/export_qwen3_reranker.py)
107
+ in the coreai-model-zoo.
qwen3-reranker-0.6b_float16_s512_static.aimodel/main.hash ADDED
@@ -0,0 +1 @@
 
 
1
+ &��o�i_e��M� �*�����@a���cYX
qwen3-reranker-0.6b_float16_s512_static.aimodel/main.mlirb ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:26c4ef6f91695f161d6589e44da20b8d172a1ceaf2f6a1b34061fdd2e6635958
3
+ size 1192490779
qwen3-reranker-0.6b_float16_s512_static.aimodel/metadata.json ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ {
2
+ "description" : "Qwen3-Reranker-0.6B cross-encoder reranker (Qwen3-0.6B backbone; yes\/no logit score). Output probs[1] = P(yes) = relevance. Source: https:\/\/huggingface.co\/Qwen\/Qwen3-Reranker-0.6B",
3
+ "assetVersion" : "2.0",
4
+ "creationDate" : "20260614T052234Z",
5
+ "license" : "Apache-2.0",
6
+ "author" : "Alibaba Qwen"
7
+ }
reference.json ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "Qwen/Qwen3-Reranker-0.6B",
3
+ "seq_len": 512,
4
+ "dtype": "float16",
5
+ "yes_id": 9693,
6
+ "no_id": 2152,
7
+ "pad_token_id": 151643,
8
+ "padding_side": "right",
9
+ "prefix": "<|im_start|>system\nJudge whether the Document meets the requirements based on the Query and the Instruct provided. Note that the answer can only be \"yes\" or \"no\".<|im_end|>\n<|im_start|>user\n",
10
+ "suffix": "<|im_end|>\n<|im_start|>assistant\n<think>\n\n</think>\n\n",
11
+ "default_instruction": "Given a web search query, retrieve relevant passages that answer the query",
12
+ "output": "probs [1,2] = softmax([no, yes]); relevance = probs[1] = P(yes)",
13
+ "pairs": {
14
+ "rel_capital": {
15
+ "relevant": true,
16
+ "query": "What is the capital of Japan?",
17
+ "doc": "Tokyo is the capital and largest city of Japan."
18
+ },
19
+ "rel_beesting": {
20
+ "relevant": true,
21
+ "query": "How do I treat a bee sting?",
22
+ "doc": "Remove the stinger, wash with soap and water, then apply a cold pack to reduce swelling."
23
+ },
24
+ "rel_fuji_ja": {
25
+ "relevant": true,
26
+ "query": "富士山の高さはどのくらいですか?",
27
+ "doc": "富士山は標高3,776メートルで、日本で最も高い山です。"
28
+ },
29
+ "irr_capital": {
30
+ "relevant": false,
31
+ "query": "What is the capital of Japan?",
32
+ "doc": "Python is the most widely used programming language for machine learning."
33
+ },
34
+ "irr_beesting": {
35
+ "relevant": false,
36
+ "query": "How do I treat a bee sting?",
37
+ "doc": "Tokyo is the capital and largest city of Japan."
38
+ },
39
+ "irr_fuji_ja": {
40
+ "relevant": false,
41
+ "query": "富士山の高さはどのくらいですか?",
42
+ "doc": "The recipe calls for two eggs and a cup of flour."
43
+ }
44
+ },
45
+ "scores": {
46
+ "rel_capital": 0.9937748908996582,
47
+ "rel_beesting": 0.9814825654029846,
48
+ "rel_fuji_ja": 0.9997767806053162,
49
+ "irr_capital": 8.651458301756065e-06,
50
+ "irr_beesting": 3.616727553890087e-05,
51
+ "irr_fuji_ja": 5.813539701193804e-06
52
+ },
53
+ "official_scores": {
54
+ "rel_capital": 0.9937747716903687,
55
+ "rel_beesting": 0.9814824461936951,
56
+ "rel_fuji_ja": 0.9997767806053162,
57
+ "irr_capital": 8.651466487208381e-06,
58
+ "irr_beesting": 3.616731191868894e-05,
59
+ "irr_fuji_ja": 5.813562438561348e-06
60
+ },
61
+ "rank_groups": {
62
+ "capital": [
63
+ "rel_capital",
64
+ "irr_capital"
65
+ ],
66
+ "beesting": [
67
+ "rel_beesting",
68
+ "irr_beesting"
69
+ ],
70
+ "fuji_ja": [
71
+ "rel_fuji_ja",
72
+ "irr_fuji_ja"
73
+ ]
74
+ }
75
+ }
tokenizer/chat_template.jinja ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {%- set instruction = messages | selectattr("role", "eq", "system") | map(attribute="content") | first | default("Given a web search query, retrieve relevant passages that answer the query") -%}
2
+ {%- set query_text = messages | selectattr("role", "eq", "query") | map(attribute="content") | first -%}
3
+ {%- set document_text = messages | selectattr("role", "eq", "document") | map(attribute="content") | first -%}
4
+ <|im_start|>system
5
+ Judge whether the Document meets the requirements based on the Query and the Instruct provided. Note that the answer can only be "yes" or "no".<|im_end|>
6
+ <|im_start|>user
7
+ <Instruct>: {{ instruction }}
8
+ <Query>: {{ query_text }}
9
+ <Document>: {{ document_text }}<|im_end|>
10
+ <|im_start|>assistant
11
+ <think>
12
+
13
+ </think>
14
+
15
+
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,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ "is_local": false,
9
+ "local_files_only": false,
10
+ "model_max_length": 131072,
11
+ "pad_token": "<|endoftext|>",
12
+ "split_special_tokens": false,
13
+ "tokenizer_class": "Qwen2Tokenizer",
14
+ "unk_token": null
15
+ }