chroma-haystack 4.2.0__tar.gz → 4.3.0__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 (60) hide show
  1. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/CHANGELOG.md +21 -0
  2. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/PKG-INFO +4 -3
  3. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/pyproject.toml +17 -4
  4. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/src/haystack_integrations/components/retrievers/chroma/retriever.py +6 -2
  5. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/src/haystack_integrations/document_stores/chroma/document_store.py +97 -49
  6. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/src/haystack_integrations/document_stores/chroma/filters.py +5 -5
  7. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/src/haystack_integrations/document_stores/chroma/utils.py +2 -1
  8. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/tests/test_document_store.py +159 -179
  9. chroma_haystack-4.3.0/tests/test_document_store_async.py +217 -0
  10. chroma_haystack-4.3.0/tests/test_filters.py +46 -0
  11. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/tests/test_retriever.py +70 -0
  12. chroma_haystack-4.2.0/tests/test_document_store_async.py +0 -444
  13. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/.gitignore +0 -0
  14. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/LICENSE +0 -0
  15. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/README.md +0 -0
  16. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_01.txt +0 -0
  17. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_02.txt +0 -0
  18. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_03.txt +0 -0
  19. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_04.txt +0 -0
  20. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_05.txt +0 -0
  21. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_06.txt +0 -0
  22. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_07.txt +0 -0
  23. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_08.txt +0 -0
  24. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_09.txt +0 -0
  25. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_10.txt +0 -0
  26. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_11.txt +0 -0
  27. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_12.txt +0 -0
  28. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_20.txt +0 -0
  29. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_21.txt +0 -0
  30. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_22.txt +0 -0
  31. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_23.txt +0 -0
  32. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_24.txt +0 -0
  33. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_25.txt +0 -0
  34. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_26.txt +0 -0
  35. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_27.txt +0 -0
  36. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_28.txt +0 -0
  37. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_29.txt +0 -0
  38. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_30.txt +0 -0
  39. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_31.txt +0 -0
  40. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_32.txt +0 -0
  41. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_40.txt +0 -0
  42. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_41.txt +0 -0
  43. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_42.txt +0 -0
  44. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_43.txt +0 -0
  45. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_44.txt +0 -0
  46. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_45.txt +0 -0
  47. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_46.txt +0 -0
  48. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_50.txt +0 -0
  49. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_51.txt +0 -0
  50. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_52.txt +0 -0
  51. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/data/usr_90.txt +0 -0
  52. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/example/example.py +0 -0
  53. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/pydoc/config_docusaurus.yml +0 -0
  54. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/src/haystack_integrations/components/retrievers/chroma/__init__.py +0 -0
  55. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/src/haystack_integrations/components/retrievers/py.typed +0 -0
  56. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/src/haystack_integrations/document_stores/chroma/__init__.py +0 -0
  57. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/src/haystack_integrations/document_stores/chroma/errors.py +0 -0
  58. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/src/haystack_integrations/document_stores/py.typed +0 -0
  59. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/tests/__init__.py +0 -0
  60. {chroma_haystack-4.2.0 → chroma_haystack-4.3.0}/tests/conftest.py +0 -0
@@ -1,5 +1,26 @@
1
1
  # Changelog
2
2
 
