chroma-haystack 4.3.0__tar.gz → 4.3.2__tar.gz

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 (59) hide show
  1. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/CHANGELOG.md +31 -0
  2. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/PKG-INFO +1 -1
  3. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/src/haystack_integrations/document_stores/chroma/document_store.py +13 -10
  4. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/src/haystack_integrations/document_stores/chroma/filters.py +1 -1
  5. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/tests/test_document_store.py +39 -0
  6. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/tests/test_filters.py +7 -0
  7. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/tests/test_retriever.py +2 -0
  8. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/.gitignore +0 -0
  9. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/LICENSE +0 -0
  10. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/README.md +0 -0
  11. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_01.txt +0 -0
  12. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_02.txt +0 -0
  13. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_03.txt +0 -0
  14. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_04.txt +0 -0
  15. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_05.txt +0 -0
  16. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_06.txt +0 -0
  17. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_07.txt +0 -0
  18. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_08.txt +0 -0
  19. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_09.txt +0 -0
  20. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_10.txt +0 -0
  21. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_11.txt +0 -0
  22. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_12.txt +0 -0
  23. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_20.txt +0 -0
  24. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_21.txt +0 -0
  25. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_22.txt +0 -0
  26. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_23.txt +0 -0
  27. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_24.txt +0 -0
  28. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_25.txt +0 -0
  29. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_26.txt +0 -0
  30. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_27.txt +0 -0
  31. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_28.txt +0 -0
  32. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_29.txt +0 -0
  33. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_30.txt +0 -0
  34. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_31.txt +0 -0
  35. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_32.txt +0 -0
  36. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_40.txt +0 -0
  37. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_41.txt +0 -0
  38. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_42.txt +0 -0
  39. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_43.txt +0 -0
  40. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_44.txt +0 -0
  41. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_45.txt +0 -0
  42. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_46.txt +0 -0
  43. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_50.txt +0 -0
  44. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_51.txt +0 -0
  45. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_52.txt +0 -0
  46. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/data/usr_90.txt +0 -0
  47. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/example/example.py +0 -0
  48. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/pydoc/config_docusaurus.yml +0 -0
  49. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/pyproject.toml +0 -0
  50. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/src/haystack_integrations/components/retrievers/chroma/__init__.py +0 -0
  51. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/src/haystack_integrations/components/retrievers/chroma/retriever.py +0 -0
  52. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/src/haystack_integrations/components/retrievers/py.typed +0 -0
  53. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/src/haystack_integrations/document_stores/chroma/__init__.py +0 -0
  54. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/src/haystack_integrations/document_stores/chroma/errors.py +0 -0
  55. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/src/haystack_integrations/document_stores/chroma/utils.py +0 -0
  56. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/src/haystack_integrations/document_stores/py.typed +0 -0
  57. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/tests/__init__.py +0 -0
  58. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/tests/conftest.py +0 -0
  59. {chroma_haystack-4.3.0 → chroma_haystack-4.3.2}/tests/test_document_store_async.py +0 -0
@@ -1,5 +1,36 @@
1
1
  # Changelog
2
2
 
