@ia-ccun/code-agent-cli 0.0.52-beta.6 → 0.0.52-beta.8
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/config/agent/bin/README.md +102 -0
- package/config/agent/bin/fd.exe +0 -0
- package/config/agent/bin/rg.exe +0 -0
- package/config/agent/extensions/aicode-safety-guard.ts +2 -2
- package/config/agent/extensions/aicode-tips.ts +8 -0
- package/config/agent/skills/chroma/LICENSE +21 -0
- package/config/agent/skills/chroma/chroma-local/SKILL.md +165 -0
- package/config/agent/skills/chroma/chroma-local/cli.md +48 -0
- package/config/agent/skills/chroma/chroma-local/data-model.md +103 -0
- package/config/agent/skills/chroma/chroma-local/error-handling/python.md +166 -0
- package/config/agent/skills/chroma/chroma-local/error-handling/typescript.md +231 -0
- package/config/agent/skills/chroma/chroma-local/local-chroma/python.md +95 -0
- package/config/agent/skills/chroma/chroma-local/local-chroma/typescript.md +101 -0
- package/config/agent/skills/chroma/chroma-local/metadata/python.md +154 -0
- package/config/agent/skills/chroma/chroma-local/metadata/typescript.md +153 -0
- package/config/agent/skills/chroma/chroma-local/querying/python.md +147 -0
- package/config/agent/skills/chroma/chroma-local/querying/typescript.md +157 -0
- package/config/agent/skills/chroma/chroma-local/regex/python.md +69 -0
- package/config/agent/skills/chroma/chroma-local/regex/typescript.md +71 -0
- package/config/agent/skills/chroma/chroma-local/understanding-a-codebase.md +80 -0
- package/config/agent/skills/chroma/chroma-local/updating-deleting/python.md +159 -0
- package/config/agent/skills/chroma/chroma-local/updating-deleting/typescript.md +228 -0
- package/config/agent/skills/milvus-skill/LICENSE +202 -0
- package/config/agent/skills/milvus-skill/README.md +37 -0
- package/config/agent/skills/milvus-skill/SKILL.md +259 -0
- package/config/agent/skills/milvus-skill/references/collection.md +86 -0
- package/config/agent/skills/milvus-skill/references/database.md +24 -0
- package/config/agent/skills/milvus-skill/references/index.md +69 -0
- package/config/agent/skills/milvus-skill/references/partition.md +29 -0
- package/config/agent/skills/milvus-skill/references/patterns.md +150 -0
- package/config/agent/skills/milvus-skill/references/user-role.md +90 -0
- package/config/agent/skills/milvus-skill/references/vector.md +247 -0
- package/package.json +1 -1
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Error Handling
|
|
3
|
+
description: Handling errors and failures when working with Chroma
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Error Handling
|
|
7
|
+
|
|
8
|
+
Local Chroma operations can fail for various reasons: the local server may not be running, collections may be missing, or input data may be invalid. This guide covers the common local error scenarios and how to handle them.
|
|
9
|
+
|
|
10
|
+
```typescript
|
|
11
|
+
import { ChromaClient } from 'chromadb';
|
|
12
|
+
import { DefaultEmbeddingFunction } from '@chroma-core/default-embed';
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### Error types
|
|
16
|
+
|
|
17
|
+
**Python** uses specific exception classes:
|
|
18
|
+
- `chromadb.errors.NotFoundError` - Collection, tenant, or database doesn't exist
|
|
19
|
+
- `ValueError` - Invalid collection name or duplicate creation attempt
|
|
20
|
+
|
|
21
|
+
**TypeScript** throws standard `Error` objects with descriptive messages. Check the error message to determine the cause.
|
|
22
|
+
|
|
23
|
+
### Connection errors
|
|
24
|
+
|
|
25
|
+
Connection failures occur when the client can't reach the Chroma server. This is common during startup or when network issues occur.
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
async function connectWithRetry(maxRetries = 3): Promise<ChromaClient> {
|
|
29
|
+
const client = new ChromaClient();
|
|
30
|
+
|
|
31
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
32
|
+
try {
|
|
33
|
+
// heartbeat() verifies the connection is working
|
|
34
|
+
await client.heartbeat();
|
|
35
|
+
return client;
|
|
36
|
+
} catch (error) {
|
|
37
|
+
if (attempt === maxRetries) {
|
|
38
|
+
throw new Error(
|
|
39
|
+
`Failed to connect to Chroma after ${maxRetries} attempts: ${error}`
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
// Exponential backoff: 1s, 2s, 4s...
|
|
43
|
+
const delay = Math.pow(2, attempt - 1) * 1000;
|
|
44
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
throw new Error('Unreachable');
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Collection not found
|
|
52
|
+
|
|
53
|
+
When working with collections that may not exist, handle the `NotFoundError` (Python) or catch the error and check its message (TypeScript).
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
const client = new ChromaClient();
|
|
57
|
+
const embeddingFunction = new DefaultEmbeddingFunction();
|
|
58
|
+
|
|
59
|
+
// getCollection throws if the collection doesn't exist
|
|
60
|
+
try {
|
|
61
|
+
const collection = await client.getCollection({
|
|
62
|
+
name: 'my_collection',
|
|
63
|
+
embeddingFunction,
|
|
64
|
+
});
|
|
65
|
+
} catch (error) {
|
|
66
|
+
if (error instanceof Error && error.message.includes('does not exist')) {
|
|
67
|
+
console.log('Collection not found, creating it...');
|
|
68
|
+
// Handle missing collection
|
|
69
|
+
} else {
|
|
70
|
+
throw error; // Re-throw unexpected errors
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Safe collection access pattern
|
|
76
|
+
|
|
77
|
+
The `getOrCreateCollection` method is the recommended way to avoid "not found" errors entirely. Use `getCollection` only when you specifically need to verify a collection exists.
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
const client2 = new ChromaClient();
|
|
81
|
+
const embeddingFunction2 = new DefaultEmbeddingFunction();
|
|
82
|
+
|
|
83
|
+
// Preferred: getOrCreateCollection never throws "not found"
|
|
84
|
+
const collection = await client2.getOrCreateCollection({
|
|
85
|
+
name: 'my_collection',
|
|
86
|
+
embeddingFunction: embeddingFunction2,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// Check if results exist before accessing
|
|
90
|
+
const results = await collection.query({
|
|
91
|
+
queryTexts: ['search query'],
|
|
92
|
+
nResults: 5,
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
if (results.documents[0] && results.documents[0].length > 0) {
|
|
96
|
+
const firstDoc = results.documents[0][0];
|
|
97
|
+
// Safe to use firstDoc
|
|
98
|
+
} else {
|
|
99
|
+
// No results found
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Validation errors
|
|
104
|
+
|
|
105
|
+
Chroma validates data before operations. Common validation failures include:
|
|
106
|
+
- Document content exceeding 16KB
|
|
107
|
+
- Embedding dimensions not matching the collection
|
|
108
|
+
- Metadata exceeding limits (4KB total, 32 keys max)
|
|
109
|
+
- Invalid collection names
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
const client3 = new ChromaClient();
|
|
113
|
+
const embeddingFunction3 = new DefaultEmbeddingFunction();
|
|
114
|
+
|
|
115
|
+
// Validate document size before adding (16KB limit, recommend < 8KB)
|
|
116
|
+
function validateDocument(doc: string): boolean {
|
|
117
|
+
const byteSize = new TextEncoder().encode(doc).length;
|
|
118
|
+
return byteSize <= 16384;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Validate metadata size (4KB limit, 32 keys max)
|
|
122
|
+
function validateMetadata(
|
|
123
|
+
metadata: Record<string, string | number | boolean>
|
|
124
|
+
): boolean {
|
|
125
|
+
const keys = Object.keys(metadata);
|
|
126
|
+
if (keys.length > 32) return false;
|
|
127
|
+
|
|
128
|
+
const jsonSize = new TextEncoder().encode(JSON.stringify(metadata)).length;
|
|
129
|
+
return jsonSize <= 4096;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async function safeAdd(
|
|
133
|
+
collectionName: string,
|
|
134
|
+
ids: string[],
|
|
135
|
+
documents: string[],
|
|
136
|
+
metadatas?: Record<string, string | number | boolean>[]
|
|
137
|
+
) {
|
|
138
|
+
// Pre-validate
|
|
139
|
+
for (const doc of documents) {
|
|
140
|
+
if (!validateDocument(doc)) {
|
|
141
|
+
throw new Error(`Document exceeds 16KB limit`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (metadatas) {
|
|
146
|
+
for (const meta of metadatas) {
|
|
147
|
+
if (!validateMetadata(meta)) {
|
|
148
|
+
throw new Error(`Metadata exceeds limits (4KB or 32 keys)`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const collection = await client3.getOrCreateCollection({
|
|
154
|
+
name: collectionName,
|
|
155
|
+
embeddingFunction: embeddingFunction3,
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
try {
|
|
159
|
+
await collection.add({ ids, documents, metadatas });
|
|
160
|
+
} catch (error) {
|
|
161
|
+
// Handle specific validation errors from server
|
|
162
|
+
if (error instanceof Error) {
|
|
163
|
+
if (error.message.includes('dimension')) {
|
|
164
|
+
throw new Error('Embedding dimensions do not match collection');
|
|
165
|
+
}
|
|
166
|
+
if (error.message.includes('duplicate')) {
|
|
167
|
+
throw new Error('Duplicate IDs in batch');
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
throw error;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Batch operation failures
|
|
176
|
+
|
|
177
|
+
When adding or upserting multiple documents, a single invalid document fails the entire batch. Validate data before sending, or implement retry logic for partial failures.
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
const client4 = new ChromaClient();
|
|
181
|
+
const embeddingFunction4 = new DefaultEmbeddingFunction();
|
|
182
|
+
|
|
183
|
+
// Process documents in batches to avoid memory issues and partial failures
|
|
184
|
+
async function batchAdd(
|
|
185
|
+
collectionName: string,
|
|
186
|
+
ids: string[],
|
|
187
|
+
documents: string[],
|
|
188
|
+
batchSize = 100
|
|
189
|
+
) {
|
|
190
|
+
const collection = await client4.getOrCreateCollection({
|
|
191
|
+
name: collectionName,
|
|
192
|
+
embeddingFunction: embeddingFunction4,
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
const failures: { index: number; error: string }[] = [];
|
|
196
|
+
|
|
197
|
+
for (let i = 0; i < ids.length; i += batchSize) {
|
|
198
|
+
const batchIds = ids.slice(i, i + batchSize);
|
|
199
|
+
const batchDocs = documents.slice(i, i + batchSize);
|
|
200
|
+
|
|
201
|
+
try {
|
|
202
|
+
await collection.add({
|
|
203
|
+
ids: batchIds,
|
|
204
|
+
documents: batchDocs,
|
|
205
|
+
});
|
|
206
|
+
} catch (error) {
|
|
207
|
+
// Log failure but continue with other batches
|
|
208
|
+
failures.push({
|
|
209
|
+
index: i,
|
|
210
|
+
error: error instanceof Error ? error.message : String(error),
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (failures.length > 0) {
|
|
216
|
+
console.error(`${failures.length} batches failed:`, failures);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return { totalBatches: Math.ceil(ids.length / batchSize), failures };
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Defensive patterns summary
|
|
224
|
+
|
|
225
|
+
| Scenario | Recommended approach |
|
|
226
|
+
|----------|---------------------|
|
|
227
|
+
| Collection access | Use `getOrCreateCollection` instead of `getCollection` |
|
|
228
|
+
| Missing data | Check results length before accessing |
|
|
229
|
+
| Connection issues | Implement retry with exponential backoff |
|
|
230
|
+
| Large batches | Validate data size before operations |
|
|
231
|
+
| Local server startup | Verify the server is running before debugging query logic |
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Local Chroma
|
|
3
|
+
description: How to run and use local chroma
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Local Chroma
|
|
7
|
+
|
|
8
|
+
Running Chroma locally is useful for development, testing, and production applications where data privacy or offline operation is important. Local Chroma stores data on disk and runs as a separate process that your application connects to over HTTP.
|
|
9
|
+
|
|
10
|
+
### When to use local vs cloud
|
|
11
|
+
|
|
12
|
+
**Use local Chroma when:**
|
|
13
|
+
- Developing and testing before deploying to production
|
|
14
|
+
- Data must stay on-premises for compliance or privacy reasons
|
|
15
|
+
- You need offline operation without network dependencies
|
|
16
|
+
- Running integration tests in CI/CD pipelines
|
|
17
|
+
|
|
18
|
+
**Use Chroma Cloud when:**
|
|
19
|
+
- You need the Schema() and Search() APIs for advanced indexing
|
|
20
|
+
- You want managed infrastructure without operational overhead
|
|
21
|
+
- You need hybrid search with SPLADE or other cloud-only features
|
|
22
|
+
- Scaling beyond what a single machine can handle
|
|
23
|
+
|
|
24
|
+
### Installation
|
|
25
|
+
|
|
26
|
+
For Python, install with pip or uv:
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
pip install chromadb
|
|
30
|
+
# or
|
|
31
|
+
uv pip install chromadb
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
To start the Chroma server from a Python environment:
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
chroma run
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
By default, this starts Chroma on `localhost:8000` and persists data to a local directory.
|
|
41
|
+
|
|
42
|
+
For JavaScript/TypeScript, install with npm:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
npm install chromadb
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
To start the Chroma server:
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
npx chroma run
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Connecting to local Chroma
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
import chromadb
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Once the server is running, connect using the `ChromaClient` (not `CloudClient`):
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
chroma_client = chromadb.HttpClient(host='localhost', port=8000)
|
|
64
|
+
|
|
65
|
+
# this will automaically use the default embedding function
|
|
66
|
+
collection = chroma_client.get_or_create_collection(name="my_collection")
|
|
67
|
+
|
|
68
|
+
collection.add(
|
|
69
|
+
ids=["id1", "id2"],
|
|
70
|
+
documents=[
|
|
71
|
+
"This is a document about pineapple",
|
|
72
|
+
"This is a document about oranges"
|
|
73
|
+
]
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
results = collection.query(
|
|
77
|
+
query_texts=["This is a query document about hawaii"], # Chroma will embed this for you
|
|
78
|
+
n_results=2 # how many results to return
|
|
79
|
+
)
|
|
80
|
+
print(results)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Persistence
|
|
84
|
+
|
|
85
|
+
Local Chroma persists data to disk automatically. By default, data is stored in `.chroma/` in the current directory. You can specify a different path when starting the server:
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
chroma run --path /path/to/data
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
This makes it safe to restart the server without losing your indexed documents.
|
|
92
|
+
|
|
93
|
+
### Further reading
|
|
94
|
+
|
|
95
|
+
For full the full configuration of the chroma server, see: https://docs.trychroma.com/reference/server-env-vars
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Local Chroma
|
|
3
|
+
description: How to run and use local chroma
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Local Chroma
|
|
7
|
+
|
|
8
|
+
Running Chroma locally is useful for development, testing, and production applications where data privacy or offline operation is important. Local Chroma stores data on disk and runs as a separate process that your application connects to over HTTP.
|
|
9
|
+
|
|
10
|
+
### When to use local vs cloud
|
|
11
|
+
|
|
12
|
+
**Use local Chroma when:**
|
|
13
|
+
- Developing and testing before deploying to production
|
|
14
|
+
- Data must stay on-premises for compliance or privacy reasons
|
|
15
|
+
- You need offline operation without network dependencies
|
|
16
|
+
- Running integration tests in CI/CD pipelines
|
|
17
|
+
|
|
18
|
+
**Use Chroma Cloud when:**
|
|
19
|
+
- You need the Schema() and Search() APIs for advanced indexing
|
|
20
|
+
- You want managed infrastructure without operational overhead
|
|
21
|
+
- You need hybrid search with SPLADE or other cloud-only features
|
|
22
|
+
- Scaling beyond what a single machine can handle
|
|
23
|
+
|
|
24
|
+
### Installation
|
|
25
|
+
|
|
26
|
+
For Python, install with pip or uv:
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
pip install chromadb
|
|
30
|
+
# or
|
|
31
|
+
uv pip install chromadb
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
To start the Chroma server from a Python environment:
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
chroma run
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
By default, this starts Chroma on `localhost:8000` and persists data to a local directory.
|
|
41
|
+
|
|
42
|
+
For JavaScript/TypeScript, install with npm:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
npm install chromadb
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
To start the Chroma server:
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
npx chroma run
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Connecting to local Chroma
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
import { ChromaClient } from 'chromadb';
|
|
58
|
+
import { DefaultEmbeddingFunction } from '@chroma-core/default-embed';
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Once the server is running, connect using the `ChromaClient` (not `CloudClient`):
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
// client with no args uses local chroma instance
|
|
65
|
+
const client = new ChromaClient();
|
|
66
|
+
|
|
67
|
+
const embeddingFunction = new DefaultEmbeddingFunction();
|
|
68
|
+
|
|
69
|
+
const collection = await client.getOrCreateCollection({
|
|
70
|
+
name: 'my_collection',
|
|
71
|
+
embeddingFunction,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
await collection.add({
|
|
75
|
+
ids: ['doc1', 'doc2'],
|
|
76
|
+
documents: [
|
|
77
|
+
'Apples are really good red fruit',
|
|
78
|
+
'Red cars tend to get more speeding tickets',
|
|
79
|
+
],
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
const results = await collection.query({
|
|
83
|
+
queryTexts: ['I like red apples'],
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
const firstResult = results.documents[0];
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Persistence
|
|
90
|
+
|
|
91
|
+
Local Chroma persists data to disk automatically. By default, data is stored in `.chroma/` in the current directory. You can specify a different path when starting the server:
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
chroma run --path /path/to/data
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
This makes it safe to restart the server without losing your indexed documents.
|
|
98
|
+
|
|
99
|
+
### Further reading
|
|
100
|
+
|
|
101
|
+
For full the full configuration of the chroma server, see: https://docs.trychroma.com/reference/server-env-vars
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Metadata
|
|
3
|
+
description: Store and query metadata, including filters and array values
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Metadata
|
|
7
|
+
|
|
8
|
+
Metadata in Chroma is structured key-value data stored alongside each document. You can use metadata to filter records in both `query` and `get`, and the metadata model is the same between local and cloud.
|
|
9
|
+
|
|
10
|
+
### Imports and boilerplate
|
|
11
|
+
|
|
12
|
+
```python
|
|
13
|
+
import chromadb
|
|
14
|
+
|
|
15
|
+
client = chromadb.HttpClient(host="localhost", port=8000)
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### Filtering with `where`
|
|
19
|
+
|
|
20
|
+
The `where` argument filters documents by metadata. With `query`, this reduces the candidate set before similarity search runs. The same filter syntax also works with `get` when you want metadata-based retrieval without similarity ranking.
|
|
21
|
+
|
|
22
|
+
```python
|
|
23
|
+
collection = client.get_or_create_collection(name="articles")
|
|
24
|
+
|
|
25
|
+
query_results = collection.query(
|
|
26
|
+
query_texts=["interest rates outlook"],
|
|
27
|
+
where={
|
|
28
|
+
"category": "research",
|
|
29
|
+
},
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
filtered_docs = collection.get(
|
|
33
|
+
where={
|
|
34
|
+
"$and": [
|
|
35
|
+
{"year": {"$gte": 2025}},
|
|
36
|
+
{"region": {"$in": ["us", "eu"]}},
|
|
37
|
+
]
|
|
38
|
+
},
|
|
39
|
+
limit=20,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
direct_filter = {
|
|
43
|
+
"metadata_field": "search_string",
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
explicit_filter = {
|
|
47
|
+
"metadata_field": {
|
|
48
|
+
"$eq": "search_string",
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Available filter operators
|
|
54
|
+
|
|
55
|
+
Chroma supports these operators in `where` clauses:
|
|
56
|
+
|
|
57
|
+
- **Equality:** `$eq` (default if just a value), `$ne`
|
|
58
|
+
- **Comparison:** `$gt`, `$gte`, `$lt`, `$lte`
|
|
59
|
+
- **Set membership:** `$in`, `$nin`
|
|
60
|
+
- **Array:** `$contains`, `$not_contains`
|
|
61
|
+
- **Logical:** `$and`, `$or`
|
|
62
|
+
|
|
63
|
+
Filters can be nested and combined for complex queries. Filtering in Chroma is usually better than retrieving a larger result set and post-processing it in application code.
|
|
64
|
+
|
|
65
|
+
### Storing arrays in metadata
|
|
66
|
+
|
|
67
|
+
Chroma supports storing arrays of strings, numbers, and booleans in metadata fields. This removes the need for workarounds like comma-separated strings or JSON serialization when one field needs multiple values.
|
|
68
|
+
|
|
69
|
+
**Rules:**
|
|
70
|
+
- All elements in an array must share the same type
|
|
71
|
+
- Arrays are stored directly on metadata fields alongside regular scalar values
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
collection.add(
|
|
75
|
+
ids=["article-1", "article-2", "article-3"],
|
|
76
|
+
documents=[
|
|
77
|
+
"Net interest income rose 12% in Q3",
|
|
78
|
+
"New lending products launched in Southeast Asia",
|
|
79
|
+
"Central bank holds rates steady amid inflation concerns",
|
|
80
|
+
],
|
|
81
|
+
metadatas=[
|
|
82
|
+
{
|
|
83
|
+
"topics": ["net-interest-income", "earnings", "quarterly-results"],
|
|
84
|
+
"year": 2026,
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"topics": ["lending", "expansion", "southeast-asia"],
|
|
88
|
+
"year": 2026,
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"topics": ["rates", "central-bank", "inflation"],
|
|
92
|
+
"year": 2026,
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Querying array metadata with `$contains`
|
|
99
|
+
|
|
100
|
+
Use `$contains` in a `where` filter to find records where an array metadata field includes a specific value.
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
results = collection.query(
|
|
104
|
+
query_texts=["lending products"],
|
|
105
|
+
where={
|
|
106
|
+
"topics": {"$contains": "lending"},
|
|
107
|
+
},
|
|
108
|
+
)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Querying array metadata with `$not_contains`
|
|
112
|
+
|
|
113
|
+
Use `$not_contains` to exclude records where an array metadata field includes a specific value.
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
filtered = collection.query(
|
|
117
|
+
query_texts=["economic outlook"],
|
|
118
|
+
where={
|
|
119
|
+
"topics": {"$not_contains": "inflation"},
|
|
120
|
+
},
|
|
121
|
+
)
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Combining array and scalar filters
|
|
125
|
+
|
|
126
|
+
Array filters compose with existing logical operators (`$and`, `$or`) and can be combined with scalar metadata filters in the same query.
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
combined = collection.query(
|
|
130
|
+
query_texts=["financial results"],
|
|
131
|
+
where={
|
|
132
|
+
"$and": [
|
|
133
|
+
{"topics": {"$contains": "earnings"}},
|
|
134
|
+
{"year": {"$gte": 2025}},
|
|
135
|
+
]
|
|
136
|
+
},
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
multi_match = collection.query(
|
|
140
|
+
query_texts=["market trends"],
|
|
141
|
+
where={
|
|
142
|
+
"$or": [
|
|
143
|
+
{"topics": {"$contains": "rates"}},
|
|
144
|
+
{"topics": {"$contains": "inflation"}},
|
|
145
|
+
]
|
|
146
|
+
},
|
|
147
|
+
)
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Common use cases
|
|
151
|
+
|
|
152
|
+
- **Multi-label tagging:** Store tags or categories as arrays, then filter with `$contains` to find matching records without joins or separate tables.
|
|
153
|
+
- **Access control:** Store allowed roles or groups as an array, then filter by the current user's role at query time.
|
|
154
|
+
- **Tenant and source filtering:** Store fields like tenant ID, source system, or document type so retrieval can stay scoped to the relevant subset.
|