@anvia/weaviate 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/LICENSE +21 -0
- package/dist/index.d.ts +70 -0
- package/dist/index.js +234 -0
- package/dist/index.js.map +1 -0
- package/package.json +43 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Indra Zulfi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { VectorFilter, VectorSearchIndex, VectorSearchRequest, VectorSearchResult, VectorSearchToolOptions } from '@anvia/core/vector-store';
|
|
2
|
+
import { VectorMetadata, EmbeddingModel, EmbeddedDocument } from '@anvia/core/embeddings';
|
|
3
|
+
import { Tool } from '@anvia/core/tool';
|
|
4
|
+
|
|
5
|
+
declare function filterToWeaviateWhere(filter: VectorFilter | undefined): unknown;
|
|
6
|
+
|
|
7
|
+
type WeaviateDistance = "cosine" | "dot" | "l2" | "manhattan" | "hamming";
|
|
8
|
+
type WeaviateCollectionLike = {
|
|
9
|
+
query: {
|
|
10
|
+
nearVector(params: NearVectorParams): Promise<Array<Record<string, unknown>>>;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
type WeaviateCollectionsLike = {
|
|
14
|
+
create(config: Record<string, unknown>): Promise<unknown>;
|
|
15
|
+
get(name: string): WeaviateCollectionLike;
|
|
16
|
+
delete(name: string): Promise<unknown>;
|
|
17
|
+
exists(name: string): Promise<boolean>;
|
|
18
|
+
};
|
|
19
|
+
type WeaviateBatcherLike = {
|
|
20
|
+
withObject(obj: Record<string, unknown>): WeaviateBatcherLike;
|
|
21
|
+
do(): Promise<unknown>;
|
|
22
|
+
};
|
|
23
|
+
type WeaviateBatchLike = {
|
|
24
|
+
objectsBatcher(): WeaviateBatcherLike;
|
|
25
|
+
};
|
|
26
|
+
type NearVectorParams = {
|
|
27
|
+
vector: number[];
|
|
28
|
+
limit?: number | undefined;
|
|
29
|
+
filters?: unknown | undefined;
|
|
30
|
+
returnMetadata?: string[] | undefined;
|
|
31
|
+
returnProperties?: string[] | undefined;
|
|
32
|
+
};
|
|
33
|
+
type WeaviateClientLike = {
|
|
34
|
+
collections: WeaviateCollectionsLike;
|
|
35
|
+
batch: WeaviateBatchLike;
|
|
36
|
+
};
|
|
37
|
+
type WeaviateVectorStoreConnectOptions = {
|
|
38
|
+
client?: WeaviateClientLike | undefined;
|
|
39
|
+
className: string;
|
|
40
|
+
vectorSize: number;
|
|
41
|
+
createIfMissing?: boolean | undefined;
|
|
42
|
+
distance?: WeaviateDistance | undefined;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
declare class WeaviateVectorIndex<T, Metadata extends VectorMetadata = VectorMetadata> implements VectorSearchIndex<T, Metadata> {
|
|
46
|
+
private readonly model;
|
|
47
|
+
private readonly client;
|
|
48
|
+
private readonly className;
|
|
49
|
+
constructor(model: EmbeddingModel, client: WeaviateClientLike, className: string);
|
|
50
|
+
search(request: VectorSearchRequest): Promise<Array<VectorSearchResult<T, Metadata>>>;
|
|
51
|
+
searchIds(request: VectorSearchRequest): Promise<Array<{
|
|
52
|
+
score: number;
|
|
53
|
+
id: string;
|
|
54
|
+
}>>;
|
|
55
|
+
asTool(options: VectorSearchToolOptions): Tool<{
|
|
56
|
+
query: string;
|
|
57
|
+
topK?: number;
|
|
58
|
+
}, unknown>;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
declare class WeaviateVectorStore<T, Metadata extends VectorMetadata = VectorMetadata> {
|
|
62
|
+
private readonly client;
|
|
63
|
+
private readonly className;
|
|
64
|
+
private constructor();
|
|
65
|
+
static connect<T, Metadata extends VectorMetadata = VectorMetadata>(options: WeaviateVectorStoreConnectOptions): Promise<WeaviateVectorStore<T, Metadata>>;
|
|
66
|
+
upsertDocuments(documents: Array<EmbeddedDocument<T, Metadata>>): Promise<void>;
|
|
67
|
+
index(model: EmbeddingModel): WeaviateVectorIndex<T, Metadata>;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export { type WeaviateBatchLike, type WeaviateBatcherLike, type WeaviateClientLike, type WeaviateCollectionLike, type WeaviateCollectionsLike, type WeaviateDistance, WeaviateVectorIndex, WeaviateVectorStore, type WeaviateVectorStoreConnectOptions, filterToWeaviateWhere };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
// src/filters.ts
|
|
2
|
+
function filterToWeaviateWhere(filter) {
|
|
3
|
+
if (filter === void 0) {
|
|
4
|
+
return void 0;
|
|
5
|
+
}
|
|
6
|
+
switch (filter.type) {
|
|
7
|
+
case "eq":
|
|
8
|
+
return {
|
|
9
|
+
operator: "Equal",
|
|
10
|
+
path: [filter.key],
|
|
11
|
+
valueString: typeof filter.value === "string" ? filter.value : void 0,
|
|
12
|
+
valueInt: typeof filter.value === "number" ? filter.value : void 0,
|
|
13
|
+
valueBoolean: typeof filter.value === "boolean" ? filter.value : void 0,
|
|
14
|
+
valueNumber: typeof filter.value === "number" ? filter.value : void 0
|
|
15
|
+
};
|
|
16
|
+
case "gt":
|
|
17
|
+
return {
|
|
18
|
+
operator: "GreaterThan",
|
|
19
|
+
path: [filter.key],
|
|
20
|
+
valueNumber: typeof filter.value === "number" ? filter.value : void 0,
|
|
21
|
+
valueString: typeof filter.value === "string" ? filter.value : void 0
|
|
22
|
+
};
|
|
23
|
+
case "lt":
|
|
24
|
+
return {
|
|
25
|
+
operator: "LessThan",
|
|
26
|
+
path: [filter.key],
|
|
27
|
+
valueNumber: typeof filter.value === "number" ? filter.value : void 0,
|
|
28
|
+
valueString: typeof filter.value === "string" ? filter.value : void 0
|
|
29
|
+
};
|
|
30
|
+
case "and":
|
|
31
|
+
return {
|
|
32
|
+
operator: "And",
|
|
33
|
+
operands: filter.filters.map(filterToWeaviateWhere)
|
|
34
|
+
};
|
|
35
|
+
case "or":
|
|
36
|
+
return {
|
|
37
|
+
operator: "Or",
|
|
38
|
+
operands: filter.filters.map(filterToWeaviateWhere)
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// src/search-index.ts
|
|
44
|
+
import { embedText } from "@anvia/core/embeddings";
|
|
45
|
+
import {
|
|
46
|
+
createVectorSearchTool
|
|
47
|
+
} from "@anvia/core/vector-store";
|
|
48
|
+
|
|
49
|
+
// src/helpers.ts
|
|
50
|
+
import { createHash } from "crypto";
|
|
51
|
+
|
|
52
|
+
// src/types.ts
|
|
53
|
+
var documentIdPropertyKey = "__anvia_document_id";
|
|
54
|
+
var documentPropertyKey = "__anvia_document";
|
|
55
|
+
var reservedPropertyPrefix = "__anvia_";
|
|
56
|
+
|
|
57
|
+
// src/helpers.ts
|
|
58
|
+
function assertNoReservedMetadata(metadata) {
|
|
59
|
+
for (const key of Object.keys(metadata ?? {})) {
|
|
60
|
+
if (key.startsWith(reservedPropertyPrefix)) {
|
|
61
|
+
throw new Error(`Metadata key ${key} is reserved for Anvia Weaviate properties`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function pointId(id) {
|
|
66
|
+
const hex = createHash("sha256").update(id).digest("hex").slice(0, 32);
|
|
67
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(
|
|
68
|
+
16,
|
|
69
|
+
20
|
|
70
|
+
)}-${hex.slice(20)}`;
|
|
71
|
+
}
|
|
72
|
+
function serializeDocument(document) {
|
|
73
|
+
return typeof document === "string" ? document : JSON.stringify(document);
|
|
74
|
+
}
|
|
75
|
+
function parseDocument(document) {
|
|
76
|
+
if (document === null || document === void 0) {
|
|
77
|
+
return "";
|
|
78
|
+
}
|
|
79
|
+
if (typeof document !== "string") {
|
|
80
|
+
return document;
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
return JSON.parse(document);
|
|
84
|
+
} catch {
|
|
85
|
+
return document;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function weaviateObjects(className, document) {
|
|
89
|
+
if (document.embeddings.length === 0) {
|
|
90
|
+
throw new Error(`Document ${document.id} has no embeddings`);
|
|
91
|
+
}
|
|
92
|
+
assertNoReservedMetadata(document.metadata);
|
|
93
|
+
return document.embeddings.map((embedding, index) => {
|
|
94
|
+
const logicalId = document.embeddings.length === 1 ? document.id : `${document.id}#embedding:${index}`;
|
|
95
|
+
return {
|
|
96
|
+
class: className,
|
|
97
|
+
id: pointId(logicalId),
|
|
98
|
+
vector: embedding.vector,
|
|
99
|
+
properties: {
|
|
100
|
+
[documentIdPropertyKey]: document.id,
|
|
101
|
+
[documentPropertyKey]: serializeDocument(document.document),
|
|
102
|
+
...document.metadata ?? {}
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
function parseQueryResults(response, threshold) {
|
|
108
|
+
const byId = /* @__PURE__ */ new Map();
|
|
109
|
+
for (const item of response) {
|
|
110
|
+
const additional = item._additional;
|
|
111
|
+
const certainty = additional?.certainty;
|
|
112
|
+
const distance = additional?.distance;
|
|
113
|
+
const score = certainty ?? (distance !== void 0 ? 1 - distance : 0);
|
|
114
|
+
if (threshold !== void 0 && score < threshold) {
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
const id = String(item[documentIdPropertyKey] ?? "");
|
|
118
|
+
const result = {
|
|
119
|
+
id,
|
|
120
|
+
score,
|
|
121
|
+
document: parseDocument(item[documentPropertyKey]),
|
|
122
|
+
...metadataFromProperties(item)
|
|
123
|
+
};
|
|
124
|
+
const current = byId.get(id);
|
|
125
|
+
if (current === void 0 || result.score > current.score) {
|
|
126
|
+
byId.set(id, result);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return [...byId.values()];
|
|
130
|
+
}
|
|
131
|
+
async function defaultWeaviateClient() {
|
|
132
|
+
const weaviate = await import("weaviate-client");
|
|
133
|
+
const defaultExport = weaviate.default ?? weaviate;
|
|
134
|
+
const host = process.env.WEAVIATE_HOST ?? "localhost:8080";
|
|
135
|
+
const grpcHost = process.env.WEAVIATE_GRPC_HOST ?? "localhost:50051";
|
|
136
|
+
const client = await defaultExport.connectToCustom({
|
|
137
|
+
httpHost: host,
|
|
138
|
+
httpSecure: false,
|
|
139
|
+
grpcHost,
|
|
140
|
+
grpcSecure: false
|
|
141
|
+
});
|
|
142
|
+
return client;
|
|
143
|
+
}
|
|
144
|
+
function metadataFromProperties(properties) {
|
|
145
|
+
const metadata = Object.fromEntries(
|
|
146
|
+
Object.entries(properties).filter(
|
|
147
|
+
([key]) => !key.startsWith(reservedPropertyPrefix) && key !== "_additional"
|
|
148
|
+
)
|
|
149
|
+
);
|
|
150
|
+
return Object.keys(metadata).length === 0 ? {} : { metadata };
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// src/search-index.ts
|
|
154
|
+
var WeaviateVectorIndex = class {
|
|
155
|
+
constructor(model, client, className) {
|
|
156
|
+
this.model = model;
|
|
157
|
+
this.client = client;
|
|
158
|
+
this.className = className;
|
|
159
|
+
}
|
|
160
|
+
model;
|
|
161
|
+
client;
|
|
162
|
+
className;
|
|
163
|
+
async search(request) {
|
|
164
|
+
const queryEmbedding = await embedText(this.model, request.query);
|
|
165
|
+
const collection = this.client.collections.get(this.className);
|
|
166
|
+
const filters = filterToWeaviateWhere(request.filter);
|
|
167
|
+
const response = await collection.query.nearVector({
|
|
168
|
+
vector: queryEmbedding.vector,
|
|
169
|
+
limit: request.topK,
|
|
170
|
+
filters,
|
|
171
|
+
returnMetadata: ["certainty", "distance"],
|
|
172
|
+
returnProperties: [documentIdPropertyKey, documentPropertyKey]
|
|
173
|
+
});
|
|
174
|
+
return parseQueryResults(response, request.threshold);
|
|
175
|
+
}
|
|
176
|
+
async searchIds(request) {
|
|
177
|
+
return (await this.search(request)).map(({ score, id }) => ({ score, id }));
|
|
178
|
+
}
|
|
179
|
+
asTool(options) {
|
|
180
|
+
return createVectorSearchTool(this, options);
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
// src/store.ts
|
|
185
|
+
var WeaviateVectorStore = class _WeaviateVectorStore {
|
|
186
|
+
constructor(client, className) {
|
|
187
|
+
this.client = client;
|
|
188
|
+
this.className = className;
|
|
189
|
+
}
|
|
190
|
+
client;
|
|
191
|
+
className;
|
|
192
|
+
static async connect(options) {
|
|
193
|
+
const client = options.client ?? await defaultWeaviateClient();
|
|
194
|
+
if (options.createIfMissing === false) {
|
|
195
|
+
const exists2 = await client.collections.exists(options.className);
|
|
196
|
+
if (!exists2) {
|
|
197
|
+
throw new Error(`Collection ${options.className} does not exist`);
|
|
198
|
+
}
|
|
199
|
+
return new _WeaviateVectorStore(client, options.className);
|
|
200
|
+
}
|
|
201
|
+
const exists = await client.collections.exists(options.className);
|
|
202
|
+
if (!exists) {
|
|
203
|
+
await client.collections.create({
|
|
204
|
+
name: options.className,
|
|
205
|
+
vectorizers: null,
|
|
206
|
+
vectorIndexConfig: {
|
|
207
|
+
distance: options.distance ?? "cosine"
|
|
208
|
+
},
|
|
209
|
+
properties: [
|
|
210
|
+
{ name: "__anvia_document_id", dataType: "text" },
|
|
211
|
+
{ name: "__anvia_document", dataType: "text" }
|
|
212
|
+
]
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
return new _WeaviateVectorStore(client, options.className);
|
|
216
|
+
}
|
|
217
|
+
async upsertDocuments(documents) {
|
|
218
|
+
const objects = documents.flatMap((document) => weaviateObjects(this.className, document));
|
|
219
|
+
const batcher = this.client.batch.objectsBatcher();
|
|
220
|
+
for (const obj of objects) {
|
|
221
|
+
batcher.withObject(obj);
|
|
222
|
+
}
|
|
223
|
+
await batcher.do();
|
|
224
|
+
}
|
|
225
|
+
index(model) {
|
|
226
|
+
return new WeaviateVectorIndex(model, this.client, this.className);
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
export {
|
|
230
|
+
WeaviateVectorIndex,
|
|
231
|
+
WeaviateVectorStore,
|
|
232
|
+
filterToWeaviateWhere
|
|
233
|
+
};
|
|
234
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/filters.ts","../src/search-index.ts","../src/helpers.ts","../src/types.ts","../src/store.ts"],"sourcesContent":["import type { VectorFilter } from \"@anvia/core/vector-store\";\n\nexport function filterToWeaviateWhere(filter: VectorFilter | undefined): unknown {\n if (filter === undefined) {\n return undefined;\n }\n\n switch (filter.type) {\n case \"eq\":\n return {\n operator: \"Equal\",\n path: [filter.key],\n valueString: typeof filter.value === \"string\" ? filter.value : undefined,\n valueInt: typeof filter.value === \"number\" ? filter.value : undefined,\n valueBoolean: typeof filter.value === \"boolean\" ? filter.value : undefined,\n valueNumber: typeof filter.value === \"number\" ? filter.value : undefined,\n };\n case \"gt\":\n return {\n operator: \"GreaterThan\",\n path: [filter.key],\n valueNumber: typeof filter.value === \"number\" ? filter.value : undefined,\n valueString: typeof filter.value === \"string\" ? filter.value : undefined,\n };\n case \"lt\":\n return {\n operator: \"LessThan\",\n path: [filter.key],\n valueNumber: typeof filter.value === \"number\" ? filter.value : undefined,\n valueString: typeof filter.value === \"string\" ? filter.value : undefined,\n };\n case \"and\":\n return {\n operator: \"And\",\n operands: filter.filters.map(filterToWeaviateWhere),\n };\n case \"or\":\n return {\n operator: \"Or\",\n operands: filter.filters.map(filterToWeaviateWhere),\n };\n }\n}\n","import { type EmbeddingModel, embedText, type VectorMetadata } from \"@anvia/core/embeddings\";\nimport type { Tool } from \"@anvia/core/tool\";\nimport {\n createVectorSearchTool,\n type VectorSearchIndex,\n type VectorSearchRequest,\n type VectorSearchResult,\n type VectorSearchToolOptions,\n} from \"@anvia/core/vector-store\";\nimport { filterToWeaviateWhere } from \"./filters.js\";\nimport { parseQueryResults } from \"./helpers.js\";\nimport { documentIdPropertyKey, documentPropertyKey, type WeaviateClientLike } from \"./types.js\";\n\nexport class WeaviateVectorIndex<T, Metadata extends VectorMetadata = VectorMetadata>\n implements VectorSearchIndex<T, Metadata>\n{\n constructor(\n private readonly model: EmbeddingModel,\n private readonly client: WeaviateClientLike,\n private readonly className: string,\n ) {}\n\n async search(request: VectorSearchRequest): Promise<Array<VectorSearchResult<T, Metadata>>> {\n const queryEmbedding = await embedText(this.model, request.query);\n const collection = this.client.collections.get(this.className);\n\n const filters = filterToWeaviateWhere(request.filter);\n const response = await collection.query.nearVector({\n vector: queryEmbedding.vector,\n limit: request.topK,\n filters: filters as import(\"./types.js\").NearVectorParams[\"filters\"],\n returnMetadata: [\"certainty\", \"distance\"],\n returnProperties: [documentIdPropertyKey, documentPropertyKey],\n });\n\n return parseQueryResults<T, Metadata>(response, request.threshold);\n }\n\n async searchIds(request: VectorSearchRequest): Promise<Array<{ score: number; id: string }>> {\n return (await this.search(request)).map(({ score, id }) => ({ score, id }));\n }\n\n asTool(options: VectorSearchToolOptions): Tool<{ query: string; topK?: number }, unknown> {\n return createVectorSearchTool(this, options);\n }\n}\n","import { createHash } from \"node:crypto\";\nimport type { EmbeddedDocument, VectorMetadata } from \"@anvia/core/embeddings\";\nimport type { VectorSearchResult } from \"@anvia/core/vector-store\";\nimport { documentIdPropertyKey, documentPropertyKey, reservedPropertyPrefix } from \"./types.js\";\n\nexport function assertNoReservedMetadata(metadata: VectorMetadata | undefined): void {\n for (const key of Object.keys(metadata ?? {})) {\n if (key.startsWith(reservedPropertyPrefix)) {\n throw new Error(`Metadata key ${key} is reserved for Anvia Weaviate properties`);\n }\n }\n}\n\nexport function pointId(id: string): string {\n const hex = createHash(\"sha256\").update(id).digest(\"hex\").slice(0, 32);\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(\n 16,\n 20,\n )}-${hex.slice(20)}`;\n}\n\nexport function serializeDocument(document: unknown): string {\n return typeof document === \"string\" ? document : JSON.stringify(document);\n}\n\nexport function parseDocument<T>(document: unknown): T {\n if (document === null || document === undefined) {\n return \"\" as T;\n }\n if (typeof document !== \"string\") {\n return document as T;\n }\n try {\n return JSON.parse(document) as T;\n } catch {\n return document as T;\n }\n}\n\nexport function weaviateObjects<T, Metadata extends VectorMetadata>(\n className: string,\n document: EmbeddedDocument<T, Metadata>,\n): Array<Record<string, unknown>> {\n if (document.embeddings.length === 0) {\n throw new Error(`Document ${document.id} has no embeddings`);\n }\n assertNoReservedMetadata(document.metadata);\n\n return document.embeddings.map((embedding, index) => {\n const logicalId =\n document.embeddings.length === 1 ? document.id : `${document.id}#embedding:${index}`;\n return {\n class: className,\n id: pointId(logicalId),\n vector: embedding.vector,\n properties: {\n [documentIdPropertyKey]: document.id,\n [documentPropertyKey]: serializeDocument(document.document),\n ...(document.metadata ?? {}),\n },\n };\n });\n}\n\nexport function parseQueryResults<T, Metadata extends VectorMetadata>(\n response: Array<Record<string, unknown>>,\n threshold: number | undefined,\n): Array<VectorSearchResult<T, Metadata>> {\n const byId = new Map<string, VectorSearchResult<T, Metadata>>();\n\n for (const item of response) {\n const additional = item._additional as Record<string, unknown> | undefined;\n const certainty = additional?.certainty as number | undefined;\n const distance = additional?.distance as number | undefined;\n const score = certainty ?? (distance !== undefined ? 1 - distance : 0);\n\n if (threshold !== undefined && score < threshold) {\n continue;\n }\n\n const id = String(item[documentIdPropertyKey] ?? \"\");\n const result = {\n id,\n score,\n document: parseDocument(item[documentPropertyKey]),\n ...metadataFromProperties<Metadata>(item),\n } as VectorSearchResult<T, Metadata>;\n const current = byId.get(id);\n if (current === undefined || result.score > current.score) {\n byId.set(id, result);\n }\n }\n\n return [...byId.values()];\n}\n\nexport async function defaultWeaviateClient(): Promise<import(\"./types.js\").WeaviateClientLike> {\n const weaviate = await import(\"weaviate-client\");\n const defaultExport = weaviate.default ?? weaviate;\n const host = process.env.WEAVIATE_HOST ?? \"localhost:8080\";\n const grpcHost = process.env.WEAVIATE_GRPC_HOST ?? \"localhost:50051\";\n const client = await defaultExport.connectToCustom({\n httpHost: host,\n httpSecure: false,\n grpcHost: grpcHost,\n grpcSecure: false,\n });\n return client as unknown as import(\"./types.js\").WeaviateClientLike;\n}\n\nfunction metadataFromProperties<Metadata extends VectorMetadata>(\n properties: Record<string, unknown>,\n): { metadata?: Metadata | undefined } {\n const metadata = Object.fromEntries(\n Object.entries(properties).filter(\n ([key]) => !key.startsWith(reservedPropertyPrefix) && key !== \"_additional\",\n ),\n ) as Metadata;\n return Object.keys(metadata).length === 0 ? {} : { metadata };\n}\n","export const documentIdPropertyKey = \"__anvia_document_id\";\nexport const documentPropertyKey = \"__anvia_document\";\nexport const reservedPropertyPrefix = \"__anvia_\";\n\nexport type WeaviateDistance = \"cosine\" | \"dot\" | \"l2\" | \"manhattan\" | \"hamming\";\n\nexport type WeaviateCollectionLike = {\n query: {\n nearVector(params: NearVectorParams): Promise<Array<Record<string, unknown>>>;\n };\n};\n\nexport type WeaviateCollectionsLike = {\n create(config: Record<string, unknown>): Promise<unknown>;\n get(name: string): WeaviateCollectionLike;\n delete(name: string): Promise<unknown>;\n exists(name: string): Promise<boolean>;\n};\n\nexport type WeaviateBatcherLike = {\n withObject(obj: Record<string, unknown>): WeaviateBatcherLike;\n do(): Promise<unknown>;\n};\n\nexport type WeaviateBatchLike = {\n objectsBatcher(): WeaviateBatcherLike;\n};\n\nexport type NearVectorParams = {\n vector: number[];\n limit?: number | undefined;\n filters?: unknown | undefined;\n returnMetadata?: string[] | undefined;\n returnProperties?: string[] | undefined;\n};\n\nexport type WeaviateClientLike = {\n collections: WeaviateCollectionsLike;\n batch: WeaviateBatchLike;\n};\n\nexport type WeaviateVectorStoreConnectOptions = {\n client?: WeaviateClientLike | undefined;\n className: string;\n vectorSize: number;\n createIfMissing?: boolean | undefined;\n distance?: WeaviateDistance | undefined;\n};\n","import type { EmbeddedDocument, EmbeddingModel, VectorMetadata } from \"@anvia/core/embeddings\";\nimport { defaultWeaviateClient, weaviateObjects } from \"./helpers.js\";\nimport { WeaviateVectorIndex } from \"./search-index.js\";\nimport type { WeaviateClientLike, WeaviateVectorStoreConnectOptions } from \"./types.js\";\n\nexport class WeaviateVectorStore<T, Metadata extends VectorMetadata = VectorMetadata> {\n private constructor(\n private readonly client: WeaviateClientLike,\n private readonly className: string,\n ) {}\n\n static async connect<T, Metadata extends VectorMetadata = VectorMetadata>(\n options: WeaviateVectorStoreConnectOptions,\n ): Promise<WeaviateVectorStore<T, Metadata>> {\n const client = options.client ?? (await defaultWeaviateClient());\n\n if (options.createIfMissing === false) {\n const exists = await client.collections.exists(options.className);\n if (!exists) {\n throw new Error(`Collection ${options.className} does not exist`);\n }\n return new WeaviateVectorStore<T, Metadata>(client, options.className);\n }\n\n const exists = await client.collections.exists(options.className);\n if (!exists) {\n await client.collections.create({\n name: options.className,\n vectorizers: null,\n vectorIndexConfig: {\n distance: options.distance ?? \"cosine\",\n },\n properties: [\n { name: \"__anvia_document_id\", dataType: \"text\" },\n { name: \"__anvia_document\", dataType: \"text\" },\n ],\n });\n }\n\n return new WeaviateVectorStore<T, Metadata>(client, options.className);\n }\n\n async upsertDocuments(documents: Array<EmbeddedDocument<T, Metadata>>): Promise<void> {\n const objects = documents.flatMap((document) => weaviateObjects(this.className, document));\n const batcher = this.client.batch.objectsBatcher();\n for (const obj of objects) {\n batcher.withObject(obj);\n }\n await batcher.do();\n }\n\n index(model: EmbeddingModel): WeaviateVectorIndex<T, Metadata> {\n return new WeaviateVectorIndex(model, this.client, this.className);\n }\n}\n"],"mappings":"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","names":["exists"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@anvia/weaviate",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Weaviate vector store adapter for Anvia.",
|
|
5
|
+
"author": "anvia",
|
|
6
|
+
"maintainer": "Indra Zulfi",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/anvia-hq/anvia",
|
|
11
|
+
"directory": "packages/vector-weaviate"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist"
|
|
15
|
+
],
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "public"
|
|
18
|
+
},
|
|
19
|
+
"type": "module",
|
|
20
|
+
"main": "./dist/index.js",
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"exports": {
|
|
23
|
+
".": {
|
|
24
|
+
"types": "./dist/index.d.ts",
|
|
25
|
+
"import": "./dist/index.js"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"weaviate-client": "^3.5.0",
|
|
30
|
+
"@anvia/core": "0.6.3"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@types/node": "^24.9.1",
|
|
34
|
+
"tsup": "^8.5.0",
|
|
35
|
+
"typescript": "^5.9.3",
|
|
36
|
+
"vitest": "^4.0.8"
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "tsup src/index.ts --format esm --dts --sourcemap --clean",
|
|
40
|
+
"test": "vitest run",
|
|
41
|
+
"typecheck": "tsc --noEmit"
|
|
42
|
+
}
|
|
43
|
+
}
|