3
+ ## [integrations/chroma-v4.3.1] - 2026-06-29
4
+
5
+ ### 🐛 Bug Fixes
6
+
7
+ - Serialize ChromaDocumentStore metadata in to_dict (#3445)
8
+
9
+
10
+ ## [integrations/chroma-v4.3.0] - 2026-04-29
11
+
12
+ ### 🚀 Features
13
+
14
+ - *(chroma)* Support DuplicatePolicy in write_documents and use async mixin tests (#3245)
15
+
16
+ ### 🚜 Refactor
17
+
18
+ - Weaviate, chroma, elasticsearch, opensearch, azure_ai_search use `_normalize_metadata_field_name` from haystack.utils (#2953)
19
+
20
+ ### 🧪 Testing
21
+
22
+ - `ChromaDocumentStore` use Mixin tests (#3026)
23
+ - Track test coverage for all integrations (#3065)
24
+ - Better categorize some Document Stores tests (#3085)
25
+ - Chroma - add unit tests (#3175)
26
+
27
+ ### 🧹 Chores
28
+
29
+ - Add missing -> None return type annotations to chroma __init__ methods (#2976)
30
+ - Enforce ruff docstring rules (D102/D103/D205/D209/D213/D417/D419) in first 10 integrations (#3008)
31
+ - Increase lower pins for 3.14 support in some integrations + test with 3.14 (#3033)
32
+
33
+
3
34
  ## [integrations/chroma-v4.2.0] - 2026-03-11
4
35
 
5
36
  ### 🚀 Features
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chroma-haystack
3
- Version: 4.3.0
3
+ Version: 4.3.2
4
4
  Project-URL: Documentation, https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/chroma#readme
5
5
  Project-URL: Issues, https://github.com/deepset-ai/haystack-core-integrations/issues
6
6
  Project-URL: Source, https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/chroma
@@ -140,9 +140,10 @@ class ChromaDocumentStore:
140
140
 
141
141
  self._client = client # store client for potential future use
142
142
 
143
- self._metadata = self._metadata or {}
144
- if "hnsw:space" not in self._metadata:
145
- self._metadata["hnsw:space"] = self._distance_function
143
+ # Build the collection metadata locally so `self._metadata` stays exactly as the user passed it.
144
+ # This keeps `to_dict()` deterministic and avoids mutating a user-supplied dict in place.
145
+ collection_metadata = dict(self._metadata) if self._metadata else {}
146
+ collection_metadata.setdefault("hnsw:space", self._distance_function)
146
147
 
147
148
  existing_collection_names = [c.name for c in client.list_collections()]
148
149
  if self._collection_name in existing_collection_names:
@@ -151,14 +152,14 @@ class ChromaDocumentStore:
151
152
  embedding_function=self._embedding_func,
152
153
  )
153
154
 
154
- if self._metadata != self._collection.metadata:
155
+ if collection_metadata != self._collection.metadata:
155
156
  logger.warning(
156
157
  "Collection already exists. The `distance_function` and `metadata` parameters will be ignored."
157
158
  )
158
159
  else:
159
160
  self._collection = client.create_collection(
160
161
  name=self._collection_name,
161
- metadata=self._metadata,
162
+ metadata=collection_metadata,
162
163
  embedding_function=self._embedding_func,
163
164
  )
164
165
 
@@ -188,9 +189,10 @@ class ChromaDocumentStore:
188
189
 
189
190
  self._async_client = client # store client for potential future use
190
191
 
191
- self._metadata = self._metadata or {}
192
- if "hnsw:space" not in self._metadata:
193
- self._metadata["hnsw:space"] = self._distance_function
192
+ # Build the collection metadata locally so `self._metadata` stays exactly as the user passed it.
193
+ # This keeps `to_dict()` deterministic and avoids mutating a user-supplied dict in place.
194
+ collection_metadata = dict(self._metadata) if self._metadata else {}
195
+ collection_metadata.setdefault("hnsw:space", self._distance_function)
194
196
 
195
197
  collection = await client.list_collections()
196
198
  existing_collection_names = [c.name for c in collection]
@@ -200,14 +202,14 @@ class ChromaDocumentStore:
200
202
  embedding_function=self._embedding_func,
201
203
  )
202
204
 
203
- if self._metadata != self._async_collection.metadata:
205
+ if collection_metadata != self._async_collection.metadata:
204
206
  logger.warning(
205
207
  "Collection already exists. The `distance_function` and `metadata` parameters will be ignored."
206
208
  )
207
209
  else:
208
210
  self._async_collection = await client.create_collection(
209
211
  name=self._collection_name,
210
- metadata=self._metadata,
212
+ metadata=collection_metadata,
211
213
  embedding_function=self._embedding_func,
212
214
  )
213
215
 
@@ -1373,6 +1375,7 @@ class ChromaDocumentStore:
1373
1375
  host=self._host,
1374
1376
  port=self._port,
1375
1377
  distance_function=self._distance_function,
1378
+ metadata=self._metadata,
1376
1379
  client_settings=self._client_settings,
1377
1380
  **self._embedding_function_params,
1378
1381
  )
@@ -68,7 +68,7 @@ def _convert_filters(filters: dict[str, Any]) -> ChromaFilter:
68
68
  continue
69
69
  # if field is "id", it'll be passed to Chroma's ids filter
70
70
  elif field == "id":
71
- if not value["$eq"]:
71
+ if "$eq" not in value or not value["$eq"]:
72
72
  msg = f"id filter only supports '==' operator, got {value}"
73
73
  raise ChromaDocumentStoreFilterError(msg)
74
74
  ids.append(value["$eq"])
@@ -101,6 +101,7 @@ class TestDocumentStoreUnit:
101
101
  "port": None,
102
102
  "api_key": "1234567890",
103
103
  "distance_function": "l2",
104
+ "metadata": None,
104
105
  "client_settings": {"anonymized_telemetry": False},
105
106
  },
106
107
  }
@@ -128,6 +129,44 @@ class TestDocumentStoreUnit:
128
129
  assert ds._embedding_function_params == {"api_key": "1234567890"}
129
130
  assert ds._client_settings == {"anonymized_telemetry": False}
130
131
 
132
+ def test_to_dict_and_from_dict_preserves_metadata(self):
133
+ """`metadata` configures the underlying Chroma collection (e.g.
134
+ ``hnsw:space`` and other HNSW index parameters). It must survive a
135
+ to_dict/from_dict round-trip, otherwise serializing a pipeline to YAML
136
+ silently drops the collection settings when the store is reloaded."""
137
+ metadata = {"hnsw:space": "cosine", "hnsw:search_ef": 200}
138
+ ds = ChromaDocumentStore(
139
+ collection_name="test_md",
140
+ embedding_function="HuggingFaceEmbeddingFunction",
141
+ api_key="1234567890",
142
+ metadata=metadata,
143
+ )
144
+
145
+ assert ds.to_dict()["init_parameters"]["metadata"] == metadata
146
+
147
+ restored = ChromaDocumentStore.from_dict(ds.to_dict())
148
+ assert restored._metadata == metadata
149
+
150
+ def test_ensure_initialized_does_not_mutate_metadata(self):
151
+ """Initialization derives the collection metadata (injecting ``hnsw:space``) into a
152
+ local copy, so ``self._metadata`` must stay exactly as the user passed it. Otherwise
153
+ ``to_dict()`` would become lifecycle-dependent and a user-supplied dict would be mutated
154
+ in place."""
155
+ # metadata=None must stay None after initialization
156
+ store = ChromaDocumentStore(collection_name="test_no_metadata", distance_function="cosine")
157
+ store._ensure_initialized()
158
+ assert store._metadata is None
159
+ assert store.to_dict()["init_parameters"]["metadata"] is None
160
+
161
+ # a user-supplied dict without "hnsw:space" must not be mutated
162
+ user_metadata = {"hnsw:search_ef": 200}
163
+ store = ChromaDocumentStore(
164
+ collection_name="test_user_metadata", distance_function="cosine", metadata=user_metadata
165
+ )
166
+ store._ensure_initialized()
167
+ assert store._metadata == {"hnsw:search_ef": 200}
168
+ assert "hnsw:space" not in user_metadata
169
+
131
170
  def test_same_collection_name_reinitialization(self):
132
171
  ChromaDocumentStore("test_1")
133
172
  ChromaDocumentStore("test_1")
@@ -17,6 +17,13 @@ def test_id_filter_with_empty_value_raises():
17
17
  _convert_filters({"field": "id", "operator": "==", "value": ""})
18
18
 
19
19
 
20
+ def test_id_filter_with_non_eq_operator_raises():
21
+ # A non-'==' operator produces e.g. {"$in": [...]} (no "$eq" key), which must
22
+ # surface the friendly ChromaDocumentStoreFilterError, not a raw KeyError('$eq').
23
+ with pytest.raises(ChromaDocumentStoreFilterError, match="id filter only supports"):
24
+ _convert_filters({"field": "id", "operator": "in", "value": ["1", "2"]})
25
+
26
+
20
27
  @pytest.mark.parametrize(
21
28
  ("condition", "match"),
22
29
  [
@@ -44,6 +44,7 @@ class TestChromaQueryTextRetriever:
44
44
  "port": None,
45
45
  "api_key": "1234567890",
46
46
  "distance_function": "l2",
47
+ "metadata": None,
47
48
  "client_settings": None,
48
49
  },
49
50
  },
@@ -158,6 +159,7 @@ class TestChromaEmbeddingRetriever:
158
159
  "port": None,
159
160
  "api_key": "1234567890",
160
161
  "distance_function": "l2",
162
+ "metadata": None,
161
163
  "client_settings": None,
162
164
  },
163
165
  },
File without changes