Skip to content

Commit 51b4390

Browse files
committed
Pin halfvec index-identity test to the production e.embedding alias
The dense search path qualifies the column as e.embedding; the test was asserting against a bare embedding identity that production never emits. Also document that the dense channel uses cosineDistanceExpr (plain vector or halfvec) rather than a hard-coded embedding <=> $vector.
1 parent 942dcac commit 51b4390

2 files changed

Lines changed: 13 additions & 5 deletions

File tree

‎IMPLEMENTATION.md‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,10 @@ search); otherwise it throws `KnowledgeSearchInputError` (400).
299299
3. **Dense channel** — `fetchDenseCandidates`: embeds the query
300300
(`embedTexts`), resolves the tenant's single active embedding table
301301
(`resolveActiveEmbedTable` — **not** generation-scoped, see limitation
302-
below), runs a raw-SQL cosine-distance ANN query (`embedding <=> $vector`)
302+
below), runs a raw-SQL cosine-distance ANN query via `cosineDistanceExpr`
303+
(`e.embedding <=> $vector` up to 2000 dims, or the matching
304+
`(e.embedding::halfvec(N)) <=> $vector::halfvec(N)` expression above that
305+
so the halfvec HNSW index is used)
303306
against that table joined back to
304307
`knowledge_chunk`/`knowledge_version`/`knowledge_document` with the
305308
**exact same visibility predicate**, hand-mirrored as

‎src/core/embed-model-registry.test.ts‎

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -189,10 +189,15 @@ describe("activateEmbedModel", () => {
189189
expect(indexQuery?.sql).not.toContain("ivfflat");
190190

191191
// The planner only uses an expression index when the query reproduces
192-
// the indexed expression verbatim — pin the two to the same string.
193-
const indexedExpr = `(embedding::halfvec(${dims}))`;
194-
expect(indexQuery?.sql).toContain(`(${indexedExpr} halfvec_cosine_ops)`);
195-
expect(cosineDistanceExpr("embedding", "$1", dims).startsWith(indexedExpr)).toBe(true);
192+
// the indexed expression. DDL indexes bare `embedding`; production dense
193+
// search (search.ts) passes the table-qualified alias `e.embedding` —
194+
// pin the query identity the live path actually emits.
195+
expect(indexQuery?.sql).toContain(
196+
`((embedding::halfvec(${dims})) halfvec_cosine_ops)`,
197+
);
198+
expect(cosineDistanceExpr("e.embedding", "$1", dims)).toBe(
199+
`(e.embedding::halfvec(${dims})) <=> $1::halfvec(${dims})`,
200+
);
196201
});
197202

198203
it("does not fall back to ivfflat when halfvec index creation fails", async () => {

0 commit comments

Comments
 (0)