forked from BasedHardware/omi
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvectorSearchMerge.test.ts
More file actions
62 lines (53 loc) · 2.22 KB
/
Copy pathvectorSearchMerge.test.ts
File metadata and controls
62 lines (53 loc) · 2.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import { describe, expect, it } from 'vitest'
import { VECTOR_SIM_THRESHOLD, mergeRewindSearchResults, type VectorHit } from './vectorSearchMerge'
import type { RewindFrame } from '../../shared/types'
const frame = (id: number, ts = id * 1000): RewindFrame => ({
id,
ts,
app: 'Code',
windowTitle: 'window',
processName: 'code.exe',
ocrText: `frame ${id}`,
imagePath: `C:\\frames\\${id}.jpg`,
width: 1920,
height: 1080,
indexed: 1
})
const hit = (id: number, similarity: number, ts?: number): VectorHit => ({
frame: frame(id, ts),
similarity
})
const ids = (frames: RewindFrame[]): (number | undefined)[] => frames.map((f) => f.id)
describe('mergeRewindSearchResults', () => {
it('keeps FTS results first, in their original BM25 order', () => {
const fts = [frame(3), frame(1), frame(2)]
const merged = mergeRewindSearchResults(fts, [hit(9, 0.99)])
// The 0.99 semantic hit does NOT jump the queue — keyword always leads.
expect(ids(merged)).toEqual([3, 1, 2, 9])
})
it('adds a vector hit only when it clears the similarity floor', () => {
const merged = mergeRewindSearchResults(
[],
[hit(1, VECTOR_SIM_THRESHOLD + 0.01), hit(2, VECTOR_SIM_THRESHOLD), hit(3, 0.1)]
)
// Strictly greater than 0.5 — a hit exactly at the floor is dropped.
expect(ids(merged)).toEqual([1])
})
it('never duplicates a frame FTS already returned, however strong the vector score', () => {
const merged = mergeRewindSearchResults([frame(1), frame(2)], [hit(1, 0.99), hit(3, 0.8)])
expect(ids(merged)).toEqual([1, 2, 3])
})
it('orders the additive hits strongest-first, breaking ties by recency', () => {
const merged = mergeRewindSearchResults([], [hit(1, 0.7), hit(2, 0.9), hit(3, 0.7, 999_999)])
expect(ids(merged)).toEqual([2, 3, 1])
})
// The non-fatal contract: a dead embedding backend hands the merge an empty
// list, and keyword results must still render.
it('returns FTS results unchanged when vector search yielded nothing', () => {
const fts = [frame(1), frame(2)]
expect(ids(mergeRewindSearchResults(fts, []))).toEqual([1, 2])
})
it('returns nothing when neither leg matched', () => {
expect(mergeRewindSearchResults([], [])).toEqual([])
})
})