@vectororm/adapter-chroma 0.1.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 +104 -0
- package/dist/index.cjs +423 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +84 -0
- package/dist/index.d.ts +84 -0
- package/dist/index.js +398 -0
- package/dist/index.js.map +1 -0
- package/package.json +58 -0
package/README.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# @vectororm/adapter-chroma
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@vectororm/adapter-chroma)
|
|
4
|
+
[](https://opensource.org/licenses/Apache-2.0)
|
|
5
|
+
|
|
6
|
+
[ChromaDB](https://www.trychroma.com/) adapter for [Glyph VectorORM](https://github.com/aviramroi/VectorORM).
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm install @vectororm/core @vectororm/adapter-chroma
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Prerequisites
|
|
15
|
+
|
|
16
|
+
ChromaDB running locally or accessible via network:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
docker run -p 8000:8000 chromadb/chroma
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
### Standalone Adapter
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
import { ChromaAdapter } from '@vectororm/adapter-chroma';
|
|
28
|
+
|
|
29
|
+
const adapter = new ChromaAdapter({
|
|
30
|
+
host: 'localhost',
|
|
31
|
+
port: 8000
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
await adapter.connect();
|
|
35
|
+
|
|
36
|
+
// Create a collection
|
|
37
|
+
await adapter.createCollection('my-docs', 1536, 'cosine');
|
|
38
|
+
|
|
39
|
+
// Upsert vectors
|
|
40
|
+
await adapter.upsert('my-docs', [
|
|
41
|
+
{
|
|
42
|
+
id: 'doc-1',
|
|
43
|
+
embedding: [0.1, 0.2, ...],
|
|
44
|
+
metadata: { title: 'My Document', __v_partition: 'finance' },
|
|
45
|
+
text: 'Document content...'
|
|
46
|
+
}
|
|
47
|
+
]);
|
|
48
|
+
|
|
49
|
+
// Search with filters
|
|
50
|
+
const results = await adapter.search('my-docs', queryVector, {
|
|
51
|
+
topK: 10,
|
|
52
|
+
filter: { field: '__v_partition', op: 'eq', value: 'finance' }
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### With RAGClient
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
import { RAGClient } from '@vectororm/core';
|
|
60
|
+
import { ChromaAdapter } from '@vectororm/adapter-chroma';
|
|
61
|
+
|
|
62
|
+
const client = new RAGClient({
|
|
63
|
+
adapter: new ChromaAdapter({ host: 'localhost', port: 8000 }),
|
|
64
|
+
embedder: myEmbedder,
|
|
65
|
+
llm: myLLM,
|
|
66
|
+
defaultCollection: 'docs'
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
await client.createCollection('docs');
|
|
70
|
+
await client.ingest(['documents/*.pdf'], 'docs');
|
|
71
|
+
const result = await client.retrieve('search query');
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Configuration
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
interface ChromaConfig {
|
|
78
|
+
host?: string; // Default: 'localhost'
|
|
79
|
+
port?: number; // Default: 8000
|
|
80
|
+
apiKey?: string; // Optional, for Chroma Cloud
|
|
81
|
+
ssl?: boolean; // Default: false for localhost
|
|
82
|
+
tenant?: string; // Optional multi-tenancy
|
|
83
|
+
database?: string; // Optional database name
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Environment variable fallbacks: `CHROMA_HOST`, `CHROMA_PORT`, `CHROMA_API_KEY`, `CHROMA_SSL`.
|
|
88
|
+
|
|
89
|
+
## Features
|
|
90
|
+
|
|
91
|
+
- Full CRUD operations (upsert, fetch, delete)
|
|
92
|
+
- Metadata filtering with Glyph universal filter translation
|
|
93
|
+
- Collection management (create, delete, exists, stats)
|
|
94
|
+
- Batch iteration for enrichment pipelines
|
|
95
|
+
- Metadata updates without re-uploading vectors
|
|
96
|
+
|
|
97
|
+
## Documentation
|
|
98
|
+
|
|
99
|
+
- [API Guide](https://github.com/aviramroi/VectorORM/blob/main/docs/guide.md)
|
|
100
|
+
- [Full Project](https://github.com/aviramroi/VectorORM)
|
|
101
|
+
|
|
102
|
+
## License
|
|
103
|
+
|
|
104
|
+
Apache-2.0
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
ChromaAdapter: () => ChromaAdapter
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(index_exports);
|
|
26
|
+
|
|
27
|
+
// src/chroma-adapter.ts
|
|
28
|
+
var import_core = require("@vectororm/core");
|
|
29
|
+
var import_chromadb = require("chromadb");
|
|
30
|
+
var ChromaAdapter = class extends import_core.VectorDBAdapter {
|
|
31
|
+
config;
|
|
32
|
+
client = null;
|
|
33
|
+
collectionCache = /* @__PURE__ */ new Map();
|
|
34
|
+
constructor(config = {}) {
|
|
35
|
+
super();
|
|
36
|
+
this.config = config;
|
|
37
|
+
}
|
|
38
|
+
// ============================================================================
|
|
39
|
+
// CONNECTION MANAGEMENT
|
|
40
|
+
// ============================================================================
|
|
41
|
+
async connect() {
|
|
42
|
+
try {
|
|
43
|
+
const host = this.config.host || process.env.CHROMA_HOST || "localhost";
|
|
44
|
+
const port = this.config.port || (process.env.CHROMA_PORT ? parseInt(process.env.CHROMA_PORT, 10) : 8e3);
|
|
45
|
+
const ssl = this.config.ssl !== void 0 ? this.config.ssl : process.env.CHROMA_SSL === "true" || host !== "localhost";
|
|
46
|
+
const protocol = ssl ? "https" : "http";
|
|
47
|
+
const path = `${protocol}://${host}:${port}`;
|
|
48
|
+
const clientConfig = { path };
|
|
49
|
+
const apiKey = this.config.apiKey || process.env.CHROMA_API_KEY;
|
|
50
|
+
if (apiKey) {
|
|
51
|
+
clientConfig.auth = { provider: "token", credentials: apiKey };
|
|
52
|
+
}
|
|
53
|
+
if (this.config.tenant) {
|
|
54
|
+
clientConfig.tenant = this.config.tenant;
|
|
55
|
+
}
|
|
56
|
+
if (this.config.database) {
|
|
57
|
+
clientConfig.database = this.config.database;
|
|
58
|
+
}
|
|
59
|
+
this.client = new import_chromadb.ChromaClient(clientConfig);
|
|
60
|
+
await this.client.heartbeat();
|
|
61
|
+
} catch (error) {
|
|
62
|
+
throw new Error(
|
|
63
|
+
`Chroma connection failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
64
|
+
{ cause: error }
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async disconnect() {
|
|
69
|
+
this.client = null;
|
|
70
|
+
this.collectionCache.clear();
|
|
71
|
+
}
|
|
72
|
+
async isConnected() {
|
|
73
|
+
if (!this.client) return false;
|
|
74
|
+
try {
|
|
75
|
+
await this.client.heartbeat();
|
|
76
|
+
return true;
|
|
77
|
+
} catch {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// ============================================================================
|
|
82
|
+
// COLLECTION MANAGEMENT
|
|
83
|
+
// ============================================================================
|
|
84
|
+
async createCollection(name, dimension, metric = "cosine") {
|
|
85
|
+
if (!this.client) {
|
|
86
|
+
throw new Error("Not connected. Call connect() first.");
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
const chromaMetric = this.mapDistanceMetric(metric);
|
|
90
|
+
const collection = await this.client.createCollection({
|
|
91
|
+
name,
|
|
92
|
+
metadata: {
|
|
93
|
+
"hnsw:space": chromaMetric,
|
|
94
|
+
dimension: dimension.toString()
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
this.collectionCache.set(name, collection);
|
|
98
|
+
} catch (error) {
|
|
99
|
+
throw new Error(
|
|
100
|
+
`Failed to create Chroma collection ${name}: ${error instanceof Error ? error.message : String(error)}`,
|
|
101
|
+
{ cause: error }
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
async deleteCollection(name) {
|
|
106
|
+
if (!this.client) {
|
|
107
|
+
throw new Error("Not connected. Call connect() first.");
|
|
108
|
+
}
|
|
109
|
+
try {
|
|
110
|
+
await this.client.deleteCollection({ name });
|
|
111
|
+
this.collectionCache.delete(name);
|
|
112
|
+
} catch (error) {
|
|
113
|
+
throw new Error(
|
|
114
|
+
`Failed to delete Chroma collection ${name}: ${error instanceof Error ? error.message : String(error)}`,
|
|
115
|
+
{ cause: error }
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
async collectionExists(name) {
|
|
120
|
+
if (!this.client) {
|
|
121
|
+
throw new Error("Not connected. Call connect() first.");
|
|
122
|
+
}
|
|
123
|
+
try {
|
|
124
|
+
const collections = await this.client.listCollections();
|
|
125
|
+
return collections.some((col) => col.name === name);
|
|
126
|
+
} catch (error) {
|
|
127
|
+
throw new Error(
|
|
128
|
+
`Failed to check if Chroma collection ${name} exists: ${error instanceof Error ? error.message : String(error)}`,
|
|
129
|
+
{ cause: error }
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
async getCollectionStats(name) {
|
|
134
|
+
if (!this.client) {
|
|
135
|
+
throw new Error("Not connected. Call connect() first.");
|
|
136
|
+
}
|
|
137
|
+
try {
|
|
138
|
+
const collection = await this.getCollection(name);
|
|
139
|
+
const count = await collection.count();
|
|
140
|
+
const metadata = collection.metadata || {};
|
|
141
|
+
const dimension = metadata.dimension ? parseInt(metadata.dimension, 10) : 0;
|
|
142
|
+
const metricStr = metadata["hnsw:space"] || "cosine";
|
|
143
|
+
const metric = this.unmapDistanceMetric(metricStr);
|
|
144
|
+
return {
|
|
145
|
+
vectorCount: count,
|
|
146
|
+
dimension,
|
|
147
|
+
metric,
|
|
148
|
+
...metadata
|
|
149
|
+
};
|
|
150
|
+
} catch (error) {
|
|
151
|
+
throw new Error(
|
|
152
|
+
`Failed to get Chroma collection stats for ${name}: ${error instanceof Error ? error.message : String(error)}`,
|
|
153
|
+
{ cause: error }
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// ============================================================================
|
|
158
|
+
// VECTOR OPERATIONS
|
|
159
|
+
// ============================================================================
|
|
160
|
+
async upsert(collection, records) {
|
|
161
|
+
if (!this.client) {
|
|
162
|
+
throw new Error("Not connected. Call connect() first.");
|
|
163
|
+
}
|
|
164
|
+
try {
|
|
165
|
+
const col = await this.getCollection(collection);
|
|
166
|
+
const ids = records.map((r) => r.id);
|
|
167
|
+
const embeddings = records.map((r) => r.embedding);
|
|
168
|
+
const metadatas = records.map((r) => r.metadata || {});
|
|
169
|
+
await col.upsert({
|
|
170
|
+
ids,
|
|
171
|
+
embeddings,
|
|
172
|
+
metadatas
|
|
173
|
+
});
|
|
174
|
+
} catch (error) {
|
|
175
|
+
throw new Error(
|
|
176
|
+
`Failed to upsert vectors to Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,
|
|
177
|
+
{ cause: error }
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
async fetch(collection, ids) {
|
|
182
|
+
if (!this.client) {
|
|
183
|
+
throw new Error("Not connected. Call connect() first.");
|
|
184
|
+
}
|
|
185
|
+
try {
|
|
186
|
+
const col = await this.getCollection(collection);
|
|
187
|
+
const response = await col.get({
|
|
188
|
+
ids,
|
|
189
|
+
include: ["embeddings", "metadatas"]
|
|
190
|
+
});
|
|
191
|
+
const records = [];
|
|
192
|
+
if (response.ids && response.ids.length > 0) {
|
|
193
|
+
for (let i = 0; i < response.ids.length; i++) {
|
|
194
|
+
records.push({
|
|
195
|
+
id: response.ids[i],
|
|
196
|
+
embedding: response.embeddings?.[i] || [],
|
|
197
|
+
metadata: response.metadatas?.[i] || {}
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return records;
|
|
202
|
+
} catch (error) {
|
|
203
|
+
throw new Error(
|
|
204
|
+
`Failed to fetch vectors from Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,
|
|
205
|
+
{ cause: error }
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
async delete(collection, ids) {
|
|
210
|
+
if (!this.client) {
|
|
211
|
+
throw new Error("Not connected. Call connect() first.");
|
|
212
|
+
}
|
|
213
|
+
try {
|
|
214
|
+
const col = await this.getCollection(collection);
|
|
215
|
+
await col.delete({ ids });
|
|
216
|
+
} catch (error) {
|
|
217
|
+
throw new Error(
|
|
218
|
+
`Failed to delete vectors from Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,
|
|
219
|
+
{ cause: error }
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
// ============================================================================
|
|
224
|
+
// METADATA OPERATIONS
|
|
225
|
+
// ============================================================================
|
|
226
|
+
async updateMetadata(collection, updates) {
|
|
227
|
+
if (!this.client) {
|
|
228
|
+
throw new Error("Not connected. Call connect() first.");
|
|
229
|
+
}
|
|
230
|
+
try {
|
|
231
|
+
const col = await this.getCollection(collection);
|
|
232
|
+
for (const update of updates) {
|
|
233
|
+
await col.update({
|
|
234
|
+
ids: [update.id],
|
|
235
|
+
metadatas: [update.metadata]
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
} catch (error) {
|
|
239
|
+
throw new Error(
|
|
240
|
+
`Failed to update metadata in Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,
|
|
241
|
+
{ cause: error }
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
// ============================================================================
|
|
246
|
+
// SEARCH OPERATIONS
|
|
247
|
+
// ============================================================================
|
|
248
|
+
async search(collection, queryVector, options) {
|
|
249
|
+
if (!this.client) {
|
|
250
|
+
throw new Error("Not connected. Call connect() first.");
|
|
251
|
+
}
|
|
252
|
+
try {
|
|
253
|
+
const col = await this.getCollection(collection);
|
|
254
|
+
const chromaFilter = options?.filter ? this.translateFilter(options.filter) : void 0;
|
|
255
|
+
const include = ["distances"];
|
|
256
|
+
if (options?.includeMetadata !== false) {
|
|
257
|
+
include.push("metadatas");
|
|
258
|
+
}
|
|
259
|
+
if (options?.includeValues) {
|
|
260
|
+
include.push("embeddings");
|
|
261
|
+
}
|
|
262
|
+
const response = await col.query({
|
|
263
|
+
queryEmbeddings: [queryVector],
|
|
264
|
+
nResults: options?.topK || 10,
|
|
265
|
+
where: chromaFilter,
|
|
266
|
+
include
|
|
267
|
+
});
|
|
268
|
+
const records = [];
|
|
269
|
+
if (response.ids && response.ids[0]) {
|
|
270
|
+
const resultIds = response.ids[0];
|
|
271
|
+
const distances = response.distances?.[0] || [];
|
|
272
|
+
const embeddings = response.embeddings?.[0] || [];
|
|
273
|
+
const metadatas = response.metadatas?.[0] || [];
|
|
274
|
+
for (let i = 0; i < resultIds.length; i++) {
|
|
275
|
+
const record = {
|
|
276
|
+
id: resultIds[i],
|
|
277
|
+
embedding: options?.includeValues ? embeddings[i] || [] : [],
|
|
278
|
+
metadata: options?.includeMetadata !== false ? metadatas[i] || {} : {}
|
|
279
|
+
};
|
|
280
|
+
if (distances[i] !== void 0) {
|
|
281
|
+
record.score = 1 / (1 + distances[i]);
|
|
282
|
+
}
|
|
283
|
+
records.push(record);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return { records };
|
|
287
|
+
} catch (error) {
|
|
288
|
+
throw new Error(
|
|
289
|
+
`Failed to search Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,
|
|
290
|
+
{ cause: error }
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
// ============================================================================
|
|
295
|
+
// FILTER TRANSLATION
|
|
296
|
+
// ============================================================================
|
|
297
|
+
translateFilter(filter) {
|
|
298
|
+
if ("and" in filter) {
|
|
299
|
+
const conditions = filter.and;
|
|
300
|
+
const translated = conditions.map((c) => this.translateFilter(c));
|
|
301
|
+
return { $and: translated };
|
|
302
|
+
}
|
|
303
|
+
if ("or" in filter) {
|
|
304
|
+
const conditions = filter.or;
|
|
305
|
+
const translated = conditions.map((c) => this.translateFilter(c));
|
|
306
|
+
return { $or: translated };
|
|
307
|
+
}
|
|
308
|
+
const { field, op, value } = filter;
|
|
309
|
+
const operatorMap = {
|
|
310
|
+
eq: "$eq",
|
|
311
|
+
ne: "$ne",
|
|
312
|
+
gt: "$gt",
|
|
313
|
+
gte: "$gte",
|
|
314
|
+
lt: "$lt",
|
|
315
|
+
lte: "$lte",
|
|
316
|
+
in: "$in",
|
|
317
|
+
nin: "$nin"
|
|
318
|
+
};
|
|
319
|
+
const chromaOp = operatorMap[op];
|
|
320
|
+
if (!chromaOp) {
|
|
321
|
+
throw new Error(
|
|
322
|
+
`Unsupported filter operator: ${op}`,
|
|
323
|
+
{ cause: { filter } }
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
return {
|
|
327
|
+
[field]: {
|
|
328
|
+
[chromaOp]: value
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
// ============================================================================
|
|
333
|
+
// ITERATION
|
|
334
|
+
// ============================================================================
|
|
335
|
+
async *iterate(collection, options) {
|
|
336
|
+
if (!this.client) {
|
|
337
|
+
throw new Error("Not connected. Call connect() first.");
|
|
338
|
+
}
|
|
339
|
+
try {
|
|
340
|
+
const col = await this.getCollection(collection);
|
|
341
|
+
const batchSize = options?.batchSize || 100;
|
|
342
|
+
const chromaFilter = options?.filter ? this.translateFilter(options.filter) : void 0;
|
|
343
|
+
let offset = 0;
|
|
344
|
+
let hasMore = true;
|
|
345
|
+
while (hasMore) {
|
|
346
|
+
const response = await col.get({
|
|
347
|
+
where: chromaFilter,
|
|
348
|
+
limit: batchSize,
|
|
349
|
+
offset,
|
|
350
|
+
include: ["embeddings", "metadatas"]
|
|
351
|
+
});
|
|
352
|
+
if (response.ids && response.ids.length > 0) {
|
|
353
|
+
const records = [];
|
|
354
|
+
for (let i = 0; i < response.ids.length; i++) {
|
|
355
|
+
records.push({
|
|
356
|
+
id: response.ids[i],
|
|
357
|
+
embedding: response.embeddings?.[i] || [],
|
|
358
|
+
metadata: response.metadatas?.[i] || {}
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
yield records;
|
|
362
|
+
hasMore = response.ids.length === batchSize;
|
|
363
|
+
offset += batchSize;
|
|
364
|
+
} else {
|
|
365
|
+
hasMore = false;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
} catch (error) {
|
|
369
|
+
throw new Error(
|
|
370
|
+
`Failed to iterate Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,
|
|
371
|
+
{ cause: error }
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
// ============================================================================
|
|
376
|
+
// CAPABILITY FLAGS
|
|
377
|
+
// ============================================================================
|
|
378
|
+
supportsMetadataUpdate() {
|
|
379
|
+
return true;
|
|
380
|
+
}
|
|
381
|
+
supportsFiltering() {
|
|
382
|
+
return true;
|
|
383
|
+
}
|
|
384
|
+
supportsBatchOperations() {
|
|
385
|
+
return true;
|
|
386
|
+
}
|
|
387
|
+
// ============================================================================
|
|
388
|
+
// HELPER METHODS
|
|
389
|
+
// ============================================================================
|
|
390
|
+
async getCollection(name) {
|
|
391
|
+
if (this.collectionCache.has(name)) {
|
|
392
|
+
return this.collectionCache.get(name);
|
|
393
|
+
}
|
|
394
|
+
if (!this.client) {
|
|
395
|
+
throw new Error("Not connected. Call connect() first.");
|
|
396
|
+
}
|
|
397
|
+
const collection = await this.client.getCollection({ name, embeddingFunction: void 0 });
|
|
398
|
+
this.collectionCache.set(name, collection);
|
|
399
|
+
return collection;
|
|
400
|
+
}
|
|
401
|
+
mapDistanceMetric(metric) {
|
|
402
|
+
const metricMap = {
|
|
403
|
+
cosine: "cosine",
|
|
404
|
+
euclidean: "l2",
|
|
405
|
+
dotProduct: "ip"
|
|
406
|
+
// Inner product
|
|
407
|
+
};
|
|
408
|
+
return metricMap[metric] || "cosine";
|
|
409
|
+
}
|
|
410
|
+
unmapDistanceMetric(chromaMetric) {
|
|
411
|
+
const metricMap = {
|
|
412
|
+
cosine: "cosine",
|
|
413
|
+
l2: "euclidean",
|
|
414
|
+
ip: "dotProduct"
|
|
415
|
+
};
|
|
416
|
+
return metricMap[chromaMetric] || "cosine";
|
|
417
|
+
}
|
|
418
|
+
};
|
|
419
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
420
|
+
0 && (module.exports = {
|
|
421
|
+
ChromaAdapter
|
|
422
|
+
});
|
|
423
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/chroma-adapter.ts"],"sourcesContent":["// Chroma adapter exports\nexport { ChromaAdapter } from './chroma-adapter';\nexport type { ChromaConfig } from './types';\n","import {\n VectorDBAdapter,\n type VectorRecord,\n type SearchResult,\n type UniversalFilter,\n type CollectionStats,\n type MetadataUpdate,\n type DistanceMetric,\n} from '@vectororm/core';\nimport { ChromaClient, type Collection } from 'chromadb';\nimport type { ChromaConfig } from './types.js';\n\n/**\n * ChromaAdapter implements VectorDBAdapter for Chroma vector database.\n *\n * Supports both self-hosted and cloud Chroma instances.\n * Uses chromadb npm package for native TypeScript support.\n */\nexport class ChromaAdapter extends VectorDBAdapter {\n private config: ChromaConfig;\n private client: ChromaClient | null = null;\n private collectionCache: Map<string, Collection> = new Map();\n\n constructor(config: ChromaConfig = {}) {\n super();\n this.config = config;\n }\n\n // ============================================================================\n // CONNECTION MANAGEMENT\n // ============================================================================\n\n async connect(): Promise<void> {\n try {\n const host = this.config.host || process.env.CHROMA_HOST || 'localhost';\n const port = this.config.port ||\n (process.env.CHROMA_PORT ? parseInt(process.env.CHROMA_PORT, 10) : 8000);\n\n // Determine SSL usage\n const ssl = this.config.ssl !== undefined\n ? this.config.ssl\n : (process.env.CHROMA_SSL === 'true' || host !== 'localhost');\n\n const protocol = ssl ? 'https' : 'http';\n const path = `${protocol}://${host}:${port}`;\n\n const clientConfig: any = { path };\n\n // Add auth if API key is provided\n const apiKey = this.config.apiKey || process.env.CHROMA_API_KEY;\n if (apiKey) {\n clientConfig.auth = { provider: 'token', credentials: apiKey };\n }\n\n // Add tenant/database if provided\n if (this.config.tenant) {\n clientConfig.tenant = this.config.tenant;\n }\n if (this.config.database) {\n clientConfig.database = this.config.database;\n }\n\n this.client = new ChromaClient(clientConfig);\n\n // Verify connection by getting heartbeat\n await this.client.heartbeat();\n } catch (error) {\n throw new Error(\n `Chroma connection failed: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n async disconnect(): Promise<void> {\n this.client = null;\n this.collectionCache.clear();\n }\n\n async isConnected(): Promise<boolean> {\n if (!this.client) return false;\n\n try {\n await this.client.heartbeat();\n return true;\n } catch {\n return false;\n }\n }\n\n // ============================================================================\n // COLLECTION MANAGEMENT\n // ============================================================================\n\n async createCollection(\n name: string,\n dimension: number,\n metric: DistanceMetric = 'cosine'\n ): Promise<void> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n // Map our metric to Chroma distance function\n const chromaMetric = this.mapDistanceMetric(metric);\n\n const collection = await this.client.createCollection({\n name,\n metadata: {\n 'hnsw:space': chromaMetric,\n dimension: dimension.toString(),\n },\n });\n\n this.collectionCache.set(name, collection);\n } catch (error) {\n throw new Error(\n `Failed to create Chroma collection ${name}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n async deleteCollection(name: string): Promise<void> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n await this.client.deleteCollection({ name });\n this.collectionCache.delete(name);\n } catch (error) {\n throw new Error(\n `Failed to delete Chroma collection ${name}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n async collectionExists(name: string): Promise<boolean> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n const collections = await this.client.listCollections();\n return collections.some((col: any) => col.name === name);\n } catch (error) {\n throw new Error(\n `Failed to check if Chroma collection ${name} exists: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n async getCollectionStats(name: string): Promise<CollectionStats> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n const collection = await this.getCollection(name);\n const count = await collection.count();\n\n // Get metadata from collection\n const metadata = (collection as any).metadata || {};\n const dimension = metadata.dimension\n ? parseInt(metadata.dimension, 10)\n : 0;\n\n const metricStr = metadata['hnsw:space'] || 'cosine';\n const metric = this.unmapDistanceMetric(metricStr);\n\n return {\n vectorCount: count,\n dimension,\n metric,\n ...metadata,\n };\n } catch (error) {\n throw new Error(\n `Failed to get Chroma collection stats for ${name}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n // ============================================================================\n // VECTOR OPERATIONS\n // ============================================================================\n\n async upsert(collection: string, records: VectorRecord[]): Promise<void> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n const col = await this.getCollection(collection);\n\n const ids = records.map((r) => r.id);\n const embeddings = records.map((r) => r.embedding);\n const metadatas = records.map((r) => r.metadata || {});\n\n await col.upsert({\n ids,\n embeddings,\n metadatas,\n });\n } catch (error) {\n throw new Error(\n `Failed to upsert vectors to Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n async fetch(collection: string, ids: string[]): Promise<VectorRecord[]> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n const col = await this.getCollection(collection);\n\n const response = await col.get({\n ids,\n include: ['embeddings' as any, 'metadatas' as any],\n });\n\n const records: VectorRecord[] = [];\n\n if (response.ids && response.ids.length > 0) {\n for (let i = 0; i < response.ids.length; i++) {\n records.push({\n id: response.ids[i],\n embedding: response.embeddings?.[i] || [],\n metadata: response.metadatas?.[i] || {},\n });\n }\n }\n\n return records;\n } catch (error) {\n throw new Error(\n `Failed to fetch vectors from Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n async delete(collection: string, ids: string[]): Promise<void> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n const col = await this.getCollection(collection);\n await col.delete({ ids });\n } catch (error) {\n throw new Error(\n `Failed to delete vectors from Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n // ============================================================================\n // METADATA OPERATIONS\n // ============================================================================\n\n async updateMetadata(\n collection: string,\n updates: MetadataUpdate[]\n ): Promise<void> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n const col = await this.getCollection(collection);\n\n // Chroma supports metadata updates via update method\n for (const update of updates) {\n await col.update({\n ids: [update.id],\n metadatas: [update.metadata],\n });\n }\n } catch (error) {\n throw new Error(\n `Failed to update metadata in Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n // ============================================================================\n // SEARCH OPERATIONS\n // ============================================================================\n\n async search(\n collection: string,\n queryVector: number[],\n options?: {\n topK?: number;\n filter?: UniversalFilter;\n includeMetadata?: boolean;\n includeValues?: boolean;\n }\n ): Promise<SearchResult> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n const col = await this.getCollection(collection);\n\n const chromaFilter = options?.filter\n ? this.translateFilter(options.filter)\n : undefined;\n\n const include: any[] = ['distances' as any];\n if (options?.includeMetadata !== false) {\n include.push('metadatas' as any);\n }\n if (options?.includeValues) {\n include.push('embeddings' as any);\n }\n\n const response = await col.query({\n queryEmbeddings: [queryVector],\n nResults: options?.topK || 10,\n where: chromaFilter,\n include,\n });\n\n const records: VectorRecord[] = [];\n\n if (response.ids && response.ids[0]) {\n const resultIds = response.ids[0];\n const distances = response.distances?.[0] || [];\n const embeddings = response.embeddings?.[0] || [];\n const metadatas = response.metadatas?.[0] || [];\n\n for (let i = 0; i < resultIds.length; i++) {\n const record: VectorRecord = {\n id: resultIds[i],\n embedding: options?.includeValues ? (embeddings[i] || []) : [],\n metadata: options?.includeMetadata !== false ? (metadatas[i] || {}) : {},\n };\n\n // Convert distance to score (inverse relationship)\n if (distances[i] !== undefined) {\n record.score = 1 / (1 + distances[i]);\n }\n\n records.push(record);\n }\n }\n\n return { records };\n } catch (error) {\n throw new Error(\n `Failed to search Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n // ============================================================================\n // FILTER TRANSLATION\n // ============================================================================\n\n translateFilter(filter: UniversalFilter): any {\n // Handle compound AND filter\n if ('and' in filter) {\n const conditions = filter.and;\n const translated = conditions.map((c) => this.translateFilter(c));\n\n return { $and: translated };\n }\n\n // Handle compound OR filter\n if ('or' in filter) {\n const conditions = filter.or;\n const translated = conditions.map((c) => this.translateFilter(c));\n\n return { $or: translated };\n }\n\n // Handle basic filter condition\n const { field, op, value } = filter as any;\n\n // Operator mapping to Chroma's MongoDB-like syntax\n const operatorMap: Record<string, string> = {\n eq: '$eq',\n ne: '$ne',\n gt: '$gt',\n gte: '$gte',\n lt: '$lt',\n lte: '$lte',\n in: '$in',\n nin: '$nin',\n };\n\n const chromaOp = operatorMap[op];\n if (!chromaOp) {\n throw new Error(\n `Unsupported filter operator: ${op}`,\n { cause: { filter } }\n );\n }\n\n return {\n [field]: {\n [chromaOp]: value,\n },\n };\n }\n\n // ============================================================================\n // ITERATION\n // ============================================================================\n\n async *iterate(\n collection: string,\n options?: {\n batchSize?: number;\n filter?: UniversalFilter;\n }\n ): AsyncIterableIterator<VectorRecord[]> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n const col = await this.getCollection(collection);\n const batchSize = options?.batchSize || 100;\n const chromaFilter = options?.filter\n ? this.translateFilter(options.filter)\n : undefined;\n\n // Chroma uses offset/limit pagination\n let offset = 0;\n let hasMore = true;\n\n while (hasMore) {\n const response = await col.get({\n where: chromaFilter,\n limit: batchSize,\n offset,\n include: ['embeddings' as any, 'metadatas' as any],\n });\n\n if (response.ids && response.ids.length > 0) {\n const records: VectorRecord[] = [];\n\n for (let i = 0; i < response.ids.length; i++) {\n records.push({\n id: response.ids[i],\n embedding: response.embeddings?.[i] || [],\n metadata: response.metadatas?.[i] || {},\n });\n }\n\n yield records;\n\n // Check if there are more results\n hasMore = response.ids.length === batchSize;\n offset += batchSize;\n } else {\n hasMore = false;\n }\n }\n } catch (error) {\n throw new Error(\n `Failed to iterate Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n // ============================================================================\n // CAPABILITY FLAGS\n // ============================================================================\n\n supportsMetadataUpdate(): boolean {\n return true; // Chroma supports metadata updates\n }\n\n supportsFiltering(): boolean {\n return true; // Chroma supports metadata filtering\n }\n\n supportsBatchOperations(): boolean {\n return true; // Chroma supports batch operations\n }\n\n // ============================================================================\n // HELPER METHODS\n // ============================================================================\n\n private async getCollection(name: string): Promise<Collection> {\n if (this.collectionCache.has(name)) {\n return this.collectionCache.get(name)!;\n }\n\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n const collection = await this.client.getCollection({ name, embeddingFunction: undefined as any });\n this.collectionCache.set(name, collection);\n return collection;\n }\n\n private mapDistanceMetric(metric: DistanceMetric): string {\n const metricMap: Record<DistanceMetric, string> = {\n cosine: 'cosine',\n euclidean: 'l2',\n dotProduct: 'ip', // Inner product\n };\n\n return metricMap[metric] || 'cosine';\n }\n\n private unmapDistanceMetric(chromaMetric: string): DistanceMetric {\n const metricMap: Record<string, DistanceMetric> = {\n cosine: 'cosine',\n l2: 'euclidean',\n ip: 'dotProduct',\n };\n\n return metricMap[chromaMetric] || 'cosine';\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { VectorDBAdapter, DistanceMetric, CollectionStats, VectorRecord, MetadataUpdate, UniversalFilter, SearchResult } from '@vectororm/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Configuration for ChromaAdapter.
|
|
5
|
+
*
|
|
6
|
+
* Supports hybrid config: explicit values or environment variables.
|
|
7
|
+
* Chroma can be self-hosted or used via cloud service.
|
|
8
|
+
*/
|
|
9
|
+
interface ChromaConfig {
|
|
10
|
+
/**
|
|
11
|
+
* Chroma API key (optional for self-hosted).
|
|
12
|
+
* Falls back to CHROMA_API_KEY environment variable.
|
|
13
|
+
*/
|
|
14
|
+
apiKey?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Chroma server host.
|
|
17
|
+
* Falls back to CHROMA_HOST environment variable.
|
|
18
|
+
* Defaults to 'localhost'.
|
|
19
|
+
*/
|
|
20
|
+
host?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Chroma server port.
|
|
23
|
+
* Falls back to CHROMA_PORT environment variable.
|
|
24
|
+
* Defaults to 8000.
|
|
25
|
+
*/
|
|
26
|
+
port?: number;
|
|
27
|
+
/**
|
|
28
|
+
* Use SSL/TLS for connection.
|
|
29
|
+
* Falls back to CHROMA_SSL environment variable.
|
|
30
|
+
* Defaults to false for localhost, true for remote hosts.
|
|
31
|
+
*/
|
|
32
|
+
ssl?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Optional tenant ID for multi-tenancy support.
|
|
35
|
+
*/
|
|
36
|
+
tenant?: string;
|
|
37
|
+
/**
|
|
38
|
+
* Optional database name.
|
|
39
|
+
*/
|
|
40
|
+
database?: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* ChromaAdapter implements VectorDBAdapter for Chroma vector database.
|
|
45
|
+
*
|
|
46
|
+
* Supports both self-hosted and cloud Chroma instances.
|
|
47
|
+
* Uses chromadb npm package for native TypeScript support.
|
|
48
|
+
*/
|
|
49
|
+
declare class ChromaAdapter extends VectorDBAdapter {
|
|
50
|
+
private config;
|
|
51
|
+
private client;
|
|
52
|
+
private collectionCache;
|
|
53
|
+
constructor(config?: ChromaConfig);
|
|
54
|
+
connect(): Promise<void>;
|
|
55
|
+
disconnect(): Promise<void>;
|
|
56
|
+
isConnected(): Promise<boolean>;
|
|
57
|
+
createCollection(name: string, dimension: number, metric?: DistanceMetric): Promise<void>;
|
|
58
|
+
deleteCollection(name: string): Promise<void>;
|
|
59
|
+
collectionExists(name: string): Promise<boolean>;
|
|
60
|
+
getCollectionStats(name: string): Promise<CollectionStats>;
|
|
61
|
+
upsert(collection: string, records: VectorRecord[]): Promise<void>;
|
|
62
|
+
fetch(collection: string, ids: string[]): Promise<VectorRecord[]>;
|
|
63
|
+
delete(collection: string, ids: string[]): Promise<void>;
|
|
64
|
+
updateMetadata(collection: string, updates: MetadataUpdate[]): Promise<void>;
|
|
65
|
+
search(collection: string, queryVector: number[], options?: {
|
|
66
|
+
topK?: number;
|
|
67
|
+
filter?: UniversalFilter;
|
|
68
|
+
includeMetadata?: boolean;
|
|
69
|
+
includeValues?: boolean;
|
|
70
|
+
}): Promise<SearchResult>;
|
|
71
|
+
translateFilter(filter: UniversalFilter): any;
|
|
72
|
+
iterate(collection: string, options?: {
|
|
73
|
+
batchSize?: number;
|
|
74
|
+
filter?: UniversalFilter;
|
|
75
|
+
}): AsyncIterableIterator<VectorRecord[]>;
|
|
76
|
+
supportsMetadataUpdate(): boolean;
|
|
77
|
+
supportsFiltering(): boolean;
|
|
78
|
+
supportsBatchOperations(): boolean;
|
|
79
|
+
private getCollection;
|
|
80
|
+
private mapDistanceMetric;
|
|
81
|
+
private unmapDistanceMetric;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export { ChromaAdapter, type ChromaConfig };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { VectorDBAdapter, DistanceMetric, CollectionStats, VectorRecord, MetadataUpdate, UniversalFilter, SearchResult } from '@vectororm/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Configuration for ChromaAdapter.
|
|
5
|
+
*
|
|
6
|
+
* Supports hybrid config: explicit values or environment variables.
|
|
7
|
+
* Chroma can be self-hosted or used via cloud service.
|
|
8
|
+
*/
|
|
9
|
+
interface ChromaConfig {
|
|
10
|
+
/**
|
|
11
|
+
* Chroma API key (optional for self-hosted).
|
|
12
|
+
* Falls back to CHROMA_API_KEY environment variable.
|
|
13
|
+
*/
|
|
14
|
+
apiKey?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Chroma server host.
|
|
17
|
+
* Falls back to CHROMA_HOST environment variable.
|
|
18
|
+
* Defaults to 'localhost'.
|
|
19
|
+
*/
|
|
20
|
+
host?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Chroma server port.
|
|
23
|
+
* Falls back to CHROMA_PORT environment variable.
|
|
24
|
+
* Defaults to 8000.
|
|
25
|
+
*/
|
|
26
|
+
port?: number;
|
|
27
|
+
/**
|
|
28
|
+
* Use SSL/TLS for connection.
|
|
29
|
+
* Falls back to CHROMA_SSL environment variable.
|
|
30
|
+
* Defaults to false for localhost, true for remote hosts.
|
|
31
|
+
*/
|
|
32
|
+
ssl?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Optional tenant ID for multi-tenancy support.
|
|
35
|
+
*/
|
|
36
|
+
tenant?: string;
|
|
37
|
+
/**
|
|
38
|
+
* Optional database name.
|
|
39
|
+
*/
|
|
40
|
+
database?: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* ChromaAdapter implements VectorDBAdapter for Chroma vector database.
|
|
45
|
+
*
|
|
46
|
+
* Supports both self-hosted and cloud Chroma instances.
|
|
47
|
+
* Uses chromadb npm package for native TypeScript support.
|
|
48
|
+
*/
|
|
49
|
+
declare class ChromaAdapter extends VectorDBAdapter {
|
|
50
|
+
private config;
|
|
51
|
+
private client;
|
|
52
|
+
private collectionCache;
|
|
53
|
+
constructor(config?: ChromaConfig);
|
|
54
|
+
connect(): Promise<void>;
|
|
55
|
+
disconnect(): Promise<void>;
|
|
56
|
+
isConnected(): Promise<boolean>;
|
|
57
|
+
createCollection(name: string, dimension: number, metric?: DistanceMetric): Promise<void>;
|
|
58
|
+
deleteCollection(name: string): Promise<void>;
|
|
59
|
+
collectionExists(name: string): Promise<boolean>;
|
|
60
|
+
getCollectionStats(name: string): Promise<CollectionStats>;
|
|
61
|
+
upsert(collection: string, records: VectorRecord[]): Promise<void>;
|
|
62
|
+
fetch(collection: string, ids: string[]): Promise<VectorRecord[]>;
|
|
63
|
+
delete(collection: string, ids: string[]): Promise<void>;
|
|
64
|
+
updateMetadata(collection: string, updates: MetadataUpdate[]): Promise<void>;
|
|
65
|
+
search(collection: string, queryVector: number[], options?: {
|
|
66
|
+
topK?: number;
|
|
67
|
+
filter?: UniversalFilter;
|
|
68
|
+
includeMetadata?: boolean;
|
|
69
|
+
includeValues?: boolean;
|
|
70
|
+
}): Promise<SearchResult>;
|
|
71
|
+
translateFilter(filter: UniversalFilter): any;
|
|
72
|
+
iterate(collection: string, options?: {
|
|
73
|
+
batchSize?: number;
|
|
74
|
+
filter?: UniversalFilter;
|
|
75
|
+
}): AsyncIterableIterator<VectorRecord[]>;
|
|
76
|
+
supportsMetadataUpdate(): boolean;
|
|
77
|
+
supportsFiltering(): boolean;
|
|
78
|
+
supportsBatchOperations(): boolean;
|
|
79
|
+
private getCollection;
|
|
80
|
+
private mapDistanceMetric;
|
|
81
|
+
private unmapDistanceMetric;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export { ChromaAdapter, type ChromaConfig };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
// src/chroma-adapter.ts
|
|
2
|
+
import {
|
|
3
|
+
VectorDBAdapter
|
|
4
|
+
} from "@vectororm/core";
|
|
5
|
+
import { ChromaClient } from "chromadb";
|
|
6
|
+
var ChromaAdapter = class extends VectorDBAdapter {
|
|
7
|
+
config;
|
|
8
|
+
client = null;
|
|
9
|
+
collectionCache = /* @__PURE__ */ new Map();
|
|
10
|
+
constructor(config = {}) {
|
|
11
|
+
super();
|
|
12
|
+
this.config = config;
|
|
13
|
+
}
|
|
14
|
+
// ============================================================================
|
|
15
|
+
// CONNECTION MANAGEMENT
|
|
16
|
+
// ============================================================================
|
|
17
|
+
async connect() {
|
|
18
|
+
try {
|
|
19
|
+
const host = this.config.host || process.env.CHROMA_HOST || "localhost";
|
|
20
|
+
const port = this.config.port || (process.env.CHROMA_PORT ? parseInt(process.env.CHROMA_PORT, 10) : 8e3);
|
|
21
|
+
const ssl = this.config.ssl !== void 0 ? this.config.ssl : process.env.CHROMA_SSL === "true" || host !== "localhost";
|
|
22
|
+
const protocol = ssl ? "https" : "http";
|
|
23
|
+
const path = `${protocol}://${host}:${port}`;
|
|
24
|
+
const clientConfig = { path };
|
|
25
|
+
const apiKey = this.config.apiKey || process.env.CHROMA_API_KEY;
|
|
26
|
+
if (apiKey) {
|
|
27
|
+
clientConfig.auth = { provider: "token", credentials: apiKey };
|
|
28
|
+
}
|
|
29
|
+
if (this.config.tenant) {
|
|
30
|
+
clientConfig.tenant = this.config.tenant;
|
|
31
|
+
}
|
|
32
|
+
if (this.config.database) {
|
|
33
|
+
clientConfig.database = this.config.database;
|
|
34
|
+
}
|
|
35
|
+
this.client = new ChromaClient(clientConfig);
|
|
36
|
+
await this.client.heartbeat();
|
|
37
|
+
} catch (error) {
|
|
38
|
+
throw new Error(
|
|
39
|
+
`Chroma connection failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
40
|
+
{ cause: error }
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async disconnect() {
|
|
45
|
+
this.client = null;
|
|
46
|
+
this.collectionCache.clear();
|
|
47
|
+
}
|
|
48
|
+
async isConnected() {
|
|
49
|
+
if (!this.client) return false;
|
|
50
|
+
try {
|
|
51
|
+
await this.client.heartbeat();
|
|
52
|
+
return true;
|
|
53
|
+
} catch {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// ============================================================================
|
|
58
|
+
// COLLECTION MANAGEMENT
|
|
59
|
+
// ============================================================================
|
|
60
|
+
async createCollection(name, dimension, metric = "cosine") {
|
|
61
|
+
if (!this.client) {
|
|
62
|
+
throw new Error("Not connected. Call connect() first.");
|
|
63
|
+
}
|
|
64
|
+
try {
|
|
65
|
+
const chromaMetric = this.mapDistanceMetric(metric);
|
|
66
|
+
const collection = await this.client.createCollection({
|
|
67
|
+
name,
|
|
68
|
+
metadata: {
|
|
69
|
+
"hnsw:space": chromaMetric,
|
|
70
|
+
dimension: dimension.toString()
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
this.collectionCache.set(name, collection);
|
|
74
|
+
} catch (error) {
|
|
75
|
+
throw new Error(
|
|
76
|
+
`Failed to create Chroma collection ${name}: ${error instanceof Error ? error.message : String(error)}`,
|
|
77
|
+
{ cause: error }
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
async deleteCollection(name) {
|
|
82
|
+
if (!this.client) {
|
|
83
|
+
throw new Error("Not connected. Call connect() first.");
|
|
84
|
+
}
|
|
85
|
+
try {
|
|
86
|
+
await this.client.deleteCollection({ name });
|
|
87
|
+
this.collectionCache.delete(name);
|
|
88
|
+
} catch (error) {
|
|
89
|
+
throw new Error(
|
|
90
|
+
`Failed to delete Chroma collection ${name}: ${error instanceof Error ? error.message : String(error)}`,
|
|
91
|
+
{ cause: error }
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
async collectionExists(name) {
|
|
96
|
+
if (!this.client) {
|
|
97
|
+
throw new Error("Not connected. Call connect() first.");
|
|
98
|
+
}
|
|
99
|
+
try {
|
|
100
|
+
const collections = await this.client.listCollections();
|
|
101
|
+
return collections.some((col) => col.name === name);
|
|
102
|
+
} catch (error) {
|
|
103
|
+
throw new Error(
|
|
104
|
+
`Failed to check if Chroma collection ${name} exists: ${error instanceof Error ? error.message : String(error)}`,
|
|
105
|
+
{ cause: error }
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
async getCollectionStats(name) {
|
|
110
|
+
if (!this.client) {
|
|
111
|
+
throw new Error("Not connected. Call connect() first.");
|
|
112
|
+
}
|
|
113
|
+
try {
|
|
114
|
+
const collection = await this.getCollection(name);
|
|
115
|
+
const count = await collection.count();
|
|
116
|
+
const metadata = collection.metadata || {};
|
|
117
|
+
const dimension = metadata.dimension ? parseInt(metadata.dimension, 10) : 0;
|
|
118
|
+
const metricStr = metadata["hnsw:space"] || "cosine";
|
|
119
|
+
const metric = this.unmapDistanceMetric(metricStr);
|
|
120
|
+
return {
|
|
121
|
+
vectorCount: count,
|
|
122
|
+
dimension,
|
|
123
|
+
metric,
|
|
124
|
+
...metadata
|
|
125
|
+
};
|
|
126
|
+
} catch (error) {
|
|
127
|
+
throw new Error(
|
|
128
|
+
`Failed to get Chroma collection stats for ${name}: ${error instanceof Error ? error.message : String(error)}`,
|
|
129
|
+
{ cause: error }
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// ============================================================================
|
|
134
|
+
// VECTOR OPERATIONS
|
|
135
|
+
// ============================================================================
|
|
136
|
+
async upsert(collection, records) {
|
|
137
|
+
if (!this.client) {
|
|
138
|
+
throw new Error("Not connected. Call connect() first.");
|
|
139
|
+
}
|
|
140
|
+
try {
|
|
141
|
+
const col = await this.getCollection(collection);
|
|
142
|
+
const ids = records.map((r) => r.id);
|
|
143
|
+
const embeddings = records.map((r) => r.embedding);
|
|
144
|
+
const metadatas = records.map((r) => r.metadata || {});
|
|
145
|
+
await col.upsert({
|
|
146
|
+
ids,
|
|
147
|
+
embeddings,
|
|
148
|
+
metadatas
|
|
149
|
+
});
|
|
150
|
+
} catch (error) {
|
|
151
|
+
throw new Error(
|
|
152
|
+
`Failed to upsert vectors to Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,
|
|
153
|
+
{ cause: error }
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
async fetch(collection, ids) {
|
|
158
|
+
if (!this.client) {
|
|
159
|
+
throw new Error("Not connected. Call connect() first.");
|
|
160
|
+
}
|
|
161
|
+
try {
|
|
162
|
+
const col = await this.getCollection(collection);
|
|
163
|
+
const response = await col.get({
|
|
164
|
+
ids,
|
|
165
|
+
include: ["embeddings", "metadatas"]
|
|
166
|
+
});
|
|
167
|
+
const records = [];
|
|
168
|
+
if (response.ids && response.ids.length > 0) {
|
|
169
|
+
for (let i = 0; i < response.ids.length; i++) {
|
|
170
|
+
records.push({
|
|
171
|
+
id: response.ids[i],
|
|
172
|
+
embedding: response.embeddings?.[i] || [],
|
|
173
|
+
metadata: response.metadatas?.[i] || {}
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return records;
|
|
178
|
+
} catch (error) {
|
|
179
|
+
throw new Error(
|
|
180
|
+
`Failed to fetch vectors from Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,
|
|
181
|
+
{ cause: error }
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
async delete(collection, ids) {
|
|
186
|
+
if (!this.client) {
|
|
187
|
+
throw new Error("Not connected. Call connect() first.");
|
|
188
|
+
}
|
|
189
|
+
try {
|
|
190
|
+
const col = await this.getCollection(collection);
|
|
191
|
+
await col.delete({ ids });
|
|
192
|
+
} catch (error) {
|
|
193
|
+
throw new Error(
|
|
194
|
+
`Failed to delete vectors from Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,
|
|
195
|
+
{ cause: error }
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
// ============================================================================
|
|
200
|
+
// METADATA OPERATIONS
|
|
201
|
+
// ============================================================================
|
|
202
|
+
async updateMetadata(collection, updates) {
|
|
203
|
+
if (!this.client) {
|
|
204
|
+
throw new Error("Not connected. Call connect() first.");
|
|
205
|
+
}
|
|
206
|
+
try {
|
|
207
|
+
const col = await this.getCollection(collection);
|
|
208
|
+
for (const update of updates) {
|
|
209
|
+
await col.update({
|
|
210
|
+
ids: [update.id],
|
|
211
|
+
metadatas: [update.metadata]
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
} catch (error) {
|
|
215
|
+
throw new Error(
|
|
216
|
+
`Failed to update metadata in Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,
|
|
217
|
+
{ cause: error }
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
// ============================================================================
|
|
222
|
+
// SEARCH OPERATIONS
|
|
223
|
+
// ============================================================================
|
|
224
|
+
async search(collection, queryVector, options) {
|
|
225
|
+
if (!this.client) {
|
|
226
|
+
throw new Error("Not connected. Call connect() first.");
|
|
227
|
+
}
|
|
228
|
+
try {
|
|
229
|
+
const col = await this.getCollection(collection);
|
|
230
|
+
const chromaFilter = options?.filter ? this.translateFilter(options.filter) : void 0;
|
|
231
|
+
const include = ["distances"];
|
|
232
|
+
if (options?.includeMetadata !== false) {
|
|
233
|
+
include.push("metadatas");
|
|
234
|
+
}
|
|
235
|
+
if (options?.includeValues) {
|
|
236
|
+
include.push("embeddings");
|
|
237
|
+
}
|
|
238
|
+
const response = await col.query({
|
|
239
|
+
queryEmbeddings: [queryVector],
|
|
240
|
+
nResults: options?.topK || 10,
|
|
241
|
+
where: chromaFilter,
|
|
242
|
+
include
|
|
243
|
+
});
|
|
244
|
+
const records = [];
|
|
245
|
+
if (response.ids && response.ids[0]) {
|
|
246
|
+
const resultIds = response.ids[0];
|
|
247
|
+
const distances = response.distances?.[0] || [];
|
|
248
|
+
const embeddings = response.embeddings?.[0] || [];
|
|
249
|
+
const metadatas = response.metadatas?.[0] || [];
|
|
250
|
+
for (let i = 0; i < resultIds.length; i++) {
|
|
251
|
+
const record = {
|
|
252
|
+
id: resultIds[i],
|
|
253
|
+
embedding: options?.includeValues ? embeddings[i] || [] : [],
|
|
254
|
+
metadata: options?.includeMetadata !== false ? metadatas[i] || {} : {}
|
|
255
|
+
};
|
|
256
|
+
if (distances[i] !== void 0) {
|
|
257
|
+
record.score = 1 / (1 + distances[i]);
|
|
258
|
+
}
|
|
259
|
+
records.push(record);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return { records };
|
|
263
|
+
} catch (error) {
|
|
264
|
+
throw new Error(
|
|
265
|
+
`Failed to search Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,
|
|
266
|
+
{ cause: error }
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
// ============================================================================
|
|
271
|
+
// FILTER TRANSLATION
|
|
272
|
+
// ============================================================================
|
|
273
|
+
translateFilter(filter) {
|
|
274
|
+
if ("and" in filter) {
|
|
275
|
+
const conditions = filter.and;
|
|
276
|
+
const translated = conditions.map((c) => this.translateFilter(c));
|
|
277
|
+
return { $and: translated };
|
|
278
|
+
}
|
|
279
|
+
if ("or" in filter) {
|
|
280
|
+
const conditions = filter.or;
|
|
281
|
+
const translated = conditions.map((c) => this.translateFilter(c));
|
|
282
|
+
return { $or: translated };
|
|
283
|
+
}
|
|
284
|
+
const { field, op, value } = filter;
|
|
285
|
+
const operatorMap = {
|
|
286
|
+
eq: "$eq",
|
|
287
|
+
ne: "$ne",
|
|
288
|
+
gt: "$gt",
|
|
289
|
+
gte: "$gte",
|
|
290
|
+
lt: "$lt",
|
|
291
|
+
lte: "$lte",
|
|
292
|
+
in: "$in",
|
|
293
|
+
nin: "$nin"
|
|
294
|
+
};
|
|
295
|
+
const chromaOp = operatorMap[op];
|
|
296
|
+
if (!chromaOp) {
|
|
297
|
+
throw new Error(
|
|
298
|
+
`Unsupported filter operator: ${op}`,
|
|
299
|
+
{ cause: { filter } }
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
return {
|
|
303
|
+
[field]: {
|
|
304
|
+
[chromaOp]: value
|
|
305
|
+
}
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
// ============================================================================
|
|
309
|
+
// ITERATION
|
|
310
|
+
// ============================================================================
|
|
311
|
+
async *iterate(collection, options) {
|
|
312
|
+
if (!this.client) {
|
|
313
|
+
throw new Error("Not connected. Call connect() first.");
|
|
314
|
+
}
|
|
315
|
+
try {
|
|
316
|
+
const col = await this.getCollection(collection);
|
|
317
|
+
const batchSize = options?.batchSize || 100;
|
|
318
|
+
const chromaFilter = options?.filter ? this.translateFilter(options.filter) : void 0;
|
|
319
|
+
let offset = 0;
|
|
320
|
+
let hasMore = true;
|
|
321
|
+
while (hasMore) {
|
|
322
|
+
const response = await col.get({
|
|
323
|
+
where: chromaFilter,
|
|
324
|
+
limit: batchSize,
|
|
325
|
+
offset,
|
|
326
|
+
include: ["embeddings", "metadatas"]
|
|
327
|
+
});
|
|
328
|
+
if (response.ids && response.ids.length > 0) {
|
|
329
|
+
const records = [];
|
|
330
|
+
for (let i = 0; i < response.ids.length; i++) {
|
|
331
|
+
records.push({
|
|
332
|
+
id: response.ids[i],
|
|
333
|
+
embedding: response.embeddings?.[i] || [],
|
|
334
|
+
metadata: response.metadatas?.[i] || {}
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
yield records;
|
|
338
|
+
hasMore = response.ids.length === batchSize;
|
|
339
|
+
offset += batchSize;
|
|
340
|
+
} else {
|
|
341
|
+
hasMore = false;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
} catch (error) {
|
|
345
|
+
throw new Error(
|
|
346
|
+
`Failed to iterate Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,
|
|
347
|
+
{ cause: error }
|
|
348
|
+
);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
// ============================================================================
|
|
352
|
+
// CAPABILITY FLAGS
|
|
353
|
+
// ============================================================================
|
|
354
|
+
supportsMetadataUpdate() {
|
|
355
|
+
return true;
|
|
356
|
+
}
|
|
357
|
+
supportsFiltering() {
|
|
358
|
+
return true;
|
|
359
|
+
}
|
|
360
|
+
supportsBatchOperations() {
|
|
361
|
+
return true;
|
|
362
|
+
}
|
|
363
|
+
// ============================================================================
|
|
364
|
+
// HELPER METHODS
|
|
365
|
+
// ============================================================================
|
|
366
|
+
async getCollection(name) {
|
|
367
|
+
if (this.collectionCache.has(name)) {
|
|
368
|
+
return this.collectionCache.get(name);
|
|
369
|
+
}
|
|
370
|
+
if (!this.client) {
|
|
371
|
+
throw new Error("Not connected. Call connect() first.");
|
|
372
|
+
}
|
|
373
|
+
const collection = await this.client.getCollection({ name, embeddingFunction: void 0 });
|
|
374
|
+
this.collectionCache.set(name, collection);
|
|
375
|
+
return collection;
|
|
376
|
+
}
|
|
377
|
+
mapDistanceMetric(metric) {
|
|
378
|
+
const metricMap = {
|
|
379
|
+
cosine: "cosine",
|
|
380
|
+
euclidean: "l2",
|
|
381
|
+
dotProduct: "ip"
|
|
382
|
+
// Inner product
|
|
383
|
+
};
|
|
384
|
+
return metricMap[metric] || "cosine";
|
|
385
|
+
}
|
|
386
|
+
unmapDistanceMetric(chromaMetric) {
|
|
387
|
+
const metricMap = {
|
|
388
|
+
cosine: "cosine",
|
|
389
|
+
l2: "euclidean",
|
|
390
|
+
ip: "dotProduct"
|
|
391
|
+
};
|
|
392
|
+
return metricMap[chromaMetric] || "cosine";
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
export {
|
|
396
|
+
ChromaAdapter
|
|
397
|
+
};
|
|
398
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/chroma-adapter.ts"],"sourcesContent":["import {\n VectorDBAdapter,\n type VectorRecord,\n type SearchResult,\n type UniversalFilter,\n type CollectionStats,\n type MetadataUpdate,\n type DistanceMetric,\n} from '@vectororm/core';\nimport { ChromaClient, type Collection } from 'chromadb';\nimport type { ChromaConfig } from './types.js';\n\n/**\n * ChromaAdapter implements VectorDBAdapter for Chroma vector database.\n *\n * Supports both self-hosted and cloud Chroma instances.\n * Uses chromadb npm package for native TypeScript support.\n */\nexport class ChromaAdapter extends VectorDBAdapter {\n private config: ChromaConfig;\n private client: ChromaClient | null = null;\n private collectionCache: Map<string, Collection> = new Map();\n\n constructor(config: ChromaConfig = {}) {\n super();\n this.config = config;\n }\n\n // ============================================================================\n // CONNECTION MANAGEMENT\n // ============================================================================\n\n async connect(): Promise<void> {\n try {\n const host = this.config.host || process.env.CHROMA_HOST || 'localhost';\n const port = this.config.port ||\n (process.env.CHROMA_PORT ? parseInt(process.env.CHROMA_PORT, 10) : 8000);\n\n // Determine SSL usage\n const ssl = this.config.ssl !== undefined\n ? this.config.ssl\n : (process.env.CHROMA_SSL === 'true' || host !== 'localhost');\n\n const protocol = ssl ? 'https' : 'http';\n const path = `${protocol}://${host}:${port}`;\n\n const clientConfig: any = { path };\n\n // Add auth if API key is provided\n const apiKey = this.config.apiKey || process.env.CHROMA_API_KEY;\n if (apiKey) {\n clientConfig.auth = { provider: 'token', credentials: apiKey };\n }\n\n // Add tenant/database if provided\n if (this.config.tenant) {\n clientConfig.tenant = this.config.tenant;\n }\n if (this.config.database) {\n clientConfig.database = this.config.database;\n }\n\n this.client = new ChromaClient(clientConfig);\n\n // Verify connection by getting heartbeat\n await this.client.heartbeat();\n } catch (error) {\n throw new Error(\n `Chroma connection failed: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n async disconnect(): Promise<void> {\n this.client = null;\n this.collectionCache.clear();\n }\n\n async isConnected(): Promise<boolean> {\n if (!this.client) return false;\n\n try {\n await this.client.heartbeat();\n return true;\n } catch {\n return false;\n }\n }\n\n // ============================================================================\n // COLLECTION MANAGEMENT\n // ============================================================================\n\n async createCollection(\n name: string,\n dimension: number,\n metric: DistanceMetric = 'cosine'\n ): Promise<void> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n // Map our metric to Chroma distance function\n const chromaMetric = this.mapDistanceMetric(metric);\n\n const collection = await this.client.createCollection({\n name,\n metadata: {\n 'hnsw:space': chromaMetric,\n dimension: dimension.toString(),\n },\n });\n\n this.collectionCache.set(name, collection);\n } catch (error) {\n throw new Error(\n `Failed to create Chroma collection ${name}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n async deleteCollection(name: string): Promise<void> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n await this.client.deleteCollection({ name });\n this.collectionCache.delete(name);\n } catch (error) {\n throw new Error(\n `Failed to delete Chroma collection ${name}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n async collectionExists(name: string): Promise<boolean> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n const collections = await this.client.listCollections();\n return collections.some((col: any) => col.name === name);\n } catch (error) {\n throw new Error(\n `Failed to check if Chroma collection ${name} exists: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n async getCollectionStats(name: string): Promise<CollectionStats> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n const collection = await this.getCollection(name);\n const count = await collection.count();\n\n // Get metadata from collection\n const metadata = (collection as any).metadata || {};\n const dimension = metadata.dimension\n ? parseInt(metadata.dimension, 10)\n : 0;\n\n const metricStr = metadata['hnsw:space'] || 'cosine';\n const metric = this.unmapDistanceMetric(metricStr);\n\n return {\n vectorCount: count,\n dimension,\n metric,\n ...metadata,\n };\n } catch (error) {\n throw new Error(\n `Failed to get Chroma collection stats for ${name}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n // ============================================================================\n // VECTOR OPERATIONS\n // ============================================================================\n\n async upsert(collection: string, records: VectorRecord[]): Promise<void> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n const col = await this.getCollection(collection);\n\n const ids = records.map((r) => r.id);\n const embeddings = records.map((r) => r.embedding);\n const metadatas = records.map((r) => r.metadata || {});\n\n await col.upsert({\n ids,\n embeddings,\n metadatas,\n });\n } catch (error) {\n throw new Error(\n `Failed to upsert vectors to Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n async fetch(collection: string, ids: string[]): Promise<VectorRecord[]> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n const col = await this.getCollection(collection);\n\n const response = await col.get({\n ids,\n include: ['embeddings' as any, 'metadatas' as any],\n });\n\n const records: VectorRecord[] = [];\n\n if (response.ids && response.ids.length > 0) {\n for (let i = 0; i < response.ids.length; i++) {\n records.push({\n id: response.ids[i],\n embedding: response.embeddings?.[i] || [],\n metadata: response.metadatas?.[i] || {},\n });\n }\n }\n\n return records;\n } catch (error) {\n throw new Error(\n `Failed to fetch vectors from Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n async delete(collection: string, ids: string[]): Promise<void> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n const col = await this.getCollection(collection);\n await col.delete({ ids });\n } catch (error) {\n throw new Error(\n `Failed to delete vectors from Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n // ============================================================================\n // METADATA OPERATIONS\n // ============================================================================\n\n async updateMetadata(\n collection: string,\n updates: MetadataUpdate[]\n ): Promise<void> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n const col = await this.getCollection(collection);\n\n // Chroma supports metadata updates via update method\n for (const update of updates) {\n await col.update({\n ids: [update.id],\n metadatas: [update.metadata],\n });\n }\n } catch (error) {\n throw new Error(\n `Failed to update metadata in Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n // ============================================================================\n // SEARCH OPERATIONS\n // ============================================================================\n\n async search(\n collection: string,\n queryVector: number[],\n options?: {\n topK?: number;\n filter?: UniversalFilter;\n includeMetadata?: boolean;\n includeValues?: boolean;\n }\n ): Promise<SearchResult> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n const col = await this.getCollection(collection);\n\n const chromaFilter = options?.filter\n ? this.translateFilter(options.filter)\n : undefined;\n\n const include: any[] = ['distances' as any];\n if (options?.includeMetadata !== false) {\n include.push('metadatas' as any);\n }\n if (options?.includeValues) {\n include.push('embeddings' as any);\n }\n\n const response = await col.query({\n queryEmbeddings: [queryVector],\n nResults: options?.topK || 10,\n where: chromaFilter,\n include,\n });\n\n const records: VectorRecord[] = [];\n\n if (response.ids && response.ids[0]) {\n const resultIds = response.ids[0];\n const distances = response.distances?.[0] || [];\n const embeddings = response.embeddings?.[0] || [];\n const metadatas = response.metadatas?.[0] || [];\n\n for (let i = 0; i < resultIds.length; i++) {\n const record: VectorRecord = {\n id: resultIds[i],\n embedding: options?.includeValues ? (embeddings[i] || []) : [],\n metadata: options?.includeMetadata !== false ? (metadatas[i] || {}) : {},\n };\n\n // Convert distance to score (inverse relationship)\n if (distances[i] !== undefined) {\n record.score = 1 / (1 + distances[i]);\n }\n\n records.push(record);\n }\n }\n\n return { records };\n } catch (error) {\n throw new Error(\n `Failed to search Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n // ============================================================================\n // FILTER TRANSLATION\n // ============================================================================\n\n translateFilter(filter: UniversalFilter): any {\n // Handle compound AND filter\n if ('and' in filter) {\n const conditions = filter.and;\n const translated = conditions.map((c) => this.translateFilter(c));\n\n return { $and: translated };\n }\n\n // Handle compound OR filter\n if ('or' in filter) {\n const conditions = filter.or;\n const translated = conditions.map((c) => this.translateFilter(c));\n\n return { $or: translated };\n }\n\n // Handle basic filter condition\n const { field, op, value } = filter as any;\n\n // Operator mapping to Chroma's MongoDB-like syntax\n const operatorMap: Record<string, string> = {\n eq: '$eq',\n ne: '$ne',\n gt: '$gt',\n gte: '$gte',\n lt: '$lt',\n lte: '$lte',\n in: '$in',\n nin: '$nin',\n };\n\n const chromaOp = operatorMap[op];\n if (!chromaOp) {\n throw new Error(\n `Unsupported filter operator: ${op}`,\n { cause: { filter } }\n );\n }\n\n return {\n [field]: {\n [chromaOp]: value,\n },\n };\n }\n\n // ============================================================================\n // ITERATION\n // ============================================================================\n\n async *iterate(\n collection: string,\n options?: {\n batchSize?: number;\n filter?: UniversalFilter;\n }\n ): AsyncIterableIterator<VectorRecord[]> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n const col = await this.getCollection(collection);\n const batchSize = options?.batchSize || 100;\n const chromaFilter = options?.filter\n ? this.translateFilter(options.filter)\n : undefined;\n\n // Chroma uses offset/limit pagination\n let offset = 0;\n let hasMore = true;\n\n while (hasMore) {\n const response = await col.get({\n where: chromaFilter,\n limit: batchSize,\n offset,\n include: ['embeddings' as any, 'metadatas' as any],\n });\n\n if (response.ids && response.ids.length > 0) {\n const records: VectorRecord[] = [];\n\n for (let i = 0; i < response.ids.length; i++) {\n records.push({\n id: response.ids[i],\n embedding: response.embeddings?.[i] || [],\n metadata: response.metadatas?.[i] || {},\n });\n }\n\n yield records;\n\n // Check if there are more results\n hasMore = response.ids.length === batchSize;\n offset += batchSize;\n } else {\n hasMore = false;\n }\n }\n } catch (error) {\n throw new Error(\n `Failed to iterate Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n // ============================================================================\n // CAPABILITY FLAGS\n // ============================================================================\n\n supportsMetadataUpdate(): boolean {\n return true; // Chroma supports metadata updates\n }\n\n supportsFiltering(): boolean {\n return true; // Chroma supports metadata filtering\n }\n\n supportsBatchOperations(): boolean {\n return true; // Chroma supports batch operations\n }\n\n // ============================================================================\n // HELPER METHODS\n // ============================================================================\n\n private async getCollection(name: string): Promise<Collection> {\n if (this.collectionCache.has(name)) {\n return this.collectionCache.get(name)!;\n }\n\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n const collection = await this.client.getCollection({ name, embeddingFunction: undefined as any });\n this.collectionCache.set(name, collection);\n return collection;\n }\n\n private mapDistanceMetric(metric: DistanceMetric): string {\n const metricMap: Record<DistanceMetric, string> = {\n cosine: 'cosine',\n euclidean: 'l2',\n dotProduct: 'ip', // Inner product\n };\n\n return metricMap[metric] || 'cosine';\n }\n\n private unmapDistanceMetric(chromaMetric: string): DistanceMetric {\n const metricMap: Record<string, DistanceMetric> = {\n cosine: 'cosine',\n l2: 'euclidean',\n ip: 'dotProduct',\n };\n\n return metricMap[chromaMetric] || 'cosine';\n }\n}\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vectororm/adapter-chroma",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "ChromaDB adapter for Glyph VectorORM",
|
|
5
|
+
"author": "Aviram Roisman",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"homepage": "https://github.com/aviramroi/VectorORM",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/aviramroi/VectorORM.git",
|
|
11
|
+
"directory": "packages/adapter-chroma"
|
|
12
|
+
},
|
|
13
|
+
"publishConfig": {
|
|
14
|
+
"access": "public"
|
|
15
|
+
},
|
|
16
|
+
"type": "module",
|
|
17
|
+
"main": "./dist/index.js",
|
|
18
|
+
"module": "./dist/index.mjs",
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"exports": {
|
|
21
|
+
".": {
|
|
22
|
+
"types": "./dist/index.d.ts",
|
|
23
|
+
"require": "./dist/index.js",
|
|
24
|
+
"import": "./dist/index.mjs"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"files": ["dist", "README.md"],
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=18.0.0"
|
|
30
|
+
},
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "tsup",
|
|
33
|
+
"test": "vitest run",
|
|
34
|
+
"test:watch": "vitest",
|
|
35
|
+
"test:integration": "vitest run --config vitest.integration.config.ts"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@vectororm/core": "*",
|
|
39
|
+
"chromadb": "^1.8.1"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/node": "^20.10.0",
|
|
43
|
+
"tsup": "^8.0.0",
|
|
44
|
+
"typescript": "^5.3.3",
|
|
45
|
+
"vitest": "^1.0.0"
|
|
46
|
+
},
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"@vectororm/core": "^0.1.0"
|
|
49
|
+
},
|
|
50
|
+
"keywords": [
|
|
51
|
+
"glyph",
|
|
52
|
+
"vectororm",
|
|
53
|
+
"chroma",
|
|
54
|
+
"chromadb",
|
|
55
|
+
"vector-database",
|
|
56
|
+
"adapter"
|
|
57
|
+
]
|
|
58
|
+
}
|