@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.
Files changed (33) hide show
  1. package/config/agent/bin/README.md +102 -0
  2. package/config/agent/bin/fd.exe +0 -0
  3. package/config/agent/bin/rg.exe +0 -0
  4. package/config/agent/extensions/aicode-safety-guard.ts +2 -2
  5. package/config/agent/extensions/aicode-tips.ts +8 -0
  6. package/config/agent/skills/chroma/LICENSE +21 -0
  7. package/config/agent/skills/chroma/chroma-local/SKILL.md +165 -0
  8. package/config/agent/skills/chroma/chroma-local/cli.md +48 -0
  9. package/config/agent/skills/chroma/chroma-local/data-model.md +103 -0
  10. package/config/agent/skills/chroma/chroma-local/error-handling/python.md +166 -0
  11. package/config/agent/skills/chroma/chroma-local/error-handling/typescript.md +231 -0
  12. package/config/agent/skills/chroma/chroma-local/local-chroma/python.md +95 -0
  13. package/config/agent/skills/chroma/chroma-local/local-chroma/typescript.md +101 -0
  14. package/config/agent/skills/chroma/chroma-local/metadata/python.md +154 -0
  15. package/config/agent/skills/chroma/chroma-local/metadata/typescript.md +153 -0
  16. package/config/agent/skills/chroma/chroma-local/querying/python.md +147 -0
  17. package/config/agent/skills/chroma/chroma-local/querying/typescript.md +157 -0
  18. package/config/agent/skills/chroma/chroma-local/regex/python.md +69 -0
  19. package/config/agent/skills/chroma/chroma-local/regex/typescript.md +71 -0
  20. package/config/agent/skills/chroma/chroma-local/understanding-a-codebase.md +80 -0
  21. package/config/agent/skills/chroma/chroma-local/updating-deleting/python.md +159 -0
  22. package/config/agent/skills/chroma/chroma-local/updating-deleting/typescript.md +228 -0
  23. package/config/agent/skills/milvus-skill/LICENSE +202 -0
  24. package/config/agent/skills/milvus-skill/README.md +37 -0
  25. package/config/agent/skills/milvus-skill/SKILL.md +259 -0
  26. package/config/agent/skills/milvus-skill/references/collection.md +86 -0
  27. package/config/agent/skills/milvus-skill/references/database.md +24 -0
  28. package/config/agent/skills/milvus-skill/references/index.md +69 -0
  29. package/config/agent/skills/milvus-skill/references/partition.md +29 -0
  30. package/config/agent/skills/milvus-skill/references/patterns.md +150 -0
  31. package/config/agent/skills/milvus-skill/references/user-role.md +90 -0
  32. package/config/agent/skills/milvus-skill/references/vector.md +247 -0
  33. package/package.json +1 -1
