feat(evidence): add Qdrant BM25 vector in place
This commit is contained in:
@@ -28,6 +28,90 @@ const compatible = (size = 1024, distance = "Cosine", schema = payloadSchema) =>
|
||||
payload_schema: schema,
|
||||
});
|
||||
|
||||
test("Evidence maintenance adds an absent BM25 vector without changing the dense contract", async () => {
|
||||
const info = compatible();
|
||||
const requests: Array<{ url: string; init?: any }> = [];
|
||||
const request = async (url: string, init?: any) => {
|
||||
requests.push({ url, init });
|
||||
if (init?.method === "PUT" && /\/vectors\/bm25$/.test(url)) {
|
||||
expect(JSON.parse(String(init.body))).toEqual({ sparse: { modifier: "idf" } });
|
||||
(info.config.params as any).sparse_vectors = { bm25: { modifier: "idf" } };
|
||||
return { status: 200, ok: true, json: async () => ({}) } as any;
|
||||
}
|
||||
return { status: 200, ok: true, json: async () => ({ result: info }) } as any;
|
||||
};
|
||||
|
||||
const result = await reconcileCollection({
|
||||
baseUrl: "http://qdrant:6333", collection: "c", dimensions: 1024, distance: "cosine",
|
||||
mode: "evidence_maintenance", request,
|
||||
});
|
||||
|
||||
expect(result).toEqual({ ok: true, state: "upgraded" });
|
||||
expect(info.config.params.vectors).toEqual({ size: 1024, distance: "Cosine" });
|
||||
expect(requests.filter(({ init }) => init?.method === "PUT")).toHaveLength(1);
|
||||
expect(requests[1]?.url).toBe("http://qdrant:6333/collections/c/vectors/bm25");
|
||||
});
|
||||
|
||||
test("Evidence maintenance creates a missing collection with both required vector contracts", async () => {
|
||||
let info: any;
|
||||
let createdBody: any;
|
||||
const request = async (url: string, init?: any) => {
|
||||
if (init?.method === "PUT") {
|
||||
createdBody = JSON.parse(String(init.body));
|
||||
info = { config: { params: createdBody }, payload_schema: payloadSchema };
|
||||
return { status: 200, ok: true, json: async () => ({}) } as any;
|
||||
}
|
||||
if (info === undefined) return { status: 404, ok: false, json: async () => ({}) } as any;
|
||||
return { status: 200, ok: true, json: async () => ({ result: info }) } as any;
|
||||
};
|
||||
|
||||
const result = await reconcileCollection({
|
||||
baseUrl: "http://qdrant:6333", collection: "c", dimensions: 1024, distance: "cosine",
|
||||
mode: "evidence_maintenance", request,
|
||||
});
|
||||
|
||||
expect(result).toEqual({ ok: true, state: "ready" });
|
||||
expect(createdBody).toEqual({
|
||||
vectors: { size: 1024, distance: "Cosine" },
|
||||
sparse_vectors: { bm25: { modifier: "idf" } },
|
||||
});
|
||||
});
|
||||
|
||||
test("Evidence maintenance refuses an incompatible BM25 definition without mutating", async () => {
|
||||
const info = compatible();
|
||||
(info.config.params as any).sparse_vectors = { bm25: { modifier: "none" } };
|
||||
const requests: Array<{ url: string; init?: any }> = [];
|
||||
const request = async (url: string, init?: any) => {
|
||||
requests.push({ url, init });
|
||||
return { status: 200, ok: true, json: async () => ({ result: info }) } as any;
|
||||
};
|
||||
|
||||
const result = await reconcileCollection({
|
||||
baseUrl: "http://qdrant:6333", collection: "c", dimensions: 1024, distance: "cosine",
|
||||
mode: "evidence_maintenance", request,
|
||||
});
|
||||
|
||||
expect(result).toEqual({ ok: false, code: "semantic_index_incompatible" });
|
||||
expect(requests.filter(({ init }) => init?.method === "PUT")).toEqual([]);
|
||||
});
|
||||
|
||||
test("ordinary session reconciliation does not add BM25", async () => {
|
||||
const info = compatible();
|
||||
const requests: Array<{ url: string; init?: any }> = [];
|
||||
const request = async (url: string, init?: any) => {
|
||||
requests.push({ url, init });
|
||||
return { status: 200, ok: true, json: async () => ({ result: info }) } as any;
|
||||
};
|
||||
|
||||
const result = await reconcileCollection({
|
||||
baseUrl: "http://qdrant:6333", collection: "c", dimensions: 1024, distance: "cosine",
|
||||
mode: "self_heal", request,
|
||||
});
|
||||
|
||||
expect(result).toEqual({ ok: true, state: "ready" });
|
||||
expect(requests.filter(({ url }) => /\/vectors\/bm25$/.test(url))).toEqual([]);
|
||||
});
|
||||
|
||||
test("self-heal creates a missing compatible collection", async () => {
|
||||
const r = await reconcileCollection({
|
||||
baseUrl: "http://qdrant:6333", collection: "c", dimensions: 1024, distance: "cosine",
|
||||
|
||||
Reference in New Issue
Block a user