chroma-haystack 3.3.0__tar.gz → 3.4.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-3.3.0 → chroma_haystack-3.4.0}/CHANGELOG.md +7 -0
  2. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/PKG-INFO +8 -22
  3. chroma_haystack-3.4.0/README.md +13 -0
  4. chroma_haystack-3.4.0/pydoc/config_docusaurus.yml +31 -0
  5. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/pyproject.toml +1 -6
  6. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/src/haystack_integrations/document_stores/chroma/document_store.py +85 -0
  7. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/tests/test_document_store.py +39 -0
  8. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/tests/test_document_store_async.py +50 -0
  9. chroma_haystack-3.3.0/README.md +0 -27
  10. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/.gitignore +0 -0
  11. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/LICENSE +0 -0
  12. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_01.txt +0 -0
  13. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_02.txt +0 -0
  14. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_03.txt +0 -0
  15. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_04.txt +0 -0
  16. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_05.txt +0 -0
  17. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_06.txt +0 -0
  18. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_07.txt +0 -0
  19. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_08.txt +0 -0
  20. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_09.txt +0 -0
  21. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_10.txt +0 -0
  22. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_11.txt +0 -0
  23. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_12.txt +0 -0
  24. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_20.txt +0 -0
  25. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_21.txt +0 -0
  26. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_22.txt +0 -0
  27. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_23.txt +0 -0
  28. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_24.txt +0 -0
  29. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_25.txt +0 -0
  30. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_26.txt +0 -0
  31. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_27.txt +0 -0
  32. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_28.txt +0 -0
  33. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_29.txt +0 -0
  34. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_30.txt +0 -0
  35. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_31.txt +0 -0
  36. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_32.txt +0 -0
  37. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_40.txt +0 -0
  38. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_41.txt +0 -0
  39. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_42.txt +0 -0
  40. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_43.txt +0 -0
  41. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_44.txt +0 -0
  42. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_45.txt +0 -0
  43. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_46.txt +0 -0
  44. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_50.txt +0 -0
  45. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_51.txt +0 -0
  46. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_52.txt +0 -0
  47. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/data/usr_90.txt +0 -0
  48. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/example/example.py +0 -0
  49. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/pydoc/config.yml +0 -0
  50. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/src/haystack_integrations/components/retrievers/chroma/__init__.py +0 -0
  51. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/src/haystack_integrations/components/retrievers/chroma/retriever.py +0 -0
  52. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/src/haystack_integrations/components/retrievers/py.typed +0 -0
  53. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/src/haystack_integrations/document_stores/chroma/__init__.py +0 -0
  54. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/src/haystack_integrations/document_stores/chroma/errors.py +0 -0
  55. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/src/haystack_integrations/document_stores/chroma/filters.py +0 -0
  56. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/src/haystack_integrations/document_stores/chroma/utils.py +0 -0
  57. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/src/haystack_integrations/document_stores/py.typed +0 -0
  58. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/tests/__init__.py +0 -0
  59. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/tests/conftest.py +0 -0
  60. {chroma_haystack-3.3.0 → chroma_haystack-3.4.0}/tests/test_retriever.py +0 -0
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [integrations/chroma-v3.3.0] - 2025-06-09
4
+
5
+ ### 🚀 Features
6
+
7
+ - Chroma - fix typing + ship types by adding py.typed files (#1910)
8
+
9
+
3
10
  ## [integrations/chroma-v3.2.0] - 2025-06-06
4
11
 
5
12
  ### 🚀 Features
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chroma-haystack
3
- Version: 3.3.0
3
+ Version: 3.4.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
@@ -18,34 +18,20 @@ Classifier: Programming Language :: Python :: 3.13
18
18
  Classifier: Programming Language :: Python :: Implementation :: CPython
19
19
  Classifier: Programming Language :: Python :: Implementation :: PyPy
20
20
  Requires-Python: >=3.9
21
- Requires-Dist: chromadb>=1.0.0
21
+ Requires-Dist: chromadb>=1.0.2
22
22
  Requires-Dist: haystack-ai>=2.11.0
23
23
  Description-Content-Type: text/markdown
24
24
 
25
- # Chroma Document Store for Haystack
25
+ # chroma-haystack
26
26
 
27
27
  [![PyPI - Version](https://img.shields.io/pypi/v/chroma-haystack.svg)](https://pypi.org/project/chroma-haystack)
28
28
  [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/chroma-haystack.svg)](https://pypi.org/project/chroma-haystack)
29
- [![test](https://github.com/masci/chroma-haystack/actions/workflows/test.yml/badge.svg)](https://github.com/masci/chroma-haystack/actions/workflows/test.yml)
30
29
 
31
- -----
30
+ - [Integration page](https://haystack.deepset.ai/integrations/chroma-documentstore)
31
+ - [Changelog](https://github.com/deepset-ai/haystack-core-integrations/blob/main/integrations/chroma/CHANGELOG.md)
32
32
 
33
- **Table of Contents**
33
+ ---
34
34
 
35
- - [Chroma Document Store for Haystack](#chroma-document-store-for-haystack)
36
- - [Installation](#installation)
37
- - [Examples](#examples)
38
- - [License](#license)
35
+ ## Contributing
39
36
 
40
- ## Installation
41
-
42
- ```console
43
- pip install chroma-haystack
44
- ```
45
-
46
- ## Examples
47
- You can find a code example showing how to use the Document Store and the Retriever under the `example/` folder of this repo or in [this Colab](https://colab.research.google.com/drive/1YpDetI8BRbObPDEVdfqUcwhEX9UUXP-m?usp=sharing).
48
-
49
- ## License
50
-
51
- `chroma-haystack` is distributed under the terms of the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) license.
37
+ Refer to the general [Contribution Guidelines](https://github.com/deepset-ai/haystack-core-integrations/blob/main/CONTRIBUTING.md).
@@ -0,0 +1,13 @@
1
+ # chroma-haystack
2
+
3
+ [![PyPI - Version](https://img.shields.io/pypi/v/chroma-haystack.svg)](https://pypi.org/project/chroma-haystack)
4
+ [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/chroma-haystack.svg)](https://pypi.org/project/chroma-haystack)
5
+
6
+ - [Integration page](https://haystack.deepset.ai/integrations/chroma-documentstore)
7
+ - [Changelog](https://github.com/deepset-ai/haystack-core-integrations/blob/main/integrations/chroma/CHANGELOG.md)
8
+
9
+ ---
10
+
11
+ ## Contributing
12
+
13
+ Refer to the general [Contribution Guidelines](https://github.com/deepset-ai/haystack-core-integrations/blob/main/CONTRIBUTING.md).
@@ -0,0 +1,31 @@
1
+ loaders:
2
+ - ignore_when_discovered:
3
+ - __init__
4
+ modules:
5
+ - haystack_integrations.components.retrievers.chroma.retriever
6
+ - haystack_integrations.document_stores.chroma.document_store
7
+ - haystack_integrations.document_stores.chroma.errors
8
+ - haystack_integrations.document_stores.chroma.utils
9
+ search_path:
10
+ - ../src
11
+ type: haystack_pydoc_tools.loaders.CustomPythonLoader
12
+ processors:
13
+ - do_not_filter_modules: false
14
+ documented_only: true
15
+ expression: null
16
+ skip_empty_modules: true
17
+ type: filter
18
+ - type: smart
19
+ - type: crossref
20
+ renderer:
21
+ description: Chroma integration for Haystack
22
+ id: integrations-chroma
23
+ markdown:
24
+ add_member_class_prefix: false
25
+ add_method_class_prefix: true
26
+ classdef_code_block: false
27
+ descriptive_class_title: false
28
+ descriptive_module_title: true
29
+ filename: chroma.md
30
+ title: Chroma
31
+ type: haystack_pydoc_tools.renderers.DocusaurusRenderer
@@ -23,7 +23,7 @@ classifiers = [
23
23
  "Programming Language :: Python :: Implementation :: CPython",
24
24
  "Programming Language :: Python :: Implementation :: PyPy",
25
25
  ]
26
- dependencies = ["haystack-ai>=2.11.0", "chromadb>=1.0.0"]
26
+ dependencies = ["haystack-ai>=2.11.0", "chromadb>=1.0.2"]
27
27
 
28
28
  [project.urls]
29
29
  Documentation = "https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/chroma#readme"
@@ -77,11 +77,6 @@ disallow_incomplete_defs = true
77
77
  [tool.hatch.metadata]
78
78
  allow-direct-references = true
79
79
 
80
- [tool.black]
81
- target-version = ["py38"]
82
- line-length = 120
83
- skip-string-normalization = true
84
-
85
80
  [tool.ruff]
86
81
  target-version = "py38"
87
82
  line-length = 120
@@ -9,6 +9,7 @@ from chromadb.api.models.AsyncCollection import AsyncCollection
9
9
  from chromadb.api.types import GetResult, QueryResult
10
10
  from haystack import default_from_dict, default_to_dict, logging
11
11
  from haystack.dataclasses import Document
12
+ from haystack.document_stores.errors import DocumentStoreError
12
13
  from haystack.document_stores.types import DuplicatePolicy
13
14
 
14
15
  from .filters import _convert_filters
@@ -113,6 +114,8 @@ class ChromaDocumentStore:
113
114
  # Local persistent storage
114
115
  client = chromadb.PersistentClient(path=self._persist_path)
115
116
 
117
+ self._client = client # store client for potential future use
118
+
116
119
  self._metadata = self._metadata or {}
117
120
  if "hnsw:space" not in self._metadata:
118
121
  self._metadata["hnsw:space"] = self._distance_function
@@ -149,6 +152,8 @@ class ChromaDocumentStore:
149
152
  port=self._port,
150
153
  )
151
154
 
155
+ self._async_client = client # store client for potential future use
156
+
152
157
  self._metadata = self._metadata or {}
153
158
  if "hnsw:space" not in self._metadata:
154
159
  self._metadata["hnsw:space"] = self._distance_function
@@ -408,6 +413,86 @@ class ChromaDocumentStore:
408
413
 
409
414
  await self._async_collection.delete(ids=document_ids)
410
415
 
416
+ def delete_all_documents(self, *, recreate_index: bool = False) -> None:
417
+ """
418
+ Deletes all documents in the document store.
419
+
420
+ A fast way to clear all documents from the document store while preserving any collection settings and mappings.
421
+ :param recreate_index: Whether to recreate the index after deleting all documents.
422
+ """
423
+ self._ensure_initialized() # _ensure_initialized ensures _client is not None and a collection exists
424
+ assert self._collection is not None
425
+
426
+ try:
427
+ if recreate_index:
428
+ # Store existing collection metadata and embedding function
429
+ metadata = self._collection.metadata
430
+ embedding_function = self._collection._embedding_function
431
+ collection_name = self._collection_name
432
+
433
+ # Delete the collection
434
+ self._client.delete_collection(name=collection_name)
435
+
436
+ # Recreate the collection with previous metadata
437
+ self._collection = self._client.create_collection(
438
+ name=collection_name,
439
+ metadata=metadata,
440
+ embedding_function=embedding_function,
441
+ )
442
+
443
+ else:
444
+ collection = self._collection.get()
445
+ ids = collection.get("ids", [])
446
+ self._collection.delete(ids=ids) # type: ignore
447
+ logger.info(
448
+ "Deleted all the {n_docs} documents from the collection '{name}'.",
449
+ name=self._collection_name,
450
+ n_docs=len(ids),
451
+ )
452
+ except Exception as e:
453
+ msg = f"Failed to delete all documents from ChromaDB: {e!s}"
454
+ raise DocumentStoreError(msg) from e
455
+
456
+ async def delete_all_documents_async(self, *, recreate_index: bool = False) -> None:
457
+ """
458
+ Asynchronously deletes all documents in the document store.
459
+
460
+ A fast way to clear all documents from the document store while preserving any collection settings and mappings.
461
+ :param recreate_index: Whether to recreate the index after deleting all documents.
462
+ """
463
+ await self._ensure_initialized_async() # ensures _async_client is not None
464
+ assert self._async_collection is not None
465
+
466
+ try:
467
+ if recreate_index:
468
+ # Store existing collection metadata and embedding function
469
+ metadata = self._async_collection.metadata
470
+ embedding_function = self._async_collection._embedding_function
471
+ collection_name = self._collection_name
472
+
473
+ # Delete the collection
474
+ await self._async_client.delete_collection(name=collection_name)
475
+
476
+ # Recreate the collection with previous metadata
477
+ self._async_collection = await self._async_client.create_collection(
478
+ name=collection_name,
479
+ metadata=metadata,
480
+ embedding_function=embedding_function,
481
+ )
482
+ else:
483
+ collection = await self._async_collection.get()
484
+ ids = collection.get("ids", [])
485
+ await self._async_collection.delete(ids=ids) # type: ignore
486
+ logger.info(
487
+ "Deleted all the {n_docs} documents from the collection '{name}'.",
488
+ name=self._collection_name,
489
+ n_docs=len(ids),
490
+ )
491
+
492
+ except Exception as e:
493
+ msg = f"Failed to delete all documents from ChromaDB: {e!s}"
494
+ raise DocumentStoreError(msg) from e
495
+
411
496
  def search(
412
497
  self,
413
498
  queries: List[str],
@@ -4,6 +4,7 @@
4
4
 
5
5
  import logging
6
6
  import operator
7
+ import time
7
8
  import uuid
8
9
  from typing import List
9
10
  from unittest import mock
@@ -381,3 +382,41 @@ class TestDocumentStore(CountDocumentsTest, DeleteDocumentsTest, FilterDocuments
381
382
  # check that empty filters behave as no filters
382
383
  result_empty_filters = document_store.search(["Third"], filters={}, top_k=1)
383
384
  assert result == result_empty_filters
385
+
386
+ def test_delete_all_documents_index_recreation(self, document_store: ChromaDocumentStore):
387
+ # write some documents
388
+ docs = [Document(id="1", content="A first document"), Document(id="2", content="Second document")]
389
+ document_store.write_documents(docs)
390
+
391
+ # get the current document_store config
392
+ config_before = document_store._collection.get(document_store._collection_name)
393
+
394
+ # delete all documents with recreating the index
395
+ document_store.delete_all_documents(recreate_index=True)
396
+ assert document_store.count_documents() == 0
397
+
398
+ # assure that with the same config
399
+ config_after = document_store._collection.get(document_store._collection_name)
400
+
401
+ assert config_before == config_after
402
+
403
+ # ensure the collection still exists by writing documents again
404
+ document_store.write_documents(docs)
405
+ assert document_store.count_documents() == 2
406
+
407
+ def test_delete_all_documents_no_index_recreation(self, document_store: ChromaDocumentStore):
408
+ docs = [Document(id="1", content="A first document"), Document(id="2", content="Second document")]
409
+ document_store.write_documents(docs)
410
+ assert document_store.count_documents() == 2
411
+
412
+ document_store.delete_all_documents()
413
+ time.sleep(2) # need to wait for the deletion to be reflected in count_documents
414
+ assert document_store.count_documents() == 0
415
+
416
+ new_doc = Document(id="3", content="New document after delete all")
417
+ document_store.write_documents([new_doc])
418
+ assert document_store.count_documents() == 1
419
+
420
+ results = document_store.filter_documents()
421
+ assert len(results) == 1
422
+ assert results[0].content == "New document after delete all"
@@ -120,3 +120,53 @@ class TestDocumentStoreAsync:
120
120
  # check that empty filters behave as no filters
121
121
  result_empty_filters = document_store.search(["Third"], filters={}, top_k=1)
122
122
  assert result == result_empty_filters
123
+
124
+ @pytest.mark.asyncio
125
+ async def test_delete_all_documents_index_recreation(self, document_store: ChromaDocumentStore):
126
+ # write some documents
127
+ docs = [
128
+ Document(id="1", content="First document", meta={"category": "test"}),
129
+ Document(id="2", content="Second document", meta={"category": "test"}),
130
+ Document(id="3", content="Third document", meta={"category": "other"}),
131
+ ]
132
+ await document_store.write_documents_async(docs)
133
+
134
+ # get the current document_store config
135
+ config_before = await document_store._async_collection.get(document_store._collection_name)
136
+
137
+ # delete all documents with recreating the index
138
+ await document_store.delete_all_documents_async(recreate_index=True)
139
+ assert await document_store.count_documents_async() == 0
140
+
141
+ # assure that with the same config
142
+ config_after = await document_store._async_collection.get(document_store._collection_name)
143
+
144
+ assert config_before == config_after
145
+
146
+ # ensure the collection still exists by writing documents again
147
+ await document_store.write_documents_async(docs)
148
+ assert await document_store.count_documents_async() == 3
149
+
150
+ @pytest.mark.asyncio
151
+ async def test_delete_all_documents_async(self, document_store):
152
+ docs = [
153
+ Document(id="1", content="First document", meta={"category": "test"}),
154
+ Document(id="2", content="Second document", meta={"category": "test"}),
155
+ Document(id="3", content="Third document", meta={"category": "other"}),
156
+ ]
157
+ await document_store.write_documents_async(docs)
158
+ assert await document_store.count_documents_async() == 3
159
+
160
+ # delete all documents
161
+ await document_store.delete_all_documents_async()
162
+ assert await document_store.count_documents_async() == 0
163
+
164
+ # verify index still exists and can accept new documents and retrieve
165
+ new_doc = Document(id="4", content="New document after delete all")
166
+ await document_store.write_documents_async([new_doc])
167
+ assert await document_store.count_documents_async() == 1
168
+
169
+ results = await document_store.filter_documents_async()
170
+ assert len(results) == 1
171
+ assert results[0].id == "4"
172
+ assert results[0].content == "New document after delete all"
@@ -1,27 +0,0 @@
1
- # Chroma Document Store for Haystack
2
-
3
- [![PyPI - Version](https://img.shields.io/pypi/v/chroma-haystack.svg)](https://pypi.org/project/chroma-haystack)
4
- [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/chroma-haystack.svg)](https://pypi.org/project/chroma-haystack)
5
- [![test](https://github.com/masci/chroma-haystack/actions/workflows/test.yml/badge.svg)](https://github.com/masci/chroma-haystack/actions/workflows/test.yml)
6
-
7
- -----
8
-
9
- **Table of Contents**
10
-
11
- - [Chroma Document Store for Haystack](#chroma-document-store-for-haystack)
12
- - [Installation](#installation)
13
- - [Examples](#examples)
14
- - [License](#license)
15
-
16
- ## Installation
17
-
18
- ```console
19
- pip install chroma-haystack
20
- ```
21
-
22
- ## Examples
23
- You can find a code example showing how to use the Document Store and the Retriever under the `example/` folder of this repo or in [this Colab](https://colab.research.google.com/drive/1YpDetI8BRbObPDEVdfqUcwhEX9UUXP-m?usp=sharing).
24
-
25
- ## License
26
-
27
- `chroma-haystack` is distributed under the terms of the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) license.
File without changes