@@ -0,0 +1,153 @@
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
+ ```typescript
13
+ import { ChromaClient } from 'chromadb';
14
+ import { DefaultEmbeddingFunction } from '@chroma-core/default-embed';
15
+
16
+ const client = new ChromaClient();
17
+ const embeddingFunction = new DefaultEmbeddingFunction();
18
+ ```
19
+
20
+ ### Filtering with `where`
21
+
22
+ 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.
23
+
24
+ ```typescript
25
+ const collection = await client.getOrCreateCollection({
26
+ name: 'articles',
27
+ embeddingFunction,
28
+ });
29
+
30
+ const queryResults = await collection.query({
31
+ queryTexts: ['interest rates outlook'],
32
+ where: {
33
+ category: 'research',
34
+ },
35
+ });
36
+
37
+ const filteredDocs = await collection.get({
38
+ where: {
39
+ $and: [{ year: { $gte: 2025 } }, { region: { $in: ['us', 'eu'] } }],
40
+ },
41
+ limit: 20,
42
+ });
43
+
44
+ const directFilter = {
45
+ metadata_field: 'search_string',
46
+ };
47
+
48
+ const explicitFilter = {
49
+ metadata_field: {
50
+ $eq: 'search_string',
51
+ },
52
+ };
53
+ ```
54
+
55
+ ### Available filter operators
56
+
57
+ Chroma supports these operators in `where` clauses:
58
+
59
+ - **Equality:** `$eq` (default if just a value), `$ne`
60
+ - **Comparison:** `$gt`, `$gte`, `$lt`, `$lte`
61
+ - **Set membership:** `$in`, `$nin`
62
+ - **Array:** `$contains`, `$not_contains`
63
+ - **Logical:** `$and`, `$or`
64
+
65
+ 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.
66
+
67
+ ### Storing arrays in metadata
68
+
69
+ 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.
70
+
71
+ **Rules:**
72
+ - All elements in an array must share the same type
73
+ - Arrays are stored directly on metadata fields alongside regular scalar values
74
+
75
+ ```typescript
76
+ await collection.add({
77
+ ids: ['article-1', 'article-2', 'article-3'],
78
+ documents: [
79
+ 'Net interest income rose 12% in Q3',
80
+ 'New lending products launched in Southeast Asia',
81
+ 'Central bank holds rates steady amid inflation concerns',
82
+ ],
83
+ metadatas: [
84
+ {
85
+ topics: ['net-interest-income', 'earnings', 'quarterly-results'],
86
+ year: 2026,
87
+ },
88
+ {
89
+ topics: ['lending', 'expansion', 'southeast-asia'],
90
+ year: 2026,
91
+ },
92
+ {
93
+ topics: ['rates', 'central-bank', 'inflation'],
94
+ year: 2026,
95
+ },
96
+ ],
97
+ });
98
+ ```
99
+
100
+ ### Querying array metadata with `$contains`
101
+
102
+ Use `$contains` in a `where` filter to find records where an array metadata field includes a specific value.
103
+
104
+ ```typescript
105
+ const results = await collection.query({
106
+ queryTexts: ['lending products'],
107
+ where: {
108
+ topics: { $contains: 'lending' },
109
+ },
110
+ });
111
+ ```
112
+
113
+ ### Querying array metadata with `$not_contains`
114
+
115
+ Use `$not_contains` to exclude records where an array metadata field includes a specific value.
116
+
117
+ ```typescript
118
+ const filtered = await collection.query({
119
+ queryTexts: ['economic outlook'],
120
+ where: {
121
+ topics: { $not_contains: 'inflation' },
122
+ },
123
+ });
124
+ ```
125
+
126
+ ### Combining array and scalar filters
127
+
128
+ Array filters compose with existing logical operators (`$and`, `$or`) and can be combined with scalar metadata filters in the same query.
129
+
130
+ ```typescript
131
+ const combined = await collection.query({
132
+ queryTexts: ['financial results'],
133
+ where: {
134
+ $and: [{ topics: { $contains: 'earnings' } }, { year: { $gte: 2025 } }],
135
+ },
136
+ });
137
+
138
+ const multiMatch = await collection.query({
139
+ queryTexts: ['market trends'],
140
+ where: {
141
+ $or: [
142
+ { topics: { $contains: 'rates' } },
143
+ { topics: { $contains: 'inflation' } },
144
+ ],
145
+ },
146
+ });
147
+ ```
148
+
149
+ ### Common use cases
150
+
151
+ - **Multi-label tagging:** Store tags or categories as arrays, then filter with `$contains` to find matching records without joins or separate tables.
152
+ - **Access control:** Store allowed roles or groups as an array, then filter by the current user's role at query time.
153
+ - **Tenant and source filtering:** Store fields like tenant ID, source system, or document type so retrieval can stay scoped to the relevant subset.
@@ -0,0 +1,147 @@
1
+ ---
2
+ name: Query and Get
3
+ description: Query and Get Data from Chroma Collections
4
+ ---
5
+
6
+ ## Querying
7
+
8
+ Chroma provides two main methods for retrieving documents: `query` and `get`. Understanding when to use each is important for building effective search.
9
+
10
+ ### Query vs Get
11
+
12
+ **Use `query` when:**
13
+ - You have a search query (text that needs to be embedded and compared)
14
+ - You want results ranked by semantic similarity
15
+ - Building search features, RAG systems, or recommendation engines
16
+
17
+ **Use `get` when:**
18
+ - You know the exact document IDs you want
19
+ - You need to retrieve documents by metadata without similarity ranking
20
+ - Fetching documents to display after a search, or for batch operations
21
+
22
+ ### Imports and boilerplate
23
+
24
+ ```python
25
+ from typing import Optional, TypedDict
26
+
27
+ import chromadb
28
+
29
+ client = chromadb.HttpClient(host="localhost", port=8000)
30
+ ```
31
+
32
+ ### Basic query
33
+
34
+ The `query` method embeds your query text and finds the nearest neighbors in the collection. Results are returned in order of similarity.
35
+
36
+ ```python
37
+ collection = client.get_or_create_collection(name="my_collection")
38
+
39
+ collection.add(
40
+ ids=["doc1", "doc2"],
41
+ documents=[
42
+ "Apples are really good red fruit",
43
+ "Red cars tend to get more speeding tickets",
44
+ ],
45
+ )
46
+
47
+ results = collection.query(
48
+ query_texts=["I like red apples"],
49
+ )
50
+
51
+ first_result = results["documents"][0]
52
+ ```
53
+
54
+ ### Query with options
55
+
56
+ You can control what data is returned using `include`, and limit results with `nResults`. By default, Chroma returns 10 results.
57
+
58
+ ```python
59
+ collection2 = client.get_or_create_collection(name="my_collection")
60
+
61
+ results2 = collection2.query(
62
+ query_texts=["I like red apples"],
63
+ n_results=2,
64
+ include=["metadatas", "documents", "embeddings", "distances"],
65
+ ids=["id1", "id2"],
66
+ where={"category": "philosophy"},
67
+ where_document={"$contains": "wikipedia"},
68
+ )
69
+
70
+
71
+ class QueryResult(TypedDict):
72
+ ids: list[list[str]]
73
+ embeddings: Optional[list[list[list[float]]]]
74
+ documents: Optional[list[list[str]]]
75
+ metadatas: Optional[list[list[dict]]]
76
+ distances: Optional[list[list[float]]]
77
+
78
+
79
+ class GetResult(TypedDict):
80
+ ids: list[str]
81
+ embeddings: Optional[list[list[float]]]
82
+ documents: Optional[list[str]]
83
+ metadatas: Optional[list[dict]]
84
+
85
+
86
+ typed_results: QueryResult = results2
87
+ ```
88
+
89
+ The `include` parameter accepts: `documents`, `metadatas`, `embeddings`, and `distances`. Only request what you need to minimize response size.
90
+
91
+ ### Document content filtering
92
+
93
+ The `whereDocument` parameter filters on the actual document text, not metadata. This is useful for full-text search within your semantic results.
94
+
95
+ **Operators:**
96
+ - `$contains` - documents must contain the string (case-sensitive)
97
+ - `$not_contains` - documents must not contain the string
98
+
99
+ ```python
100
+ contains_results = collection.query(
101
+ query_texts=["search query"],
102
+ where_document={"$contains": "important keyword"},
103
+ )
104
+
105
+ excluded_results = collection.query(
106
+ query_texts=["search query"],
107
+ where_document={"$not_contains": "deprecated"},
108
+ )
109
+
110
+ combined_results = collection.query(
111
+ query_texts=["search query"],
112
+ where_document={
113
+ "$and": [
114
+ {"$contains": "python"},
115
+ {"$not_contains": "legacy"},
116
+ ]
117
+ },
118
+ )
119
+
120
+ full_filter_results = collection.query(
121
+ query_texts=["search query"],
122
+ n_results=10,
123
+ where={"status": "published"},
124
+ where_document={"$contains": "tutorial"},
125
+ )
126
+ ```
127
+
128
+ ## The `get` method
129
+
130
+ Use `get` when you need to retrieve documents without similarity ranking. Common use cases:
131
+
132
+ - Fetching specific documents by ID after a search
133
+ - Paginating through all documents in a collection
134
+ - Retrieving documents by metadata filter only
135
+
136
+ ```python
137
+ docs = collection.get(ids=["doc1", "doc2"])
138
+
139
+ page = collection.get(limit=20, offset=0)
140
+
141
+ filtered = collection.get(
142
+ where={"category": "blog"},
143
+ limit=50,
144
+ )
145
+ ```
146
+
147
+ The key difference from `query`: `get` returns documents in insertion order (or filtered by metadata), while `query` returns documents ranked by similarity to your query text.
@@ -0,0 +1,157 @@
1
+ ---
2
+ name: Query and Get
3
+ description: Query and Get Data from Chroma Collections
4
+ ---
5
+
6
+ ## Querying
7
+
8
+ Chroma provides two main methods for retrieving documents: `query` and `get`. Understanding when to use each is important for building effective search.
9
+
10
+ ### Query vs Get
11
+
12
+ **Use `query` when:**
13
+ - You have a search query (text that needs to be embedded and compared)
14
+ - You want results ranked by semantic similarity
15
+ - Building search features, RAG systems, or recommendation engines
16
+
17
+ **Use `get` when:**
18
+ - You know the exact document IDs you want
19
+ - You need to retrieve documents by metadata without similarity ranking
20
+ - Fetching documents to display after a search, or for batch operations
21
+
22
+ ### Imports and boilerplate
23
+
24
+ ```typescript
25
+ import { ChromaClient, type IncludeEnum } from 'chromadb';
26
+ import { DefaultEmbeddingFunction } from '@chroma-core/default-embed';
27
+
28
+ const client = new ChromaClient();
29
+ ```
30
+
31
+ ### Basic query
32
+
33
+ The `query` method embeds your query text and finds the nearest neighbors in the collection. Results are returned in order of similarity.
34
+
35
+ ```typescript
36
+ const embeddingFunction = new DefaultEmbeddingFunction();
37
+
38
+ const collection = await client.getOrCreateCollection({
39
+ name: 'my_collection',
40
+ embeddingFunction,
41
+ });
42
+
43
+ await collection.add({
44
+ ids: ['doc1', 'doc2'],
45
+ documents: [
46
+ 'Apples are really good red fruit',
47
+ 'Red cars tend to get more speeding tickets',
48
+ ],
49
+ });
50
+
51
+ const results = await collection.query({
52
+ queryTexts: ['I like red apples'],
53
+ });
54
+
55
+ const firstResult = results.documents[0];
56
+ ```
57
+
58
+ ### Query with options
59
+
60
+ You can control what data is returned using `include`, and limit results with `nResults`. By default, Chroma returns 10 results.
61
+
62
+ ```typescript
63
+ const embeddingFunction2 = new DefaultEmbeddingFunction();
64
+
65
+ const collection2 = await client.getOrCreateCollection({
66
+ name: 'my_collection',
67
+ embeddingFunction: embeddingFunction2,
68
+ });
69
+
70
+ const results2 = await collection2.query({
71
+ queryTexts: ['I like red apples'],
72
+ nResults: 2,
73
+ include: ['distances', 'embeddings', 'metadatas'],
74
+ ids: ['id1', 'id2'],
75
+ where: { category: 'philosophy' },
76
+ whereDocument: { $contains: 'wikipedia' },
77
+ });
78
+
79
+ type QueryResult = {
80
+ distances: (number | null)[][];
81
+ documents: (string | null)[][];
82
+ embeddings: (number[] | null)[][];
83
+ ids: string[][];
84
+ include: IncludeEnum[];
85
+ metadatas: (Record<string, string | number | boolean> | null)[][];
86
+ };
87
+
88
+ type GetResult = {
89
+ documents: (string | null)[];
90
+ embeddings: number[][];
91
+ ids: string[];
92
+ include: IncludeEnum[];
93
+ metadatas: (Record<string, string | number | boolean> | null)[];
94
+ };
95
+ ```
96
+
97
+ The `include` parameter accepts: `documents`, `metadatas`, `embeddings`, and `distances`. Only request what you need to minimize response size.
98
+
99
+ ### Document content filtering
100
+
101
+ The `whereDocument` parameter filters on the actual document text, not metadata. This is useful for full-text search within your semantic results.
102
+
103
+ **Operators:**
104
+ - `$contains` - documents must contain the string (case-sensitive)
105
+ - `$not_contains` - documents must not contain the string
106
+
107
+ ```typescript
108
+ const containsResults = await collection.query({
109
+ queryTexts: ['search query'],
110
+ whereDocument: { $contains: 'important keyword' },
111
+ });
112
+
113
+ const excludedResults = await collection.query({
114
+ queryTexts: ['search query'],
115
+ whereDocument: { $not_contains: 'deprecated' },
116
+ });
117
+
118
+ const combinedResults = await collection.query({
119
+ queryTexts: ['search query'],
120
+ whereDocument: {
121
+ $and: [{ $contains: 'python' }, { $not_contains: 'legacy' }],
122
+ },
123
+ });
124
+
125
+ const fullFilterResults = await collection.query({
126
+ queryTexts: ['search query'],
127
+ nResults: 10,
128
+ where: { status: 'published' },
129
+ whereDocument: { $contains: 'tutorial' },
130
+ });
131
+ ```
132
+
133
+ ## The `get` method
134
+
135
+ Use `get` when you need to retrieve documents without similarity ranking. Common use cases:
136
+
137
+ - Fetching specific documents by ID after a search
138
+ - Paginating through all documents in a collection
139
+ - Retrieving documents by metadata filter only
140
+
141
+ ```typescript
142
+ const docs = await collection.get({
143
+ ids: ['doc1', 'doc2'],
144
+ });
145
+
146
+ const page = await collection.get({
147
+ limit: 20,
148
+ offset: 0,
149
+ });
150
+
151
+ const filtered = await collection.get({
152
+ where: { category: 'blog' },
153
+ limit: 50,
154
+ });
155
+ ```
156
+
157
+ The key difference from `query`: `get` returns documents in insertion order (or filtered by metadata), while `query` returns documents ranked by similarity to your query text.
@@ -0,0 +1,69 @@
1
+ ---
2
+ name: Chroma Regex Filtering
3
+ description: Learn how to use regex filters in Chroma queries
4
+ ---
5
+
6
+ ## Regex Filtering in Chroma
7
+
8
+ Chroma supports regex filtering on document content. This is useful when you need exact pattern matching that semantic search can't provide.
9
+
10
+ ### When to use regex vs semantic search
11
+
12
+ **Use regex when:**
13
+ - Matching exact patterns like email addresses, URLs, or code identifiers
14
+ - Finding documents containing specific formats (dates, phone numbers, IDs)
15
+ - Filtering by prefixes or suffixes in structured data
16
+ - You need deterministic, repeatable matches
17
+
18
+ **Use semantic search when:**
19
+ - Looking for conceptually similar content regardless of exact wording
20
+ - The user's query is natural language
21
+ - You want to find related content even if it uses different terminology
22
+
23
+ You can combine both: use regex to narrow results, then rank by semantic similarity.
24
+
25
+ ### Imports and boilerplate
26
+
27
+ ```python
28
+ import chromadb
29
+
30
+ client = chromadb.HttpClient(host="localhost", port=8000)
31
+ collection = client.get_or_create_collection(name="my_collection")
32
+ ```
33
+
34
+ ### Basic Regex Filter
35
+
36
+ Use the `$regex` operator in `where_document` to match document content against a regular expression. The regex follows standard regex syntax.
37
+
38
+ ```python
39
+ results = collection.query(
40
+ query_texts=["search query"],
41
+ where_document={
42
+ "$regex": "^tech.*"
43
+ },
44
+ n_results=10,
45
+ )
46
+ ```
47
+
48
+ ### Combining regex with metadata filters
49
+
50
+ Regex filters can be combined with metadata filters using `$and` and `$or` operators. This is powerful for narrowing results by both content patterns and structured metadata. Note however regex can not be used on metadata string values.
51
+
52
+ ```python
53
+ collection.query(
54
+ query_texts=["query1", "query2"],
55
+ where_document={
56
+ "$and": [
57
+ {"$contains": "search_string_1"},
58
+ {"$regex": "[a-z]+"},
59
+ ]
60
+ },
61
+ )
62
+ ```
63
+
64
+ ### Performance considerations
65
+
66
+ Regex filtering happens after the initial vector search retrieves candidates. For best performance:
67
+ - Keep regex patterns simple when possible
68
+ - Use metadata filters to reduce the candidate set before regex matching
69
+ - Consider whether a metadata field with pre-extracted values would be faster than runtime regex
@@ -0,0 +1,71 @@
1
+ ---
2
+ name: Chroma Regex Filtering
3
+ description: Learn how to use regex filters in Chroma queries
4
+ ---
5
+
6
+ ## Regex Filtering in Chroma
7
+
8
+ Chroma supports regex filtering on document content. This is useful when you need exact pattern matching that semantic search can't provide.
9
+
10
+ ### When to use regex vs semantic search
11
+
12
+ **Use regex when:**
13
+ - Matching exact patterns like email addresses, URLs, or code identifiers
14
+ - Finding documents containing specific formats (dates, phone numbers, IDs)
15
+ - Filtering by prefixes or suffixes in structured data
16
+ - You need deterministic, repeatable matches
17
+
18
+ **Use semantic search when:**
19
+ - Looking for conceptually similar content regardless of exact wording
20
+ - The user's query is natural language
21
+ - You want to find related content even if it uses different terminology
22
+
23
+ You can combine both: use regex to narrow results, then rank by semantic similarity.
24
+
25
+ ### Imports and boilerplate
26
+
27
+ ```typescript
28
+ import { DefaultEmbeddingFunction } from '@chroma-core/default-embed';
29
+ import { ChromaClient } from 'chromadb';
30
+
31
+ const client = new ChromaClient();
32
+ const embedder = new DefaultEmbeddingFunction();
33
+
34
+ const collection = await client.getOrCreateCollection({
35
+ name: 'example-collection',
36
+ embeddingFunction: embedder,
37
+ });
38
+ ```
39
+
40
+ ### Basic Regex Filter
41
+
42
+ Use the `$regex` operator in `where_document` to match document content against a regular expression. The regex follows standard regex syntax.
43
+
44
+ ```typescript
45
+ await collection.query({
46
+ queryTexts: ['find support tickets with email addresses'],
47
+ whereDocument: {
48
+ $regex: '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$',
49
+ },
50
+ });
51
+ ```
52
+
53
+ ### Combining regex with metadata filters
54
+
55
+ Regex filters can be combined with metadata filters using `$and` and `$or` operators. This is powerful for narrowing results by both content patterns and structured metadata. Note however regex can not be used on metadata string values.
56
+
57
+ ```typescript
58
+ await collection.query({
59
+ queryTexts: ['query1', 'query2'],
60
+ whereDocument: {
61
+ $and: [{ $contains: 'search_string_1' }, { $regex: '[a-z]+' }],
62
+ },
63
+ });
64
+ ```
65
+
66
+ ### Performance considerations
67
+
68
+ Regex filtering happens after the initial vector search retrieves candidates. For best performance:
69
+ - Keep regex patterns simple when possible
70
+ - Use metadata filters to reduce the candidate set before regex matching
71
+ - Consider whether a metadata field with pre-extracted values would be faster than runtime regex
@@ -0,0 +1,80 @@
1
+ ---
2
+ name: Integrating Chroma into an existing system
3
+ description: Guidance for adding Chroma search to an existing application
4
+ ---
5
+
6
+ ## Integrating Chroma into an existing system
7
+
8
+ Adding search to an existing application requires understanding the data flow and planning both the initial import and ongoing synchronization. This guide helps identify the key questions to answer.
9
+
10
+ ### Key questions to ask the user
11
+
12
+ Before writing any code, clarify:
13
+
14
+ 1. **What data should be searchable?** (documents, products, messages, etc.)
15
+ 2. **Where does that data currently live?** (database, S3, API, files)
16
+ 3. **How is the data structured?** (helps determine chunking strategy)
17
+ 4. **How often does the data change?** (informs sync strategy)
18
+ 5. **What latency is acceptable for updates to appear in search?**
19
+
20
+ ## Understanding the source data
21
+
22
+ Before designing the import pipeline, ask the user if you can look at a sample of the data that will be made searchable. Seeing real records is far more useful than a description of the schema.
23
+
24
+ **If the data is in a database:** Write a short script that connects to the database and prints a few records. For example, a script that queries 3-5 rows from the relevant table and prints them to the terminal. This lets you see the actual field names, content lengths, and metadata available.
25
+
26
+ **If the data is on disk:** Read a few of the files directly to understand their structure, format, and size. For example, if indexing markdown files, read 2-3 of them to see how they're organized.
27
+
28
+ What to look for:
29
+ - **Which field(s) contain the searchable text** — this becomes the document content in Chroma
30
+ - **How long the content is** — determines whether chunking is needed
31
+ - **What metadata is available** — fields like category, author, date, or tenant ID that could be useful for filtering
32
+ - **How records are identified** — the primary key or filename that will link Chroma documents back to the source
33
+
34
+ This step prevents guesswork and leads to better chunking and metadata design decisions.
35
+
36
+ ## Initial data import (offline ingest)
37
+
38
+ The first step is getting existing data into Chroma. This typically involves:
39
+
40
+ 1. **Reading from the source** - database queries, S3 listing, API pagination
41
+ 2. **Chunking** - breaking large documents into searchable pieces (see data-model.md)
42
+ 3. **Embedding** - converting text chunks to vectors
43
+ 4. **Writing to Chroma** - batching for efficiency
44
+
45
+ Build this as a reusable pipeline, not a one-off script. The same chunking and embedding logic will be needed for ongoing updates.
46
+
47
+ **Progress tracking:** For large imports, track which records have been processed. This allows resuming after failures and re-running for updates. A simple approach is storing the last processed ID or timestamp.
48
+
49
+ ## Keeping data in sync (online writes)
50
+
51
+ After the initial import, new and updated data must flow to Chroma. There are two main patterns:
52
+
53
+ ### Asynchronous (recommended)
54
+
55
+ Use a message queue (SQS, RabbitMQ, Redis streams, etc.) to decouple the primary write path from Chroma updates:
56
+
57
+ 1. Application writes to primary database
58
+ 2. Application publishes an event with the record ID
59
+ 3. Queue consumer fetches the record, chunks, embeds, and writes to Chroma
60
+
61
+ **Benefits:** Primary writes aren't slowed by embedding latency. Retries are handled by the queue. Search updates can lag slightly without affecting the main application.
62
+
63
+ ### Synchronous
64
+
65
+ If no queue infrastructure exists and slight latency is acceptable, update Chroma in the same request:
66
+
67
+ 1. Application writes to primary database
68
+ 2. Application chunks, embeds, and writes to Chroma
69
+ 3. Request completes
70
+
71
+ **Tradeoffs:** Simpler infrastructure but adds latency to every write. Failures in Chroma can affect the primary write path unless carefully handled.
72
+
73
+ **Ask the user:** Do they have an async queue? If not, is synchronous acceptable, or should we set one up?
74
+
75
+ ## Handling updates and deletes
76
+
77
+ - **Updates:** Re-chunk and re-embed the document, then use `upsert` to replace existing chunks
78
+ - **Deletes:** Delete all chunks for the document by ID prefix or metadata filter
79
+
80
+ Storing the source record ID in chunk metadata makes this straightforward. For example, if a blog post with ID `post-123` has 3 chunks, store `{"source_id": "post-123", "chunk_index": 0}` etc. on each chunk.