fix(ts-oss/baidu): convert L2 distance to similarity score in search() (#6485)
Co-authored-by: kartik-mem0 <kartik.labhshetwar@mem0.ai>
This commit is contained in:
@@ -453,7 +453,13 @@ export class BaiduDB implements VectorStore {
|
||||
return (response.rows ?? []).map((result) => ({
|
||||
id: String(result.row.id),
|
||||
payload: resultPayload(result.row),
|
||||
score: result.score,
|
||||
// L2 is a distance (lower = closer); the VectorStore contract wants higher = better.
|
||||
score:
|
||||
this.metricType === "L2"
|
||||
? result.score != null
|
||||
? 1 / (1 + result.score)
|
||||
: undefined
|
||||
: result.score,
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
@@ -431,9 +431,12 @@ describe("BaiduDB reads", () => {
|
||||
],
|
||||
});
|
||||
|
||||
const results = await makeStore(client).search([1, 2, 3], 5, {
|
||||
userId: "alice",
|
||||
});
|
||||
// Non-L2 metrics already return a higher-is-better score and pass through untouched.
|
||||
const results = await makeStore(client, { metricType: "COSINE" }).search(
|
||||
[1, 2, 3],
|
||||
5,
|
||||
{ userId: "alice" },
|
||||
);
|
||||
expect(results).toEqual([{ id: "m1", payload: { data: "x" }, score: 0.8 }]);
|
||||
|
||||
const { request } = client.vectorSearch.mock.calls[0][0];
|
||||
@@ -445,6 +448,35 @@ describe("BaiduDB reads", () => {
|
||||
expect(request.config.params).toEqual({ ef: 200 });
|
||||
});
|
||||
|
||||
it("converts an L2 distance into a similarity score (higher = better)", async () => {
|
||||
// Mirrors the Python provider (#6435): 1 / (1 + distance), so closer scores higher.
|
||||
const client = fakeClient();
|
||||
client.vectorSearch.mockResolvedValue({
|
||||
...OK,
|
||||
rows: [
|
||||
{ row: { id: "near", metadata: {} }, score: 0.5 },
|
||||
{ row: { id: "far", metadata: {} }, score: 2.0 },
|
||||
],
|
||||
});
|
||||
|
||||
const results = await makeStore(client).search([1, 2, 3], 2);
|
||||
|
||||
expect(results[0].score).toBeCloseTo(1 / 1.5, 10);
|
||||
expect(results[1].score).toBeCloseTo(1 / 3.0, 10);
|
||||
});
|
||||
|
||||
it("leaves an unscored L2 row's score undefined instead of treating it as the closest match", async () => {
|
||||
const client = fakeClient();
|
||||
client.vectorSearch.mockResolvedValue({
|
||||
...OK,
|
||||
rows: [{ row: { id: "unscored", metadata: {} } }],
|
||||
});
|
||||
|
||||
const results = await makeStore(client).search([1, 2, 3], 1);
|
||||
|
||||
expect(results[0].score).toBeUndefined();
|
||||
});
|
||||
|
||||
it("omits the filter when no filters are supplied", async () => {
|
||||
const client = fakeClient();
|
||||
client.vectorSearch.mockResolvedValue({ ...OK, rows: [] });
|
||||
|
||||
Reference in New Issue
Block a user