88 credentialGroup ,
99 document ,
1010 embedding ,
11+ embeddingSearch ,
1112 knowledgeBase ,
1213 knowledgeConnector ,
1314 knowledgeConnectorMember ,
@@ -19,7 +20,7 @@ import {
1920} from '@sim/db/schema'
2021import { createLogger , Logger } from '@sim/logger'
2122import { generateId } from '@sim/utils/id'
22- import { and , eq , inArray , sql } from 'drizzle-orm'
23+ import { and , eq , inArray , type SQL , sql } from 'drizzle-orm'
2324import { NextRequest } from 'next/server'
2425import { afterAll , beforeAll , describe , expect , it , type MockInstance , vi } from 'vitest'
2526import { z } from 'zod'
@@ -41,13 +42,15 @@ import {
4142 seedKnowledgeMemberFixture ,
4243} from '@/lib/knowledge/__integration__/seed-source-access-fixture'
4344import { type KnowledgeSearchTagFilter , searchKnowledge } from '@/lib/knowledge/application/search'
45+ import type { KbEmbeddingDimensions } from '@/lib/knowledge/embedding-models'
4446import {
4547 SearchBudget ,
4648 SearchDeadlineError ,
4749 type SearchExecutor ,
4850} from '@/lib/knowledge/search/budget'
4951import type { SearchStage } from '@/lib/knowledge/search/diagnostics'
5052import type { WorkspaceSearchFilters } from '@/lib/knowledge/search/filters'
53+ import { embeddingCandidateDistance } from '@/lib/knowledge/vector-columns'
5154import { POST as searchRoute } from '@/app/api/knowledge/search/route'
5255import { ResolvedSecretTraceRegistry } from '@/executor/utils/resolved-secret-trace-registry'
5356
@@ -120,6 +123,23 @@ function topicVector(topic = 0) {
120123 return vector . map ( ( value ) => value / magnitude )
121124}
122125const queryVector = topicVector ( )
126+
127+ /**
128+ * The exact nearest chunks on the projection's stored halfvec, which is what the page's order
129+ * is measured against: the walk ranks on that column, and nothing rescores it.
130+ */
131+ async function exactProjectionNeighbors ( vector : number [ ] , limit : number , readerClause ?: SQL ) {
132+ const distance = embeddingCandidateDistance (
133+ dimensions as KbEmbeddingDimensions ,
134+ JSON . stringify ( vector ) ,
135+ 'text-embedding-3-small'
136+ )
137+ return db . execute < { id : string } > ( sql `SELECT s.id FROM ${ embeddingSearch } s
138+ INNER JOIN document d ON d.id = s.document_id
139+ WHERE s.knowledge_base_id = ${ ids . knowledgeBaseId } AND s.enabled ${ readerClause ?? sql `` }
140+ ORDER BY (${ distance } ) + 0, s.id
141+ LIMIT ${ limit } ` )
142+ }
123143const captured : CapturedQuery [ ] = [ ]
124144const report : Record < string , unknown > = {
125145 fixture : ids ,
@@ -213,6 +233,10 @@ function explainNodes(node: ExplainNode): ExplainNode[] {
213233 * aliases its own lateral `scoped_chunk`, so this cannot match it, and matching on the rendered
214234 * clause casing would silently stop these assertions from running at all.
215235 */
236+ /** The vector page reads a pool slice's identities from the projection and its documents. */
237+ const VECTOR_PAGE_JOIN =
238+ 'INNER JOIN "document" ON "document"."id" = "embedding_search"."document_id"'
239+
216240function isVectorCandidateQuery ( statement : string ) {
217241 return statement . toLowerCase ( ) . includes ( ') as visible' )
218242}
@@ -476,12 +500,12 @@ async function sample(
476500 item . query . includes ( 'limit' ) ||
477501 item . query . includes ( 'CROSS JOIN LATERAL' ) ||
478502 isVectorCandidateQuery ( item . query ) ||
479- item . query . includes ( 'WITH scored_search_candidates' ) ||
503+ item . query . includes ( VECTOR_PAGE_JOIN ) ||
480504 item . query . includes ( 'WITH matched_keyword_chunks' ) )
481505 )
482506 const plans : Array <
483507 CapturedQuery & {
484- kind : 'keyword' | 'vector' | 'rerank ' | 'probe'
508+ kind : 'keyword' | 'vector' | 'page ' | 'probe'
485509 plan : z . infer < typeof explainSchema >
486510 }
487511 > = [ ]
@@ -516,9 +540,8 @@ async function sample(
516540 ? 'keyword'
517541 : isVectorCandidateQuery ( query . query )
518542 ? 'vector'
519- : query . query . includes ( 'order by' ) ||
520- query . query . includes ( 'WITH scored_search_candidates' )
521- ? 'rerank'
543+ : query . query . includes ( 'order by' ) || query . query . includes ( VECTOR_PAGE_JOIN )
544+ ? 'page'
522545 : 'probe' ,
523546 query : query . query ,
524547 parameters : query . parameters ,
@@ -1004,13 +1027,10 @@ describe.skipIf(!enabled)('Knowledge search latency on a realistic indexed corpu
10041027 expect ( vectorPlans ) . toHaveLength ( 1 )
10051028 expect ( vectorPlans [ 0 ] . plan [ 0 ] . Plan [ 'Actual Rows' ] ) . toBeGreaterThan ( 0 )
10061029 assertCompactCandidates ( vectorPlans [ 0 ] . plan [ 0 ] . Plan )
1007- expect ( plans . some ( ( plan ) => plan . kind === 'rerank' ) ) . toBe ( true )
1008- const rerank = plans . find ( ( plan ) => plan . kind === 'rerank' ) !
1009- const actual = await db . $client . unsafe ( rerank . query , rerank . parameters ) . values ( )
1010- const expected = await db . execute < { id : string } > ( sql `SELECT id FROM embedding
1011- WHERE knowledge_base_id = ${ ids . knowledgeBaseId } AND enabled
1012- ORDER BY (embedding <=> ${ JSON . stringify ( queryVector ) } ::vector) + 0, id
1013- LIMIT ${ actual . length } ` )
1030+ expect ( plans . some ( ( plan ) => plan . kind === 'page' ) ) . toBe ( true )
1031+ const page = plans . find ( ( plan ) => plan . kind === 'page' ) !
1032+ const actual = await db . $client . unsafe ( page . query , page . parameters ) . values ( )
1033+ const expected = await exactProjectionNeighbors ( queryVector , actual . length )
10141034 const expectedIds = new Set ( expected . map ( ( { id } ) => id ) )
10151035 const recall = actual . filter ( ( [ id ] ) => expectedIds . has ( id ) ) . length / expected . length
10161036 expect ( recall ) . toBeGreaterThanOrEqual ( 0.95 )
@@ -1028,12 +1048,9 @@ describe.skipIf(!enabled)('Knowledge search latency on a realistic indexed corpu
10281048 expectCompleteVectorSearch ( diagnostics )
10291049 const candidates = plans . find ( ( plan ) => plan . kind === 'vector' ) !
10301050 assertCompactCandidates ( candidates . plan [ 0 ] . Plan )
1031- const rerank = plans . find ( ( plan ) => plan . kind === 'rerank' ) !
1032- const actual = await db . $client . unsafe ( rerank . query , rerank . parameters ) . values ( )
1033- const expected = await db . execute < { id : string } > ( sql `SELECT id FROM embedding
1034- WHERE knowledge_base_id = ${ ids . knowledgeBaseId } AND enabled
1035- ORDER BY (embedding <=> ${ JSON . stringify ( topicVector ( topic ) ) } ::vector) + 0, id
1036- LIMIT ${ actual . length } ` )
1051+ const page = plans . find ( ( plan ) => plan . kind === 'page' ) !
1052+ const actual = await db . $client . unsafe ( page . query , page . parameters ) . values ( )
1053+ const expected = await exactProjectionNeighbors ( topicVector ( topic ) , actual . length )
10371054 const expectedIds = new Set ( expected . map ( ( { id } ) => id ) )
10381055 const recall = actual . filter ( ( [ id ] ) => expectedIds . has ( id ) ) . length / expected . length
10391056 expect ( recall ) . toBeGreaterThanOrEqual ( 0.95 )
@@ -1082,15 +1099,14 @@ describe.skipIf(!enabled)('Knowledge search latency on a realistic indexed corpu
10821099 )
10831100 expectCompleteVectorSearch ( diagnostics )
10841101 expect ( result . data . results ) . toHaveLength ( 15 )
1085- const rerank = plans . find ( ( plan ) => plan . kind === 'rerank' ) !
1086- expect ( rerank ) . toBeDefined ( )
1087- const actual = await db . $client . unsafe ( rerank . query , rerank . parameters ) . values ( )
1088- const expected = await db . execute < { id : string } > ( sql `SELECT e.id FROM embedding e
1089- INNER JOIN document d ON d.id = e.document_id
1090- WHERE e.knowledge_base_id = ${ ids . knowledgeBaseId } AND e.enabled
1091- AND d.acl @> ARRAY[${ reader } ]::text[]
1092- ORDER BY (e.embedding <=> ${ JSON . stringify ( queryVector ) } ::vector) + 0, e.id
1093- LIMIT ${ actual . length } ` )
1102+ const page = plans . find ( ( plan ) => plan . kind === 'page' ) !
1103+ expect ( page ) . toBeDefined ( )
1104+ const actual = await db . $client . unsafe ( page . query , page . parameters ) . values ( )
1105+ const expected = await exactProjectionNeighbors (
1106+ queryVector ,
1107+ actual . length ,
1108+ sql `AND d.acl @> ARRAY[${ reader } ]::text[]`
1109+ )
10941110 expect ( expected . length ) . toBeGreaterThan ( 0 )
10951111 const expectedIds = new Set ( expected . map ( ( { id } ) => id ) )
10961112 const recall = actual . filter ( ( [ id ] ) => expectedIds . has ( id ) ) . length / expected . length
@@ -1128,9 +1144,10 @@ describe.skipIf(!enabled)('Knowledge search latency on a realistic indexed corpu
11281144 expect ( probe [ 0 ] . query ) . not . toContain ( '<=>' )
11291145 expect ( probe [ 0 ] . plan [ 0 ] . Plan [ 'Actual Rows' ] ) . toBe ( 12 )
11301146 expect ( assertIndexedChunkProbe ( probe [ 0 ] . plan [ 0 ] . Plan ) ) . toBe ( documentIds . length )
1131- const vector = plans . filter ( ( plan ) => plan . kind === 'rerank' )
1132- expect ( vector ) . toHaveLength ( 1 )
1133- expect ( vector [ 0 ] . query ) . toContain ( '"embedding"."id" in' )
1147+ /** The page reads the bounded ranking's identities from the projection, never the original vectors. */
1148+ const page = plans . filter ( ( plan ) => plan . kind === 'page' )
1149+ expect ( page ) . toHaveLength ( 1 )
1150+ expect ( page [ 0 ] . query ) . not . toContain ( '"embedding"."embedding"' )
11341151 }
11351152 } finally {
11361153 await db
@@ -1175,16 +1192,16 @@ describe.skipIf(!enabled)('Knowledge search latency on a realistic indexed corpu
11751192 count < HYBRID_CANDIDATE_LIMIT ? 0 : 1
11761193 )
11771194 if ( count > HYBRID_CANDIDATE_LIMIT ) {
1178- const rerank = plans . find ( ( plan ) => plan . kind === 'rerank ' ) !
1179- const actual = await db . $client . unsafe ( rerank . query , rerank . parameters ) . values ( )
1180- const expected = await db . execute < { id : string } > ( sql `SELECT id FROM embedding
1181- WHERE knowledge_base_id = ${ ids . knowledgeBaseId } AND enabled
1182- AND document_id IN ( ${ sql . join (
1183- documentIds . map ( ( id ) => sql ` ${ id } ` ) ,
1184- sql `, `
1185- ) } )
1186- ORDER BY (embedding <=> ${ JSON . stringify ( queryVector ) } ::vector) + 0, id
1187- LIMIT ${ actual . length } ` )
1195+ const page = plans . find ( ( plan ) => plan . kind === 'page ' ) !
1196+ const actual = await db . $client . unsafe ( page . query , page . parameters ) . values ( )
1197+ const expected = await exactProjectionNeighbors (
1198+ queryVector ,
1199+ actual . length ,
1200+ sql `AND s.document_id IN ( ${ sql . join (
1201+ documentIds . map ( ( id ) => sql `${ id } ` ) ,
1202+ sql `, `
1203+ ) } )`
1204+ )
11881205 const expectedIds = new Set ( expected . map ( ( { id } ) => id ) )
11891206 const recall = actual . filter ( ( [ id ] ) => expectedIds . has ( id ) ) . length / expected . length
11901207 expect ( recall ) . toBeGreaterThanOrEqual ( 0.95 )
@@ -1352,7 +1369,7 @@ describe.skipIf(!enabled)('Knowledge search latency on a realistic indexed corpu
13521369 )
13531370 expectCompleteVectorSearch ( diagnostics )
13541371 expect ( diagnostics . accessScopeKind ) . toBe ( 'workspace' )
1355- expect ( diagnostics . vectorRanking ) . toBe ( 'candidate-rerank ' )
1372+ expect ( diagnostics . vectorRanking ) . toBe ( 'projection-walk ' )
13561373 expect ( result . data . results ) . toHaveLength ( 15 )
13571374 expect ( plans . some ( ( plan ) => plan . kind === 'vector' ) ) . toBe ( true )
13581375 for ( const row of result . data . results ) {
@@ -1441,7 +1458,7 @@ describe.skipIf(!enabled)('Knowledge search latency on a realistic indexed corpu
14411458 } )
14421459 )
14431460 expectCompleteVectorSearch ( tagged . diagnostics )
1444- expect ( tagged . diagnostics . vectorRanking ) . toBe ( 'candidate-rerank ' )
1461+ expect ( tagged . diagnostics . vectorRanking ) . toBe ( 'projection-walk ' )
14451462 expect ( tagged . result . data . results ) . toHaveLength ( 15 )
14461463 for ( const row of tagged . result . data . results ) {
14471464 const ordinal = Number ( row . documentId . split ( '-doc-' ) [ 1 ] )
0 commit comments