@tpsdev-ai/flair-bench 0.48.0 → 0.50.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cosine.d.ts CHANGED
@@ -11,11 +11,11 @@
11
11
  export declare function cosineSimilarity(a: readonly number[], b: readonly number[]): number;
12
12
  /**
13
13
  * 0-based rank of `targetIndex` within `corpusVectors` when sorted by
14
- * descending cosine similarity to `query`. Ties are broken by corpus
15
- * insertion order (stable sort Array.prototype.sort is guaranteed stable
16
- * since ES2019/V8 since Node 11), the simplest documented tie-break
17
- * available without reverse-engineering Harper's own HNSW/BM25-RRF
18
- * tie-break internals. See README's "exact-vs-HNSW caveat" for what this
19
- * does and doesn't guarantee to reproduce.
14
+ * descending cosine similarity to `query`. Ties break on corpus `.index`
15
+ * ascending (the total-order tailnot `.id`; this ranking never has one).
16
+ * Input order of the scored array must not leak: the same corpus in two
17
+ * permutations of equal-score rows ranks identically (flair#1412).
18
+ * See README's "exact-vs-HNSW caveat" for what this does and doesn't
19
+ * guarantee to reproduce of Harper's HNSW.
20
20
  */
21
21
  export declare function rankOf(query: readonly number[], corpusVectors: readonly (readonly number[])[], targetIndex: number): number;
package/dist/cosine.js CHANGED
@@ -8,6 +8,7 @@
8
8
  * (251 records), and the reason the tool can claim exact recall numbers
9
9
  * rather than approximate ones.
10
10
  */
11
+ import { compareKey } from "./sort-comparators.js";
11
12
  export function cosineSimilarity(a, b) {
12
13
  if (a.length !== b.length) {
13
14
  throw new Error(`cosineSimilarity: dimension mismatch (${a.length} vs ${b.length})`);
@@ -28,15 +29,15 @@ export function cosineSimilarity(a, b) {
28
29
  }
29
30
  /**
30
31
  * 0-based rank of `targetIndex` within `corpusVectors` when sorted by
31
- * descending cosine similarity to `query`. Ties are broken by corpus
32
- * insertion order (stable sort Array.prototype.sort is guaranteed stable
33
- * since ES2019/V8 since Node 11), the simplest documented tie-break
34
- * available without reverse-engineering Harper's own HNSW/BM25-RRF
35
- * tie-break internals. See README's "exact-vs-HNSW caveat" for what this
36
- * does and doesn't guarantee to reproduce.
32
+ * descending cosine similarity to `query`. Ties break on corpus `.index`
33
+ * ascending (the total-order tailnot `.id`; this ranking never has one).
34
+ * Input order of the scored array must not leak: the same corpus in two
35
+ * permutations of equal-score rows ranks identically (flair#1412).
36
+ * See README's "exact-vs-HNSW caveat" for what this does and doesn't
37
+ * guarantee to reproduce of Harper's HNSW.
37
38
  */
38
39
  export function rankOf(query, corpusVectors, targetIndex) {
39
40
  const scored = corpusVectors.map((v, index) => ({ index, score: cosineSimilarity(query, v) }));
40
- scored.sort((x, y) => y.score - x.score);
41
+ scored.sort((x, y) => (y.score - x.score) || compareKey(x.index, y.index));
41
42
  return scored.findIndex((s) => s.index === targetIndex);
42
43
  }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Generic total-order tail (flair#1412). Same helper as
3
+ * `resources/sort-comparators.ts` — copied so this package stays
4
+ * standalone (no flair install, no Harper). Cosine ranking keys on
5
+ * corpus `.index`, not `.id`; force-fitting `byNumberDescThenId` here
6
+ * would be the over-abstraction the #1412 spec names as the failure mode.
7
+ *
8
+ * Locale-independent code-unit / numeric comparison — not localeCompare.
9
+ */
10
+ export declare function compareKey<T extends string | number>(a: T, b: T): number;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Generic total-order tail (flair#1412). Same helper as
3
+ * `resources/sort-comparators.ts` — copied so this package stays
4
+ * standalone (no flair install, no Harper). Cosine ranking keys on
5
+ * corpus `.index`, not `.id`; force-fitting `byNumberDescThenId` here
6
+ * would be the over-abstraction the #1412 spec names as the failure mode.
7
+ *
8
+ * Locale-independent code-unit / numeric comparison — not localeCompare.
9
+ */
10
+ export function compareKey(a, b) {
11
+ return a < b ? -1 : a > b ? 1 : 0;
12
+ }
package/dist/version.d.ts CHANGED
@@ -5,4 +5,4 @@
5
5
  * attribute edge cases in a published dist/ build. test/version-sync.test.ts
6
6
  * asserts this stays equal to package.json's "version" field.
7
7
  */
8
- export declare const TOOL_VERSION = "0.48.0";
8
+ export declare const TOOL_VERSION = "0.50.0";
package/dist/version.js CHANGED
@@ -5,4 +5,4 @@
5
5
  * attribute edge cases in a published dist/ build. test/version-sync.test.ts
6
6
  * asserts this stays equal to package.json's "version" field.
7
7
  */
8
- export const TOOL_VERSION = "0.48.0";
8
+ export const TOOL_VERSION = "0.50.0";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tpsdev-ai/flair-bench",
3
- "version": "0.48.0",
3
+ "version": "0.50.0",
4
4
  "description": "Standalone embedding recall benchmark for flair — run real recall numbers (p@3/MRR) against any GGUF embedding model, batch-compare, get a host-aware recommendation, and share redacted results. No flair install required.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",