@sprucelabs/chroma-data-store 1.0.0 → 1.0.2
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 +42 -0
- package/build/.spruce/settings.json +3 -1
- package/build/ChromaDatabase.d.ts +6 -1
- package/build/ChromaDatabase.js +23 -8
- package/build/MockChromaDatabase.d.ts +8 -0
- package/build/MockChromaDatabase.js +20 -0
- package/build/chroma.types.d.ts +21 -174
- package/build/chromaDbAssert.utility.d.ts +4 -0
- package/build/chromaDbAssert.utility.js +20 -0
- package/build/esm/ChromaDatabase.d.ts +6 -1
- package/build/esm/ChromaDatabase.js +28 -10
- package/build/esm/MockChromaDatabase.d.ts +8 -0
- package/build/esm/MockChromaDatabase.js +31 -0
- package/build/esm/chroma.types.d.ts +21 -174
- package/build/esm/chromaDbAssert.utility.d.ts +4 -0
- package/build/esm/chromaDbAssert.utility.js +16 -0
- package/build/esm/index.d.ts +2 -0
- package/build/esm/index.js +2 -0
- package/build/index.d.ts +2 -0
- package/build/index.js +5 -1
- package/package.json +26 -23
- package/build/esm/.spruce/errors/chromaDataStore/featureNotSupported.schema.d.ts +0 -3
- package/build/esm/.spruce/errors/chromaDataStore/featureNotSupported.schema.js +0 -18
- package/build/esm/.spruce/errors/chromaDataStore/featureNotSupported.schema.js.map +0 -1
- package/build/esm/.spruce/errors/errors.types.js.map +0 -1
- package/build/esm/.spruce/errors/options.types.js.map +0 -1
- package/build/esm/.spruce/schemas/fields/fieldClassMap.d.ts +0 -2
- package/build/esm/.spruce/schemas/fields/fieldClassMap.js +0 -4
- package/build/esm/.spruce/schemas/fields/fieldClassMap.js.map +0 -1
- package/build/esm/.spruce/schemas/fields/fields.types.d.ts +0 -1
- package/build/esm/.spruce/schemas/fields/fields.types.js +0 -2
- package/build/esm/.spruce/schemas/fields/fields.types.js.map +0 -1
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/choice.schema.d.ts +0 -1
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/choice.schema.js +0 -5
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/choice.schema.js.map +0 -1
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/link.schema.d.ts +0 -1
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/link.schema.js +0 -5
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/link.schema.js.map +0 -1
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/location.schema.d.ts +0 -1
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/location.schema.js +0 -5
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/location.schema.js.map +0 -1
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/message.schema.d.ts +0 -1
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/message.schema.js +0 -5
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/message.schema.js.map +0 -1
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/messageSource.schema.d.ts +0 -1
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/messageSource.schema.js +0 -5
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/messageSource.schema.js.map +0 -1
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/messageTarget.schema.d.ts +0 -1
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/messageTarget.schema.js +0 -5
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/messageTarget.schema.js.map +0 -1
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/organization.schema.d.ts +0 -1
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/organization.schema.js +0 -5
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/organization.schema.js.map +0 -1
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/person.schema.d.ts +0 -1
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/person.schema.js +0 -5
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/person.schema.js.map +0 -1
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/personLocation.schema.d.ts +0 -1
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/personLocation.schema.js +0 -5
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/personLocation.schema.js.map +0 -1
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/personOrganization.schema.d.ts +0 -1
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/personOrganization.schema.js +0 -5
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/personOrganization.schema.js.map +0 -1
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/role.schema.d.ts +0 -1
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/role.schema.js +0 -5
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/role.schema.js.map +0 -1
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/sendMessage.schema.d.ts +0 -1
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/sendMessage.schema.js +0 -5
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/sendMessage.schema.js.map +0 -1
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/skill.schema.d.ts +0 -1
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/skill.schema.js +0 -5
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/skill.schema.js.map +0 -1
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/skillCreator.schema.d.ts +0 -1
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/skillCreator.schema.js +0 -5
- package/build/esm/.spruce/schemas/spruce/v2020_07_22/skillCreator.schema.js.map +0 -1
- package/build/esm/.spruce/settings.json +0 -13
- package/build/esm/ChromaDatabase.js.map +0 -1
- package/build/esm/chroma.types.js.map +0 -1
- package/build/esm/errors/SpruceError.js.map +0 -1
- package/build/esm/errors/featureNotSupported.builder.js.map +0 -1
- package/build/esm/index.js.map +0 -1
package/README.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Chroma Data Store
|
|
2
|
+
|
|
3
|
+
Give your skill the ability to store and retrieve data from a Chroma database.
|
|
4
|
+
|
|
5
|
+
## Running the Chroma Database
|
|
6
|
+
|
|
7
|
+
1. Clone this rep
|
|
8
|
+
2. Run `yarn start.chroma.docker`
|
|
9
|
+
|
|
10
|
+
## Setting an embedding model
|
|
11
|
+
|
|
12
|
+
By default, the ChromaDabatase class will use llama3.2 hosted through Ollama to generate embeddings
|
|
13
|
+
|
|
14
|
+
### Installing Ollama
|
|
15
|
+
|
|
16
|
+
1. Visit https://ollama.com
|
|
17
|
+
2. Click "Download"
|
|
18
|
+
3. Select your OS
|
|
19
|
+
|
|
20
|
+
### Installing Llama3.2
|
|
21
|
+
|
|
22
|
+
Llama 3.2 is the newest version of Llama (as of this writing) that supports embeddings.
|
|
23
|
+
|
|
24
|
+
1. Inside of terminal, run `ollama run llama3.2`
|
|
25
|
+
2. You should be able to visit http://localhost:11434/api/embeddings and get a 405 response (this is because the route only accepts POST requests)
|
|
26
|
+
|
|
27
|
+
### Improving embeddings with `nomic-embed-text`
|
|
28
|
+
|
|
29
|
+
We have seen significantly better search performance when using `nomic-embed-text` to generate embeddings.
|
|
30
|
+
|
|
31
|
+
Run `ollama pull nomic-embed-text`
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
## Using in your skill
|
|
35
|
+
|
|
36
|
+
Add the following to your env:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
DB_CONNECTION_STRING="chromadb://localhost:8000"
|
|
40
|
+
DB_ADAPTER="@sprucelabs/chroma-data-store"
|
|
41
|
+
|
|
42
|
+
```
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import { CreateOptions, Database, DatabaseInternalOptions, Index, IndexWithFilter, QueryOptions } from '@sprucelabs/data-stores';
|
|
2
|
+
import { OllamaEmbeddingFunction } from '@chroma-core/ollama';
|
|
2
3
|
export default class ChromaDatabase implements Database {
|
|
4
|
+
static Class?: new (connectionString: string) => Database;
|
|
5
|
+
static EmbeddingFunction: typeof OllamaEmbeddingFunction;
|
|
6
|
+
private static embeddingFields?;
|
|
3
7
|
private connectionString;
|
|
4
8
|
private client;
|
|
5
9
|
private _isConnected;
|
|
6
10
|
private embeddings;
|
|
7
11
|
private collections;
|
|
8
|
-
private static embeddingFields?;
|
|
9
12
|
constructor(connectionString: string);
|
|
13
|
+
static Database(connectionString: string): ChromaDatabase | Database;
|
|
10
14
|
static setEmbeddingsFields(collectionName: string, fields: string[]): void;
|
|
11
15
|
static clearEmbeddingsFields(): void;
|
|
16
|
+
static getEmbeddingsFields(): Record<string, string[]> | undefined;
|
|
12
17
|
syncUniqueIndexes(_collectionName: string, _indexes: Index[]): Promise<void>;
|
|
13
18
|
syncIndexes(_collectionName: string, _indexes: Index[]): Promise<void>;
|
|
14
19
|
dropIndex(_collectionName: string, _index: Index): Promise<void>;
|
package/build/ChromaDatabase.js
CHANGED
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
const data_stores_1 = require("@sprucelabs/data-stores");
|
|
7
7
|
const schema_1 = require("@sprucelabs/schema");
|
|
8
8
|
const test_utils_1 = require("@sprucelabs/test-utils");
|
|
9
|
+
const ollama_1 = require("@chroma-core/ollama");
|
|
9
10
|
const chromadb_1 = require("chromadb");
|
|
10
11
|
const SpruceError_1 = __importDefault(require("./errors/SpruceError"));
|
|
11
12
|
class ChromaDatabase {
|
|
@@ -13,9 +14,9 @@ class ChromaDatabase {
|
|
|
13
14
|
this._isConnected = false;
|
|
14
15
|
this.collections = {};
|
|
15
16
|
(0, schema_1.assertOptions)({ connectionString }, ['connectionString']);
|
|
16
|
-
this.embeddings = new
|
|
17
|
-
model: 'llama3.2',
|
|
18
|
-
url: 'http://localhost:11434
|
|
17
|
+
this.embeddings = new ChromaDatabase.EmbeddingFunction({
|
|
18
|
+
model: process.env.CHROMA_EMBEDDING_MODEL ?? 'llama3.2',
|
|
19
|
+
url: 'http://localhost:11434',
|
|
19
20
|
});
|
|
20
21
|
if (!connectionString.startsWith('chroma://')) {
|
|
21
22
|
throw new data_stores_1.DataStoresError({
|
|
@@ -24,6 +25,9 @@ class ChromaDatabase {
|
|
|
24
25
|
}
|
|
25
26
|
this.connectionString = connectionString.replace('chroma://', 'http://');
|
|
26
27
|
}
|
|
28
|
+
static Database(connectionString) {
|
|
29
|
+
return new (this.Class ?? this)(connectionString);
|
|
30
|
+
}
|
|
27
31
|
static setEmbeddingsFields(collectionName, fields) {
|
|
28
32
|
if (!this.embeddingFields) {
|
|
29
33
|
this.embeddingFields = {};
|
|
@@ -33,6 +37,9 @@ class ChromaDatabase {
|
|
|
33
37
|
static clearEmbeddingsFields() {
|
|
34
38
|
delete this.embeddingFields;
|
|
35
39
|
}
|
|
40
|
+
static getEmbeddingsFields() {
|
|
41
|
+
return this.embeddingFields;
|
|
42
|
+
}
|
|
36
43
|
async syncUniqueIndexes(_collectionName, _indexes) {
|
|
37
44
|
throw new SpruceError_1.default({
|
|
38
45
|
code: 'FEATURE_NOT_SUPPORTED',
|
|
@@ -183,14 +190,19 @@ class ChromaDatabase {
|
|
|
183
190
|
async find(collection, query, options, _dbOptions) {
|
|
184
191
|
let { ids, where, skipIds } = this.buildQuery(query);
|
|
185
192
|
let matches;
|
|
186
|
-
|
|
193
|
+
let { limit, includeFields } = options ?? {};
|
|
187
194
|
const col = await this.getCollection(collection);
|
|
195
|
+
if (!limit && where?.$prompt) {
|
|
196
|
+
limit = 10;
|
|
197
|
+
}
|
|
188
198
|
if (where?.$prompt) {
|
|
189
199
|
const { $prompt, ...rest } = where;
|
|
190
200
|
const queryResults = await col.query({
|
|
191
201
|
queryTexts: [$prompt],
|
|
192
|
-
nResults:
|
|
193
|
-
where: Object.keys(rest).length > 0
|
|
202
|
+
nResults: limit,
|
|
203
|
+
where: (Object.keys(rest).length > 0
|
|
204
|
+
? rest
|
|
205
|
+
: undefined),
|
|
194
206
|
});
|
|
195
207
|
matches = {
|
|
196
208
|
ids: queryResults.ids[0],
|
|
@@ -201,7 +213,7 @@ class ChromaDatabase {
|
|
|
201
213
|
matches = await col.get({
|
|
202
214
|
ids,
|
|
203
215
|
include: ['metadatas'],
|
|
204
|
-
where,
|
|
216
|
+
where: where,
|
|
205
217
|
limit: limit == 0 ? 1 : limit,
|
|
206
218
|
});
|
|
207
219
|
}
|
|
@@ -255,7 +267,6 @@ class ChromaDatabase {
|
|
|
255
267
|
where = rest;
|
|
256
268
|
}
|
|
257
269
|
if (where?.$or && where.$or.length === 1) {
|
|
258
|
-
//@ts-ignore
|
|
259
270
|
where = where.$or[0];
|
|
260
271
|
}
|
|
261
272
|
if (where) {
|
|
@@ -348,6 +359,9 @@ class ChromaDatabase {
|
|
|
348
359
|
}
|
|
349
360
|
async delete(collection, query) {
|
|
350
361
|
const matches = await this.find(collection, query);
|
|
362
|
+
if (matches.length === 0) {
|
|
363
|
+
return 0;
|
|
364
|
+
}
|
|
351
365
|
const col = await this.getCollection(collection);
|
|
352
366
|
await col.delete({
|
|
353
367
|
ids: matches.map((m) => m.id),
|
|
@@ -382,4 +396,5 @@ class ChromaDatabase {
|
|
|
382
396
|
});
|
|
383
397
|
}
|
|
384
398
|
}
|
|
399
|
+
ChromaDatabase.EmbeddingFunction = ollama_1.OllamaEmbeddingFunction;
|
|
385
400
|
exports.default = ChromaDatabase;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { NeDbDatabase } from '@sprucelabs/data-stores';
|
|
2
|
+
export default class MockChromaDatabase extends NeDbDatabase {
|
|
3
|
+
private connectionString;
|
|
4
|
+
constructor(connectionString: string);
|
|
5
|
+
assertConnectionStringEquals(connectionString: string): void;
|
|
6
|
+
connect(): Promise<void>;
|
|
7
|
+
assertIsConnected(): void;
|
|
8
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const data_stores_1 = require("@sprucelabs/data-stores");
|
|
4
|
+
const test_utils_1 = require("@sprucelabs/test-utils");
|
|
5
|
+
class MockChromaDatabase extends data_stores_1.NeDbDatabase {
|
|
6
|
+
constructor(connectionString) {
|
|
7
|
+
super();
|
|
8
|
+
this.connectionString = connectionString;
|
|
9
|
+
}
|
|
10
|
+
assertConnectionStringEquals(connectionString) {
|
|
11
|
+
test_utils_1.assert.isEqual(this.connectionString, connectionString, 'The connection string you passed to your ChromaDb does not equal what I expected!');
|
|
12
|
+
}
|
|
13
|
+
async connect() {
|
|
14
|
+
await super.connect();
|
|
15
|
+
}
|
|
16
|
+
assertIsConnected() {
|
|
17
|
+
test_utils_1.assert.isTrue(this.isConnected(), 'Database is not connected! Try calling db.connect()');
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
exports.default = MockChromaDatabase;
|
package/build/chroma.types.d.ts
CHANGED
|
@@ -1,177 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
* @returns {Promise<void>}
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
* ```typescript
|
|
15
|
-
* const response = await collection.upsert({
|
|
16
|
-
* ids: ["id1", "id2"],
|
|
17
|
-
* embeddings: [[1, 2, 3], [4, 5, 6]],
|
|
18
|
-
* metadatas: [{ "key": "value" }, { "key": "value" }],
|
|
19
|
-
* documents: ["document1", "document2"],
|
|
20
|
-
* });
|
|
21
|
-
* ```
|
|
22
|
-
*/
|
|
23
|
-
upsert(params: UpsertRecordsParams): Promise<void>;
|
|
24
|
-
/**
|
|
25
|
-
* Count the number of items in the collection
|
|
26
|
-
* @returns {Promise<number>} - The number of items in the collection.
|
|
27
|
-
*
|
|
28
|
-
* @example
|
|
29
|
-
* ```typescript
|
|
30
|
-
* const count = await collection.count();
|
|
31
|
-
* ```
|
|
32
|
-
*/
|
|
33
|
-
count(): Promise<number>;
|
|
34
|
-
/**
|
|
35
|
-
* Get items from the collection
|
|
36
|
-
* @param {Object} params - The parameters for the query.
|
|
37
|
-
* @param {ID | IDs} [params.ids] - Optional IDs of the items to get.
|
|
38
|
-
* @param {Where} [params.where] - Optional where clause to filter items by.
|
|
39
|
-
* @param {PositiveInteger} [params.limit] - Optional limit on the number of items to get.
|
|
40
|
-
* @param {PositiveInteger} [params.offset] - Optional offset on the items to get.
|
|
41
|
-
* @param {IncludeEnum[]} [params.include] - Optional list of items to include in the response.
|
|
42
|
-
* @param {WhereDocument} [params.whereDocument] - Optional where clause to filter items by.
|
|
43
|
-
* @returns {Promise<GetResponse>} - The response from the server.
|
|
44
|
-
*
|
|
45
|
-
* @example
|
|
46
|
-
* ```typescript
|
|
47
|
-
* const response = await collection.get({
|
|
48
|
-
* ids: ["id1", "id2"],
|
|
49
|
-
* where: { "key": "value" },
|
|
50
|
-
* limit: 10,
|
|
51
|
-
* offset: 0,
|
|
52
|
-
* include: ["embeddings", "metadatas", "documents"],
|
|
53
|
-
* whereDocument: { $contains: "value" },
|
|
54
|
-
* });
|
|
55
|
-
* ```
|
|
56
|
-
*/
|
|
57
|
-
get(options?: BaseGetParams): Promise<GetResponse>;
|
|
58
|
-
/**
|
|
59
|
-
* Update items in the collection
|
|
60
|
-
* @param {Object} params - The parameters for the query.
|
|
61
|
-
* @param {ID | IDs} [params.ids] - IDs of the items to add.
|
|
62
|
-
* @param {Embedding | Embeddings} [params.embeddings] - Optional embeddings of the items to add.
|
|
63
|
-
* @param {Metadata | Metadatas} [params.metadatas] - Optional metadata of the items to add.
|
|
64
|
-
* @param {Document | Documents} [params.documents] - Optional documents of the items to add.
|
|
65
|
-
* @returns {Promise<void>}
|
|
66
|
-
*
|
|
67
|
-
* @example
|
|
68
|
-
* ```typescript
|
|
69
|
-
* const response = await collection.update({
|
|
70
|
-
* ids: ["id1", "id2"],
|
|
71
|
-
* embeddings: [[1, 2, 3], [4, 5, 6]],
|
|
72
|
-
* metadatas: [{ "key": "value" }, { "key": "value" }],
|
|
73
|
-
* documents: ["document1", "document2"],
|
|
74
|
-
* });
|
|
75
|
-
* ```
|
|
76
|
-
*/
|
|
77
|
-
update(params: UpdateRecordsParams): Promise<void>;
|
|
78
|
-
/**
|
|
79
|
-
* Performs a query on the collection using the specified parameters.
|
|
80
|
-
*
|
|
81
|
-
* @param {Object} params - The parameters for the query.
|
|
82
|
-
* @param {Embedding | Embeddings} [params.queryEmbeddings] - Optional query embeddings to use for the search.
|
|
83
|
-
* @param {PositiveInteger} [params.nResults] - Optional number of results to return (default is 10).
|
|
84
|
-
* @param {Where} [params.where] - Optional query condition to filter results based on metadata values.
|
|
85
|
-
* @param {string | string[]} [params.queryTexts] - Optional query text(s) to search for in the collection.
|
|
86
|
-
* @param {WhereDocument} [params.whereDocument] - Optional query condition to filter results based on document content.
|
|
87
|
-
* @param {IncludeEnum[]} [params.include] - Optional array of fields to include in the result, such as "metadata" and "document".
|
|
88
|
-
*
|
|
89
|
-
* @returns {Promise<QueryResponse>} A promise that resolves to the query results.
|
|
90
|
-
* @throws {Error} If there is an issue executing the query.
|
|
91
|
-
* @example
|
|
92
|
-
* // Query the collection using embeddings
|
|
93
|
-
* const results = await collection.query({
|
|
94
|
-
* queryEmbeddings: [[0.1, 0.2, ...], ...],
|
|
95
|
-
* nResults: 10,
|
|
96
|
-
* where: {"name": {"$eq": "John Doe"}},
|
|
97
|
-
* include: ["metadata", "document"]
|
|
98
|
-
* });
|
|
99
|
-
* @example
|
|
100
|
-
* ```js
|
|
101
|
-
* // Query the collection using query text
|
|
102
|
-
* const results = await collection.query({
|
|
103
|
-
* queryTexts: "some text",
|
|
104
|
-
* nResults: 10,
|
|
105
|
-
* where: {"name": {"$eq": "John Doe"}},
|
|
106
|
-
* include: ["metadata", "document"]
|
|
107
|
-
* });
|
|
108
|
-
* ```
|
|
109
|
-
*
|
|
110
|
-
*/
|
|
111
|
-
query({ nResults, where, whereDocument, include, queryTexts, queryEmbeddings, }: QueryRecordsParams): Promise<QueryResponse>;
|
|
112
|
-
/**
|
|
113
|
-
* Modify the collection name or metadata
|
|
114
|
-
* @param {Object} params - The parameters for the query.
|
|
115
|
-
* @param {string} [params.name] - Optional new name for the collection.
|
|
116
|
-
* @param {CollectionMetadata} [params.metadata] - Optional new metadata for the collection.
|
|
117
|
-
* @returns {Promise<void>} - The response from the API.
|
|
118
|
-
*
|
|
119
|
-
* @example
|
|
120
|
-
* ```typescript
|
|
121
|
-
* const response = await client.updateCollection({
|
|
122
|
-
* name: "new name",
|
|
123
|
-
* metadata: { "key": "value" },
|
|
124
|
-
* });
|
|
125
|
-
* ```
|
|
126
|
-
*/
|
|
127
|
-
modify({ name, metadata, }: {
|
|
128
|
-
name?: string;
|
|
129
|
-
metadata?: CollectionMetadata;
|
|
130
|
-
}): Promise<CollectionParams>;
|
|
131
|
-
/**
|
|
132
|
-
* Peek inside the collection
|
|
133
|
-
* @param {Object} params - The parameters for the query.
|
|
134
|
-
* @param {PositiveInteger} [params.limit] - Optional number of results to return (default is 10).
|
|
135
|
-
* @returns {Promise<GetResponse>} A promise that resolves to the query results.
|
|
136
|
-
* @throws {Error} If there is an issue executing the query.
|
|
137
|
-
*
|
|
138
|
-
* @example
|
|
139
|
-
* ```typescript
|
|
140
|
-
* const results = await collection.peek({
|
|
141
|
-
* limit: 10
|
|
142
|
-
* });
|
|
143
|
-
* ```
|
|
144
|
-
*/
|
|
145
|
-
peek(options?: PeekParams): Promise<GetResponse>;
|
|
146
|
-
/**
|
|
147
|
-
* Deletes items from the collection.
|
|
148
|
-
* @param {Object} params - The parameters for deleting items from the collection.
|
|
149
|
-
* @param {ID | IDs} [params.ids] - Optional ID or array of IDs of items to delete.
|
|
150
|
-
* @param {Where} [params.where] - Optional query condition to filter items to delete based on metadata values.
|
|
151
|
-
* @param {WhereDocument} [params.whereDocument] - Optional query condition to filter items to delete based on document content.
|
|
152
|
-
* @returns {Promise<string[]>} A promise that resolves to the IDs of the deleted items.
|
|
153
|
-
* @throws {Error} If there is an issue deleting items from the collection.
|
|
154
|
-
*
|
|
155
|
-
* @example
|
|
156
|
-
* ```typescript
|
|
157
|
-
* const results = await collection.delete({
|
|
158
|
-
* ids: "some_id",
|
|
159
|
-
* where: {"name": {"$eq": "John Doe"}},
|
|
160
|
-
* whereDocument: {"$contains":"search_string"}
|
|
161
|
-
* });
|
|
162
|
-
* ```
|
|
163
|
-
*/
|
|
164
|
-
delete(options?: DeleteParams): Promise<void>;
|
|
1
|
+
import { IncludeEnum, Metadata } from 'chromadb';
|
|
2
|
+
export type ID = string;
|
|
3
|
+
export type Embedding = number[];
|
|
4
|
+
export type Embeddings = Embedding[];
|
|
5
|
+
export interface GetResponse {
|
|
6
|
+
ids: ID[];
|
|
7
|
+
embeddings: Embeddings | null;
|
|
8
|
+
documents: (Document | null)[];
|
|
9
|
+
metadatas: (Metadata | null)[];
|
|
10
|
+
included: IncludeEnum[];
|
|
165
11
|
}
|
|
166
|
-
|
|
167
|
-
ids?: ID | IDs;
|
|
168
|
-
where?: Where;
|
|
169
|
-
limit?: number;
|
|
170
|
-
offset?: number;
|
|
171
|
-
include?: IncludeEnum[];
|
|
172
|
-
whereDocument?: WhereDocument;
|
|
173
|
-
}
|
|
174
|
-
export type WhereWithPrompt = Where & {
|
|
12
|
+
export type WhereWithPrompt = WhereDocument & {
|
|
175
13
|
$prompt?: string;
|
|
176
14
|
};
|
|
177
|
-
export {
|
|
15
|
+
export interface WhereDocument {
|
|
16
|
+
$contains?: string;
|
|
17
|
+
$not_contains?: string;
|
|
18
|
+
$matches?: string;
|
|
19
|
+
$not_matches?: string;
|
|
20
|
+
$regex?: string;
|
|
21
|
+
$not_regex?: string;
|
|
22
|
+
$and?: WhereDocument[];
|
|
23
|
+
$or?: WhereDocument[];
|
|
24
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const schema_1 = require("@sprucelabs/schema");
|
|
7
|
+
const test_utils_1 = require("@sprucelabs/test-utils");
|
|
8
|
+
const ChromaDatabase_1 = __importDefault(require("./ChromaDatabase"));
|
|
9
|
+
const chromaDbAssert = {
|
|
10
|
+
embeddingFieldsForCollectionEqual(collection, fields) {
|
|
11
|
+
(0, schema_1.assertOptions)({
|
|
12
|
+
collection,
|
|
13
|
+
fields,
|
|
14
|
+
}, ['collection', 'fields']);
|
|
15
|
+
const actual = ChromaDatabase_1.default.getEmbeddingsFields()?.[collection];
|
|
16
|
+
test_utils_1.assert.isTruthy(actual, `I could not find any embedding fields for the collection called ${collection}`);
|
|
17
|
+
test_utils_1.assert.isEqualDeep(actual, fields, `The embedding fields for the collection did not match.`);
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
exports.default = chromaDbAssert;
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import { CreateOptions, Database, DatabaseInternalOptions, Index, IndexWithFilter, QueryOptions } from '@sprucelabs/data-stores';
|
|
2
|
+
import { OllamaEmbeddingFunction } from '@chroma-core/ollama';
|
|
2
3
|
export default class ChromaDatabase implements Database {
|
|
4
|
+
static Class?: new (connectionString: string) => Database;
|
|
5
|
+
static EmbeddingFunction: typeof OllamaEmbeddingFunction;
|
|
6
|
+
private static embeddingFields?;
|
|
3
7
|
private connectionString;
|
|
4
8
|
private client;
|
|
5
9
|
private _isConnected;
|
|
6
10
|
private embeddings;
|
|
7
11
|
private collections;
|
|
8
|
-
private static embeddingFields?;
|
|
9
12
|
constructor(connectionString: string);
|
|
13
|
+
static Database(connectionString: string): ChromaDatabase | Database;
|
|
10
14
|
static setEmbeddingsFields(collectionName: string, fields: string[]): void;
|
|
11
15
|
static clearEmbeddingsFields(): void;
|
|
16
|
+
static getEmbeddingsFields(): Record<string, string[]> | undefined;
|
|
12
17
|
syncUniqueIndexes(_collectionName: string, _indexes: Index[]): Promise<void>;
|
|
13
18
|
syncIndexes(_collectionName: string, _indexes: Index[]): Promise<void>;
|
|
14
19
|
dropIndex(_collectionName: string, _index: Index): Promise<void>;
|
|
@@ -21,16 +21,18 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
21
21
|
import { DataStoresError, generateId, } from '@sprucelabs/data-stores';
|
|
22
22
|
import { assertOptions, flattenValues, expandValues } from '@sprucelabs/schema';
|
|
23
23
|
import { NULL_PLACEHOLDER } from '@sprucelabs/test-utils';
|
|
24
|
-
import {
|
|
24
|
+
import { OllamaEmbeddingFunction } from '@chroma-core/ollama';
|
|
25
|
+
import { ChromaClient, } from 'chromadb';
|
|
25
26
|
import SpruceError from './errors/SpruceError.js';
|
|
26
|
-
|
|
27
|
+
class ChromaDatabase {
|
|
27
28
|
constructor(connectionString) {
|
|
29
|
+
var _a;
|
|
28
30
|
this._isConnected = false;
|
|
29
31
|
this.collections = {};
|
|
30
32
|
assertOptions({ connectionString }, ['connectionString']);
|
|
31
|
-
this.embeddings = new
|
|
32
|
-
model: 'llama3.2',
|
|
33
|
-
url: 'http://localhost:11434
|
|
33
|
+
this.embeddings = new ChromaDatabase.EmbeddingFunction({
|
|
34
|
+
model: (_a = process.env.CHROMA_EMBEDDING_MODEL) !== null && _a !== void 0 ? _a : 'llama3.2',
|
|
35
|
+
url: 'http://localhost:11434',
|
|
34
36
|
});
|
|
35
37
|
if (!connectionString.startsWith('chroma://')) {
|
|
36
38
|
throw new DataStoresError({
|
|
@@ -39,6 +41,10 @@ export default class ChromaDatabase {
|
|
|
39
41
|
}
|
|
40
42
|
this.connectionString = connectionString.replace('chroma://', 'http://');
|
|
41
43
|
}
|
|
44
|
+
static Database(connectionString) {
|
|
45
|
+
var _a;
|
|
46
|
+
return new ((_a = this.Class) !== null && _a !== void 0 ? _a : this)(connectionString);
|
|
47
|
+
}
|
|
42
48
|
static setEmbeddingsFields(collectionName, fields) {
|
|
43
49
|
if (!this.embeddingFields) {
|
|
44
50
|
this.embeddingFields = {};
|
|
@@ -48,6 +54,9 @@ export default class ChromaDatabase {
|
|
|
48
54
|
static clearEmbeddingsFields() {
|
|
49
55
|
delete this.embeddingFields;
|
|
50
56
|
}
|
|
57
|
+
static getEmbeddingsFields() {
|
|
58
|
+
return this.embeddingFields;
|
|
59
|
+
}
|
|
51
60
|
syncUniqueIndexes(_collectionName, _indexes) {
|
|
52
61
|
return __awaiter(this, void 0, void 0, function* () {
|
|
53
62
|
throw new SpruceError({
|
|
@@ -227,14 +236,19 @@ export default class ChromaDatabase {
|
|
|
227
236
|
return __awaiter(this, void 0, void 0, function* () {
|
|
228
237
|
let { ids, where, skipIds } = this.buildQuery(query);
|
|
229
238
|
let matches;
|
|
230
|
-
|
|
239
|
+
let { limit, includeFields } = options !== null && options !== void 0 ? options : {};
|
|
231
240
|
const col = yield this.getCollection(collection);
|
|
241
|
+
if (!limit && (where === null || where === void 0 ? void 0 : where.$prompt)) {
|
|
242
|
+
limit = 10;
|
|
243
|
+
}
|
|
232
244
|
if (where === null || where === void 0 ? void 0 : where.$prompt) {
|
|
233
245
|
const { $prompt } = where, rest = __rest(where, ["$prompt"]);
|
|
234
246
|
const queryResults = yield col.query({
|
|
235
247
|
queryTexts: [$prompt],
|
|
236
|
-
nResults:
|
|
237
|
-
where: Object.keys(rest).length > 0
|
|
248
|
+
nResults: limit,
|
|
249
|
+
where: (Object.keys(rest).length > 0
|
|
250
|
+
? rest
|
|
251
|
+
: undefined),
|
|
238
252
|
});
|
|
239
253
|
matches = {
|
|
240
254
|
ids: queryResults.ids[0],
|
|
@@ -245,7 +259,7 @@ export default class ChromaDatabase {
|
|
|
245
259
|
matches = yield col.get({
|
|
246
260
|
ids,
|
|
247
261
|
include: ['metadatas'],
|
|
248
|
-
where,
|
|
262
|
+
where: where,
|
|
249
263
|
limit: limit == 0 ? 1 : limit,
|
|
250
264
|
});
|
|
251
265
|
}
|
|
@@ -298,7 +312,6 @@ export default class ChromaDatabase {
|
|
|
298
312
|
where = rest;
|
|
299
313
|
}
|
|
300
314
|
if ((where === null || where === void 0 ? void 0 : where.$or) && where.$or.length === 1) {
|
|
301
|
-
//@ts-ignore
|
|
302
315
|
where = where.$or[0];
|
|
303
316
|
}
|
|
304
317
|
if (where) {
|
|
@@ -398,6 +411,9 @@ export default class ChromaDatabase {
|
|
|
398
411
|
delete(collection, query) {
|
|
399
412
|
return __awaiter(this, void 0, void 0, function* () {
|
|
400
413
|
const matches = yield this.find(collection, query);
|
|
414
|
+
if (matches.length === 0) {
|
|
415
|
+
return 0;
|
|
416
|
+
}
|
|
401
417
|
const col = yield this.getCollection(collection);
|
|
402
418
|
yield col.delete({
|
|
403
419
|
ids: matches.map((m) => m.id),
|
|
@@ -443,3 +459,5 @@ export default class ChromaDatabase {
|
|
|
443
459
|
});
|
|
444
460
|
}
|
|
445
461
|
}
|
|
462
|
+
ChromaDatabase.EmbeddingFunction = OllamaEmbeddingFunction;
|
|
463
|
+
export default ChromaDatabase;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { NeDbDatabase } from '@sprucelabs/data-stores';
|
|
2
|
+
export default class MockChromaDatabase extends NeDbDatabase {
|
|
3
|
+
private connectionString;
|
|
4
|
+
constructor(connectionString: string);
|
|
5
|
+
assertConnectionStringEquals(connectionString: string): void;
|
|
6
|
+
connect(): Promise<void>;
|
|
7
|
+
assertIsConnected(): void;
|
|
8
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { NeDbDatabase } from '@sprucelabs/data-stores';
|
|
11
|
+
import { assert } from '@sprucelabs/test-utils';
|
|
12
|
+
export default class MockChromaDatabase extends NeDbDatabase {
|
|
13
|
+
constructor(connectionString) {
|
|
14
|
+
super();
|
|
15
|
+
this.connectionString = connectionString;
|
|
16
|
+
}
|
|
17
|
+
assertConnectionStringEquals(connectionString) {
|
|
18
|
+
assert.isEqual(this.connectionString, connectionString, 'The connection string you passed to your ChromaDb does not equal what I expected!');
|
|
19
|
+
}
|
|
20
|
+
connect() {
|
|
21
|
+
const _super = Object.create(null, {
|
|
22
|
+
connect: { get: () => super.connect }
|
|
23
|
+
});
|
|
24
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
25
|
+
yield _super.connect.call(this);
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
assertIsConnected() {
|
|
29
|
+
assert.isTrue(this.isConnected(), 'Database is not connected! Try calling db.connect()');
|
|
30
|
+
}
|
|
31
|
+
}
|