@vivantel/virage-store-lancedb 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +78 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/query-perf.d.ts +3 -0
- package/dist/query-perf.d.ts.map +1 -0
- package/dist/query-perf.js +49 -0
- package/dist/query-perf.js.map +1 -0
- package/dist/query-perf.test.d.ts +2 -0
- package/dist/query-perf.test.d.ts.map +1 -0
- package/dist/query-perf.test.js +67 -0
- package/dist/query-perf.test.js.map +1 -0
- package/dist/stats.d.ts +3 -0
- package/dist/stats.d.ts.map +1 -0
- package/dist/stats.js +40 -0
- package/dist/stats.js.map +1 -0
- package/dist/stats.test.d.ts +2 -0
- package/dist/stats.test.d.ts.map +1 -0
- package/dist/stats.test.js +96 -0
- package/dist/stats.test.js.map +1 -0
- package/dist/store.d.ts +27 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +131 -0
- package/dist/store.js.map +1 -0
- package/package.json +72 -0
package/README.md
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# @vivantel/virage-store-lancedb
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@vivantel/virage-store-lancedb)
|
|
4
|
+
|
|
5
|
+
LanceDB vector store for [`@vivantel/virage-core`](../rag-core/README.md). Embedded and file-based — no server required. Data lives in a local directory (or LanceDB Cloud with an API key).
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @vivantel/virage-store-lancedb @vivantel/virage-core
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick start (JSON config)
|
|
14
|
+
|
|
15
|
+
Local file storage — no server needed:
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"vectorStore": {
|
|
20
|
+
"package": "@vivantel/virage-store-lancedb",
|
|
21
|
+
"config": {
|
|
22
|
+
"uri": "./lancedb"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## LanceDB Cloud
|
|
29
|
+
|
|
30
|
+
Pass your LanceDB Cloud URI and API key:
|
|
31
|
+
|
|
32
|
+
```json
|
|
33
|
+
{
|
|
34
|
+
"vectorStore": {
|
|
35
|
+
"package": "@vivantel/virage-store-lancedb",
|
|
36
|
+
"config": {
|
|
37
|
+
"uri": "db://my-project",
|
|
38
|
+
"apiKey": "${LANCEDB_API_KEY}"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Configuration
|
|
45
|
+
|
|
46
|
+
| Option | Type | Default | Description |
|
|
47
|
+
|--------|------|---------|-------------|
|
|
48
|
+
| `uri` | `string` | **required** | Local path (`"./lancedb"`) or LanceDB Cloud URI (`"db://…"`) |
|
|
49
|
+
| `apiKey` | `string` | `undefined` | LanceDB Cloud API key |
|
|
50
|
+
| `tableName` | `string` | `"documents"` | Table name inside the database |
|
|
51
|
+
| `dimensions` | `number` | `1536` | Vector size — must match your embedder |
|
|
52
|
+
|
|
53
|
+
## TypeScript usage
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
import { LanceDBVectorStore } from "@vivantel/virage-store-lancedb";
|
|
57
|
+
|
|
58
|
+
const store = new LanceDBVectorStore({
|
|
59
|
+
uri: "./lancedb",
|
|
60
|
+
tableName: "my-docs",
|
|
61
|
+
dimensions: 1536,
|
|
62
|
+
});
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Self-registration
|
|
66
|
+
|
|
67
|
+
This package declares a `"rag-plugin"` field in its `package.json`. Once installed, `virage init` discovers it automatically — no manual config required.
|
|
68
|
+
|
|
69
|
+
```jsonc
|
|
70
|
+
// package.json (excerpt)
|
|
71
|
+
"rag-plugin": {
|
|
72
|
+
"type": "vectorStore",
|
|
73
|
+
"label": "LanceDB (embedded, file-based)",
|
|
74
|
+
"key": "lancedb",
|
|
75
|
+
"envVars": [],
|
|
76
|
+
"defaultConfig": { "uri": "./lancedb" }
|
|
77
|
+
}
|
|
78
|
+
```
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { LanceDBVectorStore, type LanceDBVectorStoreOptions } from "./store.js";
|
|
2
|
+
import type { VectorStore } from "@vivantel/virage-core";
|
|
3
|
+
/** Factory used by the JSON config loader. */
|
|
4
|
+
export declare function createVectorStore(config: Record<string, unknown>): VectorStore;
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,KAAK,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAEhF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAGzD,8CAA8C;AAC9C,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,WAAW,CAeb"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export { LanceDBVectorStore } from "./store.js";
|
|
2
|
+
import { LanceDBVectorStore } from "./store.js";
|
|
3
|
+
/** Factory used by the JSON config loader. */
|
|
4
|
+
export function createVectorStore(config) {
|
|
5
|
+
const uri = typeof config.uri === "string" ? config.uri : undefined;
|
|
6
|
+
if (!uri) {
|
|
7
|
+
throw new Error('@vivantel/virage-store-lancedb: config.uri is required (e.g. "./lancedb" for local file storage)');
|
|
8
|
+
}
|
|
9
|
+
return new LanceDBVectorStore({
|
|
10
|
+
uri,
|
|
11
|
+
apiKey: typeof config.apiKey === "string" ? config.apiKey : undefined,
|
|
12
|
+
tableName: typeof config.tableName === "string" ? config.tableName : undefined,
|
|
13
|
+
dimensions: typeof config.dimensions === "number" ? config.dimensions : undefined,
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAkC,MAAM,YAAY,CAAC;AAGhF,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEhD,8CAA8C;AAC9C,MAAM,UAAU,iBAAiB,CAC/B,MAA+B;IAE/B,MAAM,GAAG,GAAG,OAAO,MAAM,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;IACpE,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CACb,kGAAkG,CACnG,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,kBAAkB,CAAC;QAC5B,GAAG;QACH,MAAM,EAAE,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;QACrE,SAAS,EACP,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;QACrE,UAAU,EACR,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS;KACxE,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-perf.d.ts","sourceRoot":"","sources":["../src/query-perf.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAa7D,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,GAAG,EACV,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,eAAe,CAAC,CA4C1B"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
const SAMPLE_COUNT = 20;
|
|
2
|
+
function percentile(sorted, p) {
|
|
3
|
+
if (sorted.length === 0)
|
|
4
|
+
return -1;
|
|
5
|
+
return (sorted[Math.floor((p / 100) * sorted.length)] ??
|
|
6
|
+
sorted[sorted.length - 1] ??
|
|
7
|
+
0);
|
|
8
|
+
}
|
|
9
|
+
export async function getQueryPerfReport(table, dimensions, timeframeHours) {
|
|
10
|
+
const zeroVector = Array(dimensions).fill(0);
|
|
11
|
+
const latencies = [];
|
|
12
|
+
for (let i = 0; i < SAMPLE_COUNT; i++) {
|
|
13
|
+
const start = performance.now();
|
|
14
|
+
try {
|
|
15
|
+
await table
|
|
16
|
+
.vectorSearch(zeroVector)
|
|
17
|
+
.column("embedding")
|
|
18
|
+
.distanceType("cosine")
|
|
19
|
+
.limit(10)
|
|
20
|
+
.toArray();
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
// Table may be empty or index unavailable — still record timing
|
|
24
|
+
}
|
|
25
|
+
latencies.push(performance.now() - start);
|
|
26
|
+
}
|
|
27
|
+
latencies.sort((a, b) => a - b);
|
|
28
|
+
const p50 = percentile(latencies, 50);
|
|
29
|
+
const p95 = percentile(latencies, 95);
|
|
30
|
+
const p99 = percentile(latencies, 99);
|
|
31
|
+
const slowQueryCount = latencies.filter((ms) => ms > 100).length;
|
|
32
|
+
const suggestedIndexes = [];
|
|
33
|
+
if (p95 > 50) {
|
|
34
|
+
suggestedIndexes.push(`p95 latency (${p95.toFixed(1)} ms) is high. ` +
|
|
35
|
+
`Consider creating an IVF-PQ index to speed up searches.`);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
suggestedIndexes.push("Query performance looks healthy.");
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
timeframeHours,
|
|
42
|
+
p50LatencyMs: Math.round(p50 * 10) / 10,
|
|
43
|
+
p95LatencyMs: Math.round(p95 * 10) / 10,
|
|
44
|
+
p99LatencyMs: Math.round(p99 * 10) / 10,
|
|
45
|
+
slowQueryCount,
|
|
46
|
+
suggestedIndexes,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=query-perf.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-perf.js","sourceRoot":"","sources":["../src/query-perf.ts"],"names":[],"mappings":"AAEA,MAAM,YAAY,GAAG,EAAE,CAAC;AAExB,SAAS,UAAU,CAAC,MAAgB,EAAE,CAAS;IAC7C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC,CAAC;IACnC,OAAO,CACL,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QAC7C,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;QACzB,CAAC,CACF,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,KAAU,EACV,UAAkB,EAClB,cAAsB;IAEtB,MAAM,UAAU,GAAG,KAAK,CAAS,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACrD,MAAM,SAAS,GAAa,EAAE,CAAC;IAE/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QAChC,IAAI,CAAC;YACH,MAAM,KAAK;iBACR,YAAY,CAAC,UAAU,CAAC;iBACxB,MAAM,CAAC,WAAW,CAAC;iBACnB,YAAY,CAAC,QAAQ,CAAC;iBACtB,KAAK,CAAC,EAAE,CAAC;iBACT,OAAO,EAAE,CAAC;QACf,CAAC;QAAC,MAAM,CAAC;YACP,gEAAgE;QAClE,CAAC;QACD,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC;IAC5C,CAAC;IAED,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAEhC,MAAM,GAAG,GAAG,UAAU,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IACtC,MAAM,GAAG,GAAG,UAAU,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IACtC,MAAM,GAAG,GAAG,UAAU,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IACtC,MAAM,cAAc,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,MAAM,CAAC;IAEjE,MAAM,gBAAgB,GAAa,EAAE,CAAC;IACtC,IAAI,GAAG,GAAG,EAAE,EAAE,CAAC;QACb,gBAAgB,CAAC,IAAI,CACnB,gBAAgB,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB;YAC5C,yDAAyD,CAC5D,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,gBAAgB,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;IAC5D,CAAC;IAED,OAAO;QACL,cAAc;QACd,YAAY,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,EAAE,CAAC,GAAG,EAAE;QACvC,YAAY,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,EAAE,CAAC,GAAG,EAAE;QACvC,YAAY,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,EAAE,CAAC,GAAG,EAAE;QACvC,cAAc;QACd,gBAAgB;KACjB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-perf.test.d.ts","sourceRoot":"","sources":["../src/query-perf.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from "vitest";
|
|
2
|
+
import { getQueryPerfReport } from "./query-perf.js";
|
|
3
|
+
function makeTable(searchDelayMs = 5) {
|
|
4
|
+
return {
|
|
5
|
+
vectorSearch: vi.fn().mockReturnValue({
|
|
6
|
+
column: vi.fn().mockReturnThis(),
|
|
7
|
+
distanceType: vi.fn().mockReturnThis(),
|
|
8
|
+
limit: vi.fn().mockReturnThis(),
|
|
9
|
+
toArray: vi
|
|
10
|
+
.fn()
|
|
11
|
+
.mockImplementation(() => new Promise((resolve) => setTimeout(() => resolve([]), searchDelayMs))),
|
|
12
|
+
}),
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
describe("getQueryPerfReport (LanceDB)", () => {
|
|
16
|
+
it("returns valid latency percentiles (p50 ≤ p95 ≤ p99)", async () => {
|
|
17
|
+
const report = await getQueryPerfReport(makeTable(1), 384, 24);
|
|
18
|
+
expect(report.timeframeHours).toBe(24);
|
|
19
|
+
expect(report.p50LatencyMs).toBeGreaterThanOrEqual(0);
|
|
20
|
+
expect(report.p95LatencyMs).toBeGreaterThanOrEqual(report.p50LatencyMs);
|
|
21
|
+
expect(report.p99LatencyMs).toBeGreaterThanOrEqual(report.p95LatencyMs);
|
|
22
|
+
});
|
|
23
|
+
it("timeframeHours is reflected in the report", async () => {
|
|
24
|
+
const report = await getQueryPerfReport(makeTable(1), 384, 48);
|
|
25
|
+
expect(report.timeframeHours).toBe(48);
|
|
26
|
+
});
|
|
27
|
+
it("slowQueryCount is 0 for fast queries (< 100 ms)", async () => {
|
|
28
|
+
const report = await getQueryPerfReport(makeTable(1), 384, 24);
|
|
29
|
+
expect(report.slowQueryCount).toBe(0);
|
|
30
|
+
});
|
|
31
|
+
it("returns healthy suggestion when p95 latency ≤ 50 ms", async () => {
|
|
32
|
+
const report = await getQueryPerfReport(makeTable(1), 384, 24);
|
|
33
|
+
expect(report.suggestedIndexes[0]).toMatch(/healthy/i);
|
|
34
|
+
});
|
|
35
|
+
it("suggests IVF-PQ when p95 latency > 50 ms", async () => {
|
|
36
|
+
const report = await getQueryPerfReport(makeTable(80), 384, 24);
|
|
37
|
+
expect(report.suggestedIndexes[0]).toMatch(/IVF-PQ/i);
|
|
38
|
+
}, 10_000);
|
|
39
|
+
it("records timing even when table.vectorSearch throws", async () => {
|
|
40
|
+
const table = {
|
|
41
|
+
vectorSearch: vi.fn().mockReturnValue({
|
|
42
|
+
column: vi.fn().mockReturnThis(),
|
|
43
|
+
distanceType: vi.fn().mockReturnThis(),
|
|
44
|
+
limit: vi.fn().mockReturnThis(),
|
|
45
|
+
toArray: vi.fn().mockRejectedValue(new Error("table is empty")),
|
|
46
|
+
}),
|
|
47
|
+
};
|
|
48
|
+
const report = await getQueryPerfReport(table, 384, 24);
|
|
49
|
+
// Must still return a report with valid (≥ 0) latencies
|
|
50
|
+
expect(report.p50LatencyMs).toBeGreaterThanOrEqual(0);
|
|
51
|
+
expect(report.slowQueryCount).toBeGreaterThanOrEqual(0);
|
|
52
|
+
});
|
|
53
|
+
it("uses the provided dimensions to build the zero-vector query", async () => {
|
|
54
|
+
const searchSpy = vi.fn().mockReturnValue({
|
|
55
|
+
column: vi.fn().mockReturnThis(),
|
|
56
|
+
distanceType: vi.fn().mockReturnThis(),
|
|
57
|
+
limit: vi.fn().mockReturnThis(),
|
|
58
|
+
toArray: vi.fn().mockResolvedValue([]),
|
|
59
|
+
});
|
|
60
|
+
await getQueryPerfReport({ vectorSearch: searchSpy }, 128, 24);
|
|
61
|
+
// vectorSearch should have been called with a 128-dimensional zero vector
|
|
62
|
+
const firstArg = searchSpy.mock.calls[0][0];
|
|
63
|
+
expect(firstArg).toHaveLength(128);
|
|
64
|
+
expect(firstArg.every((v) => v === 0)).toBe(true);
|
|
65
|
+
});
|
|
66
|
+
}, 30_000);
|
|
67
|
+
//# sourceMappingURL=query-perf.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-perf.test.js","sourceRoot":"","sources":["../src/query-perf.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErD,SAAS,SAAS,CAAC,aAAa,GAAG,CAAC;IAClC,OAAO;QACL,YAAY,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC;YACpC,MAAM,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,cAAc,EAAE;YAChC,YAAY,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,cAAc,EAAE;YACtC,KAAK,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,cAAc,EAAE;YAC/B,OAAO,EAAE,EAAE;iBACR,EAAE,EAAE;iBACJ,kBAAkB,CACjB,GAAG,EAAE,CACH,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CACtB,UAAU,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,aAAa,CAAC,CAC7C,CACJ;SACJ,CAAC;KACH,CAAC;AACJ,CAAC;AAED,QAAQ,CAAC,8BAA8B,EAAE,GAAG,EAAE;IAC5C,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QACnE,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;QAE/D,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACvC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;QACtD,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,sBAAsB,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QACxE,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,sBAAsB,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;QACzD,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;QAC/D,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;QAC/D,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;QAC/D,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QACnE,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;QAC/D,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;QACxD,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;QAChE,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACxD,CAAC,EAAE,MAAM,CAAC,CAAC;IAEX,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,KAAK,GAAG;YACZ,YAAY,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC;gBACpC,MAAM,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,cAAc,EAAE;gBAChC,YAAY,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,cAAc,EAAE;gBACtC,KAAK,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,cAAc,EAAE;gBAC/B,OAAO,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;aAChE,CAAC;SACH,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;QAExD,wDAAwD;QACxD,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;QACtD,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;QAC3E,MAAM,SAAS,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC;YACxC,MAAM,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,cAAc,EAAE;YAChC,YAAY,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,cAAc,EAAE;YACtC,KAAK,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,cAAc,EAAE;YAC/B,OAAO,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,CAAC;SACvC,CAAC,CAAC;QAEH,MAAM,kBAAkB,CAAC,EAAE,YAAY,EAAE,SAAS,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;QAE/D,0EAA0E;QAC1E,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAa,CAAC;QACxD,MAAM,CAAC,QAAQ,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QACnC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;AACL,CAAC,EAAE,MAAM,CAAC,CAAC"}
|
package/dist/stats.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../src/stats.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAGxD,wBAAsB,aAAa,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC,UAAU,CAAC,CA0CnE"}
|
package/dist/stats.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2
|
+
export async function getIndexStats(table) {
|
|
3
|
+
const totalVectors = (await table.countRows());
|
|
4
|
+
const suggestions = [];
|
|
5
|
+
let indexType = "flat";
|
|
6
|
+
try {
|
|
7
|
+
const indices = (await table.listIndices());
|
|
8
|
+
if (indices.length > 0) {
|
|
9
|
+
const types = indices.map((i) => (i.indexType ?? "").toLowerCase());
|
|
10
|
+
if (types.some((t) => t.includes("hnsw"))) {
|
|
11
|
+
indexType = "hnsw";
|
|
12
|
+
}
|
|
13
|
+
else if (types.some((t) => t.includes("ivf"))) {
|
|
14
|
+
indexType = "ivfflat";
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
// listIndices unavailable — assume flat
|
|
20
|
+
}
|
|
21
|
+
if (totalVectors === 0) {
|
|
22
|
+
suggestions.push("Table is empty.");
|
|
23
|
+
}
|
|
24
|
+
else if (totalVectors > 10_000 && indexType === "flat") {
|
|
25
|
+
suggestions.push(`Table has ${totalVectors.toLocaleString()} vectors on a flat index. ` +
|
|
26
|
+
`Consider creating an IVF-PQ index for faster searches.`);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
suggestions.push("Index looks healthy.");
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
totalVectors,
|
|
33
|
+
indexType,
|
|
34
|
+
annRecallAt10: -1,
|
|
35
|
+
indexAgeHours: -1,
|
|
36
|
+
deadTupleFraction: 0,
|
|
37
|
+
suggestions,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=stats.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stats.js","sourceRoot":"","sources":["../src/stats.ts"],"names":[],"mappings":"AAEA,8DAA8D;AAC9D,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,KAAU;IAC5C,MAAM,YAAY,GAAG,CAAC,MAAM,KAAK,CAAC,SAAS,EAAE,CAAW,CAAC;IACzD,MAAM,WAAW,GAAa,EAAE,CAAC;IAEjC,IAAI,SAAS,GAA4B,MAAM,CAAC;IAEhD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,CAAC,MAAM,KAAK,CAAC,WAAW,EAAE,CAGxC,CAAC;QACH,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;YACpE,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;gBAC1C,SAAS,GAAG,MAAM,CAAC;YACrB,CAAC;iBAAM,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;gBAChD,SAAS,GAAG,SAAS,CAAC;YACxB,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,wCAAwC;IAC1C,CAAC;IAED,IAAI,YAAY,KAAK,CAAC,EAAE,CAAC;QACvB,WAAW,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IACtC,CAAC;SAAM,IAAI,YAAY,GAAG,MAAM,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;QACzD,WAAW,CAAC,IAAI,CACd,aAAa,YAAY,CAAC,cAAc,EAAE,4BAA4B;YACpE,wDAAwD,CAC3D,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,WAAW,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;IAC3C,CAAC;IAED,OAAO;QACL,YAAY;QACZ,SAAS;QACT,aAAa,EAAE,CAAC,CAAC;QACjB,aAAa,EAAE,CAAC,CAAC;QACjB,iBAAiB,EAAE,CAAC;QACpB,WAAW;KACZ,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stats.test.d.ts","sourceRoot":"","sources":["../src/stats.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from "vitest";
|
|
2
|
+
import { getIndexStats } from "./stats.js";
|
|
3
|
+
function makeTable(overrides = {}) {
|
|
4
|
+
return {
|
|
5
|
+
countRows: vi.fn().mockResolvedValue(0),
|
|
6
|
+
listIndices: vi.fn().mockResolvedValue([]),
|
|
7
|
+
...overrides,
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
describe("getIndexStats (LanceDB)", () => {
|
|
11
|
+
describe("empty table", () => {
|
|
12
|
+
it("returns flat indexType and empty-table suggestion when table has no rows", async () => {
|
|
13
|
+
const table = makeTable({ countRows: vi.fn().mockResolvedValue(0) });
|
|
14
|
+
const stats = await getIndexStats(table);
|
|
15
|
+
expect(stats.totalVectors).toBe(0);
|
|
16
|
+
expect(stats.indexType).toBe("flat");
|
|
17
|
+
expect(stats.suggestions[0]).toMatch(/empty/i);
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
describe("flat index with various vector counts", () => {
|
|
21
|
+
it("returns healthy suggestion for a small table (≤ 10 000 vectors, no index)", async () => {
|
|
22
|
+
const stats = await getIndexStats(makeTable({ countRows: vi.fn().mockResolvedValue(500) }));
|
|
23
|
+
expect(stats.suggestions[0]).toMatch(/healthy/i);
|
|
24
|
+
});
|
|
25
|
+
it("returns healthy suggestion at exactly 10 000 vectors (boundary)", async () => {
|
|
26
|
+
const stats = await getIndexStats(makeTable({ countRows: vi.fn().mockResolvedValue(10_000) }));
|
|
27
|
+
expect(stats.suggestions[0]).toMatch(/healthy/i);
|
|
28
|
+
});
|
|
29
|
+
it("suggests creating an IVF-PQ index when > 10 000 vectors and no index", async () => {
|
|
30
|
+
const stats = await getIndexStats(makeTable({ countRows: vi.fn().mockResolvedValue(15_000) }));
|
|
31
|
+
expect(stats.totalVectors).toBe(15_000);
|
|
32
|
+
expect(stats.indexType).toBe("flat");
|
|
33
|
+
expect(stats.suggestions[0]).toMatch(/IVF-PQ/i);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
describe("index type detection via listIndices", () => {
|
|
37
|
+
it("detects hnsw from HNSW indexType", async () => {
|
|
38
|
+
const table = makeTable({
|
|
39
|
+
countRows: vi.fn().mockResolvedValue(1000),
|
|
40
|
+
listIndices: vi
|
|
41
|
+
.fn()
|
|
42
|
+
.mockResolvedValue([{ name: "emb_idx", indexType: "HNSW" }]),
|
|
43
|
+
});
|
|
44
|
+
const stats = await getIndexStats(table);
|
|
45
|
+
expect(stats.indexType).toBe("hnsw");
|
|
46
|
+
expect(stats.suggestions[0]).toMatch(/healthy/i);
|
|
47
|
+
});
|
|
48
|
+
it("detects ivfflat from IVF_PQ indexType", async () => {
|
|
49
|
+
const table = makeTable({
|
|
50
|
+
countRows: vi.fn().mockResolvedValue(20_000),
|
|
51
|
+
listIndices: vi
|
|
52
|
+
.fn()
|
|
53
|
+
.mockResolvedValue([{ name: "emb_idx", indexType: "IVF_PQ" }]),
|
|
54
|
+
});
|
|
55
|
+
const stats = await getIndexStats(table);
|
|
56
|
+
expect(stats.indexType).toBe("ivfflat");
|
|
57
|
+
// Has a real index → should be healthy, not suggest IVF-PQ creation
|
|
58
|
+
expect(stats.suggestions[0]).toMatch(/healthy/i);
|
|
59
|
+
});
|
|
60
|
+
it("does not suggest IVF-PQ creation when a non-flat index is present (even > 10k)", async () => {
|
|
61
|
+
const table = makeTable({
|
|
62
|
+
countRows: vi.fn().mockResolvedValue(50_000),
|
|
63
|
+
listIndices: vi
|
|
64
|
+
.fn()
|
|
65
|
+
.mockResolvedValue([{ name: "idx", indexType: "IVF_PQ" }]),
|
|
66
|
+
});
|
|
67
|
+
const stats = await getIndexStats(table);
|
|
68
|
+
expect(stats.suggestions.every((s) => !/IVF-PQ creation/i.test(s))).toBe(true);
|
|
69
|
+
});
|
|
70
|
+
it("falls back to flat when listIndices throws", async () => {
|
|
71
|
+
const table = makeTable({
|
|
72
|
+
countRows: vi.fn().mockResolvedValue(500),
|
|
73
|
+
listIndices: vi.fn().mockRejectedValue(new Error("not supported")),
|
|
74
|
+
});
|
|
75
|
+
const stats = await getIndexStats(table);
|
|
76
|
+
expect(stats.indexType).toBe("flat");
|
|
77
|
+
});
|
|
78
|
+
it("falls back to flat when listIndices returns an empty array", async () => {
|
|
79
|
+
const table = makeTable({
|
|
80
|
+
countRows: vi.fn().mockResolvedValue(500),
|
|
81
|
+
listIndices: vi.fn().mockResolvedValue([]),
|
|
82
|
+
});
|
|
83
|
+
const stats = await getIndexStats(table);
|
|
84
|
+
expect(stats.indexType).toBe("flat");
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
describe("fixed metadata fields", () => {
|
|
88
|
+
it("always returns annRecallAt10 = -1, indexAgeHours = -1, deadTupleFraction = 0", async () => {
|
|
89
|
+
const stats = await getIndexStats(makeTable({ countRows: vi.fn().mockResolvedValue(100) }));
|
|
90
|
+
expect(stats.annRecallAt10).toBe(-1);
|
|
91
|
+
expect(stats.indexAgeHours).toBe(-1);
|
|
92
|
+
expect(stats.deadTupleFraction).toBe(0);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
//# sourceMappingURL=stats.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stats.test.js","sourceRoot":"","sources":["../src/stats.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,SAAS,SAAS,CAAC,YAAqC,EAAE;IACxD,OAAO;QACL,SAAS,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC;QACvC,WAAW,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,CAAC;QAC1C,GAAG,SAAS;KACb,CAAC;AACJ,CAAC;AAED,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;QAC3B,EAAE,CAAC,0EAA0E,EAAE,KAAK,IAAI,EAAE;YACxF,MAAM,KAAK,GAAG,SAAS,CAAC,EAAE,SAAS,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAErE,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,KAAK,CAAC,CAAC;YAEzC,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACnC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACrC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACjD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,uCAAuC,EAAE,GAAG,EAAE;QACrD,EAAE,CAAC,2EAA2E,EAAE,KAAK,IAAI,EAAE;YACzF,MAAM,KAAK,GAAG,MAAM,aAAa,CAC/B,SAAS,CAAC,EAAE,SAAS,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC,CACzD,CAAC;YACF,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iEAAiE,EAAE,KAAK,IAAI,EAAE;YAC/E,MAAM,KAAK,GAAG,MAAM,aAAa,CAC/B,SAAS,CAAC,EAAE,SAAS,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,MAAM,CAAC,EAAE,CAAC,CAC5D,CAAC;YACF,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sEAAsE,EAAE,KAAK,IAAI,EAAE;YACpF,MAAM,KAAK,GAAG,MAAM,aAAa,CAC/B,SAAS,CAAC,EAAE,SAAS,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,MAAM,CAAC,EAAE,CAAC,CAC5D,CAAC;YAEF,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACxC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACrC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAClD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,sCAAsC,EAAE,GAAG,EAAE;QACpD,EAAE,CAAC,kCAAkC,EAAE,KAAK,IAAI,EAAE;YAChD,MAAM,KAAK,GAAG,SAAS,CAAC;gBACtB,SAAS,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC;gBAC1C,WAAW,EAAE,EAAE;qBACZ,EAAE,EAAE;qBACJ,iBAAiB,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;aAC/D,CAAC,CAAC;YAEH,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,KAAK,CAAC,CAAC;YAEzC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACrC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;YACrD,MAAM,KAAK,GAAG,SAAS,CAAC;gBACtB,SAAS,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,MAAM,CAAC;gBAC5C,WAAW,EAAE,EAAE;qBACZ,EAAE,EAAE;qBACJ,iBAAiB,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;aACjE,CAAC,CAAC;YAEH,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,KAAK,CAAC,CAAC;YAEzC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACxC,oEAAoE;YACpE,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gFAAgF,EAAE,KAAK,IAAI,EAAE;YAC9F,MAAM,KAAK,GAAG,SAAS,CAAC;gBACtB,SAAS,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,MAAM,CAAC;gBAC5C,WAAW,EAAE,EAAE;qBACZ,EAAE,EAAE;qBACJ,iBAAiB,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;aAC7D,CAAC,CAAC;YAEH,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,KAAK,CAAC,CAAC;YAEzC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CACtE,IAAI,CACL,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;YAC1D,MAAM,KAAK,GAAG,SAAS,CAAC;gBACtB,SAAS,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,GAAG,CAAC;gBACzC,WAAW,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;aACnE,CAAC,CAAC;YAEH,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,KAAK,CAAC,CAAC;YAEzC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;YAC1E,MAAM,KAAK,GAAG,SAAS,CAAC;gBACtB,SAAS,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,GAAG,CAAC;gBACzC,WAAW,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,CAAC;aAC3C,CAAC,CAAC;YAEH,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,KAAK,CAAC,CAAC;YAEzC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;QACrC,EAAE,CAAC,8EAA8E,EAAE,KAAK,IAAI,EAAE;YAC5F,MAAM,KAAK,GAAG,MAAM,aAAa,CAC/B,SAAS,CAAC,EAAE,SAAS,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC,CACzD,CAAC;YAEF,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YACrC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YACrC,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC1C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/dist/store.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { VectorDocument, VectorSearchResult, VectorStore, IndexStats, QueryPerfReport, Logger } from "@vivantel/virage-core";
|
|
2
|
+
export interface LanceDBVectorStoreOptions {
|
|
3
|
+
uri: string;
|
|
4
|
+
apiKey?: string;
|
|
5
|
+
tableName?: string;
|
|
6
|
+
dimensions?: number;
|
|
7
|
+
}
|
|
8
|
+
export declare class LanceDBVectorStore implements VectorStore {
|
|
9
|
+
readonly name = "lancedb";
|
|
10
|
+
private readonly uri;
|
|
11
|
+
private readonly apiKey;
|
|
12
|
+
private readonly tableName;
|
|
13
|
+
private readonly dimensions;
|
|
14
|
+
private db;
|
|
15
|
+
private table;
|
|
16
|
+
private logger;
|
|
17
|
+
constructor(options: LanceDBVectorStoreOptions);
|
|
18
|
+
setLogger(logger: Logger): void;
|
|
19
|
+
initialize(): Promise<void>;
|
|
20
|
+
upsert(documents: VectorDocument[]): Promise<void>;
|
|
21
|
+
deleteBySourceFile(sourceFiles: string[]): Promise<void>;
|
|
22
|
+
getCurrentState(): Promise<Map<string, string>>;
|
|
23
|
+
getIndexStats(): Promise<IndexStats>;
|
|
24
|
+
getQueryPerfReport(timeframeHours: number): Promise<QueryPerfReport>;
|
|
25
|
+
search(queryEmbedding: number[], topK: number): Promise<VectorSearchResult[]>;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,kBAAkB,EAClB,WAAW,EACX,UAAU,EACV,eAAe,EACf,MAAM,EACP,MAAM,uBAAuB,CAAC;AAK/B,MAAM,WAAW,yBAAyB;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAKD,qBAAa,kBAAmB,YAAW,WAAW;IACpD,QAAQ,CAAC,IAAI,aAAa;IAE1B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IAEpC,OAAO,CAAC,EAAE,CAAM;IAEhB,OAAO,CAAC,KAAK,CAAM;IACnB,OAAO,CAAC,MAAM,CAAuB;gBAEzB,OAAO,EAAE,yBAAyB;IAU9C,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAIzB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IA8B3B,MAAM,CAAC,SAAS,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAyBlD,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAUxD,eAAe,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAoB/C,aAAa,IAAI,OAAO,CAAC,UAAU,CAAC;IAIpC,kBAAkB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAIpE,MAAM,CACV,cAAc,EAAE,MAAM,EAAE,EACxB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,kBAAkB,EAAE,CAAC;CAiCjC"}
|
package/dist/store.js
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { Field, FixedSizeList, Float32, Schema, Utf8 } from "apache-arrow";
|
|
2
|
+
import { getIndexStats } from "./stats.js";
|
|
3
|
+
import { getQueryPerfReport } from "./query-perf.js";
|
|
4
|
+
const DEFAULT_TABLE = "documents";
|
|
5
|
+
const DEFAULT_DIMENSIONS = 1536;
|
|
6
|
+
export class LanceDBVectorStore {
|
|
7
|
+
name = "lancedb";
|
|
8
|
+
uri;
|
|
9
|
+
apiKey;
|
|
10
|
+
tableName;
|
|
11
|
+
dimensions;
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
13
|
+
db;
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
15
|
+
table;
|
|
16
|
+
logger = null;
|
|
17
|
+
constructor(options) {
|
|
18
|
+
if (!options.uri) {
|
|
19
|
+
throw new Error("LanceDBVectorStore: uri is required");
|
|
20
|
+
}
|
|
21
|
+
this.uri = options.uri;
|
|
22
|
+
this.apiKey = options.apiKey;
|
|
23
|
+
this.tableName = options.tableName ?? DEFAULT_TABLE;
|
|
24
|
+
this.dimensions = options.dimensions ?? DEFAULT_DIMENSIONS;
|
|
25
|
+
}
|
|
26
|
+
setLogger(logger) {
|
|
27
|
+
this.logger = logger.withTag("lancedb");
|
|
28
|
+
}
|
|
29
|
+
async initialize() {
|
|
30
|
+
this.logger?.info(`Connecting to lancedb at ${this.uri}, table: ${this.tableName}`);
|
|
31
|
+
// Dynamic import to avoid native-module issues at load time
|
|
32
|
+
const lancedb = await import("@lancedb/lancedb");
|
|
33
|
+
this.db = this.apiKey
|
|
34
|
+
? await lancedb.connect(this.uri, { apiKey: this.apiKey })
|
|
35
|
+
: await lancedb.connect(this.uri);
|
|
36
|
+
const schema = new Schema([
|
|
37
|
+
new Field("id", new Utf8()),
|
|
38
|
+
new Field("content", new Utf8()),
|
|
39
|
+
new Field("embedding", new FixedSizeList(this.dimensions, new Field("item", new Float32()))),
|
|
40
|
+
new Field("metadata_json", new Utf8()),
|
|
41
|
+
new Field("source_file", new Utf8()),
|
|
42
|
+
new Field("commit_hash", new Utf8()),
|
|
43
|
+
new Field("content_hash", new Utf8()),
|
|
44
|
+
]);
|
|
45
|
+
this.table = await this.db.createEmptyTable(this.tableName, schema, {
|
|
46
|
+
existOk: true,
|
|
47
|
+
});
|
|
48
|
+
this.logger?.debug(`Table "${this.tableName}" ready (${this.dimensions}d)`);
|
|
49
|
+
}
|
|
50
|
+
async upsert(documents) {
|
|
51
|
+
this.logger?.verbose(`Upserting ${documents.length} docs into "${this.tableName}"`);
|
|
52
|
+
const rows = documents.map((doc) => ({
|
|
53
|
+
id: doc.id ?? crypto.randomUUID(),
|
|
54
|
+
content: doc.content,
|
|
55
|
+
embedding: doc.embedding,
|
|
56
|
+
metadata_json: JSON.stringify(doc.metadata),
|
|
57
|
+
source_file: doc.sourceFile,
|
|
58
|
+
commit_hash: doc.commitHash,
|
|
59
|
+
content_hash: doc.contentHash,
|
|
60
|
+
}));
|
|
61
|
+
this.logger?.trace(` Row IDs: ${rows.map((r) => r.id.slice(0, 8)).join(", ")}`);
|
|
62
|
+
await this.table
|
|
63
|
+
.mergeInsert("id")
|
|
64
|
+
.whenMatchedUpdateAll()
|
|
65
|
+
.whenNotMatchedInsertAll()
|
|
66
|
+
.execute(rows);
|
|
67
|
+
}
|
|
68
|
+
async deleteBySourceFile(sourceFiles) {
|
|
69
|
+
if (sourceFiles.length === 0)
|
|
70
|
+
return;
|
|
71
|
+
this.logger?.verbose(`Deleting docs for ${sourceFiles.length} source file(s)`);
|
|
72
|
+
const escaped = sourceFiles.map((f) => f.replace(/'/g, "''"));
|
|
73
|
+
const list = escaped.map((f) => `'${f}'`).join(", ");
|
|
74
|
+
await this.table.delete(`source_file IN (${list})`);
|
|
75
|
+
}
|
|
76
|
+
async getCurrentState() {
|
|
77
|
+
const rows = await this.table
|
|
78
|
+
.query()
|
|
79
|
+
.select(["source_file", "commit_hash"])
|
|
80
|
+
.toArray();
|
|
81
|
+
const state = new Map();
|
|
82
|
+
for (const row of rows) {
|
|
83
|
+
const sourceFile = typeof row.source_file === "string" ? row.source_file : null;
|
|
84
|
+
const commitHash = typeof row.commit_hash === "string" ? row.commit_hash : null;
|
|
85
|
+
if (sourceFile && commitHash) {
|
|
86
|
+
state.set(sourceFile, commitHash);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
this.logger?.verbose(`getCurrentState: ${state.size} source version(s)`);
|
|
90
|
+
return state;
|
|
91
|
+
}
|
|
92
|
+
async getIndexStats() {
|
|
93
|
+
return getIndexStats(this.table);
|
|
94
|
+
}
|
|
95
|
+
async getQueryPerfReport(timeframeHours) {
|
|
96
|
+
return getQueryPerfReport(this.table, this.dimensions, timeframeHours);
|
|
97
|
+
}
|
|
98
|
+
async search(queryEmbedding, topK) {
|
|
99
|
+
this.logger?.debug(`Search: topK=${topK}`);
|
|
100
|
+
const rows = await this.table
|
|
101
|
+
.vectorSearch(queryEmbedding)
|
|
102
|
+
.column("embedding")
|
|
103
|
+
.distanceType("cosine")
|
|
104
|
+
.limit(topK)
|
|
105
|
+
.toArray();
|
|
106
|
+
return rows.map((row) => {
|
|
107
|
+
const distance = typeof row._distance === "number" ? row._distance : 1;
|
|
108
|
+
return {
|
|
109
|
+
id: typeof row.id === "string" ? row.id : "",
|
|
110
|
+
content: typeof row.content === "string" ? row.content : "",
|
|
111
|
+
metadata: (() => {
|
|
112
|
+
try {
|
|
113
|
+
const parsed = typeof row.metadata_json === "string"
|
|
114
|
+
? JSON.parse(row.metadata_json)
|
|
115
|
+
: {};
|
|
116
|
+
return parsed &&
|
|
117
|
+
typeof parsed === "object" &&
|
|
118
|
+
!Array.isArray(parsed)
|
|
119
|
+
? parsed
|
|
120
|
+
: {};
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return {};
|
|
124
|
+
}
|
|
125
|
+
})(),
|
|
126
|
+
similarity: 1 - distance,
|
|
127
|
+
};
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vivantel/virage-store-lancedb",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "LanceDB vector store for @vivantel/rag-core (embedded, file-based)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"README.md"
|
|
17
|
+
],
|
|
18
|
+
"sideEffects": false,
|
|
19
|
+
"publishConfig": {
|
|
20
|
+
"access": "public"
|
|
21
|
+
},
|
|
22
|
+
"rag-plugin": {
|
|
23
|
+
"type": "vectorStore",
|
|
24
|
+
"label": "LanceDB (embedded, file-based)",
|
|
25
|
+
"key": "lancedb",
|
|
26
|
+
"envVars": [],
|
|
27
|
+
"defaultConfig": {
|
|
28
|
+
"uri": "./lancedb"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "tsc",
|
|
33
|
+
"type-check": "tsc --noEmit",
|
|
34
|
+
"test": "vitest run",
|
|
35
|
+
"prepublishOnly": "npm run build",
|
|
36
|
+
"lint": "eslint src/",
|
|
37
|
+
"lint:fix": "eslint src/ --fix",
|
|
38
|
+
"format": "prettier --write \"src/**/*.ts\"",
|
|
39
|
+
"fix": "npm run lint:fix && npm run format"
|
|
40
|
+
},
|
|
41
|
+
"keywords": [
|
|
42
|
+
"rag",
|
|
43
|
+
"vector-store",
|
|
44
|
+
"lancedb",
|
|
45
|
+
"vector-database",
|
|
46
|
+
"semantic-search",
|
|
47
|
+
"embedded"
|
|
48
|
+
],
|
|
49
|
+
"author": "Vivantel",
|
|
50
|
+
"license": "MIT",
|
|
51
|
+
"repository": {
|
|
52
|
+
"type": "git",
|
|
53
|
+
"url": "https://github.com/vivantel/virage",
|
|
54
|
+
"directory": "packages/virage-store-lancedb"
|
|
55
|
+
},
|
|
56
|
+
"dependencies": {
|
|
57
|
+
"@lancedb/lancedb": "^0.18.0",
|
|
58
|
+
"apache-arrow": "^18.0.0"
|
|
59
|
+
},
|
|
60
|
+
"peerDependencies": {
|
|
61
|
+
"@vivantel/virage-core": "*"
|
|
62
|
+
},
|
|
63
|
+
"devDependencies": {
|
|
64
|
+
"@types/node": "^25.9.1",
|
|
65
|
+
"@vivantel/virage-core": "0.2.0",
|
|
66
|
+
"typescript": "^6.0.3",
|
|
67
|
+
"vitest": "^4.1.8"
|
|
68
|
+
},
|
|
69
|
+
"engines": {
|
|
70
|
+
"node": ">=18.0.0"
|
|
71
|
+
}
|
|
72
|
+
}
|