DylanCouzon commited on
Commit
6d58742
·
verified ·
1 Parent(s): 712df34

constella-zero — FastEmbed-first card, run p35w-2m-s2500

Browse files
Files changed (1) hide show
  1. README.md +67 -3
README.md CHANGED
@@ -148,15 +148,79 @@ table shipped here (sha `a7007b1a…`).
148
  | system | arguana | fiqa | nfcorpus | scidocs | scifact | trec-covid | **average** |
149
  |---|---|---|---|---|---|---|---|
150
  | **constella-zero (int8)** | 0.5916 | 0.3728 | 0.3124 | 0.1677 | 0.6101 | 0.5490 | **0.4339** |
151
- | + BM25, convex fusion | 0.5975 | 0.4026 | 0.3497 | 0.1881 | 0.7068 | 0.7018 | **0.4911** |
 
152
  | BM25 alone | 0.4878 | 0.2532 | 0.3180 | 0.1565 | 0.6791 | 0.6099 | 0.4174 |
153
  | the teacher, used on both sides | 0.6369 | 0.5536 | 0.4134 | 0.2395 | 0.7796 | 0.8234 | 0.5744 |
154
 
155
  A lookup table retains **75.5%** of the teacher's quality (0.4339 / 0.5744), with a query side
156
  that does no matrix multiplication at all.
157
 
158
- The fused row is **weighted score fusion**, `0.8 × dense + 0.2 × BM25` on min-max normalized
159
- scores — not reciprocal rank fusion, so Qdrant's `Fusion.RRF` will not reproduce it.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
 
161
  ## Limits
162
 
 
148
  | system | arguana | fiqa | nfcorpus | scidocs | scifact | trec-covid | **average** |
149
  |---|---|---|---|---|---|---|---|
150
  | **constella-zero (int8)** | 0.5916 | 0.3728 | 0.3124 | 0.1677 | 0.6101 | 0.5490 | **0.4339** |
151
+ | **+ BM25, Qdrant `Fusion.DBSF`, prefetch 100** | 0.5800 | 0.3872 | 0.3442 | 0.1850 | 0.7173 | 0.7184 | **0.4887** |
152
+ | + BM25, convex fusion (not runnable in Qdrant) | 0.5975 | 0.4026 | 0.3497 | 0.1881 | 0.7068 | 0.7018 | **0.4911** |
153
  | BM25 alone | 0.4878 | 0.2532 | 0.3180 | 0.1565 | 0.6791 | 0.6099 | 0.4174 |
154
  | the teacher, used on both sides | 0.6369 | 0.5536 | 0.4134 | 0.2395 | 0.7796 | 0.8234 | 0.5744 |
155
 
156
  A lookup table retains **75.5%** of the teacher's quality (0.4339 / 0.5744), with a query side
157
  that does no matrix multiplication at all.
158
 
159
+ ### Fusing with BM25 in Qdrant
160
+
161
+ **The recommended fused system is `Fusion.DBSF` with a prefetch limit of 100** — the row in bold
162
+ above. DBSF has **no fitted fusion weights**; the prefetch limit of 100 was chosen from where DBSF
163
+ saturates on our development set, plus a deployability criterion, so the configuration is
164
+ development-informed even though the operator itself fits nothing.
165
+
166
+ Fusion needs **named** vectors, so hybrid search gets its own collection:
167
+
168
+ ```python
169
+ # The sparse side is whatever lexical model you use -- FastEmbed's `Qdrant/bm25`, or your own.
170
+ # Placeholder sparse vectors here, so this snippet runs with no extra download.
171
+ client.create_collection(
172
+ "hybrid",
173
+ vectors_config={"dense": models.VectorParams(size=1024, distance=models.Distance.COSINE)},
174
+ sparse_vectors_config={"bm25": models.SparseVectorParams()},
175
+ )
176
+ client.upsert("hybrid", points=[
177
+ models.PointStruct(
178
+ id=i,
179
+ vector={"dense": D[i].tolist(),
180
+ "bm25": models.SparseVector(indices=[i], values=[1.0])},
181
+ payload={"text": t})
182
+ for i, t in enumerate(docs)])
183
+
184
+ hits = client.query_points(
185
+ "hybrid",
186
+ prefetch=[
187
+ models.Prefetch(query=q.tolist(), using="dense", limit=100),
188
+ models.Prefetch(query=models.SparseVector(indices=[0], values=[1.0]),
189
+ using="bm25", limit=100),
190
+ ],
191
+ query=models.FusionQuery(fusion=models.Fusion.DBSF),
192
+ limit=10,
193
+ ).points
194
+ print(hits[0].payload["text"])
195
+ ```
196
+
197
+ **On the four datasets with no disclosed teacher overlap** (see Limits), DBSF at prefetch 100 scores
198
+ **0.4912** against convex fusion's 0.4866; across all six, 0.4887 vs 0.4911. Both differences are
199
+ inside the ~0.005 band we treat as noise, and we computed no confidence interval for them, so read
200
+ this as **no measured quality difference in either direction** — not as DBSF being better. The
201
+ reason to prefer it is that it *runs in the product*, needs no 1000-deep prefetch, and removes a
202
+ tuned weight from the system.
203
+
204
+ The `convex fusion` row is retained for continuity: it was the operator of record when this model
205
+ was released. It is `0.8 × dense + 0.2 × BM25`, each channel divided by its per-query maximum, at
206
+ prefetch depth 1000 — **Qdrant does not implement it**, and a 1000-deep prefetch to return 10
207
+ results is not a realistic configuration.
208
+
209
+ `Fusion.RRF` is the weaker choice. We swept it fairly — `k` from 1 to 101 in Qdrant's units (best
210
+ `k=3`), and 24 weighted configurations (best `k=2, weights=[2, 1]`) — and its best point lands
211
+ below DBSF on our development set. An earlier version of this card said only that RRF "will not
212
+ reproduce" the fused row; that was true, but rested on an unweighted, badly-ranged comparison,
213
+ which has since been redone.
214
+
215
+ **Caveats.** Numbers use `bm25s` (lucene defaults), not Qdrant's own BM25, which has a fixed
216
+ `avg_len` and its own tokenizer; DBSF normalises over the returned scores, so a different lexical
217
+ implementation shifts its inputs.
218
+
219
+ Our evaluation excludes each query's own document *before* truncating to 100, so the numbers
220
+ describe a prefetch with a **self-exclusion filter** (`must_not` on the point id). Without one, a
221
+ plain `limit: 100` spends a slot on the self-match. This matters only where queries are also
222
+ documents — ArguAna (1,298 of 1,406 queries) and FiQA (55); the other four datasets have none, so
223
+ the clean-4 figures are unaffected either way.
224
 
225
  ## Limits
226