3
+ ## [integrations/chroma-v4.2.0] - 2026-03-11
4
+
5
+ ### 🚀 Features
6
+
7
+ - Add support for metadata that contains lists of supported types (#2877)
8
+
9
+ ### 📚 Documentation
10
+
11
+ - Simplify pydoc configs (#2855)
12
+
13
+ ### 🧪 Testing
14
+
15
+ - Replacing each `DocumentStore` specific tests and used the generalised ones from `haystack.testing.document_store` (#2812)
16
+ - Chroma - remove tests for invalid Settings (now ignored) (#2935)
17
+
18
+ ### 🧹 Chores
19
+
20
+ - Remove unused allow-direct-references (#2866)
21
+ - Standardize author mentions (#2897)
22
+
23
+
3
24
  ## [integrations/chroma-v4.1.1] - 2026-02-10
4
25
 
5
26
  ### 📚 Documentation
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chroma-haystack
3
- Version: 4.2.0
3
+ Version: 4.3.0
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
@@ -14,11 +14,12 @@ Classifier: Programming Language :: Python :: 3.10
14
14
  Classifier: Programming Language :: Python :: 3.11
15
15
  Classifier: Programming Language :: Python :: 3.12
16
16
  Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Programming Language :: Python :: 3.14
17
18
  Classifier: Programming Language :: Python :: Implementation :: CPython
18
19
  Classifier: Programming Language :: Python :: Implementation :: PyPy
19
20
  Requires-Python: >=3.10
20
- Requires-Dist: chromadb>=1.5.0
21
- Requires-Dist: haystack-ai>=2.24.0
21
+ Requires-Dist: chromadb>=1.5.4
22
+ Requires-Dist: haystack-ai>=2.28.0
22
23
  Description-Content-Type: text/markdown
23
24
 
24
25
  # chroma-haystack
@@ -19,12 +19,13 @@ classifiers = [
19
19
  "Programming Language :: Python :: 3.11",
20
20
  "Programming Language :: Python :: 3.12",
21
21
  "Programming Language :: Python :: 3.13",
22
+ "Programming Language :: Python :: 3.14",
22
23
  "Programming Language :: Python :: Implementation :: CPython",
23
24
  "Programming Language :: Python :: Implementation :: PyPy",
24
25
  ]
25
26
  dependencies = [
26
- "haystack-ai>=2.24.0",
27
- "chromadb>=1.5.0"
27
+ "haystack-ai>=2.28.0",
28
+ "chromadb>=1.5.4"
28
29
  ]
29
30
 
30
31
  [project.urls]
@@ -66,7 +67,8 @@ dependencies = [
66
67
  unit = 'pytest -m "not integration" {args:tests}'
67
68
  integration = 'pytest -m "integration" {args:tests}'
68
69
  all = 'pytest {args:tests}'
69
- cov-retry = 'pytest --cov=haystack_integrations --reruns 3 --reruns-delay 30 -x {args:tests}'
70
+ unit-cov-retry = 'pytest --cov=haystack_integrations --reruns 3 --reruns-delay 30 -x -m "not integration" {args:tests}'
71
+ integration-cov-append-retry = 'pytest --cov=haystack_integrations --cov-append --reruns 3 --reruns-delay 30 -x -m "integration" {args:tests}'
70
72
 
71
73
  types = "mypy -p haystack_integrations.components.retrievers.chroma -p haystack_integrations.document_stores.chroma {args}"
72
74
 
@@ -83,9 +85,17 @@ line-length = 120
83
85
  [tool.ruff.lint]
84
86
  select = [
85
87
  "A",
88
+ "ANN",
86
89
  "ARG",
87
90
  "B",
88
91
  "C",
92
+ "D102", # Missing docstring in public method
93
+ "D103", # Missing docstring in public function
94
+ "D205", # 1 blank line required between summary line and description
95
+ "D209", # Closing triple quotes go to new line
96
+ "D213", # summary lines must be positioned on the second physical line of the docstring
97
+ "D417", # Missing argument descriptions in the docstring
98
+ "D419", # Docstring is empty
89
99
  "DTZ",
90
100
  "E",
91
101
  "EM",
@@ -111,6 +121,8 @@ select = [
111
121
  ignore = [
112
122
  # Allow non-abstract empty methods in abstract base classes
113
123
  "B027",
124
+ # Allow `Any` - used legitimately for **kwargs and dynamic metadata values
125
+ "ANN401",
114
126
  # Allow boolean positional values in function calls, like `dict.get(... True)`
115
127
  "FBT003",
116
128
  # Ignore checks for possible passwords
@@ -138,12 +150,13 @@ ban-relative-imports = "parents"
138
150
 
139
151
  [tool.ruff.lint.per-file-ignores]
140
152
  # Tests can use magic values, assertions, and relative imports
141
- "tests/**/*" = ["PLR2004", "S101", "TID252"]
153
+ "tests/**/*" = ["PLR2004", "S101", "TID252", "D", "ANN"]
142
154
  "example/**/*" = ["T201"]
143
155
 
144
156
  [tool.coverage.run]
145
157
  source = ["haystack_integrations"]
146
158
  branch = true
159
+ relative_files = true
147
160
  parallel = false
148
161
 
149
162
 
@@ -51,8 +51,10 @@ class ChromaQueryTextRetriever:
51
51
  filters: dict[str, Any] | None = None,
52
52
  top_k: int = 10,
53
53
  filter_policy: str | FilterPolicy = FilterPolicy.REPLACE,
54
- ):
54
+ ) -> None:
55
55
  """
56
+ Initialize the ChromaQueryTextRetriever.
57
+
56
58
  :param document_store: an instance of `ChromaDocumentStore`.
57
59
  :param filters: filters to narrow down the search space.
58
60
  :param top_k: the maximum number of documents to retrieve.
@@ -164,8 +166,10 @@ class ChromaEmbeddingRetriever:
164
166
  filters: dict[str, Any] | None = None,
165
167
  top_k: int = 10,
166
168
  filter_policy: str | FilterPolicy = FilterPolicy.REPLACE,
167
- ):
169
+ ) -> None:
168
170
  """
171
+ Initialize the ChromaEmbeddingRetriever.
172
+
169
173
  :param document_store: an instance of `ChromaDocumentStore`.
170
174
  :param filters: filters to narrow down the search space.
171
175
  :param top_k: the maximum number of documents to retrieve.
@@ -11,8 +11,9 @@ from chromadb.api.types import GetResult, Metadata, OneOrMany, QueryResult
11
11
  from chromadb.config import Settings
12
12
  from haystack import default_from_dict, default_to_dict, logging
13
13
  from haystack.dataclasses import Document
14
- from haystack.document_stores.errors import DocumentStoreError
14
+ from haystack.document_stores.errors import DocumentStoreError, DuplicateDocumentError
15
15
  from haystack.document_stores.types import DuplicatePolicy
16
+ from haystack.utils.misc import _normalize_metadata_field_name
16
17
 
17
18
  from .filters import _convert_filters
18
19
  from .utils import get_embedding_function
@@ -45,9 +46,10 @@ class ChromaDocumentStore:
45
46
  metadata: dict | None = None,
46
47
  client_settings: dict[str, Any] | None = None,
47
48
  **embedding_function_params: Any,
48
- ):
49
+ ) -> None:
49
50
  """
50
51
  Creates a new ChromaDocumentStore instance.
52
+
51
53
  It is meant to be connected to a Chroma collection.
52
54
 
53
55
  Note: for the component to be part of a serializable pipeline, the __init__
@@ -102,7 +104,7 @@ class ChromaDocumentStore:
102
104
  self._collection: chromadb.Collection | None = None
103
105
  self._async_collection: AsyncCollection | None = None
104
106
 
105
- def _ensure_initialized(self):
107
+ def _ensure_initialized(self) -> None:
106
108
  if not self._collection:
107
109
  # Create the client instance
108
110
  if self._persist_path and (self._host or self._port is not None):
@@ -160,7 +162,7 @@ class ChromaDocumentStore:
160
162
  embedding_function=self._embedding_func,
161
163
  )
162
164
 
163
- async def _ensure_initialized_async(self):
165
+ async def _ensure_initialized_async(self) -> None:
164
166
  if not self._async_collection:
165
167
  if self._host is None or self._port is None:
166
168
  error_message = (
@@ -242,16 +244,6 @@ class ChromaDocumentStore:
242
244
  "include": ["embeddings", "documents", "metadatas", "distances"],
243
245
  }
244
246
 
245
- @staticmethod
246
- def _normalize_metadata_field_name(metadata_field: str) -> str:
247
- """
248
- Normalizes a metadata field name by removing the "meta." prefix if present.
249
-
250
- :param metadata_field: The metadata field name to normalize.
251
- :returns: The normalized field name without "meta." prefix.
252
- """
253
- return metadata_field[5:] if metadata_field.startswith("meta.") else metadata_field
254
-
255
247
  @staticmethod
256
248
  def _infer_type_from_value(value: Any) -> str:
257
249
  """
@@ -341,7 +333,7 @@ class ChromaDocumentStore:
341
333
  for meta in metadatas:
342
334
  if meta and field_name in meta:
343
335
  val = meta.get(field_name)
344
- if isinstance(val, (str, int, float)):
336
+ if isinstance(val, str | int | float):
345
337
  values.append(val)
346
338
 
347
339
  if not values:
@@ -581,62 +573,123 @@ class ChromaDocumentStore:
581
573
  def write_documents(
582
574
  self,
583
575
  documents: list[Document],
584
- policy: DuplicatePolicy = DuplicatePolicy.FAIL,
576
+ policy: DuplicatePolicy = DuplicatePolicy.NONE,
585
577
  ) -> int:
586
578
  """
587
- Writes (or overwrites) documents into the store.
579
+ Writes documents into the store.
588
580
 
589
581
  :param documents:
590
582
  A list of documents to write into the document store.
591
583
  :param policy:
592
- Not supported at the moment.
584
+ How to handle documents whose `id` already exists in the store:
585
+ - `NONE` (default): treated as `FAIL`.
586
+ - `OVERWRITE`: replace the existing document.
587
+ - `SKIP`: keep the existing document and skip the new one.
588
+ - `FAIL`: raise `DuplicateDocumentError`.
593
589
 
594
590
  :raises ValueError:
595
591
  When input is not valid.
592
+ :raises DuplicateDocumentError:
593
+ When `policy` is `FAIL` (or `NONE`) and any document `id` already exists.
596
594
 
597
595
  :returns:
598
- The number of documents written
596
+ The number of documents written.
599
597
  """
600
598
  self._ensure_initialized()
601
599
  assert self._collection is not None
602
600
 
603
- for doc in documents:
604
- data = ChromaDocumentStore._convert_document_to_chroma(doc)
605
- if data is not None:
606
- self._collection.add(**data)
601
+ if policy == DuplicatePolicy.NONE:
602
+ policy = DuplicatePolicy.FAIL
603
+
604
+ chroma_payloads: list[dict[str, Any]] = [
605
+ p for p in (ChromaDocumentStore._convert_document_to_chroma(doc) for doc in documents) if p is not None
606
+ ]
607
+ if not chroma_payloads:
608
+ return 0
609
+
610
+ if policy in (DuplicatePolicy.FAIL, DuplicatePolicy.SKIP):
611
+ existing_ids = set(self._collection.get(ids=[p["ids"][0] for p in chroma_payloads])["ids"])
612
+ payloads_to_write = self._apply_duplicate_policy(chroma_payloads, existing_ids, policy)
613
+ else:
614
+ payloads_to_write = chroma_payloads
615
+
616
+ for payload in payloads_to_write:
617
+ if policy == DuplicatePolicy.OVERWRITE:
618
+ self._collection.upsert(**payload)
619
+ else:
620
+ self._collection.add(**payload)
607
621
 
608
- return len(documents)
622
+ return len(payloads_to_write)
609
623
 
610
624
  async def write_documents_async(
611
625
  self,
612
626
  documents: list[Document],
613
- policy: DuplicatePolicy = DuplicatePolicy.FAIL,
627
+ policy: DuplicatePolicy = DuplicatePolicy.NONE,
614
628
  ) -> int:
615
629
  """
616
- Asynchronously writes (or overwrites) documents into the store.
630
+ Asynchronously writes documents into the store.
617
631
 
618
632
  Asynchronous methods are only supported for HTTP connections.
619
633
 
620
634
  :param documents:
621
635
  A list of documents to write into the document store.
622
636
  :param policy:
623
- Not supported at the moment.
637
+ How to handle documents whose `id` already exists in the store:
638
+ - `NONE` (default): treated as `FAIL`.
639
+ - `OVERWRITE`: replace the existing document.
640
+ - `SKIP`: keep the existing document and skip the new one.
641
+ - `FAIL`: raise `DuplicateDocumentError`.
624
642
 
625
643
  :raises ValueError:
626
644
  When input is not valid.
645
+ :raises DuplicateDocumentError:
646
+ When `policy` is `FAIL` (or `NONE`) and any document `id` already exists.
627
647
 
628
648
  :returns:
629
- The number of documents written
649
+ The number of documents written.
630
650
  """
631
651
  await self._ensure_initialized_async()
632
652
  assert self._async_collection is not None
633
653
 
634
- for doc in documents:
635
- data = ChromaDocumentStore._convert_document_to_chroma(doc)
636
- if data is not None:
637
- await self._async_collection.add(**data)
654
+ if policy == DuplicatePolicy.NONE:
655
+ policy = DuplicatePolicy.FAIL
656
+
657
+ chroma_payloads: list[dict[str, Any]] = [
658
+ p for p in (ChromaDocumentStore._convert_document_to_chroma(doc) for doc in documents) if p is not None
659
+ ]
660
+ if not chroma_payloads:
661
+ return 0
662
+
663
+ if policy in (DuplicatePolicy.FAIL, DuplicatePolicy.SKIP):
664
+ existing = await self._async_collection.get(ids=[p["ids"][0] for p in chroma_payloads])
665
+ existing_ids = set(existing["ids"])
666
+ payloads_to_write = self._apply_duplicate_policy(chroma_payloads, existing_ids, policy)
667
+ else:
668
+ payloads_to_write = chroma_payloads
638
669
 
639
- return len(documents)
670
+ for payload in payloads_to_write:
671
+ if policy == DuplicatePolicy.OVERWRITE:
672
+ await self._async_collection.upsert(**payload)
673
+ else:
674
+ await self._async_collection.add(**payload)
675
+
676
+ return len(payloads_to_write)
677
+
678
+ @staticmethod
679
+ def _apply_duplicate_policy(
680
+ payloads: list[dict[str, Any]],
681
+ existing_ids: set[str],
682
+ policy: DuplicatePolicy,
683
+ ) -> list[dict[str, Any]]:
684
+ if policy == DuplicatePolicy.FAIL:
685
+ duplicates = [p["ids"][0] for p in payloads if p["ids"][0] in existing_ids]
686
+ if duplicates:
687
+ msg = f"Documents with ids {duplicates} already exist in the document store."
688
+ raise DuplicateDocumentError(msg)
689
+ return payloads
690
+ if policy == DuplicatePolicy.SKIP:
691
+ return [p for p in payloads if p["ids"][0] not in existing_ids]
692
+ return payloads
640
693
 
641
694
  def delete_documents(self, document_ids: list[str]) -> None:
642
695
  """
@@ -1008,8 +1061,7 @@ class ChromaDocumentStore:
1008
1061
  filters: dict[str, Any] | None = None,
1009
1062
  ) -> list[list[Document]]:
1010
1063
  """
1011
- Asynchronously perform vector search on the stored document, pass the embeddings of the queries instead of
1012
- their text.
1064
+ Asynchronously perform vector search using query embeddings instead of text.
1013
1065
 
1014
1066
  Asynchronous methods are only supported for HTTP connections.
1015
1067
 
@@ -1074,8 +1126,7 @@ class ChromaDocumentStore:
1074
1126
 
1075
1127
  def count_unique_metadata_by_filter(self, filters: dict[str, Any], metadata_fields: list[str]) -> dict[str, int]:
1076
1128
  """
1077
- Returns the number of unique values for each specified metadata field
1078
- of the documents that match the provided filters.
1129
+ Return unique value counts for metadata fields of documents matching the provided filters.
1079
1130
 
1080
1131
  :param filters: The filters to apply to count documents.
1081
1132
  For filter syntax, see [Haystack metadata filtering](https://docs.haystack.deepset.ai/docs/metadata-filtering)
@@ -1087,7 +1138,7 @@ class ChromaDocumentStore:
1087
1138
  self._ensure_initialized()
1088
1139
  assert self._collection is not None
1089
1140
 
1090
- normalized_fields = [self._normalize_metadata_field_name(field) for field in metadata_fields]
1141
+ normalized_fields = [_normalize_metadata_field_name(field) for field in metadata_fields]
1091
1142
 
1092
1143
  kwargs = ChromaDocumentStore._prepare_get_kwargs(filters)
1093
1144
  kwargs["include"] = ["metadatas"]
@@ -1099,8 +1150,7 @@ class ChromaDocumentStore:
1099
1150
  self, filters: dict[str, Any], metadata_fields: list[str]
1100
1151
  ) -> dict[str, int]:
1101
1152
  """
1102
- Asynchronously returns the number of unique values for each specified metadata field
1103
- of the documents that match the provided filters.
1153
+ Asynchronously return unique value counts for metadata fields of documents matching the provided filters.
1104
1154
 
1105
1155
  Asynchronous methods are only supported for HTTP connections.
1106
1156
 
@@ -1114,7 +1164,7 @@ class ChromaDocumentStore:
1114
1164
  await self._ensure_initialized_async()
1115
1165
  assert self._async_collection is not None
1116
1166
 
1117
- normalized_fields = [self._normalize_metadata_field_name(field) for field in metadata_fields]
1167
+ normalized_fields = [_normalize_metadata_field_name(field) for field in metadata_fields]
1118
1168
 
1119
1169
  kwargs = ChromaDocumentStore._prepare_get_kwargs(filters)
1120
1170
  kwargs["include"] = ["metadatas"]
@@ -1205,7 +1255,7 @@ class ChromaDocumentStore:
1205
1255
  self._ensure_initialized()
1206
1256
  assert self._collection is not None
1207
1257
 
1208
- field_name = self._normalize_metadata_field_name(metadata_field)
1258
+ field_name = _normalize_metadata_field_name(metadata_field)
1209
1259
 
1210
1260
  result = self._collection.get(include=["metadatas"])
1211
1261
  return self._compute_field_min_max(result.get("metadatas", []), field_name)
@@ -1229,7 +1279,7 @@ class ChromaDocumentStore:
1229
1279
  await self._ensure_initialized_async()
1230
1280
  assert self._async_collection is not None
1231
1281
 
1232
- field_name = self._normalize_metadata_field_name(metadata_field)
1282
+ field_name = _normalize_metadata_field_name(metadata_field)
1233
1283
 
1234
1284
  result = await self._async_collection.get(include=["metadatas"])
1235
1285
  return self._compute_field_min_max(result.get("metadatas", []), field_name)
@@ -1242,8 +1292,7 @@ class ChromaDocumentStore:
1242
1292
  size: int = 10,
1243
1293
  ) -> tuple[list[str], int]:
1244
1294
  """
1245
- Returns unique values for a metadata field, optionally filtered by
1246
- a search term in the content field, with pagination support.
1295
+ Return unique metadata field values, optionally filtered by a content search term, with pagination.
1247
1296
 
1248
1297
  :param metadata_field: The metadata field to get unique values for.
1249
1298
  Can include or omit the "meta." prefix.
@@ -1256,7 +1305,7 @@ class ChromaDocumentStore:
1256
1305
  self._ensure_initialized()
1257
1306
  assert self._collection is not None
1258
1307
 
1259
- field_name = self._normalize_metadata_field_name(metadata_field)
1308
+ field_name = _normalize_metadata_field_name(metadata_field)
1260
1309
 
1261
1310
  kwargs: dict[str, Any] = {"include": ["metadatas"]}
1262
1311
  if search_term:
@@ -1273,8 +1322,7 @@ class ChromaDocumentStore:
1273
1322
  size: int = 10,
1274
1323
  ) -> tuple[list[str], int]:
1275
1324
  """
1276
- Asynchronously returns unique values for a metadata field, optionally filtered by
1277
- a search term in the content field, with pagination support.
1325
+ Asynchronously return unique metadata field values, optionally filtered by content, with pagination.
1278
1326
 
1279
1327
  Asynchronous methods are only supported for HTTP connections.
1280
1328
 
@@ -1289,7 +1337,7 @@ class ChromaDocumentStore:
1289
1337
  await self._ensure_initialized_async()
1290
1338
  assert self._async_collection is not None
1291
1339
 
1292
- field_name = self._normalize_metadata_field_name(metadata_field)
1340
+ field_name = _normalize_metadata_field_name(metadata_field)
1293
1341
 
1294
1342
  kwargs: dict[str, Any] = {"include": ["metadatas"]}
1295
1343
  if search_term:
@@ -44,8 +44,10 @@ class ChromaFilter:
44
44
 
45
45
  def _convert_filters(filters: dict[str, Any]) -> ChromaFilter:
46
46
  """
47
- Converts Haystack filters into a format compatible with Chroma, separating them into ids, metadata filters,
48
- and content filters to be passed to chroma as ids, where, and where_document clauses respectively.
47
+ Converts Haystack filters into a format compatible with Chroma.
48
+
49
+ Separates filters into ids, metadata filters, and content filters to be passed to chroma as ids, where,
50
+ and where_document clauses respectively.
49
51
  """
50
52
 
51
53
  ids = []
@@ -103,9 +105,7 @@ def _convert_filter_clause(filters: dict[str, Any]) -> dict[str, Any]:
103
105
 
104
106
  def _create_where_document_filter(field: str, value: dict[Any, Any]) -> dict[str, Any]:
105
107
  """
106
- Method to check if given haystack filter is a document filter
107
- and converts it to Chroma-compatible where_document filter.
108
-
108
+ Check if a given Haystack filter is a document filter and convert it to a Chroma-compatible where_document filter.
109
109
  """
110
110
  where_document: dict[str, list[Any]] = defaultdict(list)
111
111
 
@@ -37,7 +37,8 @@ FUNCTION_REGISTRY = {
37
37
 
38
38
 
39
39
  def get_embedding_function(function_name: str, **kwargs: Any) -> EmbeddingFunction:
40
- """Load an embedding function by name.
40
+ """
41
+ Load an embedding function by name.
41
42
 
42
43
  :param function_name: the name of the embedding function.
43
44
  :param kwargs: additional arguments to pass to the embedding function.