@functional-systems/lambdadb 0.4.2 → 0.5.0-rc.1
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/CHANGELOG.md +71 -0
- package/FUNCTIONS.md +7 -2
- package/README.md +60 -2
- package/RUNTIMES.md +7 -0
- package/USAGE.md +20 -0
- package/dist/commonjs/client.d.ts +25 -10
- package/dist/commonjs/client.d.ts.map +1 -1
- package/dist/commonjs/client.js +233 -59
- package/dist/commonjs/client.js.map +1 -1
- package/dist/commonjs/compat/qdrant/client.d.ts +6 -10
- package/dist/commonjs/compat/qdrant/client.d.ts.map +1 -1
- package/dist/commonjs/compat/qdrant/client.js +33 -15
- package/dist/commonjs/compat/qdrant/client.js.map +1 -1
- package/dist/commonjs/compat/qdrant/filters.js +5 -1
- package/dist/commonjs/compat/qdrant/filters.js.map +1 -1
- package/dist/commonjs/funcs/collectionsCreate.js +1 -1
- package/dist/commonjs/funcs/collectionsDelete.js +1 -1
- package/dist/commonjs/funcs/collectionsDocsGetBulkUpsert.js +4 -0
- package/dist/commonjs/funcs/collectionsDocsGetBulkUpsert.js.map +1 -1
- package/dist/commonjs/funcs/collectionsDocsListDocs.js +3 -0
- package/dist/commonjs/funcs/collectionsDocsListDocs.js.map +1 -1
- package/dist/commonjs/funcs/collectionsDocsListDocsExtended.d.ts +15 -0
- package/dist/commonjs/funcs/collectionsDocsListDocsExtended.d.ts.map +1 -0
- package/dist/commonjs/funcs/collectionsDocsListDocsExtended.js +131 -0
- package/dist/commonjs/funcs/collectionsDocsListDocsExtended.js.map +1 -0
- package/dist/commonjs/index.d.ts +4 -1
- package/dist/commonjs/index.d.ts.map +1 -1
- package/dist/commonjs/index.js +15 -1
- package/dist/commonjs/index.js.map +1 -1
- package/dist/commonjs/lib/config.d.ts +2 -2
- package/dist/commonjs/lib/config.js +2 -2
- package/dist/commonjs/lib/config.js.map +1 -1
- package/dist/commonjs/lib/queryInput.d.ts +3 -11
- package/dist/commonjs/lib/queryInput.d.ts.map +1 -1
- package/dist/commonjs/lib/queryInput.js.map +1 -1
- package/dist/commonjs/models/collectionresponse.d.ts +12 -21
- package/dist/commonjs/models/collectionresponse.d.ts.map +1 -1
- package/dist/commonjs/models/collectionresponse.js +5 -6
- package/dist/commonjs/models/collectionresponse.js.map +1 -1
- package/dist/commonjs/models/index.d.ts +1 -0
- package/dist/commonjs/models/index.d.ts.map +1 -1
- package/dist/commonjs/models/index.js +1 -0
- package/dist/commonjs/models/index.js.map +1 -1
- package/dist/commonjs/models/operations/bulkupsertdocs.d.ts +6 -0
- package/dist/commonjs/models/operations/bulkupsertdocs.d.ts.map +1 -1
- package/dist/commonjs/models/operations/bulkupsertdocs.js +2 -0
- package/dist/commonjs/models/operations/bulkupsertdocs.js.map +1 -1
- package/dist/commonjs/models/operations/createcollection.d.ts +20 -13
- package/dist/commonjs/models/operations/createcollection.d.ts.map +1 -1
- package/dist/commonjs/models/operations/createcollection.js +15 -7
- package/dist/commonjs/models/operations/createcollection.js.map +1 -1
- package/dist/commonjs/models/operations/deletedocs.d.ts +3 -0
- package/dist/commonjs/models/operations/deletedocs.d.ts.map +1 -1
- package/dist/commonjs/models/operations/deletedocs.js +1 -0
- package/dist/commonjs/models/operations/deletedocs.js.map +1 -1
- package/dist/commonjs/models/operations/fetchdocs.d.ts +3 -0
- package/dist/commonjs/models/operations/fetchdocs.d.ts.map +1 -1
- package/dist/commonjs/models/operations/fetchdocs.js +9 -0
- package/dist/commonjs/models/operations/fetchdocs.js.map +1 -1
- package/dist/commonjs/models/operations/getbulkupsertdocs.d.ts +5 -0
- package/dist/commonjs/models/operations/getbulkupsertdocs.d.ts.map +1 -1
- package/dist/commonjs/models/operations/getbulkupsertdocs.js +5 -3
- package/dist/commonjs/models/operations/getbulkupsertdocs.js.map +1 -1
- package/dist/commonjs/models/operations/listdocs.d.ts +69 -0
- package/dist/commonjs/models/operations/listdocs.d.ts.map +1 -1
- package/dist/commonjs/models/operations/listdocs.js +41 -1
- package/dist/commonjs/models/operations/listdocs.js.map +1 -1
- package/dist/commonjs/models/operations/querycollection.d.ts +3 -0
- package/dist/commonjs/models/operations/querycollection.d.ts.map +1 -1
- package/dist/commonjs/models/operations/querycollection.js +9 -0
- package/dist/commonjs/models/operations/querycollection.js.map +1 -1
- package/dist/commonjs/models/operations/updatecollection.d.ts +10 -4
- package/dist/commonjs/models/operations/updatecollection.d.ts.map +1 -1
- package/dist/commonjs/models/operations/updatecollection.js +8 -1
- package/dist/commonjs/models/operations/updatecollection.js.map +1 -1
- package/dist/commonjs/models/operations/updatedocs.d.ts +3 -0
- package/dist/commonjs/models/operations/updatedocs.d.ts.map +1 -1
- package/dist/commonjs/models/operations/updatedocs.js +1 -0
- package/dist/commonjs/models/operations/updatedocs.js.map +1 -1
- package/dist/commonjs/models/operations/upsertdocs.d.ts +3 -0
- package/dist/commonjs/models/operations/upsertdocs.d.ts.map +1 -1
- package/dist/commonjs/models/operations/upsertdocs.js +1 -0
- package/dist/commonjs/models/operations/upsertdocs.js.map +1 -1
- package/dist/commonjs/models/versioning.d.ts +100 -0
- package/dist/commonjs/models/versioning.d.ts.map +1 -0
- package/dist/commonjs/models/versioning.js +93 -0
- package/dist/commonjs/models/versioning.js.map +1 -0
- package/dist/commonjs/types/public.d.ts +86 -8
- package/dist/commonjs/types/public.d.ts.map +1 -1
- package/dist/commonjs/types/public.js +30 -7
- package/dist/commonjs/types/public.js.map +1 -1
- package/dist/commonjs/versioning.d.ts +63 -0
- package/dist/commonjs/versioning.d.ts.map +1 -0
- package/dist/commonjs/versioning.js +390 -0
- package/dist/commonjs/versioning.js.map +1 -0
- package/dist/esm/client.d.ts +25 -10
- package/dist/esm/client.d.ts.map +1 -1
- package/dist/esm/client.js +234 -61
- package/dist/esm/client.js.map +1 -1
- package/dist/esm/compat/qdrant/client.d.ts +6 -10
- package/dist/esm/compat/qdrant/client.d.ts.map +1 -1
- package/dist/esm/compat/qdrant/client.js +33 -15
- package/dist/esm/compat/qdrant/client.js.map +1 -1
- package/dist/esm/compat/qdrant/filters.js +5 -1
- package/dist/esm/compat/qdrant/filters.js.map +1 -1
- package/dist/esm/funcs/collectionsCreate.js +1 -1
- package/dist/esm/funcs/collectionsDelete.js +1 -1
- package/dist/esm/funcs/collectionsDocsGetBulkUpsert.js +5 -1
- package/dist/esm/funcs/collectionsDocsGetBulkUpsert.js.map +1 -1
- package/dist/esm/funcs/collectionsDocsListDocs.js +3 -0
- package/dist/esm/funcs/collectionsDocsListDocs.js.map +1 -1
- package/dist/esm/funcs/collectionsDocsListDocsExtended.d.ts +15 -0
- package/dist/esm/funcs/collectionsDocsListDocsExtended.d.ts.map +1 -0
- package/dist/esm/funcs/collectionsDocsListDocsExtended.js +95 -0
- package/dist/esm/funcs/collectionsDocsListDocsExtended.js.map +1 -0
- package/dist/esm/index.d.ts +4 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +3 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/lib/config.d.ts +2 -2
- package/dist/esm/lib/config.js +2 -2
- package/dist/esm/lib/config.js.map +1 -1
- package/dist/esm/lib/queryInput.d.ts +3 -11
- package/dist/esm/lib/queryInput.d.ts.map +1 -1
- package/dist/esm/lib/queryInput.js.map +1 -1
- package/dist/esm/models/collectionresponse.d.ts +12 -21
- package/dist/esm/models/collectionresponse.d.ts.map +1 -1
- package/dist/esm/models/collectionresponse.js +5 -6
- package/dist/esm/models/collectionresponse.js.map +1 -1
- package/dist/esm/models/index.d.ts +1 -0
- package/dist/esm/models/index.d.ts.map +1 -1
- package/dist/esm/models/index.js +1 -0
- package/dist/esm/models/index.js.map +1 -1
- package/dist/esm/models/operations/bulkupsertdocs.d.ts +6 -0
- package/dist/esm/models/operations/bulkupsertdocs.d.ts.map +1 -1
- package/dist/esm/models/operations/bulkupsertdocs.js +2 -0
- package/dist/esm/models/operations/bulkupsertdocs.js.map +1 -1
- package/dist/esm/models/operations/createcollection.d.ts +20 -13
- package/dist/esm/models/operations/createcollection.d.ts.map +1 -1
- package/dist/esm/models/operations/createcollection.js +15 -7
- package/dist/esm/models/operations/createcollection.js.map +1 -1
- package/dist/esm/models/operations/deletedocs.d.ts +3 -0
- package/dist/esm/models/operations/deletedocs.d.ts.map +1 -1
- package/dist/esm/models/operations/deletedocs.js +1 -0
- package/dist/esm/models/operations/deletedocs.js.map +1 -1
- package/dist/esm/models/operations/fetchdocs.d.ts +3 -0
- package/dist/esm/models/operations/fetchdocs.d.ts.map +1 -1
- package/dist/esm/models/operations/fetchdocs.js +9 -0
- package/dist/esm/models/operations/fetchdocs.js.map +1 -1
- package/dist/esm/models/operations/getbulkupsertdocs.d.ts +5 -0
- package/dist/esm/models/operations/getbulkupsertdocs.d.ts.map +1 -1
- package/dist/esm/models/operations/getbulkupsertdocs.js +6 -4
- package/dist/esm/models/operations/getbulkupsertdocs.js.map +1 -1
- package/dist/esm/models/operations/listdocs.d.ts +69 -0
- package/dist/esm/models/operations/listdocs.d.ts.map +1 -1
- package/dist/esm/models/operations/listdocs.js +38 -0
- package/dist/esm/models/operations/listdocs.js.map +1 -1
- package/dist/esm/models/operations/querycollection.d.ts +3 -0
- package/dist/esm/models/operations/querycollection.d.ts.map +1 -1
- package/dist/esm/models/operations/querycollection.js +9 -0
- package/dist/esm/models/operations/querycollection.js.map +1 -1
- package/dist/esm/models/operations/updatecollection.d.ts +10 -4
- package/dist/esm/models/operations/updatecollection.d.ts.map +1 -1
- package/dist/esm/models/operations/updatecollection.js +8 -1
- package/dist/esm/models/operations/updatecollection.js.map +1 -1
- package/dist/esm/models/operations/updatedocs.d.ts +3 -0
- package/dist/esm/models/operations/updatedocs.d.ts.map +1 -1
- package/dist/esm/models/operations/updatedocs.js +1 -0
- package/dist/esm/models/operations/updatedocs.js.map +1 -1
- package/dist/esm/models/operations/upsertdocs.d.ts +3 -0
- package/dist/esm/models/operations/upsertdocs.d.ts.map +1 -1
- package/dist/esm/models/operations/upsertdocs.js +1 -0
- package/dist/esm/models/operations/upsertdocs.js.map +1 -1
- package/dist/esm/models/versioning.d.ts +100 -0
- package/dist/esm/models/versioning.d.ts.map +1 -0
- package/dist/esm/models/versioning.js +57 -0
- package/dist/esm/models/versioning.js.map +1 -0
- package/dist/esm/types/public.d.ts +86 -8
- package/dist/esm/types/public.d.ts.map +1 -1
- package/dist/esm/types/public.js +26 -7
- package/dist/esm/types/public.js.map +1 -1
- package/dist/esm/versioning.d.ts +63 -0
- package/dist/esm/versioning.d.ts.map +1 -0
- package/dist/esm/versioning.js +344 -0
- package/dist/esm/versioning.js.map +1 -0
- package/jsr.json +3 -1
- package/package.json +14 -2
- package/src/client.ts +367 -72
- package/src/compat/qdrant/client.ts +46 -20
- package/src/compat/qdrant/filters.ts +5 -3
- package/src/funcs/collectionsCreate.ts +1 -1
- package/src/funcs/collectionsDelete.ts +1 -1
- package/src/funcs/collectionsDocsGetBulkUpsert.ts +6 -1
- package/src/funcs/collectionsDocsListDocs.ts +3 -0
- package/src/funcs/collectionsDocsListDocsExtended.ts +201 -0
- package/src/index.ts +17 -0
- package/src/lib/config.ts +2 -2
- package/src/lib/queryInput.ts +3 -10
- package/src/models/collectionresponse.ts +17 -26
- package/src/models/index.ts +1 -0
- package/src/models/operations/bulkupsertdocs.ts +8 -0
- package/src/models/operations/createcollection.ts +39 -18
- package/src/models/operations/deletedocs.ts +4 -0
- package/src/models/operations/fetchdocs.ts +12 -0
- package/src/models/operations/getbulkupsertdocs.ts +11 -4
- package/src/models/operations/listdocs.ts +120 -0
- package/src/models/operations/querycollection.ts +12 -0
- package/src/models/operations/updatecollection.ts +21 -3
- package/src/models/operations/updatedocs.ts +4 -0
- package/src/models/operations/upsertdocs.ts +4 -0
- package/src/models/versioning.ts +118 -0
- package/src/types/public.ts +136 -16
- package/src/versioning.ts +490 -0
- package/examples/collectionScoped.example.ts +0 -38
- package/examples/collectionsList.example.ts +0 -25
- package/examples/package-lock.json +0 -612
- package/examples/package.json +0 -18
- package/test/integration/qdrant-compat-external.test.mjs +0 -351
- package/test/integration/qdrant-compat-live.test.mjs +0 -122
- package/test/null-response.test.mjs +0 -73
- package/test/public-api.test.mjs +0 -489
- package/test/qdrant-compat.test.mjs +0 -467
- package/tsconfig.json +0 -39
|
@@ -1,351 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert/strict";
|
|
2
|
-
import test from "node:test";
|
|
3
|
-
|
|
4
|
-
import { Document as LangChainDocument } from "@langchain/core/documents";
|
|
5
|
-
import { QdrantVectorStore as LangChainQdrantVectorStore } from "@langchain/qdrant";
|
|
6
|
-
import { Settings } from "@llamaindex/core/global";
|
|
7
|
-
import { TextNode } from "@llamaindex/core/schema";
|
|
8
|
-
import { QdrantVectorStore as LlamaIndexQdrantVectorStore } from "@llamaindex/qdrant";
|
|
9
|
-
|
|
10
|
-
import { QdrantCompatClient } from "../../dist/esm/compat/qdrant.js";
|
|
11
|
-
|
|
12
|
-
const shouldRun = process.env.LAMBDADB_RUN_EXTERNAL_INTEGRATION_TESTS === "1";
|
|
13
|
-
|
|
14
|
-
class StaticEmbeddings {
|
|
15
|
-
async embedDocuments(texts) {
|
|
16
|
-
return texts.map(vectorForText);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
async embedQuery(text) {
|
|
20
|
-
return vectorForText(text);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
class InMemoryDocs {
|
|
25
|
-
constructor(collection) {
|
|
26
|
-
this.collection = collection;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
async upsert(body) {
|
|
30
|
-
for (const doc of body.docs) {
|
|
31
|
-
this.collection.docs.set(String(doc.id), doc);
|
|
32
|
-
}
|
|
33
|
-
return { message: "ok" };
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
async fetch(body) {
|
|
37
|
-
return {
|
|
38
|
-
docs: body.ids
|
|
39
|
-
.map((id) => this.collection.docs.get(String(id)))
|
|
40
|
-
.filter(Boolean)
|
|
41
|
-
.map((doc) => ({ collection: this.collection.name, doc: projectDoc(doc, body.fields) })),
|
|
42
|
-
total: body.ids.length,
|
|
43
|
-
took: 0,
|
|
44
|
-
isDocsInline: true,
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
async delete(body) {
|
|
49
|
-
if (body.ids) {
|
|
50
|
-
for (const id of body.ids) {
|
|
51
|
-
this.collection.docs.delete(String(id));
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
if (body.filter) {
|
|
55
|
-
for (const [id, doc] of this.collection.docs.entries()) {
|
|
56
|
-
if (matchesLambdaDBFilter(doc, body.filter)) this.collection.docs.delete(id);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
return { message: "ok" };
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
async list(body = {}) {
|
|
63
|
-
return {
|
|
64
|
-
docs: Array.from(this.collection.docs.values())
|
|
65
|
-
.slice(0, body.size ?? 10)
|
|
66
|
-
.map((doc) => ({ collection: this.collection.name, doc: projectDoc(doc, body.fields) })),
|
|
67
|
-
isDocsInline: true,
|
|
68
|
-
total: this.collection.docs.size,
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
class InMemoryCollection {
|
|
74
|
-
constructor(owner, name) {
|
|
75
|
-
this.owner = owner;
|
|
76
|
-
this.name = name;
|
|
77
|
-
this.docs = new Map();
|
|
78
|
-
this.docApi = new InMemoryDocs(this);
|
|
79
|
-
this.indexConfigs = {};
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
handle() {
|
|
83
|
-
return {
|
|
84
|
-
docs: this.docApi,
|
|
85
|
-
get: async () => ({
|
|
86
|
-
collection: {
|
|
87
|
-
collectionName: this.name,
|
|
88
|
-
indexConfigs: this.indexConfigs,
|
|
89
|
-
numDocs: this.docs.size,
|
|
90
|
-
collectionStatus: "ACTIVE",
|
|
91
|
-
},
|
|
92
|
-
}),
|
|
93
|
-
update: async (body) => {
|
|
94
|
-
this.indexConfigs = body.indexConfigs;
|
|
95
|
-
return { collection: { collectionName: this.name, indexConfigs: this.indexConfigs } };
|
|
96
|
-
},
|
|
97
|
-
delete: async () => {
|
|
98
|
-
this.owner.collections.delete(this.name);
|
|
99
|
-
return { message: "ok" };
|
|
100
|
-
},
|
|
101
|
-
query: async (body) => {
|
|
102
|
-
const knn = body.query.knn;
|
|
103
|
-
const queryVector = knn.queryVector;
|
|
104
|
-
const docs = Array.from(this.docs.values())
|
|
105
|
-
.filter((doc) => matchesLambdaDBFilter(doc, knn.filter))
|
|
106
|
-
.map((doc) => ({
|
|
107
|
-
collection: this.name,
|
|
108
|
-
doc: projectDoc(doc, body.fields),
|
|
109
|
-
score: dot(queryVector, doc[knn.field]),
|
|
110
|
-
}))
|
|
111
|
-
.sort((a, b) => b.score - a.score)
|
|
112
|
-
.slice(0, body.size ?? knn.k ?? 10);
|
|
113
|
-
return {
|
|
114
|
-
docs,
|
|
115
|
-
total: docs.length,
|
|
116
|
-
took: 0,
|
|
117
|
-
isDocsInline: true,
|
|
118
|
-
};
|
|
119
|
-
},
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
class InMemoryLambdaDB {
|
|
125
|
-
constructor() {
|
|
126
|
-
this.collections = new Map();
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
async listCollections() {
|
|
130
|
-
return {
|
|
131
|
-
collections: Array.from(this.collections.keys()).map((collectionName) => ({
|
|
132
|
-
collectionName,
|
|
133
|
-
})),
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
async createCollection(body) {
|
|
138
|
-
const collection = this.ensureCollection(body.collectionName);
|
|
139
|
-
collection.indexConfigs = body.indexConfigs ?? {};
|
|
140
|
-
return { collection: { collectionName: body.collectionName } };
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
collection(name) {
|
|
144
|
-
return this.ensureCollection(name).handle();
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
ensureCollection(name) {
|
|
148
|
-
if (!this.collections.has(name)) {
|
|
149
|
-
this.collections.set(name, new InMemoryCollection(this, name));
|
|
150
|
-
}
|
|
151
|
-
return this.collections.get(name);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
test("langchain qdrant vector store works with QdrantCompatClient", {
|
|
156
|
-
skip: shouldRun ? false : "Set LAMBDADB_RUN_EXTERNAL_INTEGRATION_TESTS=1",
|
|
157
|
-
}, async () => {
|
|
158
|
-
Settings.embedModel = {
|
|
159
|
-
getTextEmbedding: async (text) => vectorForText(text),
|
|
160
|
-
getQueryEmbedding: async (text) => vectorForText(text),
|
|
161
|
-
};
|
|
162
|
-
const client = new QdrantCompatClient(new InMemoryLambdaDB());
|
|
163
|
-
const embeddings = new StaticEmbeddings();
|
|
164
|
-
|
|
165
|
-
const store = await LangChainQdrantVectorStore.fromDocuments(
|
|
166
|
-
[
|
|
167
|
-
new LangChainDocument({
|
|
168
|
-
pageContent: "alpha",
|
|
169
|
-
metadata: { tenant: "acme" },
|
|
170
|
-
}),
|
|
171
|
-
new LangChainDocument({
|
|
172
|
-
pageContent: "beta",
|
|
173
|
-
metadata: { tenant: "acme" },
|
|
174
|
-
}),
|
|
175
|
-
],
|
|
176
|
-
embeddings,
|
|
177
|
-
{
|
|
178
|
-
client,
|
|
179
|
-
collectionName: "langchain-docs",
|
|
180
|
-
},
|
|
181
|
-
);
|
|
182
|
-
|
|
183
|
-
const results = await store.similaritySearchVectorWithScore([1, 0, 0], 1);
|
|
184
|
-
|
|
185
|
-
assert.equal(results.length, 1);
|
|
186
|
-
assert.equal(results[0][0].pageContent, "alpha");
|
|
187
|
-
assert.equal(results[0][0].metadata.tenant, "acme");
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
test("langchain qdrant vector store supports filter search and delete", {
|
|
191
|
-
skip: shouldRun ? false : "Set LAMBDADB_RUN_EXTERNAL_INTEGRATION_TESTS=1",
|
|
192
|
-
}, async () => {
|
|
193
|
-
const client = new QdrantCompatClient(new InMemoryLambdaDB());
|
|
194
|
-
const embeddings = new StaticEmbeddings();
|
|
195
|
-
|
|
196
|
-
const store = await LangChainQdrantVectorStore.fromDocuments(
|
|
197
|
-
[
|
|
198
|
-
new LangChainDocument({
|
|
199
|
-
pageContent: "alpha",
|
|
200
|
-
metadata: { tenant: "acme", group: "keep" },
|
|
201
|
-
}),
|
|
202
|
-
new LangChainDocument({
|
|
203
|
-
pageContent: "beta",
|
|
204
|
-
metadata: { tenant: "other", group: "remove" },
|
|
205
|
-
}),
|
|
206
|
-
],
|
|
207
|
-
embeddings,
|
|
208
|
-
{
|
|
209
|
-
client,
|
|
210
|
-
collectionName: "langchain-filter-docs",
|
|
211
|
-
},
|
|
212
|
-
);
|
|
213
|
-
|
|
214
|
-
const filteredResults = await store.similaritySearchVectorWithScore([1, 0, 0], 2, {
|
|
215
|
-
must: [{ key: "content", match: { value: "alpha" } }],
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
assert.equal(filteredResults.length, 1);
|
|
219
|
-
assert.equal(filteredResults[0][0].pageContent, "alpha");
|
|
220
|
-
|
|
221
|
-
await store.delete({
|
|
222
|
-
filter: {
|
|
223
|
-
must: [{ key: "content", match: { value: "beta" } }],
|
|
224
|
-
},
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
const remainingResults = await store.similaritySearchVectorWithScore([0, 1, 0], 2);
|
|
228
|
-
assert.equal(remainingResults.length, 1);
|
|
229
|
-
assert.equal(remainingResults[0][0].pageContent, "alpha");
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
test("llamaindex qdrant vector store works with QdrantCompatClient", {
|
|
233
|
-
skip: shouldRun ? false : "Set LAMBDADB_RUN_EXTERNAL_INTEGRATION_TESTS=1",
|
|
234
|
-
}, async () => {
|
|
235
|
-
const client = new QdrantCompatClient(new InMemoryLambdaDB());
|
|
236
|
-
const store = new LlamaIndexQdrantVectorStore({
|
|
237
|
-
client,
|
|
238
|
-
collectionName: "llamaindex-docs",
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
const alpha = new TextNode({
|
|
242
|
-
text: "alpha",
|
|
243
|
-
metadata: { tenant: "acme" },
|
|
244
|
-
});
|
|
245
|
-
alpha.id_ = "alpha";
|
|
246
|
-
alpha.embedding = [1, 0, 0];
|
|
247
|
-
|
|
248
|
-
const beta = new TextNode({
|
|
249
|
-
text: "beta",
|
|
250
|
-
metadata: { tenant: "acme" },
|
|
251
|
-
});
|
|
252
|
-
beta.id_ = "beta";
|
|
253
|
-
beta.embedding = [0, 1, 0];
|
|
254
|
-
|
|
255
|
-
const ids = await store.add([alpha, beta]);
|
|
256
|
-
assert.deepEqual(ids, ["alpha", "beta"]);
|
|
257
|
-
|
|
258
|
-
const results = await store.query({
|
|
259
|
-
queryEmbedding: [1, 0, 0],
|
|
260
|
-
similarityTopK: 1,
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
assert.equal(results.ids[0], "alpha");
|
|
264
|
-
assert.equal(results.nodes[0].getContent(), "alpha");
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
test("llamaindex qdrant vector store supports delete by filter", {
|
|
268
|
-
skip: shouldRun ? false : "Set LAMBDADB_RUN_EXTERNAL_INTEGRATION_TESTS=1",
|
|
269
|
-
}, async () => {
|
|
270
|
-
const client = new QdrantCompatClient(new InMemoryLambdaDB());
|
|
271
|
-
const store = new LlamaIndexQdrantVectorStore({
|
|
272
|
-
client,
|
|
273
|
-
collectionName: "llamaindex-delete-docs",
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
const alpha = new TextNode({
|
|
277
|
-
text: "alpha",
|
|
278
|
-
metadata: { tenant: "acme" },
|
|
279
|
-
relationships: { SOURCE: { nodeId: "alpha-ref" } },
|
|
280
|
-
});
|
|
281
|
-
alpha.id_ = "alpha";
|
|
282
|
-
alpha.embedding = [1, 0, 0];
|
|
283
|
-
|
|
284
|
-
const beta = new TextNode({
|
|
285
|
-
text: "beta",
|
|
286
|
-
metadata: { tenant: "acme" },
|
|
287
|
-
relationships: { SOURCE: { nodeId: "beta-ref" } },
|
|
288
|
-
});
|
|
289
|
-
beta.id_ = "beta";
|
|
290
|
-
beta.embedding = [0, 1, 0];
|
|
291
|
-
|
|
292
|
-
await store.add([alpha, beta]);
|
|
293
|
-
await store.delete("alpha-ref");
|
|
294
|
-
|
|
295
|
-
const results = await store.query({
|
|
296
|
-
queryEmbedding: [1, 0, 0],
|
|
297
|
-
similarityTopK: 2,
|
|
298
|
-
});
|
|
299
|
-
|
|
300
|
-
assert.deepEqual(results.ids, ["beta"]);
|
|
301
|
-
});
|
|
302
|
-
|
|
303
|
-
function vectorForText(text) {
|
|
304
|
-
if (text.includes("alpha")) return [1, 0, 0];
|
|
305
|
-
if (text.includes("beta")) return [0, 1, 0];
|
|
306
|
-
return [0, 0, 1];
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
function dot(left, right) {
|
|
310
|
-
if (!Array.isArray(left) || !Array.isArray(right)) return 0;
|
|
311
|
-
return left.reduce((sum, value, index) => sum + value * (right[index] ?? 0), 0);
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
function projectDoc(doc, fields) {
|
|
315
|
-
const include = fields?.include;
|
|
316
|
-
if (!Array.isArray(include)) return doc;
|
|
317
|
-
const projected = { id: doc.id };
|
|
318
|
-
for (const field of include) {
|
|
319
|
-
if (field in doc) projected[field] = doc[field];
|
|
320
|
-
}
|
|
321
|
-
return projected;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
function matchesLambdaDBFilter(doc, filter) {
|
|
325
|
-
if (!filter || Object.keys(filter).length === 0) return true;
|
|
326
|
-
if (filter.queryString) return matchesQueryString(doc, filter.queryString.query);
|
|
327
|
-
if (Array.isArray(filter.bool)) return matchesBoolClauses(doc, filter.bool);
|
|
328
|
-
if (filter.bool?.clauses) return matchesBoolClauses(doc, filter.bool.clauses);
|
|
329
|
-
return true;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
function matchesBoolClauses(doc, clauses) {
|
|
333
|
-
const shouldClauses = [];
|
|
334
|
-
for (const clause of clauses) {
|
|
335
|
-
const matched = matchesLambdaDBFilter(doc, clause);
|
|
336
|
-
if (clause.occur === "must_not") {
|
|
337
|
-
if (matched) return false;
|
|
338
|
-
} else if (clause.occur === "should") {
|
|
339
|
-
shouldClauses.push(matched);
|
|
340
|
-
} else if (!matched) {
|
|
341
|
-
return false;
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
return shouldClauses.length === 0 || shouldClauses.some(Boolean);
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
function matchesQueryString(doc, query) {
|
|
348
|
-
const [field, ...rest] = String(query).split(":");
|
|
349
|
-
const expected = rest.join(":");
|
|
350
|
-
return String(doc[field]) === expected;
|
|
351
|
-
}
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert/strict";
|
|
2
|
-
import test from "node:test";
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
QdrantCompatClient,
|
|
6
|
-
UnsupportedQdrantFeatureError,
|
|
7
|
-
models,
|
|
8
|
-
} from "../../dist/esm/compat/qdrant.js";
|
|
9
|
-
|
|
10
|
-
const shouldRun = process.env.LAMBDADB_RUN_LIVE_TESTS === "1";
|
|
11
|
-
const projectApiKey = process.env.LAMBDADB_PROJECT_API_KEY;
|
|
12
|
-
const projectName = process.env.LAMBDADB_PROJECT_NAME || "playground";
|
|
13
|
-
const baseUrl = process.env.LAMBDADB_BASE_URL || "https://api.lambdadb.ai";
|
|
14
|
-
|
|
15
|
-
test("qdrant compatibility live smoke", {
|
|
16
|
-
skip: shouldRun && projectApiKey
|
|
17
|
-
? false
|
|
18
|
-
: "Set LAMBDADB_RUN_LIVE_TESTS=1 and LAMBDADB_PROJECT_API_KEY to run live tests",
|
|
19
|
-
}, async () => {
|
|
20
|
-
const client = new QdrantCompatClient({
|
|
21
|
-
projectApiKey,
|
|
22
|
-
projectName,
|
|
23
|
-
baseUrl,
|
|
24
|
-
});
|
|
25
|
-
const collectionName = `qdrant-live-${Date.now()}`;
|
|
26
|
-
|
|
27
|
-
try {
|
|
28
|
-
await client.createCollection(collectionName, {
|
|
29
|
-
vectorsConfig: new models.VectorParams({
|
|
30
|
-
size: 3,
|
|
31
|
-
distance: models.Distance.COSINE,
|
|
32
|
-
}),
|
|
33
|
-
payloadSchema: {
|
|
34
|
-
tenant: models.PayloadSchemaType.KEYWORD,
|
|
35
|
-
},
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
assert.equal(await client.collectionExists(collectionName), true);
|
|
39
|
-
|
|
40
|
-
const upsertResult = await client.upsert(collectionName, {
|
|
41
|
-
points: [
|
|
42
|
-
new models.PointStruct({
|
|
43
|
-
id: 1,
|
|
44
|
-
vector: [1.0, 0.0, 0.0],
|
|
45
|
-
payload: { tenant: "acme", title: "alpha" },
|
|
46
|
-
}),
|
|
47
|
-
new models.PointStruct({
|
|
48
|
-
id: 2,
|
|
49
|
-
vector: [0.0, 1.0, 0.0],
|
|
50
|
-
payload: { tenant: "acme", title: "beta" },
|
|
51
|
-
}),
|
|
52
|
-
new models.PointStruct({
|
|
53
|
-
id: 3,
|
|
54
|
-
vector: [0.0, 0.0, 1.0],
|
|
55
|
-
payload: { tenant: "other", title: "gamma" },
|
|
56
|
-
}),
|
|
57
|
-
],
|
|
58
|
-
});
|
|
59
|
-
assert.equal(upsertResult.status, models.UpdateStatus.COMPLETED);
|
|
60
|
-
|
|
61
|
-
const queryResult = await client.queryPoints(collectionName, {
|
|
62
|
-
query: [1.0, 0.0, 0.0],
|
|
63
|
-
queryFilter: new models.Filter({
|
|
64
|
-
must: [
|
|
65
|
-
new models.FieldCondition({
|
|
66
|
-
key: "tenant",
|
|
67
|
-
match: new models.MatchValue({ value: "acme" }),
|
|
68
|
-
}),
|
|
69
|
-
],
|
|
70
|
-
}),
|
|
71
|
-
limit: 2,
|
|
72
|
-
});
|
|
73
|
-
assert.ok(queryResult.points.length > 0);
|
|
74
|
-
assert.equal(queryResult.points[0].payload?.tenant, "acme");
|
|
75
|
-
|
|
76
|
-
const records = await client.retrieve(collectionName, { ids: [1] });
|
|
77
|
-
assert.equal(records[0]?.id, 1);
|
|
78
|
-
assert.equal(records[0]?.payload?.tenant, "acme");
|
|
79
|
-
|
|
80
|
-
const deleteResult = await client.delete(collectionName, {
|
|
81
|
-
pointsSelector: [1],
|
|
82
|
-
});
|
|
83
|
-
assert.equal(deleteResult.status, models.UpdateStatus.COMPLETED);
|
|
84
|
-
|
|
85
|
-
const deleteByFilterResult = await client.delete(collectionName, {
|
|
86
|
-
pointsSelector: {
|
|
87
|
-
filter: new models.Filter({
|
|
88
|
-
must: [
|
|
89
|
-
new models.FieldCondition({
|
|
90
|
-
key: "tenant",
|
|
91
|
-
match: new models.MatchValue({ value: "other" }),
|
|
92
|
-
}),
|
|
93
|
-
],
|
|
94
|
-
}),
|
|
95
|
-
},
|
|
96
|
-
});
|
|
97
|
-
assert.equal(deleteByFilterResult.status, models.UpdateStatus.COMPLETED);
|
|
98
|
-
|
|
99
|
-
const deletedByFilterRecords = await client.retrieve(collectionName, { ids: [3] });
|
|
100
|
-
assert.equal(deletedByFilterRecords.length, 0);
|
|
101
|
-
|
|
102
|
-
await assert.rejects(
|
|
103
|
-
client.scroll(collectionName, {
|
|
104
|
-
scrollFilter: new models.Filter({
|
|
105
|
-
must: [
|
|
106
|
-
new models.FieldCondition({
|
|
107
|
-
key: "tenant",
|
|
108
|
-
match: new models.MatchValue({ value: "acme" }),
|
|
109
|
-
}),
|
|
110
|
-
],
|
|
111
|
-
}),
|
|
112
|
-
}),
|
|
113
|
-
UnsupportedQdrantFeatureError,
|
|
114
|
-
);
|
|
115
|
-
} finally {
|
|
116
|
-
try {
|
|
117
|
-
await client.deleteCollection(collectionName);
|
|
118
|
-
} catch (error) {
|
|
119
|
-
if (error?.name !== "ResourceNotFoundError") throw error;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
});
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert/strict";
|
|
2
|
-
import test from "node:test";
|
|
3
|
-
|
|
4
|
-
import { LambdaDBClient } from "../dist/esm/index.js";
|
|
5
|
-
import { HTTPClient } from "../dist/esm/lib/http.js";
|
|
6
|
-
import { ResponseValidationError } from "../dist/esm/models/errors/responsevalidationerror.js";
|
|
7
|
-
import { QueryCollectionResponse$inboundSchema } from "../dist/esm/models/operations/querycollection.js";
|
|
8
|
-
|
|
9
|
-
function jsonResponse(body, init = {}) {
|
|
10
|
-
return new Response(JSON.stringify(body), {
|
|
11
|
-
status: 200,
|
|
12
|
-
headers: { "content-type": "application/json" },
|
|
13
|
-
...init,
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
test("response schemas accept null for optional response fields", () => {
|
|
18
|
-
const parsed = QueryCollectionResponse$inboundSchema.parse({
|
|
19
|
-
took: 1,
|
|
20
|
-
maxScore: null,
|
|
21
|
-
total: 1,
|
|
22
|
-
docs: [{ collection: "items", score: null, doc: { id: "a" } }],
|
|
23
|
-
isDocsInline: false,
|
|
24
|
-
docsUrl: null,
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
assert.equal(parsed.maxScore, undefined);
|
|
28
|
-
assert.equal(parsed.docsUrl, undefined);
|
|
29
|
-
assert.equal(parsed.docs[0].score, undefined);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
test("safe methods return ResponseValidationError for invalid JSON bodies", async () => {
|
|
33
|
-
const httpClient = new HTTPClient({
|
|
34
|
-
fetcher: async () =>
|
|
35
|
-
new Response("{", {
|
|
36
|
-
status: 200,
|
|
37
|
-
headers: { "content-type": "application/json" },
|
|
38
|
-
}),
|
|
39
|
-
});
|
|
40
|
-
const client = new LambdaDBClient({ httpClient, projectApiKey: "test-key" });
|
|
41
|
-
|
|
42
|
-
const result = await client.listCollectionsSafe();
|
|
43
|
-
|
|
44
|
-
assert.equal(result.ok, false);
|
|
45
|
-
assert.ok(result.error instanceof ResponseValidationError);
|
|
46
|
-
assert.equal(result.error.rawValue, "{");
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
test("docsUrl fetches treat null document payloads as an empty docs array", async () => {
|
|
50
|
-
const originalFetch = globalThis.fetch;
|
|
51
|
-
globalThis.fetch = async () => jsonResponse(null);
|
|
52
|
-
|
|
53
|
-
try {
|
|
54
|
-
const httpClient = new HTTPClient({
|
|
55
|
-
fetcher: async () =>
|
|
56
|
-
jsonResponse({
|
|
57
|
-
total: 1,
|
|
58
|
-
docs: [],
|
|
59
|
-
isDocsInline: false,
|
|
60
|
-
docsUrl: "https://example.test/docs.json",
|
|
61
|
-
}),
|
|
62
|
-
});
|
|
63
|
-
const client = new LambdaDBClient({ httpClient, projectApiKey: "test-key" });
|
|
64
|
-
|
|
65
|
-
const result = await client.collection("items").docs.listSafe();
|
|
66
|
-
|
|
67
|
-
assert.equal(result.ok, true);
|
|
68
|
-
assert.deepEqual(result.value.docs, []);
|
|
69
|
-
assert.equal(result.value.isDocsInline, true);
|
|
70
|
-
} finally {
|
|
71
|
-
globalThis.fetch = originalFetch;
|
|
72
|
-
}
|
|
73
|
-
});
|