Skip to content

Commit 68b402c

Browse files
committed
improvement(knowledge): keep the default scan for a walk that asks the document per tuple
1 parent 1051c20 commit 68b402c

2 files changed

Lines changed: 24 additions & 3 deletions

File tree

‎apps/sim/lib/knowledge/search/queries.test.ts‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2299,6 +2299,12 @@ describe('filters on a resolved scope', () => {
22992299
/** The mock renders a nested condition into the params; the date test is the only `gte`. */
23002300
const datesDocument = (statement: unknown) => JSON.stringify(statement).includes('"type":"gte"')
23012301
expect(datesDocument(walks[0])).toBe(true)
2302+
/** A walk that asks the document per tuple keeps the default scan cap, not the on-row one. */
2303+
const scanCaps = () =>
2304+
statements()
2305+
.filter((query) => query.sql.includes('hnsw.max_scan_tuples'))
2306+
.map((query) => query.params.find((param) => param === '20000' || param === '100000'))
2307+
expect(scanCaps().at(-1)).toBe('20000')
23022308
resetDbChainMock()
23032309
queueTableRows(schemaMock.embedding, rerankRows)
23042310
dbChainMockFns.execute.mockImplementation(async (query) => {
@@ -2313,6 +2319,7 @@ describe('filters on a resolved scope', () => {
23132319
accessPlan: plan(),
23142320
})
23152321
expect(datesDocument(statements().filter((query) => isWalk(query.sql))[0])).toBe(false)
2322+
expect(scanCaps().at(-1)).toBe('100000')
23162323
})
23172324

23182325
it('leaves the keyword leg short when its deadline passes before the ranking is resolved', async () => {

‎apps/sim/lib/knowledge/search/queries.ts‎

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,18 @@ const CANDIDATE_HNSW_MAX_SCAN_TUPLES = '20000'
8989
* left with what the neighbourhood happened to hold.
9090
*/
9191
const ON_ROW_WALK_SCAN_TUPLES = 100_000
92+
93+
/**
94+
* How far a walk may go when readability is on the row: the on-row cap, unless the walk still
95+
* has to ask the document about each tuple — a tag or date filter — in which case a tuple costs
96+
* what it did before the columns were mirrored, and the default cap keeps a walk through a
97+
* mostly-excluded neighbourhood at a short answer rather than a missed deadline.
98+
*/
99+
function onRowWalkScanTuples(documentCondition: SQL | undefined): number {
100+
return documentCondition === undefined
101+
? ON_ROW_WALK_SCAN_TUPLES
102+
: Number(CANDIDATE_HNSW_MAX_SCAN_TUPLES)
103+
}
92104
/**
93105
* Beam width per iteration. A beam is the granularity of cancellation: pgvector calls
94106
* `CHECK_FOR_INTERRUPTS` only while building an index, never inside `hnswgettuple`, so neither
@@ -1475,7 +1487,7 @@ async function selectSourceVectorCandidates(input: {
14751487
ORDER BY ${input.candidateDistance} LIMIT ${input.candidateLimit}`),
14761488
input.budget,
14771489
'vector.source_walk',
1478-
ON_ROW_WALK_SCAN_TUPLES
1490+
onRowWalkScanTuples(input.documentCondition)
14791491
)
14801492
const walks: Array<() => RankedChunks> = sources.walked.map((connectorId) =>
14811493
walk(eq(embeddingSearch.connectorId, connectorId))
@@ -1594,7 +1606,9 @@ async function selectVectorResults(params: SearchParams): Promise<SearchResult[]
15941606
* date filter, which the row does not carry. A bounded set never walks, so this only runs when
15951607
* the filtered documents were too many to enumerate.
15961608
*/
1597-
const documentCondition = and(documentTagCondition, dateFilterCondition(params.filters))
1609+
const dateCondition = dateFilterCondition(params.filters)
1610+
const documentCondition =
1611+
documentTagCondition || dateCondition ? and(documentTagCondition, dateCondition) : undefined
15981612
/**
15991613
* Candidate selection ignores the page offset — only the rerank pages over the pool — so a
16001614
* refill reuses the pool it already has. Excluding another source is the only thing that
@@ -1754,7 +1768,7 @@ async function selectVectorResults(params: SearchParams): Promise<SearchResult[]
17541768
),
17551769
params.budget,
17561770
'vector.candidate_search',
1757-
plan ? ON_ROW_WALK_SCAN_TUPLES : undefined
1771+
plan ? onRowWalkScanTuples(documentCondition) : undefined
17581772
)
17591773
/**
17601774
* A full traversal is already the nearest permitted chunks, so nothing else is worth

0 commit comments

Comments
 (0)